From 656e830e4fd60b5ace87dfc1604a102f06ae59e1 Mon Sep 17 00:00:00 2001 From: Stanislav Bezkorovainyi Date: Thu, 1 Aug 2024 16:57:32 +0200 Subject: [PATCH] feat: Adding SLChainID (#2547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ Adding settlement layer chain id. Note, that in the future zkSync may settle onto other instances of Era. This PR does not introduce any legacy-inducing changes (e.g. amending configs) in case we'll need to change something. I also did not rename components / structs that mention "Eth", e.g. `QueryEthClientLayer`. For now, we can say that everything that says Eth means "Eth-compatible". With this PR: - L1ChainId should not be used only when *exactly* L1 is meant and not settlement layer. - SLChainId should be used otherwise. ## Why ❔ ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. --- core/bin/external_node/src/config/mod.rs | 14 +++++++-- core/bin/external_node/src/main.rs | 5 ++-- .../external_node/src/metrics/framework.rs | 10 +++++-- core/bin/external_node/src/metrics/mod.rs | 5 +++- core/bin/external_node/src/node_builder.rs | 5 ++-- core/bin/external_node/src/tests/framework.rs | 4 +-- core/bin/zksync_server/src/node_builder.rs | 4 +-- core/lib/basic_types/src/lib.rs | 16 ++++++++++ core/lib/basic_types/src/network.rs | 24 +++++++++------ core/lib/config/src/configs/en_config.rs | 3 +- core/lib/config/src/configs/genesis.rs | 10 ++++++- core/lib/config/src/testonly.rs | 2 ++ core/lib/env_config/src/genesis.rs | 6 ++-- core/lib/eth_client/src/clients/http/query.rs | 6 ++-- .../eth_client/src/clients/http/signing.rs | 12 ++++---- core/lib/eth_client/src/clients/mock.rs | 8 ++--- core/lib/eth_client/src/lib.rs | 6 ++-- core/lib/protobuf_config/src/en.rs | 1 + core/lib/protobuf_config/src/genesis.rs | 1 + core/lib/web3_decl/src/client/network.rs | 11 +++---- .../node/api_server/src/web3/namespaces/en.rs | 1 + core/node/api_server/src/web3/state.rs | 1 + .../fee_model/src/l1_gas_price/singleton.rs | 6 ++-- core/node/genesis/src/lib.rs | 5 ++-- .../layers/pk_signing_eth_client.rs | 12 ++++---- .../layers/query_eth_client.rs | 6 ++-- .../layers/validate_chain_ids.rs | 12 ++++---- .../node_sync/src/validate_chain_ids_task.rs | 30 +++++++++---------- core/tests/loadnext/src/sdk/ethereum/mod.rs | 8 ++--- zk_toolbox/crates/config/src/genesis.rs | 1 + .../commands/external_node/prepare_configs.rs | 1 + 31 files changed, 148 insertions(+), 88 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 5674396652f4..b0f0fa794fa1 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -31,7 +31,7 @@ use zksync_protobuf_config::proto; use zksync_snapshots_applier::SnapshotsApplierConfig; use zksync_types::{ api::BridgeAddresses, commitment::L1BatchCommitmentMode, url::SensitiveUrl, Address, - L1BatchNumber, L1ChainId, L2ChainId, ETHEREUM_ADDRESS, + L1BatchNumber, L1ChainId, L2ChainId, SLChainId, ETHEREUM_ADDRESS, }; use zksync_web3_decl::{ client::{DynClient, L2}, @@ -908,9 +908,11 @@ impl OptionalENConfig { /// This part of the external node config is required for its operation. #[derive(Debug, Deserialize)] pub(crate) struct RequiredENConfig { - /// L1 chain ID (e.g., 9 for Ethereum mainnet). This ID will be checked against the `eth_client_url` RPC provider on initialization - /// to ensure that there's no mismatch between the expected and actual L1 network. + /// The chain ID of the L1 network (e.g., 1 for Ethereum mainnet). In the future, it may be different from the settlement layer. pub l1_chain_id: L1ChainId, + /// The chain ID of the settlement layer (e.g., 1 for Ethereum mainnet). This ID will be checked against the `eth_client_url` RPC provider on initialization + /// to ensure that there's no mismatch between the expected and actual settlement layer network. + pub sl_chain_id: Option, /// L2 chain ID (e.g., 270 for ZKsync Era mainnet). This ID will be checked against the `main_node_url` RPC provider on initialization /// to ensure that there's no mismatch between the expected and actual L2 network. pub l2_chain_id: L2ChainId, @@ -932,6 +934,10 @@ pub(crate) struct RequiredENConfig { } impl RequiredENConfig { + pub fn settlement_layer_id(&self) -> SLChainId { + self.sl_chain_id.unwrap_or(self.l1_chain_id.into()) + } + fn from_env() -> anyhow::Result { envy::prefixed("EN_") .from_env() @@ -953,6 +959,7 @@ impl RequiredENConfig { .context("Database config is required")?; Ok(RequiredENConfig { l1_chain_id: en_config.l1_chain_id, + sl_chain_id: None, l2_chain_id: en_config.l2_chain_id, http_port: api_config.web3_json_rpc.http_port, ws_port: api_config.web3_json_rpc.ws_port, @@ -973,6 +980,7 @@ impl RequiredENConfig { fn mock(temp_dir: &tempfile::TempDir) -> Self { Self { l1_chain_id: L1ChainId(9), + sl_chain_id: None, l2_chain_id: L2ChainId::default(), http_port: 0, ws_port: 0, diff --git a/core/bin/external_node/src/main.rs b/core/bin/external_node/src/main.rs index 00ce3cc71e87..8c8ec711db32 100644 --- a/core/bin/external_node/src/main.rs +++ b/core/bin/external_node/src/main.rs @@ -841,7 +841,7 @@ async fn main() -> anyhow::Result<()> { let eth_client_url = &config.required.eth_client_url; let eth_client = Client::http(eth_client_url.clone()) .context("failed creating JSON-RPC client for Ethereum")? - .for_network(config.required.l1_chain_id.into()) + .for_network(config.required.settlement_layer_id().into()) .build(); let eth_client = Box::new(eth_client); @@ -880,6 +880,7 @@ async fn main() -> anyhow::Result<()> { RUST_METRICS.initialize(); EN_METRICS.observe_config( config.required.l1_chain_id, + config.required.settlement_layer_id(), config.required.l2_chain_id, config.postgres.max_connections, ); @@ -985,7 +986,7 @@ async fn run_node( }); let validate_chain_ids_task = ValidateChainIdsTask::new( - config.required.l1_chain_id, + config.required.settlement_layer_id(), config.required.l2_chain_id, eth_client.clone(), main_node_client.clone(), diff --git a/core/bin/external_node/src/metrics/framework.rs b/core/bin/external_node/src/metrics/framework.rs index 82f9263e44db..fc9d4fe51345 100644 --- a/core/bin/external_node/src/metrics/framework.rs +++ b/core/bin/external_node/src/metrics/framework.rs @@ -6,13 +6,14 @@ use zksync_node_framework::{ FromContext, IntoContext, StopReceiver, Task, TaskId, WiringError, WiringLayer, }; use zksync_shared_metrics::rustc::RUST_METRICS; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L1ChainId, L2ChainId, SLChainId}; use super::EN_METRICS; #[derive(Debug)] pub struct ExternalNodeMetricsLayer { pub l1_chain_id: L1ChainId, + pub sl_chain_id: SLChainId, pub l2_chain_id: L2ChainId, pub postgres_pool_size: u32, } @@ -39,7 +40,12 @@ impl WiringLayer for ExternalNodeMetricsLayer { async fn wire(self, input: Self::Input) -> Result { RUST_METRICS.initialize(); - EN_METRICS.observe_config(self.l1_chain_id, self.l2_chain_id, self.postgres_pool_size); + EN_METRICS.observe_config( + self.l1_chain_id, + self.sl_chain_id, + self.l2_chain_id, + self.postgres_pool_size, + ); let pool = input.master_pool.get_singleton().await?; let task = ProtocolVersionMetricsTask { pool }; diff --git a/core/bin/external_node/src/metrics/mod.rs b/core/bin/external_node/src/metrics/mod.rs index fe1b81adc266..9b155261ac99 100644 --- a/core/bin/external_node/src/metrics/mod.rs +++ b/core/bin/external_node/src/metrics/mod.rs @@ -3,7 +3,7 @@ use std::time::Duration; use tokio::sync::watch; use vise::{EncodeLabelSet, Gauge, Info, Metrics}; use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L1ChainId, L2ChainId, SLChainId}; use crate::metadata::SERVER_VERSION; @@ -14,6 +14,7 @@ pub(crate) mod framework; struct ExternalNodeInfo { server_version: &'static str, l1_chain_id: u64, + sl_chain_id: u64, l2_chain_id: u64, /// Size of the main Postgres connection pool. postgres_pool_size: u32, @@ -32,12 +33,14 @@ impl ExternalNodeMetrics { pub(crate) fn observe_config( &self, l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, l2_chain_id: L2ChainId, postgres_pool_size: u32, ) { let info = ExternalNodeInfo { server_version: SERVER_VERSION, l1_chain_id: l1_chain_id.0, + sl_chain_id: sl_chain_id.0, l2_chain_id: l2_chain_id.as_u64(), postgres_pool_size, }; diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index d9e216c84dd2..d71a9f0cdf57 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -121,6 +121,7 @@ impl ExternalNodeBuilder { fn add_external_node_metrics_layer(mut self) -> anyhow::Result { self.node.add_layer(ExternalNodeMetricsLayer { l1_chain_id: self.config.required.l1_chain_id, + sl_chain_id: self.config.required.settlement_layer_id(), l2_chain_id: self.config.required.l2_chain_id, postgres_pool_size: self.config.postgres.max_connections, }); @@ -166,7 +167,7 @@ impl ExternalNodeBuilder { fn add_query_eth_client_layer(mut self) -> anyhow::Result { let query_eth_client_layer = QueryEthClientLayer::new( - self.config.required.l1_chain_id, + self.config.required.settlement_layer_id(), self.config.required.eth_client_url.clone(), ); self.node.add_layer(query_eth_client_layer); @@ -256,7 +257,7 @@ impl ExternalNodeBuilder { fn add_validate_chain_ids_layer(mut self) -> anyhow::Result { let layer = ValidateChainIdsLayer::new( - self.config.required.l1_chain_id, + self.config.required.settlement_layer_id(), self.config.required.l2_chain_id, ); self.node.add_layer(layer); diff --git a/core/bin/external_node/src/tests/framework.rs b/core/bin/external_node/src/tests/framework.rs index ea0cc366ca64..71a6afe503a7 100644 --- a/core/bin/external_node/src/tests/framework.rs +++ b/core/bin/external_node/src/tests/framework.rs @@ -17,7 +17,7 @@ use zksync_node_framework::{ task::TaskKind, FromContext, IntoContext, StopReceiver, Task, TaskId, WiringError, WiringLayer, }; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L2ChainId, SLChainId}; use zksync_web3_decl::client::{MockClient, L1, L2}; use super::ExternalNodeBuilder; @@ -127,7 +127,7 @@ impl WiringLayer for MockL1ClientLayer { fn layer_name(&self) -> &'static str { // We don't care about values, we just want to hijack the layer name. - QueryEthClientLayer::new(L1ChainId(1), "https://example.com".parse().unwrap()).layer_name() + QueryEthClientLayer::new(SLChainId(1), "https://example.com".parse().unwrap()).layer_name() } async fn wire(self, _: Self::Input) -> Result { diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 3da14c920886..c0bf74946609 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -142,7 +142,7 @@ impl MainNodeBuilder { self.node.add_layer(PKSigningEthClientLayer::new( eth_config, self.contracts_config.clone(), - self.genesis_config.l1_chain_id, + self.genesis_config.settlement_layer_id(), wallets, )); Ok(self) @@ -152,7 +152,7 @@ impl MainNodeBuilder { let genesis = self.genesis_config.clone(); let eth_config = try_load_config!(self.secrets.l1); let query_eth_client_layer = - QueryEthClientLayer::new(genesis.l1_chain_id, eth_config.l1_rpc_url); + QueryEthClientLayer::new(genesis.settlement_layer_id(), eth_config.l1_rpc_url); self.node.add_layer(query_eth_client_layer); Ok(self) } diff --git a/core/lib/basic_types/src/lib.rs b/core/lib/basic_types/src/lib.rs index 21e90f4bad77..a9522407222c 100644 --- a/core/lib/basic_types/src/lib.rs +++ b/core/lib/basic_types/src/lib.rs @@ -213,12 +213,28 @@ basic_type!( u64 ); +basic_type!( + /// ChainId of a settlement layer. + SLChainId, + u64 +); + basic_type!( /// ChainId in the Ethereum network. + /// IMPORTANT: Please, use this method when exactly the L1 chain id is required. + /// Note, that typically this is not the case and the majority of methods need to work + /// with *settlement layer* chain id, which is represented by `SLChainId`. L1ChainId, u64 ); +// Every L1 can be a settlement layer. +impl From for SLChainId { + fn from(value: L1ChainId) -> Self { + SLChainId(value.0) + } +} + #[allow(clippy::derivable_impls)] impl Default for L2BlockNumber { fn default() -> Self { diff --git a/core/lib/basic_types/src/network.rs b/core/lib/basic_types/src/network.rs index cfa82e8c8464..41a5c5c4d73f 100644 --- a/core/lib/basic_types/src/network.rs +++ b/core/lib/basic_types/src/network.rs @@ -8,7 +8,7 @@ use std::{fmt, str::FromStr}; use serde::{Deserialize, Serialize}; // Workspace uses -use crate::L1ChainId; +use crate::SLChainId; // Local uses @@ -28,6 +28,8 @@ pub enum Network { Sepolia, /// Self-hosted Ethereum network. Localhost, + /// Self-hosted L2 network. + LocalhostL2, /// Unknown network type. Unknown, /// Test network for testkit purposes @@ -44,6 +46,7 @@ impl FromStr for Network { "ropsten" => Self::Ropsten, "goerli" => Self::Goerli, "localhost" => Self::Localhost, + "localhostL2" => Self::LocalhostL2, "sepolia" => Self::Sepolia, "test" => Self::Test, another => return Err(another.to_owned()), @@ -59,6 +62,7 @@ impl fmt::Display for Network { Self::Ropsten => write!(f, "ropsten"), Self::Goerli => write!(f, "goerli"), Self::Localhost => write!(f, "localhost"), + Self::LocalhostL2 => write!(f, "localhostL2"), Self::Sepolia => write!(f, "sepolia"), Self::Unknown => write!(f, "unknown"), Self::Test => write!(f, "test"), @@ -68,7 +72,7 @@ impl fmt::Display for Network { impl Network { /// Returns the network chain ID on the Ethereum side. - pub fn from_chain_id(chain_id: L1ChainId) -> Self { + pub fn from_chain_id(chain_id: SLChainId) -> Self { match *chain_id { 1 => Self::Mainnet, 3 => Self::Ropsten, @@ -76,19 +80,21 @@ impl Network { 5 => Self::Goerli, 9 => Self::Localhost, 11155111 => Self::Sepolia, + 270 => Self::LocalhostL2, _ => Self::Unknown, } } /// Returns the network chain ID on the Ethereum side. - pub fn chain_id(self) -> L1ChainId { + pub fn chain_id(self) -> SLChainId { match self { - Self::Mainnet => L1ChainId(1), - Self::Ropsten => L1ChainId(3), - Self::Rinkeby => L1ChainId(4), - Self::Goerli => L1ChainId(5), - Self::Localhost => L1ChainId(9), - Self::Sepolia => L1ChainId(11155111), + Self::Mainnet => SLChainId(1), + Self::Ropsten => SLChainId(3), + Self::Rinkeby => SLChainId(4), + Self::Goerli => SLChainId(5), + Self::Localhost => SLChainId(9), + Self::Sepolia => SLChainId(11155111), + Self::LocalhostL2 => SLChainId(270), Self::Unknown => panic!("Unknown chain ID"), Self::Test => panic!("Test chain ID"), } diff --git a/core/lib/config/src/configs/en_config.rs b/core/lib/config/src/configs/en_config.rs index 32dc5b7c7b49..94730980c0f8 100644 --- a/core/lib/config/src/configs/en_config.rs +++ b/core/lib/config/src/configs/en_config.rs @@ -2,7 +2,7 @@ use std::num::NonZeroUsize; use serde::Deserialize; use zksync_basic_types::{ - commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId, L2ChainId, + commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId, L2ChainId, SLChainId, }; /// Temporary config for initializing external node, will be completely replaced by consensus config later @@ -10,6 +10,7 @@ use zksync_basic_types::{ pub struct ENConfig { // Genesis pub l2_chain_id: L2ChainId, + pub sl_chain_id: Option, pub l1_chain_id: L1ChainId, pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, diff --git a/core/lib/config/src/configs/genesis.rs b/core/lib/config/src/configs/genesis.rs index ba3839d66eea..2c5c91128431 100644 --- a/core/lib/config/src/configs/genesis.rs +++ b/core/lib/config/src/configs/genesis.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use zksync_basic_types::{ commitment::L1BatchCommitmentMode, protocol_version::{ProtocolSemanticVersion, ProtocolVersionId}, - Address, L1ChainId, L2ChainId, H256, + Address, L1ChainId, L2ChainId, SLChainId, H256, }; /// This config represents the genesis state of the chain. @@ -18,6 +18,7 @@ pub struct GenesisConfig { pub bootloader_hash: Option, pub default_aa_hash: Option, pub l1_chain_id: L1ChainId, + pub sl_chain_id: Option, pub l2_chain_id: L2ChainId, pub recursion_scheduler_level_vk_hash: H256, pub fee_account: Address, @@ -25,6 +26,12 @@ pub struct GenesisConfig { pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, } +impl GenesisConfig { + pub fn settlement_layer_id(&self) -> SLChainId { + self.sl_chain_id.unwrap_or(self.l1_chain_id.into()) + } +} + impl GenesisConfig { pub fn for_tests() -> Self { GenesisConfig { @@ -36,6 +43,7 @@ impl GenesisConfig { bootloader_hash: Default::default(), default_aa_hash: Default::default(), l1_chain_id: L1ChainId(9), + sl_chain_id: None, protocol_version: Some(ProtocolSemanticVersion { minor: ProtocolVersionId::latest(), patch: 0.into(), diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index f77321caadb5..839853a6bd6a 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -703,6 +703,7 @@ impl Distribution for EncodeDist { default_aa_hash: Some(rng.gen()), fee_account: rng.gen(), l1_chain_id: L1ChainId(self.sample(rng)), + sl_chain_id: None, l2_chain_id: L2ChainId::default(), recursion_scheduler_level_vk_hash: rng.gen(), dummy_verifier: rng.gen(), @@ -875,6 +876,7 @@ impl Distribution for EncodeDist { configs::en_config::ENConfig { l2_chain_id: L2ChainId::default(), l1_chain_id: L1ChainId(rng.gen()), + sl_chain_id: None, main_node_url: format!("localhost:{}", rng.gen::()).parse().unwrap(), l1_batch_commit_data_generator_mode: match rng.gen_range(0..2) { 0 => L1BatchCommitmentMode::Rollup, diff --git a/core/lib/env_config/src/genesis.rs b/core/lib/env_config/src/genesis.rs index 77953c59e9ac..1eb83ae2f39e 100644 --- a/core/lib/env_config/src/genesis.rs +++ b/core/lib/env_config/src/genesis.rs @@ -1,6 +1,6 @@ use anyhow::Context; use serde::{Deserialize, Serialize}; -use zksync_basic_types::{protocol_version::ProtocolSemanticVersion, Address, H256}; +use zksync_basic_types::{protocol_version::ProtocolSemanticVersion, Address, L1ChainId, H256}; use zksync_config::{ configs::chain::{NetworkConfig, StateKeeperConfig}, GenesisConfig, @@ -68,7 +68,9 @@ impl FromEnv for GenesisConfig { genesis_commitment: contracts_config.genesis_batch_commitment, bootloader_hash: state_keeper.bootloader_hash, default_aa_hash: state_keeper.default_aa_hash, - l1_chain_id: network_config.network.chain_id(), + // TODO(EVM-676): for now, the settlement layer is always the same as the L1 network + l1_chain_id: L1ChainId(network_config.network.chain_id().0), + sl_chain_id: Some(network_config.network.chain_id()), l2_chain_id: network_config.zksync_network_id, recursion_scheduler_level_vk_hash: contracts_config.snark_wrapper_vk_hash, fee_account: state_keeper diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 3abea2c7e420..65387ff00779 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -2,7 +2,7 @@ use std::fmt; use async_trait::async_trait; use jsonrpsee::core::ClientError; -use zksync_types::{web3, Address, L1ChainId, H256, U256, U64}; +use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}; use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; @@ -16,7 +16,7 @@ impl EthInterface for T where T: L1EthNamespaceClient + fmt::Debug + Send + Sync, { - async fn fetch_chain_id(&self) -> EnrichedClientResult { + async fn fetch_chain_id(&self) -> EnrichedClientResult { COUNTERS.call[&(Method::ChainId, self.component())].inc(); let latency = LATENCIES.direct[&Method::ChainId].start(); let raw_chain_id = self.chain_id().rpc_context("chain_id").await?; @@ -25,7 +25,7 @@ where let err = ClientError::Custom(format!("invalid chainId: {err}")); EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) })?; - Ok(L1ChainId(chain_id)) + Ok(SLChainId(chain_id)) } async fn nonce_at_for_account( diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index 2b89af97a773..542b42420ae3 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use zksync_contracts::hyperchain_contract; use zksync_eth_signer::{EthereumSigner, PrivateKeySigner, TransactionParameters}; use zksync_types::{ - ethabi, web3, Address, K256PrivateKey, L1ChainId, EIP_4844_TX_TYPE, H160, U256, + ethabi, web3, Address, K256PrivateKey, SLChainId, EIP_4844_TX_TYPE, H160, U256, }; use zksync_web3_decl::client::{DynClient, L1}; @@ -22,7 +22,7 @@ impl PKSigningClient { operator_private_key: K256PrivateKey, diamond_proxy_addr: Address, default_priority_fee_per_gas: u64, - l1_chain_id: L1ChainId, + chain_id: SLChainId, query_client: Box>, ) -> Self { let operator_address = operator_private_key.address(); @@ -35,7 +35,7 @@ impl PKSigningClient { signer, diamond_proxy_addr, default_priority_fee_per_gas.into(), - l1_chain_id, + chain_id, ) } } @@ -58,7 +58,7 @@ struct EthDirectClientInner { sender_account: Address, contract_addr: H160, contract: ethabi::Contract, - chain_id: L1ChainId, + chain_id: SLChainId, default_priority_fee_per_gas: U256, } @@ -101,7 +101,7 @@ impl BoundEthInterface for SigningClient { self.inner.contract_addr } - fn chain_id(&self) -> L1ChainId { + fn chain_id(&self) -> SLChainId { self.inner.chain_id } @@ -217,7 +217,7 @@ impl SigningClient { eth_signer: S, contract_eth_addr: H160, default_priority_fee_per_gas: U256, - chain_id: L1ChainId, + chain_id: SLChainId, ) -> Self { Self { inner: Arc::new(EthDirectClientInner { diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 7c9dbcc0d3b4..d2d6b2108f53 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -8,7 +8,7 @@ use jsonrpsee::{core::ClientError, types::ErrorObject}; use zksync_types::{ ethabi, web3::{self, contract::Tokenize, BlockId}, - Address, L1ChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, + Address, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; use zksync_web3_decl::client::{DynClient, MockClient, L1}; @@ -328,7 +328,7 @@ impl MockEthereumBuilder { } fn build_client(self) -> MockClient { - const CHAIN_ID: L1ChainId = L1ChainId(9); + const CHAIN_ID: SLChainId = SLChainId(9); let base_fee_history = self.base_fee_history.clone(); let call_handler = self.call_handler; @@ -553,7 +553,7 @@ impl BoundEthInterface for MockEthereum { H160::repeat_byte(0x22) } - fn chain_id(&self) -> L1ChainId { + fn chain_id(&self) -> SLChainId { unimplemented!("Not needed right now") } @@ -630,7 +630,7 @@ mod tests { async fn getting_chain_id() { let mock = MockEthereum::builder().build(); let chain_id = mock.client.fetch_chain_id().await.unwrap(); - assert_eq!(chain_id, L1ChainId(9)); + assert_eq!(chain_id, SLChainId(9)); } #[tokio::test] diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index b6ac3a89b54f..3e8641845c61 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -8,7 +8,7 @@ use zksync_types::{ AccessList, Block, BlockId, BlockNumber, Filter, Log, Transaction, TransactionCondition, TransactionReceipt, }, - Address, L1ChainId, H160, H256, U256, U64, + Address, SLChainId, H160, H256, U256, U64, }; use zksync_web3_decl::client::{DynClient, L1}; pub use zksync_web3_decl::{ @@ -86,7 +86,7 @@ pub struct BaseFees { pub trait EthInterface: Sync + Send { /// Fetches the L1 chain ID (in contrast to [`BoundEthInterface::chain_id()`] which returns /// the *expected* L1 chain ID). - async fn fetch_chain_id(&self) -> EnrichedClientResult; + async fn fetch_chain_id(&self) -> EnrichedClientResult; /// Returns the nonce of the provided account at the specified block. async fn nonce_at_for_account( @@ -186,7 +186,7 @@ pub trait BoundEthInterface: AsRef> + 'static + Sync + Send + fmt: /// /// This value should be externally provided by the user rather than requested from the network /// to avoid accidental network mismatch. - fn chain_id(&self) -> L1ChainId; + fn chain_id(&self) -> SLChainId; /// Address of the account associated with the object implementing the trait. fn sender_account(&self) -> Address; diff --git a/core/lib/protobuf_config/src/en.rs b/core/lib/protobuf_config/src/en.rs index b6323de6ea61..b006dc61d6b7 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -18,6 +18,7 @@ impl ProtoRepr for proto::ExternalNode { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, + sl_chain_id: None, l2_chain_id: required(&self.l2_chain_id) .and_then(|x| L2ChainId::try_from(*x).map_err(|a| anyhow::anyhow!(a))) .context("l2_chain_id")?, diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 13872d1ab95a..92f639aa224e 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -71,6 +71,7 @@ impl ProtoRepr for proto::Genesis { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, + sl_chain_id: None, l2_chain_id: required(&self.l2_chain_id) .and_then(|x| L2ChainId::try_from(*x).map_err(|a| anyhow::anyhow!(a))) .context("l2_chain_id")?, diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 2e7dcce9937f..82136689d1d0 100644 --- a/core/lib/web3_decl/src/client/network.rs +++ b/core/lib/web3_decl/src/client/network.rs @@ -2,7 +2,7 @@ use std::fmt; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L2ChainId, SLChainId}; /// Marker trait for networks. Two standard network kinds are [`L1`] and [`L2`]. /// @@ -12,9 +12,10 @@ pub trait Network: 'static + Copy + Default + Sync + Send + fmt::Debug { fn metric_label(&self) -> String; } -/// L1 (i.e., Ethereum) network. +/// L1-compatible (e.g., Ethereum) network. +/// Note, that this network does not have to be an L1. It can be any network that is compatible with Ethereum JSON-RPC. #[derive(Debug, Clone, Copy, Default)] -pub struct L1(Option); +pub struct L1(Option); impl Network for L1 { fn metric_label(&self) -> String { @@ -26,8 +27,8 @@ impl Network for L1 { } } -impl From for L1 { - fn from(chain_id: L1ChainId) -> Self { +impl From for L1 { + fn from(chain_id: SLChainId) -> Self { Self(Some(chain_id)) } } diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index 7e690a064012..604d38ef94ab 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -155,6 +155,7 @@ impl EnNamespace { bootloader_hash: Some(genesis_batch.header.base_system_contracts_hashes.bootloader), default_aa_hash: Some(genesis_batch.header.base_system_contracts_hashes.default_aa), l1_chain_id: self.state.api_config.l1_chain_id, + sl_chain_id: Some(self.state.api_config.l1_chain_id.into()), l2_chain_id: self.state.api_config.l2_chain_id, recursion_scheduler_level_vk_hash: verifier_config.recursion_scheduler_level_vk_hash, fee_account, diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index b0db480b2fa9..b0e74706e523 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -95,6 +95,7 @@ impl BlockStartInfo { /// The intention is to only keep the actually used information here. #[derive(Debug, Clone)] pub struct InternalApiConfig { + /// Chain ID of the L1 network. Note, that it may be different from the chain id of the settlement layer. pub l1_chain_id: L1ChainId, pub l2_chain_id: L2ChainId, pub max_tx_size: usize, diff --git a/core/node/fee_model/src/l1_gas_price/singleton.rs b/core/node/fee_model/src/l1_gas_price/singleton.rs index 33b6e9b28e29..257c51ebe75f 100644 --- a/core/node/fee_model/src/l1_gas_price/singleton.rs +++ b/core/node/fee_model/src/l1_gas_price/singleton.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::Context as _; use tokio::{sync::watch, task::JoinHandle}; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_types::{commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId}; +use zksync_types::{commitment::L1BatchCommitmentMode, url::SensitiveUrl, SLChainId}; use zksync_web3_decl::client::Client; use crate::l1_gas_price::GasAdjuster; @@ -12,7 +12,7 @@ use crate::l1_gas_price::GasAdjuster; /// This is needed only for running the server. #[derive(Debug)] pub struct GasAdjusterSingleton { - chain_id: L1ChainId, + chain_id: SLChainId, web3_url: SensitiveUrl, gas_adjuster_config: GasAdjusterConfig, pubdata_sending_mode: PubdataSendingMode, @@ -22,7 +22,7 @@ pub struct GasAdjusterSingleton { impl GasAdjusterSingleton { pub fn new( - chain_id: L1ChainId, + chain_id: SLChainId, web3_url: SensitiveUrl, gas_adjuster_config: GasAdjusterConfig, pubdata_sending_mode: PubdataSendingMode, diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 7ff811f85343..dcb9ba2c012f 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -20,7 +20,7 @@ use zksync_types::{ protocol_version::{L1VerifierConfig, ProtocolSemanticVersion}, system_contracts::get_system_smart_contracts, web3::{BlockNumber, FilterBuilder}, - AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersion, + AccountTreeId, Address, L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId, ProtocolVersion, ProtocolVersionId, StorageKey, H256, }; use zksync_utils::{bytecode::hash_bytecode, u256_to_h256}; @@ -159,8 +159,6 @@ pub struct GenesisBatchParams { } pub fn mock_genesis_config() -> GenesisConfig { - use zksync_types::L1ChainId; - let base_system_contracts_hashes = BaseSystemContracts::load_from_disk().hashes(); let first_l1_verifier_config = L1VerifierConfig::default(); @@ -175,6 +173,7 @@ pub fn mock_genesis_config() -> GenesisConfig { bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), l1_chain_id: L1ChainId(9), + sl_chain_id: None, l2_chain_id: L2ChainId::default(), recursion_scheduler_level_vk_hash: first_l1_verifier_config .recursion_scheduler_level_vk_hash, diff --git a/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs b/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs index de570105a471..fdef23a40692 100644 --- a/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs +++ b/core/node/node_framework/src/implementations/layers/pk_signing_eth_client.rs @@ -4,7 +4,7 @@ use zksync_config::{ EthConfig, }; use zksync_eth_client::clients::PKSigningClient; -use zksync_types::L1ChainId; +use zksync_types::SLChainId; use crate::{ implementations::resources::eth_interface::{ @@ -19,7 +19,7 @@ use crate::{ pub struct PKSigningEthClientLayer { eth_sender_config: EthConfig, contracts_config: ContractsConfig, - l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, wallets: wallets::EthSender, } @@ -41,13 +41,13 @@ impl PKSigningEthClientLayer { pub fn new( eth_sender_config: EthConfig, contracts_config: ContractsConfig, - l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, wallets: wallets::EthSender, ) -> Self { Self { eth_sender_config, contracts_config, - l1_chain_id, + sl_chain_id, wallets, } } @@ -75,7 +75,7 @@ impl WiringLayer for PKSigningEthClientLayer { private_key.clone(), self.contracts_config.diamond_proxy_addr, gas_adjuster_config.default_priority_fee_per_gas, - self.l1_chain_id, + self.sl_chain_id, query_client.clone(), ); let signing_client = BoundEthInterfaceResource(Box::new(signing_client)); @@ -86,7 +86,7 @@ impl WiringLayer for PKSigningEthClientLayer { private_key.clone(), self.contracts_config.diamond_proxy_addr, gas_adjuster_config.default_priority_fee_per_gas, - self.l1_chain_id, + self.sl_chain_id, query_client, ); BoundEthInterfaceForBlobsResource(Box::new(signing_client_for_blobs)) diff --git a/core/node/node_framework/src/implementations/layers/query_eth_client.rs b/core/node/node_framework/src/implementations/layers/query_eth_client.rs index d48312d7d5b5..b3a9c7d4b275 100644 --- a/core/node/node_framework/src/implementations/layers/query_eth_client.rs +++ b/core/node/node_framework/src/implementations/layers/query_eth_client.rs @@ -1,5 +1,5 @@ use anyhow::Context; -use zksync_types::{url::SensitiveUrl, L1ChainId}; +use zksync_types::{url::SensitiveUrl, SLChainId}; use zksync_web3_decl::client::Client; use crate::{ @@ -10,12 +10,12 @@ use crate::{ /// Wiring layer for Ethereum client. #[derive(Debug)] pub struct QueryEthClientLayer { - chain_id: L1ChainId, + chain_id: SLChainId, web3_url: SensitiveUrl, } impl QueryEthClientLayer { - pub fn new(chain_id: L1ChainId, web3_url: SensitiveUrl) -> Self { + pub fn new(chain_id: SLChainId, web3_url: SensitiveUrl) -> Self { Self { chain_id, web3_url } } } diff --git a/core/node/node_framework/src/implementations/layers/validate_chain_ids.rs b/core/node/node_framework/src/implementations/layers/validate_chain_ids.rs index 1e23bdfbd622..37bf37c27bed 100644 --- a/core/node/node_framework/src/implementations/layers/validate_chain_ids.rs +++ b/core/node/node_framework/src/implementations/layers/validate_chain_ids.rs @@ -1,5 +1,5 @@ use zksync_node_sync::validate_chain_ids_task::ValidateChainIdsTask; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L2ChainId, SLChainId}; use crate::{ implementations::resources::{ @@ -12,7 +12,7 @@ use crate::{ }; /// Wiring layer for chain ID validation precondition for external node. -/// Ensures that chain IDs are consistent locally, on main node, and on L1. +/// Ensures that chain IDs are consistent locally, on main node, and on the settlement layer. /// /// ## Requests resources /// @@ -24,7 +24,7 @@ use crate::{ /// - `ValidateChainIdsTask` #[derive(Debug)] pub struct ValidateChainIdsLayer { - l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, l2_chain_id: L2ChainId, } @@ -43,9 +43,9 @@ pub struct Output { } impl ValidateChainIdsLayer { - pub fn new(l1_chain_id: L1ChainId, l2_chain_id: L2ChainId) -> Self { + pub fn new(sl_chain_id: SLChainId, l2_chain_id: L2ChainId) -> Self { Self { - l1_chain_id, + sl_chain_id, l2_chain_id, } } @@ -65,7 +65,7 @@ impl WiringLayer for ValidateChainIdsLayer { let MainNodeClientResource(main_node_client) = input.main_node_client; let task = ValidateChainIdsTask::new( - self.l1_chain_id, + self.sl_chain_id, self.l2_chain_id, query_client, main_node_client, diff --git a/core/node/node_sync/src/validate_chain_ids_task.rs b/core/node/node_sync/src/validate_chain_ids_task.rs index 1414b5ab6014..0f80bf799b15 100644 --- a/core/node/node_sync/src/validate_chain_ids_task.rs +++ b/core/node/node_sync/src/validate_chain_ids_task.rs @@ -5,7 +5,7 @@ use std::time::Duration; use futures::FutureExt; use tokio::sync::watch; use zksync_eth_client::EthInterface; -use zksync_types::{L1ChainId, L2ChainId}; +use zksync_types::{L2ChainId, SLChainId}; use zksync_web3_decl::{ client::{DynClient, L1, L2}, error::ClientRpcContext, @@ -15,7 +15,7 @@ use zksync_web3_decl::{ /// Task that validates chain IDs using main node and Ethereum clients. #[derive(Debug)] pub struct ValidateChainIdsTask { - l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, l2_chain_id: L2ChainId, eth_client: Box>, main_node_client: Box>, @@ -25,13 +25,13 @@ impl ValidateChainIdsTask { const BACKOFF_INTERVAL: Duration = Duration::from_secs(5); pub fn new( - l1_chain_id: L1ChainId, + sl_chain_id: SLChainId, l2_chain_id: L2ChainId, eth_client: Box>, main_node_client: Box>, ) -> Self { Self { - l1_chain_id, + sl_chain_id, l2_chain_id, eth_client: eth_client.for_component("chain_ids_validation"), main_node_client: main_node_client.for_component("chain_ids_validation"), @@ -40,7 +40,7 @@ impl ValidateChainIdsTask { async fn check_eth_client( eth_client: Box>, - expected: L1ChainId, + expected: SLChainId, ) -> anyhow::Result<()> { loop { match eth_client.fetch_chain_id().await { @@ -66,7 +66,7 @@ impl ValidateChainIdsTask { async fn check_l1_chain_using_main_node( main_node_client: Box>, - expected: L1ChainId, + expected: SLChainId, ) -> anyhow::Result<()> { loop { match main_node_client @@ -75,7 +75,7 @@ impl ValidateChainIdsTask { .await { Ok(chain_id) => { - let chain_id = L1ChainId(chain_id.as_u64()); + let chain_id = SLChainId(chain_id.as_u64()); anyhow::ensure!( expected == chain_id, "Configured L1 chain ID doesn't match the one from main node. \ @@ -140,9 +140,9 @@ impl ValidateChainIdsTask { /// Runs the task once, exiting either when all the checks are performed or when the stop signal is received. pub async fn run_once(self, mut stop_receiver: watch::Receiver) -> anyhow::Result<()> { - let eth_client_check = Self::check_eth_client(self.eth_client, self.l1_chain_id); + let eth_client_check = Self::check_eth_client(self.eth_client, self.sl_chain_id); let main_node_l1_check = - Self::check_l1_chain_using_main_node(self.main_node_client.clone(), self.l1_chain_id); + Self::check_l1_chain_using_main_node(self.main_node_client.clone(), self.sl_chain_id); let main_node_l2_check = Self::check_l2_chain_using_main_node(self.main_node_client, self.l2_chain_id); let joined_futures = @@ -158,9 +158,9 @@ impl ValidateChainIdsTask { pub async fn run(self, mut stop_receiver: watch::Receiver) -> anyhow::Result<()> { // Since check futures are fused, they are safe to poll after getting resolved; they will never resolve again, // so we'll just wait for another check or a stop signal. - let eth_client_check = Self::check_eth_client(self.eth_client, self.l1_chain_id).fuse(); + let eth_client_check = Self::check_eth_client(self.eth_client, self.sl_chain_id).fuse(); let main_node_l1_check = - Self::check_l1_chain_using_main_node(self.main_node_client.clone(), self.l1_chain_id) + Self::check_l1_chain_using_main_node(self.main_node_client.clone(), self.sl_chain_id) .fuse(); let main_node_l2_check = Self::check_l2_chain_using_main_node(self.main_node_client, self.l2_chain_id).fuse(); @@ -191,7 +191,7 @@ mod tests { .build(); let validation_task = ValidateChainIdsTask::new( - L1ChainId(3), // << mismatch with the Ethereum client + SLChainId(3), // << mismatch with the Ethereum client L2ChainId::default(), Box::new(eth_client.clone()), Box::new(main_node_client.clone()), @@ -208,7 +208,7 @@ mod tests { ); let validation_task = ValidateChainIdsTask::new( - L1ChainId(9), // << mismatch with the main node client + SLChainId(9), // << mismatch with the main node client L2ChainId::from(270), Box::new(eth_client.clone()), Box::new(main_node_client), @@ -229,7 +229,7 @@ mod tests { .build(); let validation_task = ValidateChainIdsTask::new( - L1ChainId(9), + SLChainId(9), L2ChainId::from(271), // << mismatch with the main node client Box::new(eth_client), Box::new(main_node_client), @@ -256,7 +256,7 @@ mod tests { .build(); let validation_task = ValidateChainIdsTask::new( - L1ChainId(9), + SLChainId(9), L2ChainId::default(), Box::new(eth_client), Box::new(main_node_client), diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index ca168152a640..31fcc5269774 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -15,7 +15,7 @@ use zksync_types::{ network::Network, url::SensitiveUrl, web3::{contract::Tokenize, TransactionReceipt}, - Address, L1ChainId, L1TxCommonData, H160, H256, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, + Address, L1TxCommonData, SLChainId, H160, H256, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, }; use zksync_web3_decl::{ client::{Client, DynClient, L1}, @@ -87,7 +87,7 @@ impl EthereumProvider { "Chain id overflow - Expected chain id to be in range 0..2^64".to_owned(), ) })?; - let l1_chain_id = L1ChainId(l1_chain_id); + let sl_chain_id = SLChainId(l1_chain_id); let contract_address = provider.get_main_contract().await?; let default_bridges = provider @@ -101,7 +101,7 @@ impl EthereumProvider { .map_err(|err| ClientError::NetworkError(err.to_string()))?; let query_client = Client::http(eth_web3_url) .map_err(|err| ClientError::NetworkError(err.to_string()))? - .for_network(l1_chain_id.into()) + .for_network(sl_chain_id.into()) .build(); let query_client: Box> = Box::new(query_client); let eth_client = SigningClient::new( @@ -111,7 +111,7 @@ impl EthereumProvider { eth_signer, contract_address, DEFAULT_PRIORITY_FEE.into(), - l1_chain_id, + sl_chain_id, ); let erc20_abi = ierc20_contract(); let l1_erc20_bridge_abi = l1_erc20_bridge_contract(); diff --git a/zk_toolbox/crates/config/src/genesis.rs b/zk_toolbox/crates/config/src/genesis.rs index 1df1da85fe1f..a6469893fed2 100644 --- a/zk_toolbox/crates/config/src/genesis.rs +++ b/zk_toolbox/crates/config/src/genesis.rs @@ -13,6 +13,7 @@ use crate::{ pub fn update_from_chain_config(genesis: &mut GenesisConfig, config: &ChainConfig) { genesis.l2_chain_id = config.chain_id; + // TODO(EVM-676): for now, the settlement layer is always the same as the L1 network genesis.l1_chain_id = L1ChainId(config.l1_network.chain_id()); genesis.l1_batch_commit_data_generator_mode = config.l1_batch_commit_data_generator_mode; } diff --git a/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs b/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs index b799a68aeb8f..2a4ad6c9de80 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/external_node/prepare_configs.rs @@ -50,6 +50,7 @@ fn prepare_configs( let en_config = ENConfig { l2_chain_id: genesis.l2_chain_id, l1_chain_id: genesis.l1_chain_id, + sl_chain_id: genesis.sl_chain_id, l1_batch_commit_data_generator_mode: genesis.l1_batch_commit_data_generator_mode, main_node_url: SensitiveUrl::from_str( &general