Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(derive): Online Module Touchups #265

Merged
merged 1 commit into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions crates/derive/src/online/beacon_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::types::{
IndexedBlobHash,
};
use alloc::{boxed::Box, format, string::String, vec::Vec};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use reqwest::Client;

Expand All @@ -21,10 +22,10 @@ pub(crate) const SIDECARS_METHOD_PREFIX: &str = "eth/v1/beacon/blob_sidecars";
#[async_trait]
pub trait BeaconClient {
/// Returns the config spec.
async fn config_spec(&self) -> anyhow::Result<APIConfigResponse>;
async fn config_spec(&self) -> Result<APIConfigResponse>;

/// Returns the beacon genesis.
async fn beacon_genesis(&self) -> anyhow::Result<APIGenesisResponse>;
async fn beacon_genesis(&self) -> Result<APIGenesisResponse>;

/// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed
/// hashes. Order of the returned sidecars is guaranteed to be that of the hashes. Blob data is
Expand All @@ -33,7 +34,7 @@ pub trait BeaconClient {
&self,
slot: u64,
hashes: &[IndexedBlobHash],
) -> anyhow::Result<Vec<APIBlobSidecar>>;
) -> Result<Vec<APIBlobSidecar>>;
}

/// An online implementation of the [BeaconClient] trait.
Expand All @@ -54,42 +55,42 @@ impl OnlineBeaconClient {

#[async_trait]
impl BeaconClient for OnlineBeaconClient {
async fn config_spec(&self) -> anyhow::Result<APIConfigResponse> {
async fn config_spec(&self) -> Result<APIConfigResponse> {
self.inner
.get(format!("{}/{}", self.base, SPEC_METHOD))
.send()
.await
.map_err(|e| anyhow::anyhow!(e))?
.map_err(|e| anyhow!(e))?
.json::<APIConfigResponse>()
.await
.map_err(|e| anyhow::anyhow!(e))
.map_err(|e| anyhow!(e))
}

async fn beacon_genesis(&self) -> anyhow::Result<APIGenesisResponse> {
async fn beacon_genesis(&self) -> Result<APIGenesisResponse> {
self.inner
.get(format!("{}/{}", self.base, GENESIS_METHOD))
.send()
.await
.map_err(|e| anyhow::anyhow!(e))?
.map_err(|e| anyhow!(e))?
.json::<APIGenesisResponse>()
.await
.map_err(|e| anyhow::anyhow!(e))
.map_err(|e| anyhow!(e))
}

async fn beacon_blob_side_cars(
&self,
slot: u64,
hashes: &[IndexedBlobHash],
) -> anyhow::Result<Vec<APIBlobSidecar>> {
) -> Result<Vec<APIBlobSidecar>> {
let raw_response = self
.inner
.get(format!("{}/{}/{}", self.base, SIDECARS_METHOD_PREFIX, slot))
.send()
.await
.map_err(|e| anyhow::anyhow!(e))?
.map_err(|e| anyhow!(e))?
.json::<APIGetBlobSidecarsResponse>()
.await
.map_err(|e| anyhow::anyhow!(e))?;
.map_err(|e| anyhow!(e))?;

let mut sidecars = Vec::with_capacity(hashes.len());

Expand Down
17 changes: 6 additions & 11 deletions crates/derive/src/online/blob_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use crate::{
types::{APIBlobSidecar, Blob, BlobProviderError, BlobSidecar, BlockInfo, IndexedBlobHash},
};
use alloc::{boxed::Box, vec::Vec};
use anyhow::{anyhow, ensure};
use async_trait::async_trait;
use core::marker::PhantomData;
use tracing::debug;

/// Specifies the derivation of a slot from a timestamp.
pub trait SlotDerivation {
Expand Down Expand Up @@ -42,11 +42,9 @@ impl<B: BeaconClient, S: SlotDerivation> OnlineBlobProvider<B, S> {
/// Loads the beacon genesis and config spec
pub async fn load_configs(&mut self) -> Result<(), BlobProviderError> {
if self.genesis_time.is_none() {
debug!("Loading missing BeaconGenesis");
self.genesis_time = Some(self.beacon_client.beacon_genesis().await?.data.genesis_time);
}
if self.slot_interval.is_none() {
debug!("Loading missing ConfigSpec");
self.slot_interval =
Some(self.beacon_client.config_spec().await?.data.seconds_per_slot);
}
Expand All @@ -72,13 +70,10 @@ pub struct SimpleSlotDerivation;

impl SlotDerivation for SimpleSlotDerivation {
fn slot(genesis: u64, slot_time: u64, timestamp: u64) -> anyhow::Result<u64> {
if timestamp < genesis {
return Err(anyhow::anyhow!(
"provided timestamp ({}) precedes genesis time ({})",
timestamp,
genesis
));
}
ensure!(
timestamp >= genesis,
"provided timestamp ({timestamp}) precedes genesis time ({genesis})"
);
Ok((timestamp - genesis) / slot_time)
}
}
Expand Down Expand Up @@ -134,7 +129,7 @@ where
.into_iter()
.enumerate()
.map(|(i, sidecar)| {
let hash = blob_hashes.get(i).ok_or(anyhow::anyhow!("failed to get blob hash"))?;
let hash = blob_hashes.get(i).ok_or(anyhow!("failed to get blob hash"))?;
match sidecar.verify_blob(hash) {
Ok(_) => Ok(sidecar.blob),
Err(e) => Err(e),
Expand Down
2 changes: 1 addition & 1 deletion crates/derive/src/online/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use crate::{
sources::EthereumDataSource,
stages::StatefulAttributesBuilder,
traits::{ChainProvider, L2ChainProvider, OriginProvider, Pipeline},
types::RollupConfig,
types::{BlockInfo, RollupConfig},
};

mod pipeline;
Expand Down
20 changes: 8 additions & 12 deletions crates/derive/src/online/pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
//! Contains online pipeline types.

use crate::{
online::{
AlloyChainProvider, AlloyL2ChainProvider, OnlineBeaconClient, OnlineBlobProvider,
SimpleSlotDerivation,
},
pipeline::{DerivationPipeline, PipelineBuilder},
sources::EthereumDataSource,
stages::{
AttributesQueue, BatchQueue, ChannelBank, ChannelReader, FrameQueue, L1Retrieval,
L1Traversal, StatefulAttributesBuilder,
},
types::{BlockInfo, RollupConfig},
use super::{
AlloyChainProvider, AlloyL2ChainProvider, BlockInfo, DerivationPipeline, EthereumDataSource,
OnlineBeaconClient, OnlineBlobProvider, PipelineBuilder, RollupConfig, SimpleSlotDerivation,
StatefulAttributesBuilder,
};
use alloc::sync::Arc;
// Pipeline internal stages aren't re-exported at the module-level.
use crate::stages::{
AttributesQueue, BatchQueue, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, L1Traversal,
};

/// An online derivation pipeline.
pub type OnlinePipeline =
Expand Down
20 changes: 9 additions & 11 deletions crates/derive/src/online/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use alloy_node_bindings::{Anvil, AnvilInstance};
use alloy_provider::{network::Ethereum, ReqwestProvider};
use alloy_rpc_client::RpcClient;
use alloy_transport_http::Http;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use reqwest::Client;

Expand Down Expand Up @@ -46,22 +47,19 @@ pub struct MockBeaconClient {

#[async_trait]
impl BeaconClient for MockBeaconClient {
async fn config_spec(&self) -> anyhow::Result<APIConfigResponse> {
self.config_spec.clone().ok_or_else(|| anyhow::anyhow!("config_spec not set"))
async fn config_spec(&self) -> Result<APIConfigResponse> {
self.config_spec.clone().ok_or_else(|| anyhow!("config_spec not set"))
}

async fn beacon_genesis(&self) -> anyhow::Result<APIGenesisResponse> {
self.beacon_genesis.clone().ok_or_else(|| anyhow::anyhow!("beacon_genesis not set"))
async fn beacon_genesis(&self) -> Result<APIGenesisResponse> {
self.beacon_genesis.clone().ok_or_else(|| anyhow!("beacon_genesis not set"))
}

async fn beacon_blob_side_cars(
&self,
_slot: u64,
_hashes: &[IndexedBlobHash],
) -> anyhow::Result<Vec<APIBlobSidecar>> {
self.blob_sidecars
.clone()
.ok_or_else(|| anyhow::anyhow!("blob_sidecars not set"))
.map(|r| r.data)
_: u64,
_: &[IndexedBlobHash],
) -> Result<Vec<APIBlobSidecar>> {
self.blob_sidecars.clone().ok_or_else(|| anyhow!("blob_sidecars not set")).map(|r| r.data)
}
}
Loading