-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(kona-derive): Updated interface (#230)
* feat(kona-derive): pipeline output validation * fix(kona-derive): pipeline interface and associated builder: * fixes * Update crates/derive/src/online/validation.rs Co-authored-by: clabby <[email protected]> --------- Co-authored-by: clabby <[email protected]>
- Loading branch information
Showing
8 changed files
with
252 additions
and
158 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
## Usage | ||
|
||
```rust | ||
use alloc::sync::Arc; | ||
use kona_derive::online::*; | ||
use kona_derive::pipeline::*; | ||
use kona_primitives::{BlockInfo, L2BlockInfo, RollupConfig}; | ||
|
||
// Creates a new chain provider using the `L1_RPC_URL` environment variable. | ||
let l1_rpc_url = std::env::var("L1_RPC_URL").expect("L1_RPC_URL must be set"); | ||
let chain_provider = AlloyChainProvider::new_http(l1_rpc_url.parse().unwrap()); | ||
|
||
// Creates a new l2 chain provider using the `L2_RPC_URL` environment variable. | ||
let l2_rpc_url = std::env::var("L2_RPC_URL").expect("L2_RPC_URL must be set"); | ||
let l2_chain_provider = AlloyL2ChainProvider::new_http(l2_rpc_url.parse().unwrap()); | ||
|
||
// TODO(refcell): replace this will a rollup config | ||
// fetched from the superchain-registry via network id. | ||
let rollup_config = Arc::new(RollupConfig::default()); | ||
|
||
// Create the beacon client used to fetch blob data. | ||
let beacon_url = std::env::var("BEACON_URL").expect("BEACON_URL must be set"); | ||
let beacon_client = OnlineBeaconClient::new_http(beacon_url.parse().unwrap()); | ||
|
||
// Build the online blob provider. | ||
let blob_provider = OnlineBlobProvider::<_, SimpleSlotDerivation>::new(true, beacon_client, None, None); | ||
|
||
// Build the ethereum data source | ||
let dap_source = EthereumDataSource::new(chain_provider.clone(), blob_provider, &rollup_config); | ||
|
||
// The payload attributes builder that is stateful. | ||
let attributes_builder = StatefulAttributesBuilder::new(rollup_config.clone(), l2_chain_provider.clone(), chain_provider.clone()); | ||
|
||
// Build the pipeline. | ||
let pipeline = PipelineBuilder::new() | ||
.rollup_config(rollup_config) | ||
.dap_source(dap_source) | ||
.l2_chain_provider(l2_chain_provider) | ||
.chain_provider(chain_provider) | ||
.builder(attributes_builder) | ||
.build(); | ||
|
||
// The pipeline should be at the default state. | ||
assert_eq!(pipeline.tip, BlockInfo::default()); | ||
assert_eq!(pipeline.cursor, L2BlockInfo::default()); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
//! Contains logic to validate derivation pipeline outputs. | ||
use crate::types::{L2AttributesWithParent, L2PayloadAttributes, RawTransaction}; | ||
use alloc::{boxed::Box, vec, vec::Vec}; | ||
use alloy_provider::{Provider, ReqwestProvider}; | ||
use alloy_rpc_types::{Block, BlockNumberOrTag, Header}; | ||
use alloy_transport::TransportResult; | ||
use anyhow::Result; | ||
use async_trait::async_trait; | ||
use tracing::warn; | ||
|
||
/// Validator | ||
/// | ||
/// The validator trait describes the interface for validating the derivation outputs. | ||
#[async_trait] | ||
pub trait Validator { | ||
/// Validates the given [`L2AttributesWithParent`]. | ||
async fn validate(&self, attributes: &L2AttributesWithParent) -> bool; | ||
} | ||
|
||
/// OnlineValidator | ||
/// | ||
/// Validates the [`L2AttributesWithParent`] by fetching the associated L2 block from | ||
/// a trusted L2 RPC and constructing the L2 Attributes from the block. | ||
#[derive(Debug, Clone)] | ||
pub struct OnlineValidator { | ||
/// The L2 provider. | ||
provider: ReqwestProvider, | ||
} | ||
|
||
impl OnlineValidator { | ||
/// Creates a new `OnlineValidator`. | ||
pub fn new(provider: ReqwestProvider) -> Self { | ||
Self { provider } | ||
} | ||
|
||
/// Creates a new [OnlineValidator] from the provided [reqwest::Url]. | ||
pub fn new_http(url: reqwest::Url) -> Self { | ||
let inner = ReqwestProvider::new_http(url); | ||
Self::new(inner) | ||
} | ||
|
||
/// Fetches a block [Header] and a list of raw RLP encoded transactions from the L2 provider. | ||
/// | ||
/// This method needs to fetch the non-hydrated block and then | ||
/// fetch the raw transactions using the `debug_*` namespace. | ||
pub(crate) async fn get_block( | ||
&self, | ||
tag: BlockNumberOrTag, | ||
) -> Result<(Header, Vec<RawTransaction>)> { | ||
// Don't hydrate the block so we only get a list of transaction hashes. | ||
let block: TransportResult<Block> = | ||
self.provider.raw_request("eth_getBlockByNumber".into(), (tag, false)).await; | ||
let block = block.map_err(|e| anyhow::anyhow!(e))?; | ||
// For each transaction hash, fetch the raw transaction RLP. | ||
let mut txs = vec![]; | ||
for tx in block.transactions.hashes() { | ||
let tx: TransportResult<RawTransaction> = | ||
self.provider.raw_request("debug_getRawTransaction".into(), tx).await; | ||
if let Ok(tx) = tx { | ||
txs.push(tx); | ||
} else { | ||
warn!("Failed to fetch transaction: {:?}", tx); | ||
} | ||
} | ||
Ok((block.header, txs)) | ||
} | ||
|
||
/// Gets the payload for the specified [BlockNumberOrTag]. | ||
pub(crate) async fn get_payload(&self, tag: BlockNumberOrTag) -> Result<L2PayloadAttributes> { | ||
let (header, transactions) = self.get_block(tag).await?; | ||
Ok(L2PayloadAttributes { | ||
timestamp: header.timestamp, | ||
prev_randao: header.mix_hash.unwrap_or_default(), | ||
fee_recipient: header.miner, | ||
// Withdrawals on optimism are always empty | ||
withdrawals: Default::default(), | ||
parent_beacon_block_root: Some(header.parent_hash), | ||
transactions, | ||
no_tx_pool: true, | ||
gas_limit: Some(header.gas_limit as u64), | ||
}) | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl Validator for OnlineValidator { | ||
async fn validate(&self, attributes: &L2AttributesWithParent) -> bool { | ||
let expected = attributes.parent.block_info.number + 1; | ||
let tag = BlockNumberOrTag::from(expected); | ||
let payload = self.get_payload(tag).await.unwrap(); | ||
attributes.attributes == payload | ||
} | ||
} |
Oops, something went wrong.