From 9a467ed5ba7fdff0518356e816a9dbd3c44604ea Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 13:54:16 -0500 Subject: [PATCH 01/11] canyon withdrawal formatting --- src/config/mod.rs | 10 ++++++++++ src/derive/stages/attributes.rs | 7 +++++++ src/engine/payload.rs | 4 ++++ 3 files changed, 21 insertions(+) diff --git a/src/config/mod.rs b/src/config/mod.rs index e3f86455..369c5747 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -141,6 +141,8 @@ pub struct ChainConfig { pub max_seq_drift: u64, /// Timestamp of the regolith hardfork pub regolith_time: u64, + /// Timestamp of the canyon hardfork + pub canyon_time: u64, /// Network blocktime #[serde(default = "default_blocktime")] pub blocktime: u64, @@ -252,6 +254,7 @@ impl ChainConfig { max_seq_drift: 600, blocktime: 2, regolith_time: 0, + canyon_time: u64::MAX, } } @@ -289,6 +292,7 @@ impl ChainConfig { seq_window_size: 3600, max_seq_drift: 600, regolith_time: 1679079600, + canyon_time: 1699981200, blocktime: 2, } } @@ -326,6 +330,7 @@ impl ChainConfig { seq_window_size: 3600, max_seq_drift: 600, regolith_time: 0, + canyon_time: 1699981200, blocktime: 2, } } @@ -363,6 +368,7 @@ impl ChainConfig { max_seq_drift: 600, blocktime: 2, regolith_time: 0, + canyon_time: u64::MAX, } } @@ -398,6 +404,7 @@ impl ChainConfig { seq_window_size: 3600, max_seq_drift: 600, regolith_time: 1683219600, + canyon_time: 1699981200, blocktime: 2, } } @@ -440,6 +447,7 @@ pub struct ExternalChainConfig { l1_chain_id: u64, l2_chain_id: u64, regolith_time: u64, + canyon_time: u64, batch_inbox_address: Address, deposit_contract_address: Address, l1_system_config_address: Address, @@ -501,6 +509,7 @@ impl From for ChainConfig { seq_window_size: external.seq_window_size, max_seq_drift: external.max_sequencer_drift, regolith_time: external.regolith_time, + canyon_time: external.canyon_time, blocktime: external.block_time, l2_to_l1_message_passer: addr("0x4200000000000000000000000000000000000016"), } @@ -546,6 +555,7 @@ impl From for ExternalChainConfig { l1_chain_id: chain_config.l1_chain_id, l2_chain_id: chain_config.l2_chain_id, regolith_time: chain_config.regolith_time, + canyon_time: chain_config.canyon_time, batch_inbox_address: chain_config.batch_inbox, deposit_contract_address: chain_config.deposit_contract, l1_system_config_address: chain_config.system_config_contract, diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 257bbe6f..7f684bff 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -74,6 +74,12 @@ impl Attributes { timestamp: l1_info.block_info.timestamp, }); + let withdrawals = if batch.timestamp >= self.config.chain.canyon_time { + Some(Vec::new()) + } else { + None + }; + let timestamp = U64([batch.timestamp]); let l1_inclusion_block = Some(batch.l1_inclusion_block); let seq_number = Some(self.sequence_number); @@ -88,6 +94,7 @@ impl Attributes { transactions, no_tx_pool: true, gas_limit: U64([l1_info.system_config.gas_limit.as_u64()]), + withdrawals, epoch, l1_inclusion_block, seq_number, diff --git a/src/engine/payload.rs b/src/engine/payload.rs index a4107dba..86ebc094 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -97,6 +97,10 @@ pub struct PayloadAttributes { /// This field overrides the gas limit used during block-building. /// If not specified as rollup, a STATUS_INVALID is returned. pub gas_limit: U64, + /// Beaconchain withdrawals. This exists only for compatibility with L1, and is not used. Prior + /// to Canyon, this value is always None. After Canyon it is an empty array. Note that we use + /// the () type here since we never have a non empty array. + pub withdrawals: Option>, /// The batch epoch number from derivation. This value is not expected by the engine is skipped /// during serialization and deserialization. #[serde(skip)] From 9f706d2f0a38c49637c364c819ca346a7d037612 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 15:18:56 -0500 Subject: [PATCH 02/11] bump op-geth docker version --- docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 4bfe46e1..964a6f92 100755 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -33,7 +33,7 @@ services: <<: *logging op-geth: - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101304.1 + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101304.2 container_name: op-geth profiles: - op-geth From 363cb107014b6607715d954b4d6fd0995ec9197e Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 16:49:32 -0500 Subject: [PATCH 03/11] migrate to engine api V2 --- bin/network.rs | 4 +- src/driver/mod.rs | 4 +- src/engine/api.rs | 10 ++-- src/engine/payload.rs | 3 ++ src/engine/types.rs | 9 ++-- src/network/handlers/block_handler.rs | 72 +++++++++++++++++++++++---- 6 files changed, 78 insertions(+), 24 deletions(-) diff --git a/bin/network.rs b/bin/network.rs index 4b6a38e5..84e1de81 100644 --- a/bin/network.rs +++ b/bin/network.rs @@ -4,7 +4,7 @@ use ethers::types::Address; use eyre::Result; use magi::{ - network::{handlers::block_handler::BlockHandler, service::Service}, + network::{handlers::block_handler::BlockHandlerV1, service::Service}, telemetry, }; use tokio::sync::watch; @@ -18,7 +18,7 @@ async fn main() -> Result<()> { let (_, recv) = watch::channel(Address::from_str( "0x715b7219d986641df9efd9c7ef01218d528e19ec", )?); - let (block_handler, block_recv) = BlockHandler::new(chain_id, recv); + let (block_handler, block_recv) = BlockHandlerV1::new(chain_id, recv); Service::new(addr, chain_id) .add_handler(Box::new(block_handler)) diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 4553d036..c02cef47 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -21,7 +21,7 @@ use crate::{ derive::{state::State, Pipeline}, engine::{Engine, EngineApi, ExecutionPayload}, l1::{BlockUpdate, ChainWatcher}, - network::{handlers::block_handler::BlockHandler, service::Service}, + network::{handlers::block_handler::BlockHandlerV1, service::Service}, rpc, telemetry::metrics, }; @@ -103,7 +103,7 @@ impl Driver { watch::channel(config.chain.system_config.unsafe_block_signer); let (block_handler, unsafe_block_recv) = - BlockHandler::new(config.chain.l2_chain_id, unsafe_block_signer_recv); + BlockHandlerV1::new(config.chain.l2_chain_id, unsafe_block_signer_recv); let service = Service::new("0.0.0.0:9876".parse()?, config.chain.l2_chain_id) .add_handler(Box::new(block_handler)); diff --git a/src/engine/api.rs b/src/engine/api.rs index f3e9cc91..6eb5e78d 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -11,11 +11,11 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::engine::DEFAULT_AUTH_PORT; -use crate::engine::ENGINE_GET_PAYLOAD_V1; use super::{ Engine, ExecutionPayload, ForkChoiceUpdate, ForkchoiceState, JwtSecret, PayloadAttributes, - PayloadId, PayloadStatus, ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_NEW_PAYLOAD_V1, + PayloadId, PayloadStatus, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_GET_PAYLOAD_V2, + ENGINE_NEW_PAYLOAD_V2, }; use super::{JSONRPC_VERSION, STATIC_ID}; @@ -217,13 +217,13 @@ impl Engine for EngineApi { }; let forkchoice_state_param = serde_json::to_value(forkchoice_state)?; let params = vec![forkchoice_state_param, payload_attributes_param]; - let res = self.post(ENGINE_FORKCHOICE_UPDATED_V1, params).await?; + let res = self.post(ENGINE_FORKCHOICE_UPDATED_V2, params).await?; Ok(res) } async fn new_payload(&self, execution_payload: ExecutionPayload) -> Result { let params = vec![serde_json::to_value(execution_payload)?]; - let res = self.post(ENGINE_NEW_PAYLOAD_V1, params).await?; + let res = self.post(ENGINE_NEW_PAYLOAD_V2, params).await?; Ok(res) } @@ -231,7 +231,7 @@ impl Engine for EngineApi { let encoded = format!("{:x}", payload_id); let padded = format!("0x{:0>16}", encoded); let params = vec![Value::String(padded)]; - let res = self.post(ENGINE_GET_PAYLOAD_V1, params).await?; + let res = self.post(ENGINE_GET_PAYLOAD_V2, params).await?; Ok(res) } } diff --git a/src/engine/payload.rs b/src/engine/payload.rs index 86ebc094..b1a838da 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -39,6 +39,8 @@ pub struct ExecutionPayload { pub block_hash: H256, /// An array of transaction objects where each object is a byte list pub transactions: Vec, + /// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility + pub withdrawals: Vec<()>, } impl TryFrom> for ExecutionPayload { @@ -71,6 +73,7 @@ impl TryFrom> for ExecutionPayload { .into(), block_hash: value.hash.unwrap(), transactions: encoded_txs, + withdrawals: Vec::new(), }) } } diff --git a/src/engine/types.rs b/src/engine/types.rs index a3b563e8..9bae9bf2 100644 --- a/src/engine/types.rs +++ b/src/engine/types.rs @@ -10,22 +10,19 @@ pub const STATIC_ID: u32 = 1; pub const JSONRPC_VERSION: &str = "2.0"; /// The new payload method string -pub const ENGINE_NEW_PAYLOAD_V1: &str = "engine_newPayloadV1"; -// pub const ENGINE_NEW_PAYLOAD_V2: &str = "engine_newPayloadV2"; +pub const ENGINE_NEW_PAYLOAD_V2: &str = "engine_newPayloadV2"; /// The new payload timeout pub const ENGINE_NEW_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(8); /// The get payload method string -pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1"; -// pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2"; +pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2"; /// The get payload timeout pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2); /// The forkchoice updated method string -pub const ENGINE_FORKCHOICE_UPDATED_V1: &str = "engine_forkchoiceUpdatedV1"; -// pub const ENGINE_FORKCHOICE_UPDATED_V2: &str = "engine_forkchoiceUpdatedV2"; +pub const ENGINE_FORKCHOICE_UPDATED_V2: &str = "engine_forkchoiceUpdatedV2"; /// The forkchoice updated timeout pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8); diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 3b4dc499..cee5e32f 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -12,17 +12,17 @@ use crate::{common::RawTransaction, engine::ExecutionPayload}; use super::Handler; -pub struct BlockHandler { +pub struct BlockHandlerV1 { chain_id: u64, block_sender: Sender, unsafe_signer_recv: watch::Receiver
, } -impl Handler for BlockHandler { +impl Handler for BlockHandlerV1 { fn handle(&self, msg: Message) -> MessageAcceptance { tracing::debug!("received block"); - match decode_block_msg(msg.data) { + match decode_block_msg::(msg.data) { Ok((payload, signature, payload_hash)) => { if self.block_valid(&payload, signature, payload_hash) { _ = self.block_sender.send(payload); @@ -44,7 +44,7 @@ impl Handler for BlockHandler { } } -impl BlockHandler { +impl BlockHandlerV1 { pub fn new( chain_id: u64, unsafe_recv: watch::Receiver
, @@ -83,7 +83,11 @@ impl BlockHandler { } } -fn decode_block_msg(data: Vec) -> Result<(ExecutionPayload, Signature, PayloadHash)> { +fn decode_block_msg(data: Vec) -> Result<(ExecutionPayload, Signature, PayloadHash)> +where + T: SimpleSerialize, + ExecutionPayload: From, +{ let mut decoder = snap::raw::Decoder::new(); let decompressed = decoder.decompress_vec(&data)?; let sig_data = &decompressed[..65]; @@ -91,7 +95,7 @@ fn decode_block_msg(data: Vec) -> Result<(ExecutionPayload, Signature, Paylo let signature = Signature::try_from(sig_data)?; - let payload: ExecutionPayloadSSZ = deserialize(block_data)?; + let payload: T = deserialize(block_data)?; let payload: ExecutionPayload = ExecutionPayload::from(payload); let payload_hash = PayloadHash::from(block_data); @@ -129,7 +133,7 @@ type VecAddress = Vector; type Transaction = List; #[derive(SimpleSerialize, Default)] -struct ExecutionPayloadSSZ { +struct ExecutionPayloadV1SSZ { pub parent_hash: Bytes32, pub fee_recipient: VecAddress, pub state_root: Bytes32, @@ -146,8 +150,8 @@ struct ExecutionPayloadSSZ { pub transactions: List, } -impl From for ExecutionPayload { - fn from(value: ExecutionPayloadSSZ) -> Self { +impl From for ExecutionPayload { + fn from(value: ExecutionPayloadV1SSZ) -> Self { Self { parent_hash: convert_hash(value.parent_hash), fee_recipient: convert_address(value.fee_recipient), @@ -163,6 +167,56 @@ impl From for ExecutionPayload { base_fee_per_gas: convert_uint(value.base_fee_per_gas), block_hash: convert_hash(value.block_hash), transactions: convert_tx_list(value.transactions), + withdrawals: Vec::new(), + } + } +} + +#[derive(SimpleSerialize, Default)] +struct ExecutionPayloadV2SSZ { + pub parent_hash: Bytes32, + pub fee_recipient: VecAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: Vector, + pub prev_randao: Bytes32, + pub block_number: u64, + pub gas_limit: u64, + pub gas_used: u64, + pub timestamp: u64, + pub extra_data: List, + pub base_fee_per_gas: U256, + pub block_hash: Bytes32, + pub transactions: List, + pub withdrawals: List, +} + +#[derive(SimpleSerialize, Default)] +struct Withdrawal { + index: u64, + validator_index: u64, + address: VecAddress, + amount: u64, +} + +impl From for ExecutionPayload { + fn from(value: ExecutionPayloadV2SSZ) -> Self { + Self { + parent_hash: convert_hash(value.parent_hash), + fee_recipient: convert_address(value.fee_recipient), + state_root: convert_hash(value.state_root), + receipts_root: convert_hash(value.receipts_root), + logs_bloom: convert_byte_vector(value.logs_bloom), + prev_randao: convert_hash(value.prev_randao), + block_number: value.block_number.into(), + gas_limit: value.gas_limit.into(), + gas_used: value.gas_used.into(), + timestamp: value.timestamp.into(), + extra_data: convert_byte_list(value.extra_data), + base_fee_per_gas: convert_uint(value.base_fee_per_gas), + block_hash: convert_hash(value.block_hash), + transactions: convert_tx_list(value.transactions), + withdrawals: Vec::new(), } } } From 88d97e130d14af042279e2980103d37478ca9881 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 16:59:30 -0500 Subject: [PATCH 04/11] make execution payload backwards compatible with v1 --- src/engine/payload.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/payload.rs b/src/engine/payload.rs index b1a838da..50eb4a83 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -40,6 +40,7 @@ pub struct ExecutionPayload { /// An array of transaction objects where each object is a byte list pub transactions: Vec, /// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility + #[serde(default)] pub withdrawals: Vec<()>, } From f2c12b50185d855e9f9dfc4ccfa5ca929918a103 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 17:10:44 -0500 Subject: [PATCH 05/11] fix get_payload response type --- src/engine/api.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/engine/api.rs b/src/engine/api.rs index 6eb5e78d..71977be5 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -231,11 +231,17 @@ impl Engine for EngineApi { let encoded = format!("{:x}", payload_id); let padded = format!("0x{:0>16}", encoded); let params = vec![Value::String(padded)]; - let res = self.post(ENGINE_GET_PAYLOAD_V2, params).await?; - Ok(res) + let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; + Ok(res.execution_payload) } } +#[derive(Debug, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +struct GetPayloadResponse { + execution_payload: ExecutionPayload, +} + #[cfg(test)] mod tests { use std::time::SystemTime; From 11ae394916c49f18181f78c3890cf5527c8de802 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 17:21:05 -0500 Subject: [PATCH 06/11] debug --- src/engine/api.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engine/api.rs b/src/engine/api.rs index 71977be5..03fce2cd 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -231,8 +231,10 @@ impl Engine for EngineApi { let encoded = format!("{:x}", payload_id); let padded = format!("0x{:0>16}", encoded); let params = vec![Value::String(padded)]; - let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; - Ok(res.execution_payload) + let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; + println!("{:?}", res); + panic!(); + // Ok(res.execution_payload) } } From f0ab83f8d6721f3ac03d5ff8901ae579466d8eea Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 17:29:41 -0500 Subject: [PATCH 07/11] fix payload deserialization --- src/engine/api.rs | 6 ++---- src/engine/payload.rs | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/engine/api.rs b/src/engine/api.rs index 03fce2cd..71977be5 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -231,10 +231,8 @@ impl Engine for EngineApi { let encoded = format!("{:x}", payload_id); let padded = format!("0x{:0>16}", encoded); let params = vec![Value::String(padded)]; - let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; - println!("{:?}", res); - panic!(); - // Ok(res.execution_payload) + let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; + Ok(res.execution_payload) } } diff --git a/src/engine/payload.rs b/src/engine/payload.rs index 50eb4a83..ffab1862 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -1,6 +1,6 @@ use ethers::types::{Block, Bytes, Transaction, H160, H256, U64}; use eyre::Result; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Deserializer}; use crate::{ common::{Epoch, RawTransaction}, @@ -40,10 +40,20 @@ pub struct ExecutionPayload { /// An array of transaction objects where each object is a byte list pub transactions: Vec, /// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility - #[serde(default)] + #[serde(default, deserialize_with = "default_on_null")] pub withdrawals: Vec<()>, } +fn default_on_null<'de, D, T>(d: D) -> Result +where + D: Deserializer<'de>, + T: Default + Deserialize<'de>, +{ + let opt = Option::deserialize(d)?; + let val = opt.unwrap_or_else(T::default); + Ok(val) +} + impl TryFrom> for ExecutionPayload { type Error = eyre::Report; From 44ebdf0281be504abd6d33968c4d66d43230a9c7 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 17:38:10 -0500 Subject: [PATCH 08/11] fix payload --- src/engine/payload.rs | 18 ++++-------------- src/network/handlers/block_handler.rs | 4 ++-- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/engine/payload.rs b/src/engine/payload.rs index ffab1862..52b75125 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -1,6 +1,6 @@ use ethers::types::{Block, Bytes, Transaction, H160, H256, U64}; use eyre::Result; -use serde::{Deserialize, Serialize, Deserializer}; +use serde::{Deserialize, Serialize}; use crate::{ common::{Epoch, RawTransaction}, @@ -40,18 +40,8 @@ pub struct ExecutionPayload { /// An array of transaction objects where each object is a byte list pub transactions: Vec, /// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility - #[serde(default, deserialize_with = "default_on_null")] - pub withdrawals: Vec<()>, -} - -fn default_on_null<'de, D, T>(d: D) -> Result -where - D: Deserializer<'de>, - T: Default + Deserialize<'de>, -{ - let opt = Option::deserialize(d)?; - let val = opt.unwrap_or_else(T::default); - Ok(val) + #[serde(skip_serializing_if = "Option::is_none")] + pub withdrawals: Option>, } impl TryFrom> for ExecutionPayload { @@ -84,7 +74,7 @@ impl TryFrom> for ExecutionPayload { .into(), block_hash: value.hash.unwrap(), transactions: encoded_txs, - withdrawals: Vec::new(), + withdrawals: Some(Vec::new()), }) } } diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index cee5e32f..99ee17c3 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -167,7 +167,7 @@ impl From for ExecutionPayload { base_fee_per_gas: convert_uint(value.base_fee_per_gas), block_hash: convert_hash(value.block_hash), transactions: convert_tx_list(value.transactions), - withdrawals: Vec::new(), + withdrawals: None, } } } @@ -216,7 +216,7 @@ impl From for ExecutionPayload { base_fee_per_gas: convert_uint(value.base_fee_per_gas), block_hash: convert_hash(value.block_hash), transactions: convert_tx_list(value.transactions), - withdrawals: Vec::new(), + withdrawals: Some(Vec::new()), } } } From 2adfcf61be5e8735513c073acb305f7afe25825b Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 18:09:57 -0500 Subject: [PATCH 09/11] implement blocks v2 gossip --- bin/network.rs | 4 ++-- src/driver/mod.rs | 4 ++-- src/engine/api.rs | 4 +++- src/network/handlers/block_handler.rs | 24 ++++++++++++++++++------ src/network/handlers/mod.rs | 2 +- src/network/service/discovery.rs | 2 +- src/network/service/mod.rs | 20 ++++++++++++++------ 7 files changed, 41 insertions(+), 19 deletions(-) diff --git a/bin/network.rs b/bin/network.rs index 84e1de81..4b6a38e5 100644 --- a/bin/network.rs +++ b/bin/network.rs @@ -4,7 +4,7 @@ use ethers::types::Address; use eyre::Result; use magi::{ - network::{handlers::block_handler::BlockHandlerV1, service::Service}, + network::{handlers::block_handler::BlockHandler, service::Service}, telemetry, }; use tokio::sync::watch; @@ -18,7 +18,7 @@ async fn main() -> Result<()> { let (_, recv) = watch::channel(Address::from_str( "0x715b7219d986641df9efd9c7ef01218d528e19ec", )?); - let (block_handler, block_recv) = BlockHandlerV1::new(chain_id, recv); + let (block_handler, block_recv) = BlockHandler::new(chain_id, recv); Service::new(addr, chain_id) .add_handler(Box::new(block_handler)) diff --git a/src/driver/mod.rs b/src/driver/mod.rs index c02cef47..4553d036 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -21,7 +21,7 @@ use crate::{ derive::{state::State, Pipeline}, engine::{Engine, EngineApi, ExecutionPayload}, l1::{BlockUpdate, ChainWatcher}, - network::{handlers::block_handler::BlockHandlerV1, service::Service}, + network::{handlers::block_handler::BlockHandler, service::Service}, rpc, telemetry::metrics, }; @@ -103,7 +103,7 @@ impl Driver { watch::channel(config.chain.system_config.unsafe_block_signer); let (block_handler, unsafe_block_recv) = - BlockHandlerV1::new(config.chain.l2_chain_id, unsafe_block_signer_recv); + BlockHandler::new(config.chain.l2_chain_id, unsafe_block_signer_recv); let service = Service::new("0.0.0.0:9876".parse()?, config.chain.l2_chain_id) .add_handler(Box::new(block_handler)); diff --git a/src/engine/api.rs b/src/engine/api.rs index 71977be5..64998c59 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -231,7 +231,9 @@ impl Engine for EngineApi { let encoded = format!("{:x}", payload_id); let padded = format!("0x{:0>16}", encoded); let params = vec![Value::String(padded)]; - let res = self.post::(ENGINE_GET_PAYLOAD_V2, params).await?; + let res = self + .post::(ENGINE_GET_PAYLOAD_V2, params) + .await?; Ok(res.execution_payload) } } diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 99ee17c3..7b97f7b2 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -12,17 +12,27 @@ use crate::{common::RawTransaction, engine::ExecutionPayload}; use super::Handler; -pub struct BlockHandlerV1 { +pub struct BlockHandler { chain_id: u64, block_sender: Sender, unsafe_signer_recv: watch::Receiver
, + blocks_v1_topic: IdentTopic, + blocks_v2_topic: IdentTopic, } -impl Handler for BlockHandlerV1 { +impl Handler for BlockHandler { fn handle(&self, msg: Message) -> MessageAcceptance { tracing::debug!("received block"); - match decode_block_msg::(msg.data) { + let decoded = if msg.topic == self.blocks_v1_topic.hash() { + decode_block_msg::(msg.data) + } else if msg.topic == self.blocks_v2_topic.hash() { + decode_block_msg::(msg.data) + } else { + return MessageAcceptance::Reject; + }; + + match decoded { Ok((payload, signature, payload_hash)) => { if self.block_valid(&payload, signature, payload_hash) { _ = self.block_sender.send(payload); @@ -39,12 +49,12 @@ impl Handler for BlockHandlerV1 { } } - fn topic(&self) -> TopicHash { - IdentTopic::new(format!("/optimism/{}/0/blocks", self.chain_id)).into() + fn topics(&self) -> Vec { + vec![self.blocks_v1_topic.hash(), self.blocks_v2_topic.hash()] } } -impl BlockHandlerV1 { +impl BlockHandler { pub fn new( chain_id: u64, unsafe_recv: watch::Receiver
, @@ -55,6 +65,8 @@ impl BlockHandlerV1 { chain_id, block_sender: sender, unsafe_signer_recv: unsafe_recv, + blocks_v1_topic: IdentTopic::new(format!("/optimism/{}/0/blocks", chain_id)).into(), + blocks_v2_topic: IdentTopic::new(format!("/optimism/{}/1/blocks", chain_id)).into(), }; (handler, recv) diff --git a/src/network/handlers/mod.rs b/src/network/handlers/mod.rs index 8f7db755..3ec9cb7b 100644 --- a/src/network/handlers/mod.rs +++ b/src/network/handlers/mod.rs @@ -4,5 +4,5 @@ pub mod block_handler; pub trait Handler: Send { fn handle(&self, msg: Message) -> MessageAcceptance; - fn topic(&self) -> TopicHash; + fn topics(&self) -> Vec; } diff --git a/src/network/service/discovery.rs b/src/network/service/discovery.rs index 82771992..85c70d39 100644 --- a/src/network/service/discovery.rs +++ b/src/network/service/discovery.rs @@ -44,7 +44,7 @@ pub fn start(addr: NetworkAddress, chain_id: u64) -> Result> { } } - sleep(Duration::from_secs(30)).await; + sleep(Duration::from_secs(10)).await; } }); diff --git a/src/network/service/mod.rs b/src/network/service/mod.rs index 1c3f13da..68fdaf2a 100644 --- a/src/network/service/mod.rs +++ b/src/network/service/mod.rs @@ -155,11 +155,17 @@ impl Behaviour { handlers .iter() - .map(|handler| { - let topic = IdentTopic::new(handler.topic().into_string()); - gossipsub - .subscribe(&topic) - .map_err(|_| eyre::eyre!("subscription failed")) + .flat_map(|handler| { + handler + .topics() + .iter() + .map(|topic| { + let topic = IdentTopic::new(topic.to_string()); + gossipsub + .subscribe(&topic) + .map_err(|_| eyre::eyre!("subscription failed")) + }) + .collect::>() }) .collect::>>()?; @@ -180,7 +186,9 @@ impl Event { message, }) = self { - let handler = handlers.iter().find(|h| h.topic() == message.topic); + let handler = handlers + .iter() + .find(|h| h.topics().contains(&message.topic)); if let Some(handler) = handler { let status = handler.handle(message); From a0c681f0adf242f15fdd9cd86b2a639f91bd01ec Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 18:30:11 -0500 Subject: [PATCH 10/11] fix tests --- src/config/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/mod.rs b/src/config/mod.rs index 369c5747..a09f7dcb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -682,6 +682,7 @@ mod test { "l1_chain_id": 900, "l2_chain_id": 901, "regolith_time": 0, + "canyon_time": 0, "batch_inbox_address": "0xff00000000000000000000000000000000000000", "deposit_contract_address": "0x6900000000000000000000000000000000000001", "l1_system_config_address": "0x6900000000000000000000000000000000000009" @@ -728,6 +729,7 @@ mod test { assert_eq!(chain.seq_window_size, 200); assert_eq!(chain.max_seq_drift, 300); assert_eq!(chain.regolith_time, 0); + assert_eq!(chain.canyon_time, 0); assert_eq!(chain.blocktime, 2); assert_eq!( chain.l2_to_l1_message_passer, From 3f311488f073a7fa9343142a7b5d5557c5618c87 Mon Sep 17 00:00:00 2001 From: Noah Citron Date: Mon, 18 Dec 2023 18:38:13 -0500 Subject: [PATCH 11/11] clippy --- src/derive/stages/attributes.rs | 4 ++-- src/network/handlers/block_handler.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 7f684bff..daacffd6 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -324,8 +324,8 @@ impl TryFrom for UserDeposited { .into_bytes() .unwrap(); - let from = Address::try_from(log.topics[1])?; - let to = Address::try_from(log.topics[2])?; + let from = Address::from(log.topics[1]); + let to = Address::from(log.topics[2]); let mint = U256::from_big_endian(&opaque_data[0..32]); let value = U256::from_big_endian(&opaque_data[32..64]); let gas = u64::from_be_bytes(opaque_data[64..72].try_into()?); diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 7b97f7b2..b1c45a5a 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -65,8 +65,8 @@ impl BlockHandler { chain_id, block_sender: sender, unsafe_signer_recv: unsafe_recv, - blocks_v1_topic: IdentTopic::new(format!("/optimism/{}/0/blocks", chain_id)).into(), - blocks_v2_topic: IdentTopic::new(format!("/optimism/{}/1/blocks", chain_id)).into(), + blocks_v1_topic: IdentTopic::new(format!("/optimism/{}/0/blocks", chain_id)), + blocks_v2_topic: IdentTopic::new(format!("/optimism/{}/1/blocks", chain_id)), }; (handler, recv)