From f79724c25412b75e7bd25e5c7f4622c5f3353f93 Mon Sep 17 00:00:00 2001 From: refcell Date: Tue, 17 Sep 2024 11:06:52 -0400 Subject: [PATCH] feat(primitives): Remove Attributes (#529) * feat: remove attributes * fixes --- Cargo.lock | 58 ++++- Cargo.toml | 13 +- bin/client/Cargo.toml | 4 +- bin/client/src/kona.rs | 5 +- bin/client/src/l1/driver.rs | 16 +- crates/derive/Cargo.toml | 3 + crates/derive/src/errors.rs | 4 +- crates/derive/src/pipeline/core.rs | 13 +- crates/derive/src/stages/attributes_queue.rs | 70 ++++-- .../src/stages/attributes_queue/builder.rs | 107 +++++---- .../src/stages/test_utils/attributes_queue.rs | 6 +- crates/derive/src/traits/attributes.rs | 10 +- crates/derive/src/traits/pipeline.rs | 8 +- crates/executor/Cargo.toml | 3 +- crates/executor/benches/execution.rs | 49 ++-- crates/executor/src/eip4788.rs | 8 +- crates/executor/src/lib.rs | 227 +++++++++++------- crates/primitives/src/attributes.rs | 79 ------ crates/primitives/src/lib.rs | 3 - examples/trusted-sync/Cargo.toml | 2 + examples/trusted-sync/src/main.rs | 2 +- examples/trusted-sync/src/validation.rs | 36 +-- 22 files changed, 394 insertions(+), 332 deletions(-) delete mode 100644 crates/primitives/src/attributes.rs diff --git a/Cargo.lock b/Cargo.lock index a0b07b0a..12332897 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -504,6 +504,21 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-rpc-types-engine" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c031a91e94a39f928244bc837c953817be5b8cc61759e1a9123b3abd17560dd" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "derive_more 1.0.0", + "serde", +] + [[package]] name = "alloy-rpc-types-eth" version = "0.3.5" @@ -644,9 +659,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398a977d774db13446b8cead8cfa9517aebf9e03fc8a1512892dc1e03e70bb04" +checksum = "0a46c9c4fdccda7982e7928904bd85fe235a0404ee3d7e197fff13d61eac8b4f" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -1146,9 +1161,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +checksum = "45bcde016d64c21da4be18b655631e5ab6d3107607e71a73a9f53eb48aae23fb" dependencies = [ "jobserver", "libc", @@ -2274,6 +2289,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", + "alloy-rpc-types-engine", "anyhow", "async-trait", "cfg-if", @@ -2288,6 +2304,7 @@ dependencies = [ "op-alloy-consensus", "op-alloy-genesis", "op-alloy-protocol", + "op-alloy-rpc-types-engine", "revm", "serde", "serde_json", @@ -2329,6 +2346,7 @@ dependencies = [ "alloy-provider", "alloy-rlp", "alloy-rpc-client", + "alloy-rpc-types-engine", "alloy-transport", "alloy-transport-http", "anyhow", @@ -2342,6 +2360,7 @@ dependencies = [ "op-alloy-consensus", "op-alloy-genesis", "op-alloy-protocol", + "op-alloy-rpc-types-engine", "prometheus", "proptest", "reqwest", @@ -2362,12 +2381,13 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", + "alloy-rpc-types-engine", "anyhow", "criterion", "kona-mpt", - "kona-primitives", "op-alloy-consensus", "op-alloy-genesis", + "op-alloy-rpc-types-engine", "pprof", "rand", "revm", @@ -2856,9 +2876,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -2869,7 +2889,7 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" version = "0.2.11" -source = "git+https://github.com/alloy-rs/op-alloy?branch=main#95fdc87239d58079c8db2226779545f10758ba77" +source = "git+https://github.com/alloy-rs/op-alloy?branch=main#81cb0e8e50ab15b0426634b569570c31bd07a642" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2884,7 +2904,7 @@ dependencies = [ [[package]] name = "op-alloy-genesis" version = "0.2.11" -source = "git+https://github.com/alloy-rs/op-alloy?branch=main#95fdc87239d58079c8db2226779545f10758ba77" +source = "git+https://github.com/alloy-rs/op-alloy?branch=main#81cb0e8e50ab15b0426634b569570c31bd07a642" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2897,7 +2917,7 @@ dependencies = [ [[package]] name = "op-alloy-protocol" version = "0.2.11" -source = "git+https://github.com/alloy-rs/op-alloy?branch=main#95fdc87239d58079c8db2226779545f10758ba77" +source = "git+https://github.com/alloy-rs/op-alloy?branch=main#81cb0e8e50ab15b0426634b569570c31bd07a642" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2910,6 +2930,18 @@ dependencies = [ "serde", ] +[[package]] +name = "op-alloy-rpc-types-engine" +version = "0.2.11" +source = "git+https://github.com/alloy-rs/op-alloy?branch=main#81cb0e8e50ab15b0426634b569570c31bd07a642" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-engine", + "alloy-serde", + "op-alloy-protocol", + "serde", +] + [[package]] name = "openssl" version = "0.10.66" @@ -4505,9 +4537,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "toml_datetime", @@ -4663,6 +4695,7 @@ dependencies = [ "alloy-primitives", "alloy-provider", "alloy-rpc-types", + "alloy-rpc-types-engine", "alloy-transport", "anyhow", "clap", @@ -4670,6 +4703,7 @@ dependencies = [ "kona-primitives", "lazy_static", "op-alloy-genesis", + "op-alloy-rpc-types-engine", "prometheus", "reqwest", "serde", diff --git a/Cargo.toml b/Cargo.toml index 86b0696c..370c9bd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ lto = "fat" op-alloy-protocol = { git = "https://github.com/alloy-rs/op-alloy", branch = "main" } op-alloy-consensus = { git = "https://github.com/alloy-rs/op-alloy", branch = "main" } op-alloy-genesis = { git = "https://github.com/alloy-rs/op-alloy", branch = "main" } +op-alloy-rpc-types-engine = { git = "https://github.com/alloy-rs/op-alloy", branch = "main" } [workspace.dependencies] # Workspace @@ -97,7 +98,7 @@ serde_json = { version = "1.0.125", default-features = false } unsigned-varint = "0.8.0" revm = { version = "14.0", default-features = false } -# Superchain +# Optimism superchain = { version = "0.5", default-features = false } # K/V database @@ -106,15 +107,19 @@ rocksdb = { version = "0.22", default-features = false, features = ["snappy"] } # Alloy alloy-rlp = { version = "0.3.8", default-features = false } alloy-trie = { version = "0.5", default-features = false } +alloy-eips = { version = "0.3.5", default-features = false } alloy-provider = { version = "0.3.5", default-features = false } alloy-primitives = { version = "0.8", default-features = false } -alloy-rpc-types = { version = "0.3.5", default-features = false } alloy-consensus = { version = "0.3.5", default-features = false } alloy-transport = { version = "0.3.5", default-features = false } -alloy-transport-http = { version = "0.3.5", default-features = false } -alloy-eips = { version = "0.3.5", default-features = false } +alloy-rpc-types = { version = "0.3.5", default-features = false } alloy-rpc-client = { version = "0.3.5", default-features = false } +alloy-rpc-types-engine = { version = "0.3.5", default-features = false } alloy-node-bindings = { version = "0.3.5", default-features = false } +alloy-transport-http = { version = "0.3.5", default-features = false } + +# OP Alloy op-alloy-consensus = { version = "0.2.11", default-features = false } op-alloy-protocol = { version = "0.2.11", default-features = false } op-alloy-genesis = { version = "0.2.11", default-features = false } +op-alloy-rpc-types-engine = { version = "0.2.11", default-features = false } diff --git a/bin/client/Cargo.toml b/bin/client/Cargo.toml index 09200fdb..771f73ac 100644 --- a/bin/client/Cargo.toml +++ b/bin/client/Cargo.toml @@ -18,7 +18,9 @@ kona-derive.workspace = true kona-executor.workspace = true kona-primitives = { workspace = true, features = ["serde"] } op-alloy-genesis = { workspace = true, features = ["serde"] } -op-alloy-protocol = { workspace = true, features = ["serde"] } +op-alloy-protocol.workspace = true +op-alloy-rpc-types-engine.workspace = true +alloy-rpc-types-engine.workspace = true # Revm + Alloy revm.workspace = true diff --git a/bin/client/src/kona.rs b/bin/client/src/kona.rs index f6a0ad72..f2f5fc60 100644 --- a/bin/client/src/kona.rs +++ b/bin/client/src/kona.rs @@ -16,7 +16,7 @@ use kona_client::{ }; use kona_common_proc::client_entry; use kona_executor::StatelessL2BlockExecutor; -use kona_primitives::L2AttributesWithParent; +use op_alloy_rpc_types_engine::OptimismAttributesWithParent; pub(crate) mod fault; use fault::{fpvm_handle_register, HINT_WRITER, ORACLE_READER}; @@ -58,7 +58,8 @@ fn main() -> Result<()> { l2_provider.clone(), ) .await?; - let L2AttributesWithParent { attributes, .. } = driver.produce_disputed_payload().await?; + let OptimismAttributesWithParent { attributes, .. } = + driver.produce_disputed_payload().await?; let mut executor = StatelessL2BlockExecutor::builder(&boot.rollup_config) .with_parent_header(driver.take_l2_safe_head_header()) diff --git a/bin/client/src/l1/driver.rs b/bin/client/src/l1/driver.rs index 24e9d7e2..9b37bfc8 100644 --- a/bin/client/src/l1/driver.rs +++ b/bin/client/src/l1/driver.rs @@ -1,7 +1,7 @@ -//! Contains the [DerivationDriver] struct, which handles the [L2PayloadAttributes] derivation +//! Contains the [DerivationDriver] struct, which handles the [OptimismPayloadAttributes] derivation //! process. //! -//! [L2PayloadAttributes]: kona_primitives::L2PayloadAttributes +//! [OptimismPayloadAttributes]: op_alloy_rpc_types_engine::OptimismPayloadAttributes use super::OracleL1ChainProvider; use crate::{l2::OracleL2ChainProvider, BootInfo, HintType}; @@ -21,8 +21,8 @@ use kona_derive::{ }; use kona_mpt::TrieDBFetcher; use kona_preimage::{CommsClient, PreimageKey, PreimageKeyType}; -use kona_primitives::L2AttributesWithParent; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; +use op_alloy_rpc_types_engine::OptimismAttributesWithParent; use tracing::{info, warn}; /// An oracle-backed derivation pipeline. @@ -50,13 +50,13 @@ pub type OracleAttributesQueue = AttributesQueue< OracleAttributesBuilder, >; -/// The [DerivationDriver] struct is responsible for handling the [L2PayloadAttributes] derivation -/// process. +/// The [DerivationDriver] struct is responsible for handling the [OptimismPayloadAttributes] +/// derivation process. /// /// It contains an inner [OraclePipeline] that is used to derive the attributes, backed by /// oracle-based data sources. /// -/// [L2PayloadAttributes]: kona_primitives::L2PayloadAttributes +/// [OptimismPayloadAttributes]: op_alloy_rpc_types_engine::OptimismPayloadAttributes #[derive(Debug)] pub struct DerivationDriver where @@ -150,9 +150,9 @@ where Ok(Self { l2_safe_head, l2_safe_head_header, pipeline }) } - /// Produces the disputed [L2AttributesWithParent] payload, directly after the starting L2 + /// Produces the disputed [OptimismAttributesWithParent] payload, directly after the starting L2 /// output root passed through the [BootInfo]. - pub async fn produce_disputed_payload(&mut self) -> Result { + pub async fn produce_disputed_payload(&mut self) -> Result { // As we start the safe head at the disputed block's parent, we step the pipeline until the // first attributes are produced. All batches at and before the safe head will be // dropped, so the first payload will always be the disputed one. diff --git a/crates/derive/Cargo.toml b/crates/derive/Cargo.toml index 32128c05..23cde623 100644 --- a/crates/derive/Cargo.toml +++ b/crates/derive/Cargo.toml @@ -14,9 +14,11 @@ alloy-eips.workspace = true alloy-rlp = { workspace = true, features = ["derive"] } alloy-consensus = { workspace = true, features = ["k256"] } alloy-primitives = { workspace = true, features = ["rlp", "k256"] } +alloy-rpc-types-engine.workspace = true op-alloy-consensus = { workspace = true, features = ["k256"] } op-alloy-protocol.workspace = true op-alloy-genesis.workspace = true +op-alloy-rpc-types-engine.workspace = true # General hashbrown.workspace = true @@ -71,6 +73,7 @@ serde = [ "op-alloy-consensus/serde", "op-alloy-protocol/serde", "op-alloy-genesis/serde", + "op-alloy-rpc-types-engine/serde", ] metrics = ["dep:prometheus", "dep:lazy_static"] online = [ diff --git a/crates/derive/src/errors.rs b/crates/derive/src/errors.rs index 63bd56f7..25cb5152 100644 --- a/crates/derive/src/errors.rs +++ b/crates/derive/src/errors.rs @@ -35,9 +35,9 @@ pub enum StageError { ChannelNotFound, /// Missing L1 origin. MissingOrigin, - /// Failed to build the [L2PayloadAttributes] for the next batch. + /// Failed to build the [OptimismPayloadAttributes] for the next batch. /// - /// [L2PayloadAttributes]: kona_primitives::L2PayloadAttributes + /// [OptimismPayloadAttributes]: op_alloy_rpc_types_engine::OptimismPayloadAttributes AttributesBuild(BuilderError), /// Reset the pipeline. Reset(ResetError), diff --git a/crates/derive/src/pipeline/core.rs b/crates/derive/src/pipeline/core.rs index 85153af8..c5069b9e 100644 --- a/crates/derive/src/pipeline/core.rs +++ b/crates/derive/src/pipeline/core.rs @@ -8,9 +8,9 @@ use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; use anyhow::bail; use async_trait::async_trait; use core::fmt::Debug; -use kona_primitives::L2AttributesWithParent; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; +use op_alloy_rpc_types_engine::OptimismAttributesWithParent; use tracing::{error, trace, warn}; /// The derivation pipeline is responsible for deriving L2 inputs from L1 data. @@ -23,8 +23,9 @@ where /// A handle to the next attributes. pub attributes: S, /// Reset provider for the pipeline. - /// A list of prepared [L2AttributesWithParent] to be used by the derivation pipeline consumer. - pub prepared: VecDeque, + /// A list of prepared [OptimismAttributesWithParent] to be used by the derivation pipeline + /// consumer. + pub prepared: VecDeque, /// The rollup config. pub rollup_config: Arc, /// The L2 Chain Provider used to fetch the system config on reset. @@ -57,7 +58,7 @@ where S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send + Sync, P: L2ChainProvider + Send + Sync + Debug, { - type Item = L2AttributesWithParent; + type Item = OptimismAttributesWithParent; fn next(&mut self) -> Option { self.prepared.pop_front() @@ -70,8 +71,8 @@ where S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send + Sync, P: L2ChainProvider + Send + Sync + Debug, { - /// Peeks at the next prepared [L2AttributesWithParent] from the pipeline. - fn peek(&self) -> Option<&L2AttributesWithParent> { + /// Peeks at the next prepared [OptimismAttributesWithParent] from the pipeline. + fn peek(&self) -> Option<&OptimismAttributesWithParent> { self.prepared.front() } diff --git a/crates/derive/src/stages/attributes_queue.rs b/crates/derive/src/stages/attributes_queue.rs index 392bb4f4..0ed7854f 100644 --- a/crates/derive/src/stages/attributes_queue.rs +++ b/crates/derive/src/stages/attributes_queue.rs @@ -3,9 +3,9 @@ use alloc::{boxed::Box, sync::Arc}; use async_trait::async_trait; use core::fmt::Debug; -use kona_primitives::{L2AttributesWithParent, L2PayloadAttributes}; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; +use op_alloy_rpc_types_engine::{OptimismAttributesWithParent, OptimismPayloadAttributes}; use tracing::info; use crate::{ @@ -33,7 +33,7 @@ pub trait AttributesProvider { } /// [AttributesQueue] accepts batches from the [BatchQueue] stage -/// and transforms them into [L2PayloadAttributes]. +/// and transforms them into [OptimismPayloadAttributes]. /// /// The outputted payload attributes cannot be buffered because each batch->attributes /// transformation pulls in data about the current L2 safe head. @@ -84,11 +84,11 @@ where self.batch.as_ref().cloned().ok_or(StageError::Eof) } - /// Returns the next [L2AttributesWithParent] from the current batch. + /// Returns the next [OptimismAttributesWithParent] from the current batch. pub async fn next_attributes( &mut self, parent: L2BlockInfo, - ) -> StageResult { + ) -> StageResult { crate::timer!(START, STAGE_ADVANCE_RESPONSE_TIME, &["attributes_queue"], timer); let batch = match self.load_batch(parent).await { Ok(batch) => batch, @@ -106,8 +106,11 @@ where return Err(e); } }; - let populated_attributes = - L2AttributesWithParent { attributes, parent, is_last_in_span: self.is_last_in_span }; + let populated_attributes = OptimismAttributesWithParent { + attributes, + parent, + is_last_in_span: self.is_last_in_span, + }; // Clear out the local state once payload attributes are prepared. self.batch = None; @@ -115,13 +118,13 @@ where Ok(populated_attributes) } - /// Creates the next attributes, transforming a [SingleBatch] into [L2PayloadAttributes]. + /// Creates the next attributes, transforming a [SingleBatch] into [OptimismPayloadAttributes]. /// This sets `no_tx_pool` and appends the batched txs to the attributes tx list. pub async fn create_next_attributes( &mut self, batch: SingleBatch, parent: L2BlockInfo, - ) -> StageResult { + ) -> StageResult { // Sanity check parent hash if batch.parent_hash != parent.block_info.hash { return Err(StageError::Reset(ResetError::BadParentHash( @@ -143,8 +146,15 @@ where .prepare_payload_attributes(parent, batch.epoch()) .await .map_err(StageError::AttributesBuild)?; - attributes.no_tx_pool = true; - attributes.transactions.extend(batch.transactions); + attributes.no_tx_pool = Some(true); + match attributes.transactions { + Some(ref mut txs) => txs.extend(batch.transactions), + None => { + if !batch.transactions.is_empty() { + attributes.transactions = Some(batch.transactions); + } + } + } info!( target: "attributes-queue", @@ -176,7 +186,7 @@ where async fn next_attributes( &mut self, parent: L2BlockInfo, - ) -> StageResult { + ) -> StageResult { self.next_attributes(parent).await } } @@ -212,10 +222,7 @@ where #[cfg(test)] mod tests { - use super::{ - AttributesQueue, BlockInfo, L2AttributesWithParent, L2BlockInfo, L2PayloadAttributes, - RollupConfig, SingleBatch, StageError, StageResult, - }; + use super::*; use crate::{ errors::BuilderError, stages::test_utils::{ @@ -223,7 +230,23 @@ mod tests { }, }; use alloc::{sync::Arc, vec, vec::Vec}; - use alloy_primitives::{b256, Bytes}; + use alloy_primitives::{b256, Address, Bytes, B256}; + use alloy_rpc_types_engine::PayloadAttributes; + + fn default_optimism_payload_attributes() -> OptimismPayloadAttributes { + OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 0, + suggested_fee_recipient: Address::default(), + prev_randao: B256::default(), + withdrawals: None, + parent_beacon_block_root: None, + }, + no_tx_pool: Some(false), + transactions: None, + gas_limit: None, + } + } fn new_attributes_queue( cfg: Option, @@ -321,7 +344,7 @@ mod tests { async fn test_create_next_attributes_success() { let cfg = RollupConfig::default(); let mock = new_attributes_provider(None, vec![]); - let mut payload_attributes = L2PayloadAttributes::default(); + let mut payload_attributes = default_optimism_payload_attributes(); let mock_builder = MockAttributesBuilder { attributes: vec![Ok(payload_attributes.clone())] }; let mut aq = AttributesQueue::new(Arc::new(cfg), mock, mock_builder); @@ -330,8 +353,11 @@ mod tests { let batch = SingleBatch { transactions: txs.clone(), ..Default::default() }; let attributes = aq.create_next_attributes(batch, parent).await.unwrap(); // update the expected attributes - payload_attributes.no_tx_pool = true; - payload_attributes.transactions.extend(txs); + payload_attributes.no_tx_pool = Some(true); + match payload_attributes.transactions { + Some(ref mut t) => t.extend(txs), + None => payload_attributes.transactions = Some(txs), + } assert_eq!(attributes, payload_attributes); } @@ -347,7 +373,7 @@ mod tests { async fn test_next_attributes_load_batch_last_in_span() { let cfg = RollupConfig::default(); let mock = new_attributes_provider(None, vec![Ok(Default::default())]); - let mut pa = L2PayloadAttributes::default(); + let mut pa = default_optimism_payload_attributes(); let mock_builder = MockAttributesBuilder { attributes: vec![Ok(pa.clone())] }; let mut aq = AttributesQueue::new(Arc::new(cfg), mock, mock_builder); // If we load the batch, we should get the last in span. @@ -358,8 +384,8 @@ mod tests { // This should successfully construct the next payload attributes. // It should also reset the last in span flag and clear the batch. let attributes = aq.next_attributes(L2BlockInfo::default()).await.unwrap(); - pa.no_tx_pool = true; - let populated_attributes = L2AttributesWithParent { + pa.no_tx_pool = Some(true); + let populated_attributes = OptimismAttributesWithParent { attributes: pa, parent: L2BlockInfo::default(), is_last_in_span: true, diff --git a/crates/derive/src/stages/attributes_queue/builder.rs b/crates/derive/src/stages/attributes_queue/builder.rs index 4955c0a0..a4db614d 100644 --- a/crates/derive/src/stages/attributes_queue/builder.rs +++ b/crates/derive/src/stages/attributes_queue/builder.rs @@ -10,20 +10,21 @@ use alloc::{boxed::Box, fmt::Debug, sync::Arc, vec, vec::Vec}; use alloy_eips::{eip2718::Encodable2718, BlockNumHash}; use alloy_primitives::Bytes; use alloy_rlp::Encodable; +use alloy_rpc_types_engine::PayloadAttributes; use async_trait::async_trait; -use kona_primitives::L2PayloadAttributes; use op_alloy_consensus::Hardforks; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{L1BlockInfoTx, L2BlockInfo}; +use op_alloy_rpc_types_engine::OptimismPayloadAttributes; -/// The [AttributesBuilder] is responsible for preparing [L2PayloadAttributes] +/// The [AttributesBuilder] is responsible for preparing [OptimismPayloadAttributes] /// that can be used to construct an L2 Block containing only deposits. #[async_trait] pub trait AttributesBuilder { - /// Prepares a template [L2PayloadAttributes] that is ready to be used to build an L2 block. - /// The block will contain deposits only, on top of the given L2 parent, with the L1 origin - /// set to the given epoch. - /// By default, the [L2PayloadAttributes] template will have `no_tx_pool` set to true, + /// Prepares a template [OptimismPayloadAttributes] that is ready to be used to build an L2 + /// block. The block will contain deposits only, on top of the given L2 parent, with the L1 + /// origin set to the given epoch. + /// By default, the [OptimismPayloadAttributes] template will have `no_tx_pool` set to true, /// and no sequencer transactions. The caller has to modify the template to add transactions. /// This can be done by either setting the `no_tx_pool` to false as sequencer, or by appending /// batch transactions as the verifier. @@ -31,7 +32,7 @@ pub trait AttributesBuilder { &mut self, l2_parent: L2BlockInfo, epoch: BlockNumHash, - ) -> Result; + ) -> Result; } /// A stateful implementation of the [AttributesBuilder]. @@ -70,7 +71,7 @@ where &mut self, l2_parent: L2BlockInfo, epoch: BlockNumHash, - ) -> Result { + ) -> Result { let l1_header; let deposit_transactions: Vec; let mut sys_config = self @@ -165,17 +166,19 @@ where parent_beacon_root = Some(l1_header.parent_beacon_block_root.unwrap_or_default()); } - Ok(L2PayloadAttributes { - timestamp: next_l2_time, - prev_randao: l1_header.mix_hash, - fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, - transactions: txs, - no_tx_pool: true, + Ok(OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: next_l2_time, + prev_randao: l1_header.mix_hash, + suggested_fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + parent_beacon_block_root: parent_beacon_root, + withdrawals, + }, + transactions: Some(txs), + no_tx_pool: Some(true), gas_limit: Some(u64::from_be_bytes( alloy_primitives::U64::from(sys_config.gas_limit).to_be_bytes(), )), - withdrawals, - parent_beacon_block_root: parent_beacon_root, }) } } @@ -298,20 +301,22 @@ mod tests { }; let next_l2_time = l2_parent.block_info.timestamp + block_time; let payload = builder.prepare_payload_attributes(l2_parent, epoch).await.unwrap(); - let expected = L2PayloadAttributes { - timestamp: next_l2_time, - prev_randao, - fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + let expected = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: next_l2_time, + prev_randao, + suggested_fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + parent_beacon_block_root: None, + withdrawals: None, + }, transactions: payload.transactions.clone(), - no_tx_pool: true, + no_tx_pool: Some(true), gas_limit: Some(u64::from_be_bytes( alloy_primitives::U64::from(SystemConfig::default().gas_limit).to_be_bytes(), )), - withdrawals: None, - parent_beacon_block_root: None, }; assert_eq!(payload, expected); - assert_eq!(payload.transactions.len(), 1); + assert_eq!(payload.transactions.unwrap().len(), 1); } #[tokio::test] @@ -341,20 +346,22 @@ mod tests { }; let next_l2_time = l2_parent.block_info.timestamp + block_time; let payload = builder.prepare_payload_attributes(l2_parent, epoch).await.unwrap(); - let expected = L2PayloadAttributes { - timestamp: next_l2_time, - prev_randao, - fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + let expected = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: next_l2_time, + prev_randao, + suggested_fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + parent_beacon_block_root: None, + withdrawals: Some(Vec::default()), + }, transactions: payload.transactions.clone(), - no_tx_pool: true, + no_tx_pool: Some(true), gas_limit: Some(u64::from_be_bytes( alloy_primitives::U64::from(SystemConfig::default().gas_limit).to_be_bytes(), )), - withdrawals: Some(Vec::default()), - parent_beacon_block_root: None, }; assert_eq!(payload, expected); - assert_eq!(payload.transactions.len(), 1); + assert_eq!(payload.transactions.unwrap().len(), 1); } #[tokio::test] @@ -386,20 +393,22 @@ mod tests { }; let next_l2_time = l2_parent.block_info.timestamp + block_time; let payload = builder.prepare_payload_attributes(l2_parent, epoch).await.unwrap(); - let expected = L2PayloadAttributes { - timestamp: next_l2_time, - prev_randao, - fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + let expected = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: next_l2_time, + prev_randao, + suggested_fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + parent_beacon_block_root, + withdrawals: None, + }, transactions: payload.transactions.clone(), - no_tx_pool: true, + no_tx_pool: Some(true), gas_limit: Some(u64::from_be_bytes( alloy_primitives::U64::from(SystemConfig::default().gas_limit).to_be_bytes(), )), - withdrawals: None, - parent_beacon_block_root, }; assert_eq!(payload, expected); - assert_eq!(payload.transactions.len(), 7); + assert_eq!(payload.transactions.unwrap().len(), 7); } #[tokio::test] @@ -430,19 +439,21 @@ mod tests { }; let next_l2_time = l2_parent.block_info.timestamp + block_time; let payload = builder.prepare_payload_attributes(l2_parent, epoch).await.unwrap(); - let expected = L2PayloadAttributes { - timestamp: next_l2_time, - prev_randao, - fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + let expected = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: next_l2_time, + prev_randao, + suggested_fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS, + parent_beacon_block_root: None, + withdrawals: None, + }, transactions: payload.transactions.clone(), - no_tx_pool: true, + no_tx_pool: Some(true), gas_limit: Some(u64::from_be_bytes( alloy_primitives::U64::from(SystemConfig::default().gas_limit).to_be_bytes(), )), - withdrawals: None, - parent_beacon_block_root: None, }; assert_eq!(payload, expected); - assert_eq!(payload.transactions.len(), 4); + assert_eq!(payload.transactions.unwrap().len(), 4); } } diff --git a/crates/derive/src/stages/test_utils/attributes_queue.rs b/crates/derive/src/stages/test_utils/attributes_queue.rs index 9c127cc5..93729a81 100644 --- a/crates/derive/src/stages/test_utils/attributes_queue.rs +++ b/crates/derive/src/stages/test_utils/attributes_queue.rs @@ -9,15 +9,15 @@ use crate::{ use alloc::{boxed::Box, vec::Vec}; use alloy_eips::BlockNumHash; use async_trait::async_trait; -use kona_primitives::L2PayloadAttributes; use op_alloy_genesis::SystemConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; +use op_alloy_rpc_types_engine::OptimismPayloadAttributes; /// A mock implementation of the [`AttributesBuilder`] for testing. #[derive(Debug, Default)] pub struct MockAttributesBuilder { /// The attributes to return. - pub attributes: Vec>, + pub attributes: Vec>, } #[async_trait] @@ -27,7 +27,7 @@ impl AttributesBuilder for MockAttributesBuilder { &mut self, _l2_parent: L2BlockInfo, _epoch: BlockNumHash, - ) -> Result { + ) -> Result { match self.attributes.pop() { Some(Ok(attrs)) => Ok(attrs), Some(Err(err)) => Err(BuilderError::Custom(err)), diff --git a/crates/derive/src/traits/attributes.rs b/crates/derive/src/traits/attributes.rs index d0d38f41..8bf79ad0 100644 --- a/crates/derive/src/traits/attributes.rs +++ b/crates/derive/src/traits/attributes.rs @@ -2,8 +2,8 @@ use alloc::boxed::Box; use async_trait::async_trait; -use kona_primitives::L2AttributesWithParent; use op_alloy_protocol::L2BlockInfo; +use op_alloy_rpc_types_engine::OptimismAttributesWithParent; use crate::errors::StageResult; @@ -11,7 +11,9 @@ use crate::errors::StageResult; /// the top level `AttributesQueue` stage of the pipeline. #[async_trait] pub trait NextAttributes { - /// Returns the next [L2AttributesWithParent] from the current batch. - async fn next_attributes(&mut self, parent: L2BlockInfo) - -> StageResult; + /// Returns the next [OptimismAttributesWithParent] from the current batch. + async fn next_attributes( + &mut self, + parent: L2BlockInfo, + ) -> StageResult; } diff --git a/crates/derive/src/traits/pipeline.rs b/crates/derive/src/traits/pipeline.rs index 04d12333..06012def 100644 --- a/crates/derive/src/traits/pipeline.rs +++ b/crates/derive/src/traits/pipeline.rs @@ -3,8 +3,8 @@ use alloc::boxed::Box; use async_trait::async_trait; use core::iter::Iterator; -use kona_primitives::L2AttributesWithParent; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; +use op_alloy_rpc_types_engine::OptimismAttributesWithParent; use super::OriginProvider; use crate::errors::StageError; @@ -24,9 +24,9 @@ pub enum StepResult { /// This trait defines the interface for interacting with the derivation pipeline. #[async_trait] -pub trait Pipeline: OriginProvider + Iterator { - /// Peeks at the next [L2AttributesWithParent] from the pipeline. - fn peek(&self) -> Option<&L2AttributesWithParent>; +pub trait Pipeline: OriginProvider + Iterator { + /// Peeks at the next [OptimismAttributesWithParent] from the pipeline. + fn peek(&self) -> Option<&OptimismAttributesWithParent>; /// Resets the pipeline on the next [Pipeline::step] call. async fn reset(&mut self, l2_block_info: BlockInfo, origin: BlockInfo) -> anyhow::Result<()>; diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml index d5cb84cd..6fe25ac2 100644 --- a/crates/executor/Cargo.toml +++ b/crates/executor/Cargo.toml @@ -17,11 +17,11 @@ alloy-eips.workspace = true alloy-consensus = { workspace = true, features = ["k256"] } op-alloy-consensus.workspace = true op-alloy-genesis.workspace = true +op-alloy-rpc-types-engine.workspace = true revm = { workspace = true, features = ["optimism"] } # Workspace kona-mpt.workspace = true -kona-primitives.workspace = true [dev-dependencies] alloy-rlp.workspace = true @@ -30,6 +30,7 @@ serde_json.workspace = true rand.workspace = true criterion.workspace = true pprof.workspace = true +alloy-rpc-types-engine.workspace = true [[bench]] name = "execution" diff --git a/crates/executor/benches/execution.rs b/crates/executor/benches/execution.rs index 732cf98a..0ad03e7d 100644 --- a/crates/executor/benches/execution.rs +++ b/crates/executor/benches/execution.rs @@ -3,12 +3,13 @@ use alloy_consensus::{Header, Sealable}; use alloy_primitives::{address, b256, hex, Bytes, B256}; use alloy_rlp::Decodable; +use alloy_rpc_types_engine::PayloadAttributes; use anyhow::{anyhow, Result}; use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use kona_executor::StatelessL2BlockExecutor; use kona_mpt::{NoopTrieDBHinter, TrieDBFetcher}; -use kona_primitives::L2PayloadAttributes; use op_alloy_genesis::{RollupConfig, OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS}; +use op_alloy_rpc_types_engine::OptimismPayloadAttributes; use pprof::criterion::{Output, PProfProfiler}; use serde::Deserialize; use std::collections::HashMap; @@ -59,7 +60,7 @@ impl TrieDBFetcher for TestdataTrieDBFetcher { fn op_mainnet_exec_bench( data_folder: &str, pre_state_header: Header, - payload_attrs: L2PayloadAttributes, + payload_attrs: OptimismPayloadAttributes, bencher: &mut Bencher, ) { // Make a mock rollup config for OP mainnet, with Ecotone activated at timestamp = 0. @@ -108,17 +109,19 @@ fn execution(c: &mut Criterion) { hex!("02f920340a8306969b84032a47f984039387008349857a94087000a300de7200382b55d40045000000e5d60e80b91fc482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000014e0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000019200000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001d600000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000cbf61a54ebe5e9152e1f6b81cbffd3027062642928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61d460bd138ee32c939dfd8e49c57a95ef4dcef2f88b92e5a1d5e2905f86d787328bb4c7a1e4eb3b8db4d59a38321cd444d510a700551beb6fdfcdc88068c02f70506c41903052ed62b6913f66c9595a218d5726ea3128be80d62f7c69887816a22f613c865b39a6e228b0d90313dad896d11000afe422c2412aa8eef93fb1a1e0cd8be0d3226796e106d56c9f3d6ea5f189f88353aecab6565a256034ee48fd00bafdf7b018aa742f06a35f8ac0442c02d1a4f75186798a33cb57b53f3b2a09507ca58f2e94f1bc503faaabb19812e52adc5446d0d3a2eaa3c37c96cd6b3937014ef84689357e91ccced5dbfda2cbcff66f237923aa145326a831953620b7fc711e8faedc7ef58112a00cf6e13cbc0f005606720fb034d7a57f591ebcf33a66c000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000007cdb62cd44f27416d3d80060887b79edbc66eed428942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae627cd53af047b648a62ebbc6b7022738934e337451e6934e285bcb17ed151e9a2156cee556c24689d42cf8d19d308cdaf32215270100cb7de2300b61d6f3805e61fad747173364b42a1fbc54501d3fe6689204bb44e095ca5aca1652d4ce018070bbbad2a1406c2ed33020899c296fb67957c0dafa5e7630c6f15eed2d85ca3921f78322e092ee4289f1f00dbc46793221e1b2439129fb05b1f185cfa857baf812e9ba7fecd26f0671e1fbc3796ab226a8484095d31360f45222167cd7dab33f11a13d59918ab5dbcbd350d47b8d48d3b52e275887e0663b63b9cba34e97377af15def44fb6d6227bc92d17b372a4779d53d4117357d4e372f15ead01502b0cc3006542ebe7436861a0a015643024b8eb364ecc758dc76e38f5cbbf461c18a73b000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000060de5ca48792914e8ed36f8294c571cb64cbc86228942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61c2f5918a5841520443a45ccf49a742a50bcd4548fd8ad248a1b8742aa75b46417c1fc6a32babcf3b5960b1cfb35d98a261641322b811053ace79049d236019205960ca817a496c09847350c58899c0008ab73f124204dacff678139ae80c95c1d7877bf7f5c4b37f570321a76e604b5a140229e1564216e722102a0131c6f442933d8de999cee105ba504babd60abf0d97ff47ccf6395159a8c2a24d24ed918029a1cde683c17c594cad199facdf9928066a73025189be71671e2df5314c0cd00c501e761df7d4b8a0cc152d6870bdf5a3f5f7ad8bdbc2d0f11ce6cdcc829bc1acb667ba2d8c86243659458f23b0c5c46fef1761cc7013ce20c5a55bf9f28481c42002db11bd87e9f501a27ffa16297536ff3bd04d44cf8385c66913b259f94000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000004427395e8d53ec91fe009b9f9f7d108a6d046fa328942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60e8eb84cafb9b1049f380e248ee56e410da056b3ac4fae01e640bf76dfa9b32c089f372414a1aa9c722f3af366ab7f4dbf700d8cfd8376f90c5125df5211c0240c1b68b374253a99342db518fff6ecc0605c35d0abc5cb9fd58d13b554ca1204306006c533a0d4e84cbdc3d1a219f562df9e5afc90dd541b8b2332ba63eba2062b9aeaa5722b7ae0e7d60a977dfc2cc05bf7064b1ed2aa897c306236b1adea8528a850bbec99f23a3c0b9a747c2f285474f266424bf6d336d0c4ec119877f5a9109eafdf5d0f879f6907ecdc9cbd20f41d43dff8d94caf9c4486f017f7d10c511da1f9629b4d2e0232c0bf208a0f9408134b1f6fcf77b33ca549ea32536e43b900f4fbb5c755d3221871fdd7c7118c1fec5559871922b1b462a5f0502b9e14e9000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000ff7fa1fcf8df81ea158cfebdad80d00d49790c1b28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6142c5c102e9eb810eec6a0fe8cb214c224de98a8ae9e73f46897df36bffe668f15c5b544e21b5c7495900a1bcba9a3b9ff362e192a88c24be1834cecbbebcb172be37dcbd251b8ad00f6a589bf6a296eadba57dbebca0ec879f7c0b101c5a2d12849f2cb39082e9a68623d3793562d40de78acc164ece4ba819b9cd41c60ddb0155ce47cccdd81c62bd4850644937385e494c711b794ea61c3f876cfae88e05805ef8c12ea3890fb78f382fd4757b43fb31e9b711d5eb6179b302bc187b621e806dcecbe346e981b671c871b81d963a58c674ba7b5aaf83203e8b6480104b02006491322421291c323149a72e34c1c9c793b6797eb2a83408faba857a60d810f0f64bf23f7d507c895edfb71d617ccdc2f1f819e16bd07cb467ee77794bfc9b6000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f34c1f7627c21d08affe689360b68e3b86bddd8e28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae603f4f9d9e44ecdfa78b3f822a00aac0a80fbde1675bed218b4e9daf3018c75c2274fc133f9df6704f4926e8201f000cdb3f5288f5bab86b24f4501734b001faa06b1f228701b430c5f77357668d11abb9aa246ec200026b8835fc8ea038dbc3721978e874ed6e196d0ee6ef1baed881ec1a8fdc818fca586e49adf1a01014d630b247457164a28f47dbef855ff71f85bc3d2d114f450bc209463a532cff56aa9183a29e8599a51c0a5a46435d21e0421a5ee0b31590e2670431f59948523a3840a6914dfcdaa1d8f4acc0999bff181168bc97f59d2e76914b8fe40da7cfd767510fcf9dce7c0aa00f582fcb232b250941dc3acdfb71328c97fb21804ad1abb181f04e30fe89e260a50e3ecff6b402e0796a12625cbb28e218565ca449bfc5d54000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000b6816921690bbb13022ce4279c741e9f10f6d25028942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60c7d7a2327da7193adb6e7da1a0011071990b12213c823686963a0fba1a43683034744575541f9edc32e3ce969ca106604b4a989340584ddc55b9728c7e2e735074515993dfc63a646b2d8f748414d5dbcd64394118e0f89d165c746caf2434209bb608dd08ab880aad6440c7340c1c684403cb97e2276590bd18963940d98eb1e1a272569a949e07dfe4a665893154eceb132e728555b80e40a51b6134c6a1e0a6fba21519df338be4c257b4a5300e8b8f22fd006f2e9fa8e2d72b60f3818e72de6b2584eda4a90fc2d78b98dc1b5ccbdf1f3c20e733bbff817158df22fbdba1d8e56cd2b62522af6b23891f4f2494e565ded4983941326df46f8895df90b261eddd0dbf8d65704970292fd40ea3c440b4f7004f8a988eaa0124ca04acc2f80000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000046cd855658bcbb261645dac5de9bcf3e86338ca528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61a678665a7ae5d9945c98f2448bf68e73e80475cbba2f1601c5be074171c21082ad67f4b03530e704fb1b232b3cddf83ed3cc000fcc0cc5137b6f4c3e89d59fe0f02287c98f5c39229b9ea0ecb3b2e927f66c5bd814bcf032c28d3b9227d3cb91154886e38171ac9cb09ad8f8a7898fe624c216c1f2753fdf2126f1e06adbecc0647e62c17a2c83ba39b269533b35a377b069f0b4ef684142f7f38360feb6e832ac89f308bf01ac0fe322a4d106b404f192b2c279299e97be3a5344516ca21ea105a99ffa98dca692c8c3f52addc90eda18cb19336aaa6d085e40463d74d3b8e0f317e0047e3c6f7f9ea5e99a7adf0afc1acffad89ac728808bb2ac3cd57c5aa2b0ccbc0976152d5b67b89e939da3ba4e0490d962b8035782ff36db7f05a23a3000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000004ef8a049f19848666c00d958723dda15310a88aa28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae629342c1f6c1e951de321ada9f9dd51886c7da9f435a971f21dcce3e8067d80b20edc4b5a3a2982f4bb2825f7e82dba0143325323491b7810c291cbcbd76e35242f9e523c196e71f608c01dc6fdda1f5a6fa0f60ee6422f0363313332b7f6c4ed2d2daaa8ded8a06a27765e33668632033a783e6a452d32f2d327f629e25106560c6251b41c8d03f2fd7617f7f3c745c899f32353223f8ab32b56f813e430391d0686a6604ba4f73d140c25c0d30a8f7aacc24696207d256f14a2d5f3e217f8a70a9254141d4351a6cfda264150d89b2a35140530990449b767f05689709488f00e227ac767806f1c3dfc1173d3886189057e5a55d147166005840d7ca50f17861700af52ea29cab029a6808d6dc6f82acaf942f9254adea7ac455916f0da4452000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000944618cd80dae4191c7f7f21c58ab13bdf81738a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61b7951b069b65c12393920364d045f8d76add6c1d9f29245188781b12600d6be0d5d127d6bd399a6ef83d157093e1f5a7f3e9a1edf67993b678a7f6b2be9b65129827246aee4b32f7d33af5d8363c7edd2b8fa882103655c0e57999d5127aee113a7fe6d4e694ec0e96cca8218f2cac3ea45a958cdb8e7a77e5b0a7f65834f12178510f9a90038299b02ca079f79890aa550ecd77b0b88e6ada0b411255a560c0e214079f6191a523d2f8dac0a1426ddb1b7aaa51f4ab184341392492f727cad29d9439d19f56f626ff8a8482bd148134d5cad497b01d310680537b8e3dbad9705cc9230d48983aee1839334e024c271ea9560ced93bfa54b880901249fc647713b1931335356f6f2c35ac21de1c2a6c3302763a0eea4461c757fb18bf8bdad3000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f2a05e7c62af3f2f02a24b43c2ae13b08890fd4628942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae622cde3d420dbb6ff32a2b0cae2a9e25945c539ad843317103de9e09595f424b328dada7a73b9e990c662830d82148ef6c90879c37ded18d7f24f9dea6c6cf01504184ca216206879d98b04f4e0eb97f6a6128a309e699e7d160201ed34f76d070c5377a5dc4baa602431b5034dce504c8e8fcb3033e605a7f9d43f5e9e4738c30c9021ba9dde79e0338b9843fbdfa7507174fbf43a28fa11b90f39bd4d0c697c0bc0c8292d6d79489b492324735a57da87a52f3fc56c83706711c86188e4734317b57e8482be2fbddd7b8999c6c403b1649ca77cae53ccb33a7466c0ba2e43670717bb2502de19dd83165e63ac0bdf45f628e77f314131766965730a44a947ab2d37be9216c866637b04e5ee682cb7fc17f92ce5c77cf9113abb1030a1997ab2000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000cbd0a779c26eb779769cc9d3a42f61c97c99602928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60396cdbbacab4ca173328793d82669df272d72cbd5f355277324d1cf707995f82b320ecd46b4bc60e11394a891aa160cc8e87ac44ae214a23cddf356c8ef90990d7c8f0c9da0e89ce98f30d4b468df256397afae21430e552c0ab9a4fac037710c7ac7c8858a6d26323a0ef3e40bd3c62fccf473eaa83aebcf6b545a7bc6fd9105811a4341bdab25b827b79253700ac63f5df83cf602db53efa3c93aef66c99d0a5b385aa594eaa55cc8eba9fc5bb179bc1745e4fa1b988e58bd438c1b6a23be0a19671d950886a2c5d8adeb93b36d55c2a6a3fd577fa1f1645edd71a36c37581a5ff14720ee29643e09096dd01785828380c42c9dbe38d2fb89ea391af5deff2ebbaf11c9e1370f4786ae7deb76760ea476ebbbb2bdfce20159706bc2e18fd5000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000377a5093c2531aeaf4f72b4d0b2c48d3d6c8684a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62375d5b21debe1c780d2dcf962266b2df4937663d6b6e93bcf22f1d64af660b51760dd6af28c91232ef017518ba734b91d159c4146074d8f8bdf5d0ca47f220f2d03765f35c93d02340b24d19aec48cbdc3f1fc9788ac2aad187ef5b9bc6bca6038a078c76db57cc594712c5c73c31afd34a7a441743799e3543968c33f76634138cd4cb56addade4da332152eee582c4bb8e416e45d3fc7f3f8ed0b7073337e2bcaf837d7d01edb32e38abf2439fa2aa55b077c1c7b60640d4dab03bf59c7f305c8ca9cd7a20b79807a5180f921a14acd7f30aa74882bc531c0b42c6e08d66904d07970d54795b0c30c383228090d4ed088af846c318e4de7c25ae9dc01e5352ed242f8f39a28c8dd178f364beed17820829d319729f3b3fbc85908339f1220000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000083b664be1badd9f38133826ed0d1051c473e474e28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61b96cb848a7076d907b26de483e289c97c2d7a37b74db23961df4cf3b7a77618019266266d91c62ff228e6016a2f9cb3635b8d7431b80a2284ea13e8692a049f0e81c6a92b69cf67abe95986bf1fd34f17bd458cf13668f47e11edc991a4aac313e246126ed023db3b6d19112f7acf890b77efb0300868a91e09d52a966e6d0315c21f20fe7630e06a0e648cd21e430e9cc12c920bb2df8ff89966830faae7243018fe0cb624573d66479c635f8d7ce04fa45292d39aafd96caeea287e08ca6210ee7e000e89bfbc77617a1f1c2c92bc25f4ca5bc4cb9fa8cff4039e27345baa09b9db170f8e1e9655ced30f72be9edefa5257ce44ad8cd3855cc9fcbaaa443923c51df11ed2f8b830c7bf83c18a77600b170ed08e7a0545c690e1357bc9cf4200000000000000000000000000000000000000000000000000000000c080a0b2ba45b0c4cabc8981799c254b90d90c019b757833e05c2742c13f52e82c7bcfa0296885d0ea2c68aa6020ac3881d89a110471efeef6327af2eb295481571c4386").into(), hex!("02f920340a8306969c84016c2d0e84039387008349cef494087000a300de7200382b55d40045000000e5d60e80b91fc482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000014e0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000019200000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001d600000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000050a76afb1154d01d6eba284069708d356d9969928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6204472fcf9520f9fb2076ff97de783931cff4485b9028f260839f5a3518c0b7c2dedb9ba79cbf3ce5e0eca92a12da266d66f21c58bc107fb961e7fdce9538d4c195256b732f3eae1f49cde40c25294963146d06212e318cfba43ec8ec274d1bf22c8f77a99a5797161aad10de1fb3f3754df5fc20ccede01674a7c7284f7bd690484bc65d8c32f6a062c6e886f8563ce28e02d2e58485273eca71a27aeb19dc70860db898acf6d32b0140c8b90355e8b4b4bcc0d01f2761d44a573421bf4af1c0e6bcc3f1b2cd42af6830438342270b83e244cb2d680021a46c6a0416683e1e10fcb9e36c27546a590b8bfdaab06385ae9c72b22160622aa8acaf404bfafa50c2fd454af5d6f6d7dc38a9fd1dc115b8f1a55b7f9a2fac0e080cc6e7acf472955000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000fd176b56e03a2a4d400c61cade47630196614e6a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61f480e5d05a2821f7b6a0da7912130ca375498b472fe02cdd1635bf57e3fc79d0e99986102ae4e27760a6d33cab28b4b77c5fc177b0030d8021b67017f7b4c931a69139b25a75a2023160dd6d6f02a21e95d3005308ce63c45c423de987d8e4b1dbec338be731bba82354b115902c3f4d702178bedea57978eb5b174459fc1b1270ea499e3a908cbda58d2c091f5616d9c2b18687adda6c24017833ce90acec200e87b2cc129df7a4f39d8f6e2c3b2a8d3f3e0905c3d4bff8ede401310ae1d9f276d6239c4c32dc9e627a1dbe6a60ea37e4f7de95512de72696e37de529686d0212ee16598faeb5445f37c581fd9a60bd3d22b1fd965a9cea3dd677df95c9fb3151ba48ffa3b5e7454aa32c6850bbed3457f6cccaac2f5cc9e399a68196b29e4000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000897e11089a878542836ec8e77b825a51ef8829b528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae600164253f8e62ae2671abad4b06d54a890f9abc01afec02287a15cf1115068951c9bdbc96cb8adaafae3aa83c4110616113c066688bb00fecc39bdeb64a1390a2917725d914fcc89e3c18a87a8ed00d9540700ec7320ab345baafb920b0441ad07c4a7e6b2dc434e9934277572be6f581fff0eb7be0857f48ddfa68c2e66cfce21fe5a394f6fcc4844335bae1029ebb014c6c08c2403aa11fbbf18cf6bffc425060e00ed6a571e020461981b6429019c35ef9f1be8bcbde05745a1c537b9472d03cba89ce21b3cb28eb03f08d7c97f1d94e8c0b55d3fd2586b74da048726ddbc1c8eb5ff64d606c6bacc97d6428a1ff83517a46b8f3d5194714a98957d2f1cd905a46fdce4364f2512312c238f9dc59ee6faffe30ee2d7f5887ab0eecd596b40000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006bc063c2b6c1c94490329f632725e22237456b3f28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62ad99a00f80269a3a77de4fc3bd9976e9ef2a94954860a99c785b2bf1b63accc26de5151dac27c1c3d92571dfba7a67ca017482bee0be2188fa571875c660e5d221a475b95129123030032cf5243f78a2e6cf478c6c3c549d46fe6811a59c3900578aa1407face18fc14174b56571888ef0c471fd66aa52a53206215429d0f8405511b5377d2e625d010030d49045e1828e2366e8d5df27068e8eb9b89891b170a61b2f39e61d48c97c6117b1f04e5ac104311785063e3acc3cbe7358b13082204a43390431779d8fad127b39c5853f9926e94e6985a0fba609e7453db8a9e7c26d930a97127bc0cb549e5723f4b92f8cc7e5f800368ef108411f31e8c2476b80eac922344044afde8e958a3af9422dda01d35584d76526fc1a2a13ae59dbd0f000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000033200fe170f61ed4ac8a09b43e3798e4ac8f195b28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62d3092e1316ce6abb3acc796d98205e786e22c1345c132b0e61070095b83993b136fae2ec9bb03d161cef5cad8bff5335812f32cea2191dfd42df867f64981542b7fc99748f6833af03f2d7c93ad8d3cfe6b5103a510deebbb029e4005dec5a201326eee2a5598f72b7500f0aedebc83563faef710c75cf0a8f69ee75645ecf0053f00c5847f869a0b27d58d6ca7314f590766b4e4eb305c3c31e64b206df10d02ae3cf650459570d00f74f002fdfa92e68bf056c8b974c07b189a33442281c51748d8cfeb75803b470f289144f38d5648bc6d2def5caf65d0cab9583dc0220f17c983c93039ed5fff9d82b233a207a1069f00bfee072c1ce04211e6571df5c825dc3cacbeb084a77f015460798ebf9a2a5e546013bbd245b57ccb3a3a60579b000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f1ba6cef8ccb2990ce7de325b7fa407906125bf328942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae620c0644be433481651df7035bc5cc1247d8eb024f08f06646a9f1a81e475902711574aa82220fd71bc6cd5f1e7a2f1c66f6cdec680e04c449fd5f65f0606f84207dac5ae5563747e3e74aca6b92fe8be94a591ba654763f2c376a984ab6bac5a07cf890ae88d46cebfabe94398e2d8aef0a277caa1de32e3a81377e564286b1e02161e7871b40c0a388af9e732df270970cd74b6bb71ec71479a1144789da3ab279ba62160fbc729e5ce188fe5925e3ec9d04988f62adfbb9c8cef7246cd0d5720705aafd2bd6f4735dc9b19b03d606a70aabb86c38e2c3fdf2f53ef92e7eb64207335417ad2b241b88d9ae80418ca07eb457f2c557a5bd4c1eb2ef3c3fcbe3120e195a0a41d0dc2aec8703992711bc3ca34432f04012e6b771841b9862a7447000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000785cb80c25d8d3618ca7962b2dd85e7513b0fda528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6291ca2fbeb9e08a732b6937ff647309d7152fb770052fe37d3c7ca22911a6bec11b0f463565e65e5c255bb13afa8fb025bf41cc4aee8f4b8d00d1826c6ab90f813e024024e4c916186ca0ec32ab1688a6a09a156462027b218f39a1f4dd4b964243e8898fc270f9621c0a45380bcb5bc9b14a236680180a042258fac8aae0c9e1dd0ec39787afd536b51527426964ccbc2ddc1ae16b0d6f11d9241d1cb53b94e0e989e1624568bb59dea3cce55fd0b21696e6153034d29e5144b91afaebbc1ca28e9eacaa694821f267617c5cc3b5812f914315097b210e50c31cccc33dcc3310166b0c3a00a800e11be916b0e02875105e99127e4b458784594de119c5be391096f4f245bd3e19ce16a035f8f784a255e4b91bf5af58e6c8b25b0ea151a74c9000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000033090fc05f8e16cae75f332ebd31bb92135ee43028942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61293b778ea3a0add86d973685193aac98de614c89ed36878548b7e2a4abb37bf244289929b41c2ca77197403e44de06d465b59e36f189cbff475f4507f7676d0080338e4831274e7ebb54e58c60ad99e45273c61a7e8928f22a52784987e49d61d915117aeeeeeb6619849969af3e29831e98e5fef5b7ee074710aa86a76bd1c27b1e5fb6cd2e22786fce1f03564cdc8c1ed37a9a7d8f036351132437c16c2bf1edf147d96e5946d37803b5b60606971186736514563b075e15c871aa8072f552659fc082dc7dde5907057306ea98d5c1d82a96fc92a5ccd31fed314579e5ce92e1c0ef05de09ea78c2b62c8b4b51b33235fbea7ec6cd6fb6678ba6a81ecfb0b09b380a270901fe8ecf3b5c8875cfafcefc3ac58e44d7233756d97e0844234f5000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006a63428000c4d1f428c3a7546dbc2b897336304a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae612cd2880f852b8d726ec68101fa2ee3011c46c3e3c111a39db1356bba256244c2b88c6ff827347a3a00d18c54feff6f30519ac8f95a4851f05c148b15072f8b20aa1e91b77afa9bbd05aef46c2b90b138a1e6117c9d87a73f682e5db6ae890232a5a58a0063bd20022baba8317a33105e3f9ed5ff9786fe114c8bcf9c93d8d092bcda239c922faf406ae57773acab2fadebcf4fde5763153fabdbf198c36146010a39e592415cd62fc4eefe6e6f00c24aee3c626c1d8e4efe0ff664324d172441e993b5f28bb82d89c318f23c0c8b34b8d3d22fa692be9918ecc1e813144be9b014021eb71ccc2649f3a3c0cb7b56eccc633b41daee6f51fc3acca801201a69620784e86e0894942c024878b4b0040040851c2bf0ca42b34381e95fc28e28a28000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000e38fb18ff3738c39b1d9f9352f2468c4426ce4ae28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61c4102b911ae374a542f5c3c2629332d107f87c9d7f084e58ad6686b8ca032d02e4945598231c20938d0af0ce8567fb69936139c2ba3d6e8e1d9c7d986367a9f29a32ba151998a6732af0747596e22828161d91a3a92ed6664a99b7a0d988c2302b6f9af088ccf5d117a451d93d5b97a4555853aae24178279175905606d3af91c3f6e575377a0504d03e34de54894bc2caec9be3dac382a8d39be54a37069442f58d5cedd52832dddece59733cd2b4a6d370681b5a48b52bc76667902f20c0d1011a2c4396ef44f6003ae3bfb73948a1ecfa6f1855984b0d211ac0f4870a7682cd9ba5ecf6858e550b4fdc10893a899d9bc5327885047c271380499c3c0a7f51be5923b17ea743f23538d8b463fd7d142301174b8b9253f11b7e74310b4c17d000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006d012fe8cdfd1b3db63e95c8d7a06dc9e0b66aef28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61f92267a1575d60651f0ca0a74d2ab67989f3ccc976b18246b504fca3df8cef31db8c4f95b1afeb35f826a69dca4995c5d2efcf3e9e459bbf99cca255ca1e8ea08c230b042609463c274ed7e6439e545d730c770ff035643c98c03bc419ef0c82eb48d9897932b8f919dc0684164b261d640c0a25e7064de8413beeb515d95121b47662c8e2fc34190f77919fa05e41226a1fa236d464cdd0c46e5d0822fdb4226ab9297b1ac2763b87897e4001bb5fd117ba894621c4f19291b31e074f4614523259e4884d735dbd2f0be3a5e687ccd4824a0a501cc311578f49a13b82beb0e18f3a1aca9688d95856c04b6a6c453397b08301bbb222c83e0a5ef28a116dce41c8ee0133596865178948427ffbfacf1856dbf317bc0d10ecb2ca1aa33dee293000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000049c0d6a9e6f273c4494f3568e55d0a313c2edcfc28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae612c4c6415c49c164f8c81c76939fde44b1e6619d1946eb673ac203903dc36a00001c8c09a245beacc76f69f41def1da2219a0cd1ea328134e3aba603e29770fc1ef007c81d6fec56f2f1633d4a5f0b185fad2f719a8b92c624c1441eb2a2f9633020b4b1a0c2a6b16dea1fe908f0d5ab7c2d6f9d7ab50abd9135c25936c317a200f31f339962c0bba6bf3878088ee151d5163df24097350d02cc00f3d5f3a2e316554592f12df06777fc2eeb343641083f6299f66bd6f6f4ae3c125da8cc15680d35cfdfc71d15f59e6e37bae016dfc96da646aea2fbdba7be6fd334c53490ee008c2f1d877ed983a8afe7f98529da6e8186cb1874695070aeb5dc126d4235ad1fd76af0b23372d37b7f5181db3da8d2a46848cf4a473d55ccd23def6db02d46000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000485d8a98bb5dc09f1735aecbc8144ab2db7b545428942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60543198b027d09bba2e1a841d4d3abd89256be8b84db977f5f651fbadf879efa05b9205ea53264deb3985cd04a071d90646a7f7f598d2caf2d2d005ad498943e15e5e0bbe91d868a0ee665e0651f8ffb6c6d2ac509c43d5bb53d805bc6c15f6d06909f64060d8c1a9519cf2b2c06a4542594ef2c3f03628ab85816700d9e6d4115ae7319fb08e0d7cc7755a766fe2be37a6f41332c900b23330c78cfb42e965b0fb6968782b33ec1dc44e79704c6eab3264b4a1a95caa47f3c1eeba76ab83dea260c18ce79fef579dacdc214b521666a9cb9c5ecd0ef82199e2b045ab073bd0926ccbdd591bacf2f04ce8b13437ec5ee71061c37a3bbd68879e0917ddf157ff5082b9767119e087ee6979a6ba346d99a2f6755aab877b680bd1973b7e6c96563000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000231a2f44fde5788ee99c2ea163be421714ee47fc28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae624bd26434331113463b0801bad03295369f09b001551e3039be9a5c86f7c463d0fdd76dae5e472d7738264ac9db2ef6179e1d90a2e2f7931de1b862d24e4cacc171d8f1057095e652a2276423f70ec952dc43abb32bc72ca8080ae10451098b40aca120d5b8822848412087d67b40498eeab7246254d95db1b49b2b77838bee02597c0796b870fe29d3e0fcb8cd2d3148cc5d29ac0e0fe3cc1b42310b6f06cc90f771c1c8425d1e6ee1929cbc01986def1ea012780d606b41cf378682c9a0a2a13e44d09eac7239b532e1c5d99fc76a5b0c0e184edc31aea2b1ded286a8b7b8b1b8c744c3b5b68a413b7710a4106993e0e3aa97c148bbc46e7bd475e4a4a0bf71a64ba3b34be6656b6760ccd4b3c080019735cbf852cd50a5608d56ead05ffe900000000000000000000000000000000000000000000000000000000c080a0f613146bcf55b47f690f88aa4d95f8e188b28065b0ddbd49f689c7776a4049b3a00b4d55033092f80ca9df1123c6437f52372e2548cb8fbeca54722d9fe760e3c2").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717730355, + prev_randao: b256!("c7acc30c856d749a81902d811e879e8dae5de2e022091aaa7eb4b586dcd3d052"), + withdrawals: Default::default(), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + parent_beacon_block_root: Some(b256!( + "a4414c4984ce7285b82bd9b21c642af30f0f648fb6f4929b67753e7345a06bab" + )), + }, gas_limit: Some(30_000_000), - timestamp: 1717730355, - prev_randao: b256!("c7acc30c856d749a81902d811e879e8dae5de2e022091aaa7eb4b586dcd3d052"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "a4414c4984ce7285b82bd9b21c642af30f0f648fb6f4929b67753e7345a06bab" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: Some(false), }; op_mainnet_exec_bench("block_121065789_exec", parent_header, payload_attrs, b) @@ -147,17 +150,19 @@ fn execution(c: &mut Criterion) { hex!("02f904da0a83012933830f424084045e2f258305e39c9400000000fc04c910a0b5fea33b03e0447ad0b0aa8702e5763b5ce075b90464a44c9ce7000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff5f082dbf2d2f930eb3d2b51bb2f1010a4d5a8900000000000000000000000000000000fcb080a4d6c39a9354da9eb9bc104cd7000000000000000000000000000000000000000000000000000000006664a0bd00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000041819edf15e18a545cbbabbd24c9f3e136a3dcec10c65f5ce19d6fb903e586e6db5f2e154210d25768487e89cb7d9b62cc611421c3456538c7d9ac39f0fd619e111c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000006664a0bd000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000205183a065a3c67e765796c2969e67b960d2ae041a36070a7ed719b18b5682bdda0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000002ef790dd7993a35fd847c053eddae940d0555960000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006664a0bd0000000000000000000000000000000000000000000000000000000000000041dd6bb97a2c5250e07ba4b0df71715c81ac9adc5ee1111a0f8ff3845321ac7d5262a7cdd80df46391bc4e41b5f1492110a42badfb7b6ebdd8944e2c3c9a9d8e621c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d5ae1701d2a1750e608e1f2b5d10280db952ddb14cc35f819f7334e9eb5133a5072108be5f5134ac6c061fa9e3bcee464ad8c8e13e206cd5c6b632a7294cd34b1c00000000000000000000000000000000000000000000000000000000000000c001a0994107041475defdb265cdbe6da3df610516ec50a81dd9c0a3602c20d1c72b22a04b28a32d391ebdc15e63ffd26dc3a91e6c3c0565538e33e04558a9d1c9d70b3f").into(), hex!("02f8b50a01830f424084045a3cc98306213f942a5c54c625220cb2166c94dd9329be1f8785977d866e5ceb32785cb844f5c358c60000000000000000000000000000000000000000000000000000000000000504000000000000000000000000000000000000000000000000000000000263b143c001a051a2584f761c7ef2216652d41840cb1e84c0576d076c72f06906777cb043d45aa02bdbb191600306e5f3ff6d65991f61979f8a10d60d0c6ccaaf1f6d5c7515dac2").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717870185, + withdrawals: Default::default(), + prev_randao: b256!("23b3d2cb1b7216ef94837fdf94767b6235ce735a19de4f3feee7c1d603f2d10b"), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + parent_beacon_block_root: Some(b256!( + "8ab0d68c0fc4fe40d31baf01bcf73de45ddf15ab58e66738ca6c60648676f9af" + )), + }, gas_limit: Some(30_000_000), - timestamp: 1717870185, - prev_randao: b256!("23b3d2cb1b7216ef94837fdf94767b6235ce735a19de4f3feee7c1d603f2d10b"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "8ab0d68c0fc4fe40d31baf01bcf73de45ddf15ab58e66738ca6c60648676f9af" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: Some(false), }; op_mainnet_exec_bench("block_121135704_exec", parent_header, payload_attrs, b) diff --git a/crates/executor/src/eip4788.rs b/crates/executor/src/eip4788.rs index 5b939868..c445c421 100644 --- a/crates/executor/src/eip4788.rs +++ b/crates/executor/src/eip4788.rs @@ -4,8 +4,8 @@ use alloc::{boxed::Box, vec::Vec}; use alloy_eips::eip4788::BEACON_ROOTS_ADDRESS; use alloy_primitives::{Address, Bytes, B256, U256}; use anyhow::{anyhow, Result}; -use kona_primitives::L2PayloadAttributes; use op_alloy_genesis::RollupConfig; +use op_alloy_rpc_types_engine::OptimismPayloadAttributes; use revm::{ primitives::{ BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, @@ -20,7 +20,7 @@ pub(crate) fn pre_block_beacon_root_contract_call block_number: u64, initialized_cfg: &CfgEnvWithHandlerCfg, initialized_block_env: &BlockEnv, - payload: &L2PayloadAttributes, + payload: &OptimismPayloadAttributes, ) -> Result<()> where DB::Error: core::fmt::Display, @@ -38,9 +38,9 @@ where // initialize a block from the env, because the pre block call needs the block itself apply_beacon_root_contract_call( config, - payload.timestamp, + payload.payload_attributes.timestamp, block_number, - payload.parent_beacon_block_root, + payload.payload_attributes.parent_beacon_block_root, &mut evm_pre_block, ) } diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 241f96f5..2df912a1 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -13,9 +13,9 @@ use alloy_eips::eip2718::{Decodable2718, Encodable2718}; use alloy_primitives::{address, keccak256, Address, Bytes, TxKind, B256, U256}; use anyhow::{anyhow, Result}; use kona_mpt::{ordered_trie_with_encoder, TrieDB, TrieDBFetcher, TrieDBHinter}; -use kona_primitives::L2PayloadAttributes; use op_alloy_consensus::{OpReceiptEnvelope, OpTxEnvelope}; use op_alloy_genesis::RollupConfig; +use op_alloy_rpc_types_engine::OptimismPayloadAttributes; use revm::{ db::{states::bundle_state::BundleRetention, State}, primitives::{ @@ -80,15 +80,15 @@ where /// 4. Merge all state transitions into the cache state. /// 5. Compute the [state root, transactions root, receipts root, logs bloom] for the processed /// block. - pub fn execute_payload(&mut self, payload: L2PayloadAttributes) -> Result<&Header> { + pub fn execute_payload(&mut self, payload: OptimismPayloadAttributes) -> Result<&Header> { // Prepare the `revm` environment. let initialized_block_env = Self::prepare_block_env( - self.revm_spec_id(payload.timestamp), + self.revm_spec_id(payload.payload_attributes.timestamp), self.config, self.trie_db.parent_block_header(), &payload, ); - let initialized_cfg = self.evm_cfg_env(payload.timestamp); + let initialized_cfg = self.evm_cfg_env(payload.payload_attributes.timestamp); let block_number = initialized_block_env.number.to::(); let base_fee = initialized_block_env.basefee.to::(); let gas_limit = @@ -99,7 +99,7 @@ where "Executing block # {block_number} | Gas limit: {gas_limit} | Tx count: {tx_len}", block_number = block_number, gas_limit = gas_limit, - tx_len = payload.transactions.len() + tx_len = payload.transactions.as_ref().map(|txs| txs.len()).unwrap_or_default(), ); let mut state = @@ -116,11 +116,16 @@ where )?; // Ensure that the create2 contract is deployed upon transition to the Canyon hardfork. - ensure_create2_deployer_canyon(&mut state, self.config, payload.timestamp)?; + ensure_create2_deployer_canyon( + &mut state, + self.config, + payload.payload_attributes.timestamp, + )?; let mut cumulative_gas_used = 0u64; - let mut receipts: Vec = Vec::with_capacity(payload.transactions.len()); - let is_regolith = self.config.is_regolith_active(payload.timestamp); + let mut receipts: Vec = + Vec::with_capacity(payload.transactions.as_ref().map(|t| t.len()).unwrap_or_default()); + let is_regolith = self.config.is_regolith_active(payload.payload_attributes.timestamp); // Construct the block-scoped EVM with the given configuration. // The transaction environment is set within the loop for each transaction. @@ -142,14 +147,17 @@ where }; // Execute the transactions in the payload. - let transactions = payload - .transactions - .iter() - .map(|raw_tx| { - let tx = OpTxEnvelope::decode_2718(&mut raw_tx.as_ref()).map_err(|e| anyhow!(e))?; - Ok((tx, raw_tx.as_ref())) - }) - .collect::>>()?; + let transactions = if let Some(ref txs) = payload.transactions { + txs.iter() + .map(|raw_tx| { + let tx = + OpTxEnvelope::decode_2718(&mut raw_tx.as_ref()).map_err(|e| anyhow!(e))?; + Ok((tx, raw_tx.as_ref())) + }) + .collect::>>()? + } else { + Vec::new() + }; for (transaction, raw_transaction) in transactions { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. @@ -214,7 +222,11 @@ where .map(|depositor| depositor.account_info().unwrap_or_default().nonce), depositor .is_some() - .then(|| self.config.is_canyon_active(payload.timestamp).then_some(1)) + .then(|| { + self.config + .is_canyon_active(payload.payload_attributes.timestamp) + .then_some(1) + }) .flatten(), ); receipts.push(receipt); @@ -239,8 +251,13 @@ where // Recompute the header roots. let state_root = state.database.state_root(&bundle)?; - let transactions_root = Self::compute_transactions_root(payload.transactions.as_slice()); - let receipts_root = Self::compute_receipts_root(&receipts, self.config, payload.timestamp); + let transactions_root = + Self::compute_transactions_root(payload.transactions.unwrap_or_default().as_slice()); + let receipts_root = Self::compute_receipts_root( + &receipts, + self.config, + payload.payload_attributes.timestamp, + ); debug!( target: "client_executor", "Computed transactions root: {transactions_root} | receipts root: {receipts_root}", @@ -248,8 +265,10 @@ where // The withdrawals root on OP Stack chains, after Canyon activation, is always the empty // root hash. - let withdrawals_root = - self.config.is_canyon_active(payload.timestamp).then_some(EMPTY_ROOT_HASH); + let withdrawals_root = self + .config + .is_canyon_active(payload.payload_attributes.timestamp) + .then_some(EMPTY_ROOT_HASH); // Compute logs bloom filter for the block. let logs_bloom = logs_bloom(receipts.iter().flat_map(|receipt| receipt.logs())); @@ -257,7 +276,7 @@ where // Compute Cancun fields, if active. let (blob_gas_used, excess_blob_gas) = self .config - .is_ecotone_active(payload.timestamp) + .is_ecotone_active(payload.payload_attributes.timestamp) .then(|| { let parent_header = state.database.parent_block_header(); let excess_blob_gas = if self.config.is_ecotone_active(parent_header.timestamp) { @@ -277,7 +296,7 @@ where let header = Header { parent_hash: state.database.parent_block_header().seal(), ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: payload.fee_recipient, + beneficiary: payload.payload_attributes.suggested_fee_recipient, state_root, transactions_root, receipts_root, @@ -288,13 +307,13 @@ where number: block_number, gas_limit: gas_limit.into(), gas_used: cumulative_gas_used as u128, - timestamp: payload.timestamp, - mix_hash: payload.prev_randao, + timestamp: payload.payload_attributes.timestamp, + mix_hash: payload.payload_attributes.prev_randao, nonce: Default::default(), base_fee_per_gas: Some(base_fee), blob_gas_used, excess_blob_gas, - parent_beacon_block_root: payload.parent_beacon_block_root, + parent_beacon_block_root: payload.payload_attributes.parent_beacon_block_root, // Provide no extra data on OP Stack chains extra_data: Bytes::default(), } @@ -462,7 +481,7 @@ where ordered_trie_with_encoder(transactions, |tx, buf| buf.put_slice(tx.as_ref())).root() } - /// Prepares a [BlockEnv] with the given [L2PayloadAttributes]. + /// Prepares a [BlockEnv] with the given [OptimismPayloadAttributes]. /// /// ## Takes /// - `payload`: The payload to prepare the environment for. @@ -471,7 +490,7 @@ where spec_id: SpecId, config: &RollupConfig, parent_header: &Header, - payload_attrs: &L2PayloadAttributes, + payload_attrs: &OptimismPayloadAttributes, ) -> BlockEnv { let blob_excess_gas_and_price = parent_header .next_block_excess_blob_gas() @@ -479,7 +498,8 @@ where .map(|x| BlobExcessGasAndPrice::new(x as u64)); // If the payload attribute timestamp is past canyon activation, // use the canyon base fee params from the rollup config. - let base_fee_params = if config.is_canyon_active(payload_attrs.timestamp) { + let base_fee_params = if config.is_canyon_active(payload_attrs.payload_attributes.timestamp) + { config.canyon_base_fee_params } else { config.base_fee_params @@ -490,11 +510,11 @@ where BlockEnv { number: U256::from(parent_header.number + 1), coinbase: address!("4200000000000000000000000000000000000011"), - timestamp: U256::from(payload_attrs.timestamp), + timestamp: U256::from(payload_attrs.payload_attributes.timestamp), gas_limit: U256::from(payload_attrs.gas_limit.expect("Gas limit not provided")), basefee: U256::from(next_block_base_fee), difficulty: U256::ZERO, - prevrandao: Some(payload_attrs.prev_randao), + prevrandao: Some(payload_attrs.payload_attributes.prev_randao), blob_excess_gas_and_price, } } @@ -626,6 +646,7 @@ mod test { use super::*; use alloy_primitives::{address, b256, hex}; use alloy_rlp::Decodable; + use alloy_rpc_types_engine::PayloadAttributes; use kona_mpt::NoopTrieDBHinter; use op_alloy_genesis::{OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS}; use serde::Deserialize; @@ -706,17 +727,21 @@ mod test { .unwrap(); let raw_tx = hex!("7ef8f8a003b511b9b71520cd62cad3b5fd5b1b8eaebd658447723c31c7f1eba87cfe98c894deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc5000000000000000300000000665a33a70000000001310e960000000000000000000000000000000000000000000000000000000214d2697300000000000000000000000000000000000000000000000000000000000000015346d208a396843018a2e666c8e7832067358433fb87ca421273c6a4e69f78d50000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985"); - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 0x665a3439, + withdrawals: Default::default(), + parent_beacon_block_root: Some(b256!( + "917693152c4a041efbc196e9d169087093336da96a8bb3af1e55fce447a7b8a9" + )), + prev_randao: b256!( + "edba75784acf3165bffd96df8b78ffdb3781db91f886f22b4bee0a6f722df939" + ), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + }, gas_limit: Some(0x1c9c380), - timestamp: 0x665a3439, - prev_randao: b256!("edba75784acf3165bffd96df8b78ffdb3781db91f886f22b4bee0a6f722df939"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "917693152c4a041efbc196e9d169087093336da96a8bb3af1e55fce447a7b8a9" - )), - transactions: alloc::vec![raw_tx.into()], - no_tx_pool: false, + transactions: Some(alloc::vec![raw_tx.into()]), + no_tx_pool: None, }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); @@ -763,17 +788,21 @@ mod test { hex!("02f9010b0a8301b419835009eb840439574783030fc3940000000000002bdbf1bf3279983603ec279cc6df8702c2ad68fd9000b89666e0daa0001e80001ec0001d0220001e01001e01000bfe1561df392590b0cb3ec093b711066774ca96cd001e01001e20001ee49dbb844d000b3678862f04290e565cca2ef163baeb92bb76790c001e01001e01001ea0000b38873c13509d36077a4638183f4a9a72f8a66b91001e20000bcaaef30cf6e70a0118e59cd3fb88164de6d144b5003a01001802c2ad68fd900000012b817fc001a098c44ee6585f33a4fbc9c999b2469697dd8007b986c79569ae6f3d077de45a1ca035c3ea5e954ae76fdf75f7d7ce215a339ac20a772081b62908d5fcf551693e3a").into(), hex!("02f904920a828a19834c4b408403dce3e7837a1200944d75a5ce454b264b187bee9e189af1564a68408d80b90424b1dc65a400018958e0d17c70a7bddf525ee0a3bf00f5c8f886a03156c522c0b256cb884d00000000000000000000000000000000000000000000000000000000001814035a6bc28056dae2cfa8a6479f5e50eee95bb3ae2b65be853a4440f15cb60211ba00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000003400000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000000000000000000000000000000000e8d4a510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000606ecf709c09afd92138cca6ee144be81e1c6ef231d4586a22eb7fc801826e837691e208839c1c58d50a31826c8b47c5218c3898ee6671f734bd9b9584ce210e8b1fb287f374f07a99bbce2ddedc655ee5c94f8fee715db21644ae134638af8c32d18b1d27dbc2e12b205ea25ab6bb4ec447ee7f40dba560e511a20fd8a3775d04ad83bf593e3587be1dd85ab9b2053d1386fae00c5fdea56a68ea147b706e5ced65ab296b8d9248aa943787a5c8aa4fd56ba7133d087e84a625fe1c3d8a390b5000000000000000000000000000000000000000000000000000000000000000666634013473fce9d0696d9f0375be4260a81518a85f2482b3f5336848f8fa3ce1a3f7032124577ee2a755122f916e4fe757fc42eb5561216892ed806d368908b69c4d4d1cd06897a3a2f02c17ffba7a762e4cbbdb086a1181f1111874f88f38f3b86fa03508822346a167de3f6afc9066cc274103cf18d62c7d6a4d93dcd000b7842951fd9a14a647148dac543f446cd9427dedbc3c3ca5ed2b36f5c27ce76de46d4291be6ef3b41679501c8f0341d35cf6afc9f7d91d56ad1a8ae34fc0e708ac001a013f549ca84754e18fae518daa617d19dfbdff6da7bc794bab89e7a17288cb5b5a00c4913669beb11412e9e04bd4311ed5b11443b9e34f7fb25488e58047ddd8820").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717698555, + withdrawals: Default::default(), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + prev_randao: b256!( + "d91ae18a8b94471ef1b15686ef8a6144a109b837c28488a0f1a2a4e4ad29d5af" + ), + parent_beacon_block_root: Some(b256!( + "5e7da14ac6b18e62306c84d9d555387d4b4a6c3d122df22a2af2b68bf219860d" + )), + }, gas_limit: Some(30000000), - timestamp: 1717698555, - prev_randao: b256!("d91ae18a8b94471ef1b15686ef8a6144a109b837c28488a0f1a2a4e4ad29d5af"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "5e7da14ac6b18e62306c84d9d555387d4b4a6c3d122df22a2af2b68bf219860d" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: Some(false), }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); @@ -827,17 +856,21 @@ mod test { hex!("02f905720a820a1e830f42408404606a2c83044bc0940000000071727de22e5e9d8baf0edac6f37da03280b90504765e827f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000004337016838785634c63fce393bfc6222564436c4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000006a2aad2e20ef62b5b56e4e2b5e342e53ee7fa04f000017719c140000000000000000000000000000000005300000000000000002000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000002265a0000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000000010a370000000000000000000000000010c8e000000000000000000000000004d4157c00000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4e9ae5c530100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000006668bc6eea73404b4da5775c774fafc815b66b36000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044a9059cbb000000000000000000000000efe1bfc13a0f086066fbe23a18c896eb697ca5cc00000000000000000000000000000000000000000000000000000001a13b8600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b59d0021a869f1ed3a661ffe8c9b41ec6244261d9800000000000000000000000000004e8a0000000000000000000000000000000100000000000000000000000000000000000000000000000000000000666095e00000000000000000000000000000000000000000000000000000000000000000dcc3f422395fc31d9308eb3c4805623ddc445433eb04f7d4d7b07a9b4abb16886820d7c9a50f7bb450cff51271a9ff789322e9a72c65cf58da188c6b77093fdb1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000042fff34f0b4b601ea1d21ac1184895b6d6b81662b95d14e59dfb768ef963838ca29f67dcaf0423b47312bd82d9f498976b28765bec3e79153ca76f644f04ef14dc001b000000000000000000000000000000000000000000000000000000000000c001a0ccd6f3e292c0acaea26b3fd6fee4bc1840fd38553b01637e01990ade4b6b26d4a05daf9fa73f7c0c0ae24097e01d04ed2d6548cd9a3668f8aa18abdb5eca623e08").into(), hex!("02f901920a820112830c5c06840af2724a830473c694a062ae8a9c5e11aaa026fc2670b0d65ccc8b285880b901245a47ddc3000000000000000000000000cb8fa9a76b8e203d8c3797bf438d8fb81ea3326a0000000000000000000000008ae125e8653821e851f12a49f7765db9a9ce73840000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000564edf7ae333278800000000000000000000000000000000000000000000000033f7ab48c542f25d000000000000000000000000000000000000000000000000564ca9d9ed92184200000000000000000000000000000000000000000000000033f656b5d849c5b30000000000000000000000004049d8f3f83365555e55e3594993fbeb30ccdc350000000000000000000000000000000000000000000000000000000066609a8ac080a071ef15fac388b7c5c9b56282610f0c7c5bde00ec3dcb07121fa04c64a0c53ccea0746f4a4cf21cf08f75ae7c078efcf148f910000986add1b7998d81874f5de009").into(), ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 0x6660938b, + withdrawals: Default::default(), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + prev_randao: b256!( + "22e77867678dc60aace7567ee344620f47a66be343eac90a82bf619ea37de357" + ), + parent_beacon_block_root: Some(b256!( + "50f4a35e2f059621cba649e719d23a2a9d030189fd19172a689c76d3adf39fec" + )), + }, gas_limit: Some(0x1c9c380), - timestamp: 0x6660938b, - prev_randao: b256!("22e77867678dc60aace7567ee344620f47a66be343eac90a82bf619ea37de357"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "50f4a35e2f059621cba649e719d23a2a9d030189fd19172a689c76d3adf39fec" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: Some(false), }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); @@ -885,17 +918,21 @@ mod test { hex!("f9032d8301c3338406244dd88304c7fc941111111254eeb25477b68fb85ed929f73a96058280b902c412aa3caf000000000000000000000000b63aae6c353636d66df13b89ba4425cfe13d10ba000000000000000000000000420000000000000000000000000000000000000600000000000000000000000068f180fcce6836688e9084f035309e29bf0a2095000000000000000000000000b63aae6c353636d66df13b89ba4425cfe13d10ba0000000000000000000000003f343211f0487eb43af2e0e773ba012015e6651a000000000000000000000000000000000000000000000000074a17b261ebbf4000000000000000000000000000000000000000000000000000000000002b13e70000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001120000000000000000000000000000000000000000000000000000000000f400a0c9e75c48000000000000000020120000000000000000000000000000000000000000000000000000c600006302a000000000000000000000000000000000000000000000000000000000000f5b3fee63c1e581e1b9cc9cc17616ce81f0fa5b958d36f789fb2c0042000000000000000000000000000000000000061111111254eeb25477b68fb85ed929f73a96058202a000000000000000000000000000000000000000000000000000000000001b4ccdee63c1e58185c31ffa3706d1cce9d525a00f1c7d4a2911754c42000000000000000000000000000000000000061111111254eeb25477b68fb85ed929f73a960582000000000000000000000000000037a088fb0295e0b68236fa1742c8d1ee86d682e86928ce4b32f27c2010addbdb7020a01310030aba22db3e46766fb7bc3ba666535d25dfd9df5f13d55632ec8638d01b").into(), hex!("02f901d30a8303cd348316e36084608dcd0e8302cde8945800249621da520adfdca16da20d8a5fc0f814d880b901640ddedd8400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000002d9f4000000000000000000000000000000000000000000000000005d423c655aa00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000eb22708b72cc00b04346eee1767c0e147f8db2d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000769127d620c000000000000000000000000000000000000000000000000000000000000000016692be0dfa2ce53a3d8c88ebcab639cf00c16197a717bc3ddeab46bbab181bbec001a0bdfb7260ed744771034511f4823380f16bb50427e1888f352c9c94d5d569e66da05cabb47cf62ed550d06af2f9555ff290f4b403fee7e32f67f19d3948db0dc1cb").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717713383, + withdrawals: Default::default(), + prev_randao: b256!( + "d8ecef54b9a072a935b297c177b54dbbd5ee9e0fd811a2b69de4b1f28656ad16" + ), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + parent_beacon_block_root: Some(b256!( + "fa918fbee01a47f475d70995e78b4505bd8714962012720cab27f7e66ec4ea5b" + )), + }, gas_limit: Some(30_000_000), - timestamp: 1717713383, - prev_randao: b256!("d8ecef54b9a072a935b297c177b54dbbd5ee9e0fd811a2b69de4b1f28656ad16"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "fa918fbee01a47f475d70995e78b4505bd8714962012720cab27f7e66ec4ea5b" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: None, }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); @@ -952,17 +989,21 @@ mod test { hex!("02f920340a8306969b84032a47f984039387008349857a94087000a300de7200382b55d40045000000e5d60e80b91fc482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000014e0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000019200000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001d600000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000cbf61a54ebe5e9152e1f6b81cbffd3027062642928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61d460bd138ee32c939dfd8e49c57a95ef4dcef2f88b92e5a1d5e2905f86d787328bb4c7a1e4eb3b8db4d59a38321cd444d510a700551beb6fdfcdc88068c02f70506c41903052ed62b6913f66c9595a218d5726ea3128be80d62f7c69887816a22f613c865b39a6e228b0d90313dad896d11000afe422c2412aa8eef93fb1a1e0cd8be0d3226796e106d56c9f3d6ea5f189f88353aecab6565a256034ee48fd00bafdf7b018aa742f06a35f8ac0442c02d1a4f75186798a33cb57b53f3b2a09507ca58f2e94f1bc503faaabb19812e52adc5446d0d3a2eaa3c37c96cd6b3937014ef84689357e91ccced5dbfda2cbcff66f237923aa145326a831953620b7fc711e8faedc7ef58112a00cf6e13cbc0f005606720fb034d7a57f591ebcf33a66c000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000007cdb62cd44f27416d3d80060887b79edbc66eed428942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae627cd53af047b648a62ebbc6b7022738934e337451e6934e285bcb17ed151e9a2156cee556c24689d42cf8d19d308cdaf32215270100cb7de2300b61d6f3805e61fad747173364b42a1fbc54501d3fe6689204bb44e095ca5aca1652d4ce018070bbbad2a1406c2ed33020899c296fb67957c0dafa5e7630c6f15eed2d85ca3921f78322e092ee4289f1f00dbc46793221e1b2439129fb05b1f185cfa857baf812e9ba7fecd26f0671e1fbc3796ab226a8484095d31360f45222167cd7dab33f11a13d59918ab5dbcbd350d47b8d48d3b52e275887e0663b63b9cba34e97377af15def44fb6d6227bc92d17b372a4779d53d4117357d4e372f15ead01502b0cc3006542ebe7436861a0a015643024b8eb364ecc758dc76e38f5cbbf461c18a73b000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000060de5ca48792914e8ed36f8294c571cb64cbc86228942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61c2f5918a5841520443a45ccf49a742a50bcd4548fd8ad248a1b8742aa75b46417c1fc6a32babcf3b5960b1cfb35d98a261641322b811053ace79049d236019205960ca817a496c09847350c58899c0008ab73f124204dacff678139ae80c95c1d7877bf7f5c4b37f570321a76e604b5a140229e1564216e722102a0131c6f442933d8de999cee105ba504babd60abf0d97ff47ccf6395159a8c2a24d24ed918029a1cde683c17c594cad199facdf9928066a73025189be71671e2df5314c0cd00c501e761df7d4b8a0cc152d6870bdf5a3f5f7ad8bdbc2d0f11ce6cdcc829bc1acb667ba2d8c86243659458f23b0c5c46fef1761cc7013ce20c5a55bf9f28481c42002db11bd87e9f501a27ffa16297536ff3bd04d44cf8385c66913b259f94000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000004427395e8d53ec91fe009b9f9f7d108a6d046fa328942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60e8eb84cafb9b1049f380e248ee56e410da056b3ac4fae01e640bf76dfa9b32c089f372414a1aa9c722f3af366ab7f4dbf700d8cfd8376f90c5125df5211c0240c1b68b374253a99342db518fff6ecc0605c35d0abc5cb9fd58d13b554ca1204306006c533a0d4e84cbdc3d1a219f562df9e5afc90dd541b8b2332ba63eba2062b9aeaa5722b7ae0e7d60a977dfc2cc05bf7064b1ed2aa897c306236b1adea8528a850bbec99f23a3c0b9a747c2f285474f266424bf6d336d0c4ec119877f5a9109eafdf5d0f879f6907ecdc9cbd20f41d43dff8d94caf9c4486f017f7d10c511da1f9629b4d2e0232c0bf208a0f9408134b1f6fcf77b33ca549ea32536e43b900f4fbb5c755d3221871fdd7c7118c1fec5559871922b1b462a5f0502b9e14e9000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000ff7fa1fcf8df81ea158cfebdad80d00d49790c1b28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6142c5c102e9eb810eec6a0fe8cb214c224de98a8ae9e73f46897df36bffe668f15c5b544e21b5c7495900a1bcba9a3b9ff362e192a88c24be1834cecbbebcb172be37dcbd251b8ad00f6a589bf6a296eadba57dbebca0ec879f7c0b101c5a2d12849f2cb39082e9a68623d3793562d40de78acc164ece4ba819b9cd41c60ddb0155ce47cccdd81c62bd4850644937385e494c711b794ea61c3f876cfae88e05805ef8c12ea3890fb78f382fd4757b43fb31e9b711d5eb6179b302bc187b621e806dcecbe346e981b671c871b81d963a58c674ba7b5aaf83203e8b6480104b02006491322421291c323149a72e34c1c9c793b6797eb2a83408faba857a60d810f0f64bf23f7d507c895edfb71d617ccdc2f1f819e16bd07cb467ee77794bfc9b6000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f34c1f7627c21d08affe689360b68e3b86bddd8e28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae603f4f9d9e44ecdfa78b3f822a00aac0a80fbde1675bed218b4e9daf3018c75c2274fc133f9df6704f4926e8201f000cdb3f5288f5bab86b24f4501734b001faa06b1f228701b430c5f77357668d11abb9aa246ec200026b8835fc8ea038dbc3721978e874ed6e196d0ee6ef1baed881ec1a8fdc818fca586e49adf1a01014d630b247457164a28f47dbef855ff71f85bc3d2d114f450bc209463a532cff56aa9183a29e8599a51c0a5a46435d21e0421a5ee0b31590e2670431f59948523a3840a6914dfcdaa1d8f4acc0999bff181168bc97f59d2e76914b8fe40da7cfd767510fcf9dce7c0aa00f582fcb232b250941dc3acdfb71328c97fb21804ad1abb181f04e30fe89e260a50e3ecff6b402e0796a12625cbb28e218565ca449bfc5d54000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000b6816921690bbb13022ce4279c741e9f10f6d25028942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60c7d7a2327da7193adb6e7da1a0011071990b12213c823686963a0fba1a43683034744575541f9edc32e3ce969ca106604b4a989340584ddc55b9728c7e2e735074515993dfc63a646b2d8f748414d5dbcd64394118e0f89d165c746caf2434209bb608dd08ab880aad6440c7340c1c684403cb97e2276590bd18963940d98eb1e1a272569a949e07dfe4a665893154eceb132e728555b80e40a51b6134c6a1e0a6fba21519df338be4c257b4a5300e8b8f22fd006f2e9fa8e2d72b60f3818e72de6b2584eda4a90fc2d78b98dc1b5ccbdf1f3c20e733bbff817158df22fbdba1d8e56cd2b62522af6b23891f4f2494e565ded4983941326df46f8895df90b261eddd0dbf8d65704970292fd40ea3c440b4f7004f8a988eaa0124ca04acc2f80000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000046cd855658bcbb261645dac5de9bcf3e86338ca528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61a678665a7ae5d9945c98f2448bf68e73e80475cbba2f1601c5be074171c21082ad67f4b03530e704fb1b232b3cddf83ed3cc000fcc0cc5137b6f4c3e89d59fe0f02287c98f5c39229b9ea0ecb3b2e927f66c5bd814bcf032c28d3b9227d3cb91154886e38171ac9cb09ad8f8a7898fe624c216c1f2753fdf2126f1e06adbecc0647e62c17a2c83ba39b269533b35a377b069f0b4ef684142f7f38360feb6e832ac89f308bf01ac0fe322a4d106b404f192b2c279299e97be3a5344516ca21ea105a99ffa98dca692c8c3f52addc90eda18cb19336aaa6d085e40463d74d3b8e0f317e0047e3c6f7f9ea5e99a7adf0afc1acffad89ac728808bb2ac3cd57c5aa2b0ccbc0976152d5b67b89e939da3ba4e0490d962b8035782ff36db7f05a23a3000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000004ef8a049f19848666c00d958723dda15310a88aa28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae629342c1f6c1e951de321ada9f9dd51886c7da9f435a971f21dcce3e8067d80b20edc4b5a3a2982f4bb2825f7e82dba0143325323491b7810c291cbcbd76e35242f9e523c196e71f608c01dc6fdda1f5a6fa0f60ee6422f0363313332b7f6c4ed2d2daaa8ded8a06a27765e33668632033a783e6a452d32f2d327f629e25106560c6251b41c8d03f2fd7617f7f3c745c899f32353223f8ab32b56f813e430391d0686a6604ba4f73d140c25c0d30a8f7aacc24696207d256f14a2d5f3e217f8a70a9254141d4351a6cfda264150d89b2a35140530990449b767f05689709488f00e227ac767806f1c3dfc1173d3886189057e5a55d147166005840d7ca50f17861700af52ea29cab029a6808d6dc6f82acaf942f9254adea7ac455916f0da4452000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000944618cd80dae4191c7f7f21c58ab13bdf81738a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61b7951b069b65c12393920364d045f8d76add6c1d9f29245188781b12600d6be0d5d127d6bd399a6ef83d157093e1f5a7f3e9a1edf67993b678a7f6b2be9b65129827246aee4b32f7d33af5d8363c7edd2b8fa882103655c0e57999d5127aee113a7fe6d4e694ec0e96cca8218f2cac3ea45a958cdb8e7a77e5b0a7f65834f12178510f9a90038299b02ca079f79890aa550ecd77b0b88e6ada0b411255a560c0e214079f6191a523d2f8dac0a1426ddb1b7aaa51f4ab184341392492f727cad29d9439d19f56f626ff8a8482bd148134d5cad497b01d310680537b8e3dbad9705cc9230d48983aee1839334e024c271ea9560ced93bfa54b880901249fc647713b1931335356f6f2c35ac21de1c2a6c3302763a0eea4461c757fb18bf8bdad3000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f2a05e7c62af3f2f02a24b43c2ae13b08890fd4628942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae622cde3d420dbb6ff32a2b0cae2a9e25945c539ad843317103de9e09595f424b328dada7a73b9e990c662830d82148ef6c90879c37ded18d7f24f9dea6c6cf01504184ca216206879d98b04f4e0eb97f6a6128a309e699e7d160201ed34f76d070c5377a5dc4baa602431b5034dce504c8e8fcb3033e605a7f9d43f5e9e4738c30c9021ba9dde79e0338b9843fbdfa7507174fbf43a28fa11b90f39bd4d0c697c0bc0c8292d6d79489b492324735a57da87a52f3fc56c83706711c86188e4734317b57e8482be2fbddd7b8999c6c403b1649ca77cae53ccb33a7466c0ba2e43670717bb2502de19dd83165e63ac0bdf45f628e77f314131766965730a44a947ab2d37be9216c866637b04e5ee682cb7fc17f92ce5c77cf9113abb1030a1997ab2000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000cbd0a779c26eb779769cc9d3a42f61c97c99602928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60396cdbbacab4ca173328793d82669df272d72cbd5f355277324d1cf707995f82b320ecd46b4bc60e11394a891aa160cc8e87ac44ae214a23cddf356c8ef90990d7c8f0c9da0e89ce98f30d4b468df256397afae21430e552c0ab9a4fac037710c7ac7c8858a6d26323a0ef3e40bd3c62fccf473eaa83aebcf6b545a7bc6fd9105811a4341bdab25b827b79253700ac63f5df83cf602db53efa3c93aef66c99d0a5b385aa594eaa55cc8eba9fc5bb179bc1745e4fa1b988e58bd438c1b6a23be0a19671d950886a2c5d8adeb93b36d55c2a6a3fd577fa1f1645edd71a36c37581a5ff14720ee29643e09096dd01785828380c42c9dbe38d2fb89ea391af5deff2ebbaf11c9e1370f4786ae7deb76760ea476ebbbb2bdfce20159706bc2e18fd5000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000377a5093c2531aeaf4f72b4d0b2c48d3d6c8684a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62375d5b21debe1c780d2dcf962266b2df4937663d6b6e93bcf22f1d64af660b51760dd6af28c91232ef017518ba734b91d159c4146074d8f8bdf5d0ca47f220f2d03765f35c93d02340b24d19aec48cbdc3f1fc9788ac2aad187ef5b9bc6bca6038a078c76db57cc594712c5c73c31afd34a7a441743799e3543968c33f76634138cd4cb56addade4da332152eee582c4bb8e416e45d3fc7f3f8ed0b7073337e2bcaf837d7d01edb32e38abf2439fa2aa55b077c1c7b60640d4dab03bf59c7f305c8ca9cd7a20b79807a5180f921a14acd7f30aa74882bc531c0b42c6e08d66904d07970d54795b0c30c383228090d4ed088af846c318e4de7c25ae9dc01e5352ed242f8f39a28c8dd178f364beed17820829d319729f3b3fbc85908339f1220000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000083b664be1badd9f38133826ed0d1051c473e474e28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61b96cb848a7076d907b26de483e289c97c2d7a37b74db23961df4cf3b7a77618019266266d91c62ff228e6016a2f9cb3635b8d7431b80a2284ea13e8692a049f0e81c6a92b69cf67abe95986bf1fd34f17bd458cf13668f47e11edc991a4aac313e246126ed023db3b6d19112f7acf890b77efb0300868a91e09d52a966e6d0315c21f20fe7630e06a0e648cd21e430e9cc12c920bb2df8ff89966830faae7243018fe0cb624573d66479c635f8d7ce04fa45292d39aafd96caeea287e08ca6210ee7e000e89bfbc77617a1f1c2c92bc25f4ca5bc4cb9fa8cff4039e27345baa09b9db170f8e1e9655ced30f72be9edefa5257ce44ad8cd3855cc9fcbaaa443923c51df11ed2f8b830c7bf83c18a77600b170ed08e7a0545c690e1357bc9cf4200000000000000000000000000000000000000000000000000000000c080a0b2ba45b0c4cabc8981799c254b90d90c019b757833e05c2742c13f52e82c7bcfa0296885d0ea2c68aa6020ac3881d89a110471efeef6327af2eb295481571c4386").into(), hex!("02f920340a8306969c84016c2d0e84039387008349cef494087000a300de7200382b55d40045000000e5d60e80b91fc482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000014e0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000019200000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001d600000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000050a76afb1154d01d6eba284069708d356d9969928942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6204472fcf9520f9fb2076ff97de783931cff4485b9028f260839f5a3518c0b7c2dedb9ba79cbf3ce5e0eca92a12da266d66f21c58bc107fb961e7fdce9538d4c195256b732f3eae1f49cde40c25294963146d06212e318cfba43ec8ec274d1bf22c8f77a99a5797161aad10de1fb3f3754df5fc20ccede01674a7c7284f7bd690484bc65d8c32f6a062c6e886f8563ce28e02d2e58485273eca71a27aeb19dc70860db898acf6d32b0140c8b90355e8b4b4bcc0d01f2761d44a573421bf4af1c0e6bcc3f1b2cd42af6830438342270b83e244cb2d680021a46c6a0416683e1e10fcb9e36c27546a590b8bfdaab06385ae9c72b22160622aa8acaf404bfafa50c2fd454af5d6f6d7dc38a9fd1dc115b8f1a55b7f9a2fac0e080cc6e7acf472955000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000fd176b56e03a2a4d400c61cade47630196614e6a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61f480e5d05a2821f7b6a0da7912130ca375498b472fe02cdd1635bf57e3fc79d0e99986102ae4e27760a6d33cab28b4b77c5fc177b0030d8021b67017f7b4c931a69139b25a75a2023160dd6d6f02a21e95d3005308ce63c45c423de987d8e4b1dbec338be731bba82354b115902c3f4d702178bedea57978eb5b174459fc1b1270ea499e3a908cbda58d2c091f5616d9c2b18687adda6c24017833ce90acec200e87b2cc129df7a4f39d8f6e2c3b2a8d3f3e0905c3d4bff8ede401310ae1d9f276d6239c4c32dc9e627a1dbe6a60ea37e4f7de95512de72696e37de529686d0212ee16598faeb5445f37c581fd9a60bd3d22b1fd965a9cea3dd677df95c9fb3151ba48ffa3b5e7454aa32c6850bbed3457f6cccaac2f5cc9e399a68196b29e4000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000897e11089a878542836ec8e77b825a51ef8829b528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae600164253f8e62ae2671abad4b06d54a890f9abc01afec02287a15cf1115068951c9bdbc96cb8adaafae3aa83c4110616113c066688bb00fecc39bdeb64a1390a2917725d914fcc89e3c18a87a8ed00d9540700ec7320ab345baafb920b0441ad07c4a7e6b2dc434e9934277572be6f581fff0eb7be0857f48ddfa68c2e66cfce21fe5a394f6fcc4844335bae1029ebb014c6c08c2403aa11fbbf18cf6bffc425060e00ed6a571e020461981b6429019c35ef9f1be8bcbde05745a1c537b9472d03cba89ce21b3cb28eb03f08d7c97f1d94e8c0b55d3fd2586b74da048726ddbc1c8eb5ff64d606c6bacc97d6428a1ff83517a46b8f3d5194714a98957d2f1cd905a46fdce4364f2512312c238f9dc59ee6faffe30ee2d7f5887ab0eecd596b40000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006bc063c2b6c1c94490329f632725e22237456b3f28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62ad99a00f80269a3a77de4fc3bd9976e9ef2a94954860a99c785b2bf1b63accc26de5151dac27c1c3d92571dfba7a67ca017482bee0be2188fa571875c660e5d221a475b95129123030032cf5243f78a2e6cf478c6c3c549d46fe6811a59c3900578aa1407face18fc14174b56571888ef0c471fd66aa52a53206215429d0f8405511b5377d2e625d010030d49045e1828e2366e8d5df27068e8eb9b89891b170a61b2f39e61d48c97c6117b1f04e5ac104311785063e3acc3cbe7358b13082204a43390431779d8fad127b39c5853f9926e94e6985a0fba609e7453db8a9e7c26d930a97127bc0cb549e5723f4b92f8cc7e5f800368ef108411f31e8c2476b80eac922344044afde8e958a3af9422dda01d35584d76526fc1a2a13ae59dbd0f000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000033200fe170f61ed4ac8a09b43e3798e4ac8f195b28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae62d3092e1316ce6abb3acc796d98205e786e22c1345c132b0e61070095b83993b136fae2ec9bb03d161cef5cad8bff5335812f32cea2191dfd42df867f64981542b7fc99748f6833af03f2d7c93ad8d3cfe6b5103a510deebbb029e4005dec5a201326eee2a5598f72b7500f0aedebc83563faef710c75cf0a8f69ee75645ecf0053f00c5847f869a0b27d58d6ca7314f590766b4e4eb305c3c31e64b206df10d02ae3cf650459570d00f74f002fdfa92e68bf056c8b974c07b189a33442281c51748d8cfeb75803b470f289144f38d5648bc6d2def5caf65d0cab9583dc0220f17c983c93039ed5fff9d82b233a207a1069f00bfee072c1ce04211e6571df5c825dc3cacbeb084a77f015460798ebf9a2a5e546013bbd245b57ccb3a3a60579b000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000f1ba6cef8ccb2990ce7de325b7fa407906125bf328942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae620c0644be433481651df7035bc5cc1247d8eb024f08f06646a9f1a81e475902711574aa82220fd71bc6cd5f1e7a2f1c66f6cdec680e04c449fd5f65f0606f84207dac5ae5563747e3e74aca6b92fe8be94a591ba654763f2c376a984ab6bac5a07cf890ae88d46cebfabe94398e2d8aef0a277caa1de32e3a81377e564286b1e02161e7871b40c0a388af9e732df270970cd74b6bb71ec71479a1144789da3ab279ba62160fbc729e5ce188fe5925e3ec9d04988f62adfbb9c8cef7246cd0d5720705aafd2bd6f4735dc9b19b03d606a70aabb86c38e2c3fdf2f53ef92e7eb64207335417ad2b241b88d9ae80418ca07eb457f2c557a5bd4c1eb2ef3c3fcbe3120e195a0a41d0dc2aec8703992711bc3ca34432f04012e6b771841b9862a7447000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000785cb80c25d8d3618ca7962b2dd85e7513b0fda528942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae6291ca2fbeb9e08a732b6937ff647309d7152fb770052fe37d3c7ca22911a6bec11b0f463565e65e5c255bb13afa8fb025bf41cc4aee8f4b8d00d1826c6ab90f813e024024e4c916186ca0ec32ab1688a6a09a156462027b218f39a1f4dd4b964243e8898fc270f9621c0a45380bcb5bc9b14a236680180a042258fac8aae0c9e1dd0ec39787afd536b51527426964ccbc2ddc1ae16b0d6f11d9241d1cb53b94e0e989e1624568bb59dea3cce55fd0b21696e6153034d29e5144b91afaebbc1ca28e9eacaa694821f267617c5cc3b5812f914315097b210e50c31cccc33dcc3310166b0c3a00a800e11be916b0e02875105e99127e4b458784594de119c5be391096f4f245bd3e19ce16a035f8f784a255e4b91bf5af58e6c8b25b0ea151a74c9000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000033090fc05f8e16cae75f332ebd31bb92135ee43028942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61293b778ea3a0add86d973685193aac98de614c89ed36878548b7e2a4abb37bf244289929b41c2ca77197403e44de06d465b59e36f189cbff475f4507f7676d0080338e4831274e7ebb54e58c60ad99e45273c61a7e8928f22a52784987e49d61d915117aeeeeeb6619849969af3e29831e98e5fef5b7ee074710aa86a76bd1c27b1e5fb6cd2e22786fce1f03564cdc8c1ed37a9a7d8f036351132437c16c2bf1edf147d96e5946d37803b5b60606971186736514563b075e15c871aa8072f552659fc082dc7dde5907057306ea98d5c1d82a96fc92a5ccd31fed314579e5ce92e1c0ef05de09ea78c2b62c8b4b51b33235fbea7ec6cd6fb6678ba6a81ecfb0b09b380a270901fe8ecf3b5c8875cfafcefc3ac58e44d7233756d97e0844234f5000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006a63428000c4d1f428c3a7546dbc2b897336304a28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae612cd2880f852b8d726ec68101fa2ee3011c46c3e3c111a39db1356bba256244c2b88c6ff827347a3a00d18c54feff6f30519ac8f95a4851f05c148b15072f8b20aa1e91b77afa9bbd05aef46c2b90b138a1e6117c9d87a73f682e5db6ae890232a5a58a0063bd20022baba8317a33105e3f9ed5ff9786fe114c8bcf9c93d8d092bcda239c922faf406ae57773acab2fadebcf4fde5763153fabdbf198c36146010a39e592415cd62fc4eefe6e6f00c24aee3c626c1d8e4efe0ff664324d172441e993b5f28bb82d89c318f23c0c8b34b8d3d22fa692be9918ecc1e813144be9b014021eb71ccc2649f3a3c0cb7b56eccc633b41daee6f51fc3acca801201a69620784e86e0894942c024878b4b0040040851c2bf0ca42b34381e95fc28e28a28000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000e38fb18ff3738c39b1d9f9352f2468c4426ce4ae28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61c4102b911ae374a542f5c3c2629332d107f87c9d7f084e58ad6686b8ca032d02e4945598231c20938d0af0ce8567fb69936139c2ba3d6e8e1d9c7d986367a9f29a32ba151998a6732af0747596e22828161d91a3a92ed6664a99b7a0d988c2302b6f9af088ccf5d117a451d93d5b97a4555853aae24178279175905606d3af91c3f6e575377a0504d03e34de54894bc2caec9be3dac382a8d39be54a37069442f58d5cedd52832dddece59733cd2b4a6d370681b5a48b52bc76667902f20c0d1011a2c4396ef44f6003ae3bfb73948a1ecfa6f1855984b0d211ac0f4870a7682cd9ba5ecf6858e550b4fdc10893a899d9bc5327885047c271380499c3c0a7f51be5923b17ea743f23538d8b463fd7d142301174b8b9253f11b7e74310b4c17d000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb00000000000000000000000000000000000000000000000000000000000000230000000000000000000000006d012fe8cdfd1b3db63e95c8d7a06dc9e0b66aef28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae61f92267a1575d60651f0ca0a74d2ab67989f3ccc976b18246b504fca3df8cef31db8c4f95b1afeb35f826a69dca4995c5d2efcf3e9e459bbf99cca255ca1e8ea08c230b042609463c274ed7e6439e545d730c770ff035643c98c03bc419ef0c82eb48d9897932b8f919dc0684164b261d640c0a25e7064de8413beeb515d95121b47662c8e2fc34190f77919fa05e41226a1fa236d464cdd0c46e5d0822fdb4226ab9297b1ac2763b87897e4001bb5fd117ba894621c4f19291b31e074f4614523259e4884d735dbd2f0be3a5e687ccd4824a0a501cc311578f49a13b82beb0e18f3a1aca9688d95856c04b6a6c453397b08301bbb222c83e0a5ef28a116dce41c8ee0133596865178948427ffbfacf1856dbf317bc0d10ecb2ca1aa33dee293000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb000000000000000000000000000000000000000000000000000000000000002300000000000000000000000049c0d6a9e6f273c4494f3568e55d0a313c2edcfc28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae612c4c6415c49c164f8c81c76939fde44b1e6619d1946eb673ac203903dc36a00001c8c09a245beacc76f69f41def1da2219a0cd1ea328134e3aba603e29770fc1ef007c81d6fec56f2f1633d4a5f0b185fad2f719a8b92c624c1441eb2a2f9633020b4b1a0c2a6b16dea1fe908f0d5ab7c2d6f9d7ab50abd9135c25936c317a200f31f339962c0bba6bf3878088ee151d5163df24097350d02cc00f3d5f3a2e316554592f12df06777fc2eeb343641083f6299f66bd6f6f4ae3c125da8cc15680d35cfdfc71d15f59e6e37bae016dfc96da646aea2fbdba7be6fd334c53490ee008c2f1d877ed983a8afe7f98529da6e8186cb1874695070aeb5dc126d4235ad1fd76af0b23372d37b7f5181db3da8d2a46848cf4a473d55ccd23def6db02d46000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000485d8a98bb5dc09f1735aecbc8144ab2db7b545428942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae60543198b027d09bba2e1a841d4d3abd89256be8b84db977f5f651fbadf879efa05b9205ea53264deb3985cd04a071d90646a7f7f598d2caf2d2d005ad498943e15e5e0bbe91d868a0ee665e0651f8ffb6c6d2ac509c43d5bb53d805bc6c15f6d06909f64060d8c1a9519cf2b2c06a4542594ef2c3f03628ab85816700d9e6d4115ae7319fb08e0d7cc7755a766fe2be37a6f41332c900b23330c78cfb42e965b0fb6968782b33ec1dc44e79704c6eab3264b4a1a95caa47f3c1eeba76ab83dea260c18ce79fef579dacdc214b521666a9cb9c5ecd0ef82199e2b045ab073bd0926ccbdd591bacf2f04ce8b13437ec5ee71061c37a3bbd68879e0917ddf157ff5082b9767119e087ee6979a6ba346d99a2f6755aab877b680bd1973b7e6c96563000000000000000000000000000000000000000000000000000000000000000000000000000000007b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184a41e6ceb0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000231a2f44fde5788ee99c2ea163be421714ee47fc28942a4cc38d6ce636ded96f848bf0f3f547664e91b63f3daa080fbebc7d6ae624bd26434331113463b0801bad03295369f09b001551e3039be9a5c86f7c463d0fdd76dae5e472d7738264ac9db2ef6179e1d90a2e2f7931de1b862d24e4cacc171d8f1057095e652a2276423f70ec952dc43abb32bc72ca8080ae10451098b40aca120d5b8822848412087d67b40498eeab7246254d95db1b49b2b77838bee02597c0796b870fe29d3e0fcb8cd2d3148cc5d29ac0e0fe3cc1b42310b6f06cc90f771c1c8425d1e6ee1929cbc01986def1ea012780d606b41cf378682c9a0a2a13e44d09eac7239b532e1c5d99fc76a5b0c0e184edc31aea2b1ded286a8b7b8b1b8c744c3b5b68a413b7710a4106993e0e3aa97c148bbc46e7bd475e4a4a0bf71a64ba3b34be6656b6760ccd4b3c080019735cbf852cd50a5608d56ead05ffe900000000000000000000000000000000000000000000000000000000c080a0f613146bcf55b47f690f88aa4d95f8e188b28065b0ddbd49f689c7776a4049b3a00b4d55033092f80ca9df1123c6437f52372e2548cb8fbeca54722d9fe760e3c2").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717730355, + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + withdrawals: Default::default(), + prev_randao: b256!( + "c7acc30c856d749a81902d811e879e8dae5de2e022091aaa7eb4b586dcd3d052" + ), + parent_beacon_block_root: Some(b256!( + "a4414c4984ce7285b82bd9b21c642af30f0f648fb6f4929b67753e7345a06bab" + )), + }, gas_limit: Some(30_000_000), - timestamp: 1717730355, - prev_randao: b256!("c7acc30c856d749a81902d811e879e8dae5de2e022091aaa7eb4b586dcd3d052"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "a4414c4984ce7285b82bd9b21c642af30f0f648fb6f4929b67753e7345a06bab" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: Some(false), }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); @@ -1024,17 +1065,21 @@ mod test { hex!("02f904da0a83012933830f424084045e2f258305e39c9400000000fc04c910a0b5fea33b03e0447ad0b0aa8702e5763b5ce075b90464a44c9ce7000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff5f082dbf2d2f930eb3d2b51bb2f1010a4d5a8900000000000000000000000000000000fcb080a4d6c39a9354da9eb9bc104cd7000000000000000000000000000000000000000000000000000000006664a0bd00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000041819edf15e18a545cbbabbd24c9f3e136a3dcec10c65f5ce19d6fb903e586e6db5f2e154210d25768487e89cb7d9b62cc611421c3456538c7d9ac39f0fd619e111c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000006664a0bd000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000205183a065a3c67e765796c2969e67b960d2ae041a36070a7ed719b18b5682bdda0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000002ef790dd7993a35fd847c053eddae940d0555960000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000006664a0bd0000000000000000000000000000000000000000000000000000000000000041dd6bb97a2c5250e07ba4b0df71715c81ac9adc5ee1111a0f8ff3845321ac7d5262a7cdd80df46391bc4e41b5f1492110a42badfb7b6ebdd8944e2c3c9a9d8e621c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d5ae1701d2a1750e608e1f2b5d10280db952ddb14cc35f819f7334e9eb5133a5072108be5f5134ac6c061fa9e3bcee464ad8c8e13e206cd5c6b632a7294cd34b1c00000000000000000000000000000000000000000000000000000000000000c001a0994107041475defdb265cdbe6da3df610516ec50a81dd9c0a3602c20d1c72b22a04b28a32d391ebdc15e63ffd26dc3a91e6c3c0565538e33e04558a9d1c9d70b3f").into(), hex!("02f8b50a01830f424084045a3cc98306213f942a5c54c625220cb2166c94dd9329be1f8785977d866e5ceb32785cb844f5c358c60000000000000000000000000000000000000000000000000000000000000504000000000000000000000000000000000000000000000000000000000263b143c001a051a2584f761c7ef2216652d41840cb1e84c0576d076c72f06906777cb043d45aa02bdbb191600306e5f3ff6d65991f61979f8a10d60d0c6ccaaf1f6d5c7515dac2").into() ]; - let payload_attrs = L2PayloadAttributes { - fee_recipient: address!("4200000000000000000000000000000000000011"), + let payload_attrs = OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1717870185, + prev_randao: b256!( + "23b3d2cb1b7216ef94837fdf94767b6235ce735a19de4f3feee7c1d603f2d10b" + ), + withdrawals: Default::default(), + suggested_fee_recipient: address!("4200000000000000000000000000000000000011"), + parent_beacon_block_root: Some(b256!( + "8ab0d68c0fc4fe40d31baf01bcf73de45ddf15ab58e66738ca6c60648676f9af" + )), + }, gas_limit: Some(30_000_000), - timestamp: 1717870185, - prev_randao: b256!("23b3d2cb1b7216ef94837fdf94767b6235ce735a19de4f3feee7c1d603f2d10b"), - withdrawals: Default::default(), - parent_beacon_block_root: Some(b256!( - "8ab0d68c0fc4fe40d31baf01bcf73de45ddf15ab58e66738ca6c60648676f9af" - )), - transactions: raw_txs, - no_tx_pool: false, + transactions: Some(raw_txs), + no_tx_pool: None, }; let produced_header = l2_block_executor.execute_payload(payload_attrs).unwrap().clone(); diff --git a/crates/primitives/src/attributes.rs b/crates/primitives/src/attributes.rs deleted file mode 100644 index 2a2af904..00000000 --- a/crates/primitives/src/attributes.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Contains Payload Attribute Types. - -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - -use alloc::vec::Vec; -use alloy_eips::eip4895::Withdrawal; -use alloy_primitives::{Address, Bytes, B256}; -use op_alloy_protocol::L2BlockInfo; - -/// Payload attributes. -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Debug, Default, Clone, Hash, PartialEq, Eq)] -pub struct L2PayloadAttributes { - /// Value for the timestamp field of the new payload. - #[cfg_attr(feature = "serde", serde(rename = "timestamp"))] - pub timestamp: u64, - /// Value for the random field of the new payload. - #[cfg_attr(feature = "serde", serde(rename = "prevRandao"))] - pub prev_randao: B256, - /// Suggested value for the coinbase field of the new payload. - #[cfg_attr(feature = "serde", serde(rename = "suggestedFeeRecipient"))] - pub fee_recipient: Address, - /// Withdrawals to include into the block -- should be nil or empty depending on Shanghai - /// enablement. - #[cfg_attr(feature = "serde", serde(rename = "withdrawals"))] - pub withdrawals: Option>, - /// Parent beacon block root optional extension in Dencun. - #[cfg_attr(feature = "serde", serde(rename = "parentBeaconBlockRoot"))] - pub parent_beacon_block_root: Option, - - // Optimism additions. - /// Transactions to force into the block (always at the start of the transactions list). - #[cfg_attr(feature = "serde", serde(rename = "transactions"))] - pub transactions: Vec, - /// NoTxPool to disable adding any transactions from the transaction-pool. - #[cfg_attr(feature = "serde", serde(rename = "noTxPool"))] - pub no_tx_pool: bool, - /// GasLimit override. - #[cfg_attr(feature = "serde", serde(rename = "gasLimit"))] - pub gas_limit: Option, -} - -/// Payload Attributes with parent block reference. -#[derive(Debug, Clone, PartialEq)] -pub struct L2AttributesWithParent { - /// The payload attributes. - pub attributes: L2PayloadAttributes, - /// The parent block reference. - pub parent: L2BlockInfo, - /// Whether the current batch is the last in its span. - pub is_last_in_span: bool, -} - -impl L2AttributesWithParent { - /// Create a new [L2AttributesWithParent] instance. - pub fn new( - attributes: L2PayloadAttributes, - parent: L2BlockInfo, - is_last_in_span: bool, - ) -> Self { - Self { attributes, parent, is_last_in_span } - } - - /// Returns the payload attributes. - pub fn attributes(&self) -> &L2PayloadAttributes { - &self.attributes - } - - /// Returns the parent block reference. - pub fn parent(&self) -> &L2BlockInfo { - &self.parent - } - - /// Returns whether the current batch is the last in its span. - pub fn is_last_in_span(&self) -> bool { - self.is_last_in_span - } -} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index aa1703bc..bf28f003 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -15,9 +15,6 @@ pub use payload::{ L2ExecutionPayload, L2ExecutionPayloadEnvelope, PAYLOAD_MEM_FIXED_COST, PAYLOAD_TX_MEM_OVERHEAD, }; -pub mod attributes; -pub use attributes::{L2AttributesWithParent, L2PayloadAttributes}; - pub mod blob; pub use blob::{BlobData, BlobDecodingError, IndexedBlobHash}; diff --git a/examples/trusted-sync/Cargo.toml b/examples/trusted-sync/Cargo.toml index 230bc7f5..0ccee725 100644 --- a/examples/trusted-sync/Cargo.toml +++ b/examples/trusted-sync/Cargo.toml @@ -34,3 +34,5 @@ alloy-primitives = { workspace = true, features = ["serde"] } alloy-provider = { workspace = true, default-features = false } alloy-transport = { workspace = true, default-features = false } op-alloy-genesis.workspace = true +op-alloy-rpc-types-engine.workspace = true +alloy-rpc-types-engine.workspace = true diff --git a/examples/trusted-sync/src/main.rs b/examples/trusted-sync/src/main.rs index 2e721339..fb4a8756 100644 --- a/examples/trusted-sync/src/main.rs +++ b/examples/trusted-sync/src/main.rs @@ -283,7 +283,7 @@ async fn sync(cli: cli::Cli) -> Result<()> { "Validated Payload Attributes {} [L2 Block Num: {}] [L2 Timestamp: {}] [L1 Origin Block Num: {:?}]", metrics::DERIVED_ATTRIBUTES_COUNT.get(), derived, - attributes.attributes.timestamp, + attributes.attributes.payload_attributes.timestamp, pipeline.origin().map(|n| n.number), ); } diff --git a/examples/trusted-sync/src/validation.rs b/examples/trusted-sync/src/validation.rs index 387506ea..f26d52f1 100644 --- a/examples/trusted-sync/src/validation.rs +++ b/examples/trusted-sync/src/validation.rs @@ -3,16 +3,17 @@ use alloy_primitives::Bytes; use alloy_provider::{Provider, ReqwestProvider}; use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind, Header}; +use alloy_rpc_types_engine::PayloadAttributes; use alloy_transport::TransportResult; use anyhow::Result; -use kona_primitives::{L2AttributesWithParent, L2PayloadAttributes}; use op_alloy_genesis::RollupConfig; +use op_alloy_rpc_types_engine::{OptimismAttributesWithParent, OptimismPayloadAttributes}; use std::vec::Vec; use tracing::{error, warn}; /// OnlineValidator /// -/// Validates the [`L2AttributesWithParent`] by fetching the associated L2 block from +/// Validates the [`OptimismAttributesWithParent`] 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 { @@ -62,26 +63,31 @@ impl OnlineValidator { } /// Gets the payload for the specified [BlockNumberOrTag]. - pub(crate) async fn get_payload(&self, tag: BlockNumberOrTag) -> Result { + pub(crate) async fn get_payload( + &self, + tag: BlockNumberOrTag, + ) -> Result { 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, *after* canyon (Shanghai) activation - withdrawals: (header.timestamp >= self.canyon_activation).then_some(Vec::default()), - parent_beacon_block_root: header.parent_beacon_block_root, - transactions, - no_tx_pool: true, + Ok(OptimismPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: header.timestamp, + suggested_fee_recipient: header.miner, + prev_randao: header.mix_hash.unwrap_or_default(), + // Withdrawals on optimism are always empty, *after* canyon (Shanghai) activation + withdrawals: (header.timestamp >= self.canyon_activation).then_some(Vec::default()), + parent_beacon_block_root: header.parent_beacon_block_root, + }, + transactions: Some(transactions), + no_tx_pool: Some(true), gas_limit: Some(header.gas_limit as u64), }) } - /// Validates the given [`L2AttributesWithParent`]. + /// Validates the given [`OptimismAttributesWithParent`]. pub async fn validate( &self, - attributes: &L2AttributesWithParent, - ) -> Result<(bool, L2PayloadAttributes)> { + attributes: &OptimismAttributesWithParent, + ) -> Result<(bool, OptimismPayloadAttributes)> { let expected = attributes.parent.block_info.number + 1; let tag = BlockNumberOrTag::from(expected); match self.get_payload(tag).await {