From a2c3a89c77d2c411e23c5cbe62cf1d5620966b55 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Tue, 30 Jul 2024 16:36:47 +0200 Subject: [PATCH 01/43] wip --- core/bin/external_node/src/config/mod.rs | 8 +++--- .../external_node/src/metrics/framework.rs | 4 +-- core/bin/external_node/src/metrics/mod.rs | 4 +-- core/bin/external_node/src/tests/framework.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 | 4 +-- core/lib/config/src/configs/genesis.rs | 10 ++++++- core/lib/config/src/testonly.rs | 6 ++--- core/lib/eth_client/src/clients/http/query.rs | 6 ++--- .../eth_client/src/clients/http/signing.rs | 10 +++---- core/lib/eth_client/src/clients/mock.rs | 8 +++--- core/lib/eth_client/src/lib.rs | 6 ++--- core/lib/protobuf_config/src/en.rs | 4 +-- core/lib/protobuf_config/src/genesis.rs | 6 ++--- core/lib/web3_decl/src/client/network.rs | 8 +++--- core/node/api_server/src/web3/state.rs | 3 ++- .../fee_model/src/l1_gas_price/singleton.rs | 6 ++--- core/node/genesis/src/lib.rs | 4 +-- .../layers/pk_signing_eth_client.rs | 6 ++--- .../layers/query_eth_client.rs | 6 ++--- .../layers/validate_chain_ids.rs | 6 ++--- .../node_sync/src/validate_chain_ids_task.rs | 26 +++++++++---------- core/tests/loadnext/src/sdk/ethereum/mod.rs | 4 +-- .../ts-integration/tests/api/web3.test.ts | 2 +- zk_toolbox/crates/config/src/genesis.rs | 4 +-- 26 files changed, 113 insertions(+), 82 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 5674396652f4..2d5548002a23 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, L2ChainId, SLChainId, ETHEREUM_ADDRESS, }; use zksync_web3_decl::{ client::{DynClient, L2}, @@ -908,9 +908,9 @@ 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 + /// The chain ID of the settlement layer (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. - pub l1_chain_id: L1ChainId, + pub l1_chain_id: SLChainId, /// 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, @@ -972,7 +972,7 @@ impl RequiredENConfig { #[cfg(test)] fn mock(temp_dir: &tempfile::TempDir) -> Self { Self { - l1_chain_id: L1ChainId(9), + l1_chain_id: SLChainId(9), l2_chain_id: L2ChainId::default(), http_port: 0, ws_port: 0, diff --git a/core/bin/external_node/src/metrics/framework.rs b/core/bin/external_node/src/metrics/framework.rs index 82f9263e44db..70efb7bd3eac 100644 --- a/core/bin/external_node/src/metrics/framework.rs +++ b/core/bin/external_node/src/metrics/framework.rs @@ -6,13 +6,13 @@ 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::{L2ChainId, SLChainId}; use super::EN_METRICS; #[derive(Debug)] pub struct ExternalNodeMetricsLayer { - pub l1_chain_id: L1ChainId, + pub l1_chain_id: SLChainId, pub l2_chain_id: L2ChainId, pub postgres_pool_size: u32, } diff --git a/core/bin/external_node/src/metrics/mod.rs b/core/bin/external_node/src/metrics/mod.rs index fe1b81adc266..d020e679e3c6 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::{L2ChainId, SLChainId}; use crate::metadata::SERVER_VERSION; @@ -31,7 +31,7 @@ pub(crate) struct ExternalNodeMetrics { impl ExternalNodeMetrics { pub(crate) fn observe_config( &self, - l1_chain_id: L1ChainId, + l1_chain_id: SLChainId, l2_chain_id: L2ChainId, postgres_pool_size: u32, ) { 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/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..ed3ebec7bf67 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, L2ChainId, SLChainId, }; /// Temporary config for initializing external node, will be completely replaced by consensus config later @@ -10,7 +10,7 @@ use zksync_basic_types::{ pub struct ENConfig { // Genesis pub l2_chain_id: L2ChainId, - pub l1_chain_id: L1ChainId, + pub l1_chain_id: SLChainId, pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, // Main node configuration diff --git a/core/lib/config/src/configs/genesis.rs b/core/lib/config/src/configs/genesis.rs index ba3839d66eea..1ac4e376a55f 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 get_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 2c2934859fe5..ee49d21c4186 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -6,7 +6,7 @@ use zksync_basic_types::{ commitment::L1BatchCommitmentMode, network::Network, protocol_version::{ProtocolSemanticVersion, ProtocolVersionId, VersionPatch}, - L1BatchNumber, L1ChainId, L2ChainId, + L1BatchNumber, L2ChainId, SLChainId, }; use zksync_consensus_utils::EncodeDist; use zksync_crypto_primitives::K256PrivateKey; @@ -701,7 +701,7 @@ impl Distribution for EncodeDist { bootloader_hash: Some(rng.gen()), default_aa_hash: Some(rng.gen()), fee_account: rng.gen(), - l1_chain_id: L1ChainId(self.sample(rng)), + l1_chain_id: SLChainId(self.sample(rng)), l2_chain_id: L2ChainId::default(), recursion_scheduler_level_vk_hash: rng.gen(), dummy_verifier: rng.gen(), @@ -873,7 +873,7 @@ impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> configs::en_config::ENConfig { configs::en_config::ENConfig { l2_chain_id: L2ChainId::default(), - l1_chain_id: L1ChainId(rng.gen()), + l1_chain_id: SLChainId(rng.gen()), 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/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..9c717042af34 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, + l1_chain_id: SLChainId, query_client: Box>, ) -> Self { let operator_address = operator_private_key.address(); @@ -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 9fbc5ceb4b2e..806c4fd1925b 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, H160, H256, U256, U64, + Address, SLChainId, H160, H256, U256, U64, }; use zksync_web3_decl::client::{DynClient, MockClient, L1}; @@ -315,7 +315,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; @@ -540,7 +540,7 @@ impl BoundEthInterface for MockEthereum { H160::repeat_byte(0x22) } - fn chain_id(&self) -> L1ChainId { + fn chain_id(&self) -> SLChainId { unimplemented!("Not needed right now") } @@ -617,7 +617,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..0831bc9017a9 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -1,7 +1,7 @@ use std::{num::NonZeroUsize, str::FromStr}; use anyhow::Context; -use zksync_basic_types::{url::SensitiveUrl, L1ChainId, L2ChainId}; +use zksync_basic_types::{url::SensitiveUrl, L2ChainId, SLChainId}; use zksync_config::configs::en_config::ENConfig; use zksync_protobuf::{required, ProtoRepr}; @@ -16,7 +16,7 @@ impl ProtoRepr for proto::ExternalNode { required(&self.main_node_url).context("main_node_url")?, )?, l1_chain_id: required(&self.l1_chain_id) - .map(|x| L1ChainId(*x)) + .map(|x| SLChainId(*x)) .context("l1_chain_id")?, l2_chain_id: required(&self.l2_chain_id) .and_then(|x| L2ChainId::try_from(*x).map_err(|a| anyhow::anyhow!(a))) diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 13872d1ab95a..ed6d00978284 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -2,8 +2,8 @@ use std::str::FromStr; use anyhow::Context as _; use zksync_basic_types::{ - commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion, L1ChainId, - L2ChainId, + commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion, L2ChainId, + SLChainId, }; use zksync_config::configs; use zksync_protobuf::{repr::ProtoRepr, required}; @@ -69,7 +69,7 @@ impl ProtoRepr for proto::Genesis { .context("default_aa_hash")?, ), l1_chain_id: required(&self.l1_chain_id) - .map(|x| L1ChainId(*x)) + .map(|x| SLChainId(*x)) .context("l1_chain_id")?, l2_chain_id: required(&self.l2_chain_id) .and_then(|x| L2ChainId::try_from(*x).map_err(|a| anyhow::anyhow!(a))) diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 2e7dcce9937f..2726599f7b23 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`]. /// @@ -14,7 +14,7 @@ pub trait Network: 'static + Copy + Default + Sync + Send + fmt::Debug { /// L1 (i.e., Ethereum) network. #[derive(Debug, Clone, Copy, Default)] -pub struct L1(Option); +pub struct L1(Option); impl Network for L1 { fn metric_label(&self) -> String { @@ -26,8 +26,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/state.rs b/core/node/api_server/src/web3/state.rs index b0db480b2fa9..41dd4b0c6c0e 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -21,7 +21,7 @@ use zksync_metadata_calculator::api_server::TreeApiClient; use zksync_node_sync::SyncState; use zksync_types::{ api, commitment::L1BatchCommitmentMode, l2::L2Tx, transaction_request::CallRequest, Address, - L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId, H256, U256, U64, + L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId, SLChainId, H256, U256, U64, }; use zksync_web3_decl::{error::Web3Error, types::Filter}; @@ -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..39c14c34f86d 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -159,7 +159,7 @@ pub struct GenesisBatchParams { } pub fn mock_genesis_config() -> GenesisConfig { - use zksync_types::L1ChainId; + use zksync_types::SLChainId; let base_system_contracts_hashes = BaseSystemContracts::load_from_disk().hashes(); let first_l1_verifier_config = L1VerifierConfig::default(); @@ -174,7 +174,7 @@ pub fn mock_genesis_config() -> GenesisConfig { genesis_commitment: Some(H256::default()), bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), - l1_chain_id: L1ChainId(9), + l1_chain_id: SLChainId(9), 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..c3be45591040 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, + l1_chain_id: SLChainId, wallets: wallets::EthSender, } @@ -41,7 +41,7 @@ impl PKSigningEthClientLayer { pub fn new( eth_sender_config: EthConfig, contracts_config: ContractsConfig, - l1_chain_id: L1ChainId, + l1_chain_id: SLChainId, wallets: wallets::EthSender, ) -> Self { Self { 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..ef150fc85dca 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::{ @@ -24,7 +24,7 @@ use crate::{ /// - `ValidateChainIdsTask` #[derive(Debug)] pub struct ValidateChainIdsLayer { - l1_chain_id: L1ChainId, + l1_chain_id: SLChainId, l2_chain_id: L2ChainId, } @@ -43,7 +43,7 @@ pub struct Output { } impl ValidateChainIdsLayer { - pub fn new(l1_chain_id: L1ChainId, l2_chain_id: L2ChainId) -> Self { + pub fn new(l1_chain_id: SLChainId, l2_chain_id: L2ChainId) -> Self { Self { l1_chain_id, l2_chain_id, 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..cfca74695bf8 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, + l1_chain_id: SLChainId, l2_chain_id: L2ChainId, eth_client: Box>, main_node_client: Box>, @@ -25,7 +25,7 @@ impl ValidateChainIdsTask { const BACKOFF_INTERVAL: Duration = Duration::from_secs(5); pub fn new( - l1_chain_id: L1ChainId, + l1_chain_id: SLChainId, l2_chain_id: L2ChainId, eth_client: Box>, main_node_client: Box>, @@ -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. \ @@ -187,11 +187,11 @@ mod tests { .build(); let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_L1ChainId", || Ok(U64::from(3))) + .method("zks_SLChainId", || Ok(U64::from(3))) .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), @@ -225,11 +225,11 @@ mod tests { let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_L1ChainId", || Ok(U64::from(9))) + .method("zks_SLChainId", || Ok(U64::from(9))) .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), @@ -252,11 +252,11 @@ mod tests { .build(); let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_L1ChainId", || Ok(U64::from(9))) + .method("zks_SLChainId", || Ok(U64::from(9))) .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..e5c18510c2ef 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 l1_chain_id = SLChainId(l1_chain_id); let contract_address = provider.get_main_contract().await?; let default_bridges = provider diff --git a/core/tests/ts-integration/tests/api/web3.test.ts b/core/tests/ts-integration/tests/api/web3.test.ts index 569321d548ce..c70ef8b629e4 100644 --- a/core/tests/ts-integration/tests/api/web3.test.ts +++ b/core/tests/ts-integration/tests/api/web3.test.ts @@ -118,7 +118,7 @@ describe('web3 API compatibility tests', () => { const tokenBalance = await alice.getBalance(l2Token); expect(balances[l2Token.toLowerCase()] == tokenBalance); } - // zks_L1ChainId + // zks_SLChainId const l1ChainId = (await alice.providerL1!.getNetwork()).chainId; const l1ChainIdFromL2Provider = BigInt(await alice.provider.l1ChainId()); expect(l1ChainId).toEqual(l1ChainIdFromL2Provider); diff --git a/zk_toolbox/crates/config/src/genesis.rs b/zk_toolbox/crates/config/src/genesis.rs index 1df1da85fe1f..4f0ca7d3e2c0 100644 --- a/zk_toolbox/crates/config/src/genesis.rs +++ b/zk_toolbox/crates/config/src/genesis.rs @@ -1,7 +1,7 @@ use std::path::Path; use xshell::Shell; -use zksync_basic_types::L1ChainId; +use zksync_basic_types::SLChainId; pub use zksync_config::GenesisConfig; use zksync_protobuf_config::{decode_yaml_repr, encode_yaml_repr}; @@ -13,7 +13,7 @@ use crate::{ pub fn update_from_chain_config(genesis: &mut GenesisConfig, config: &ChainConfig) { genesis.l2_chain_id = config.chain_id; - genesis.l1_chain_id = L1ChainId(config.l1_network.chain_id()); + genesis.l1_chain_id = SLChainId(config.l1_network.chain_id()); genesis.l1_batch_commit_data_generator_mode = config.l1_batch_commit_data_generator_mode; } From 830a952f4fd7c1ef4e19a6b5bf1cc32d6af15cdb Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 11:26:30 +0200 Subject: [PATCH 02/43] some additional changes --- core/bin/external_node/src/config/mod.rs | 18 +++++++++++++----- core/bin/external_node/src/main.rs | 6 +++--- .../bin/external_node/src/metrics/framework.rs | 4 ++-- core/bin/external_node/src/metrics/mod.rs | 4 ++-- core/bin/external_node/src/node_builder.rs | 6 +++--- core/bin/zksync_server/src/node_builder.rs | 4 ++-- core/lib/config/src/configs/en_config.rs | 5 +++-- core/lib/config/src/testonly.rs | 8 +++++--- core/lib/env_config/src/genesis.rs | 6 ++++-- .../lib/eth_client/src/clients/http/signing.rs | 4 ++-- core/lib/protobuf_config/src/en.rs | 9 ++++++++- core/lib/protobuf_config/src/genesis.rs | 9 ++++++++- core/lib/web3_decl/src/client/network.rs | 3 ++- core/node/api_server/src/web3/namespaces/en.rs | 1 + core/node/genesis/src/lib.rs | 5 +++-- .../layers/pk_signing_eth_client.rs | 10 +++++----- .../layers/validate_chain_ids.rs | 10 +++++----- .../node_sync/src/validate_chain_ids_task.rs | 14 +++++++------- 18 files changed, 78 insertions(+), 48 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 2d5548002a23..8d5f28ab5f78 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, L2ChainId, SLChainId, 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 { - /// The chain ID of the settlement layer (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. - pub l1_chain_id: SLChainId, + /// 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 get_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, @@ -972,7 +979,8 @@ impl RequiredENConfig { #[cfg(test)] fn mock(temp_dir: &tempfile::TempDir) -> Self { Self { - l1_chain_id: SLChainId(9), + 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..e60dca287c78 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.get_settlement_layer_id().into()) .build(); let eth_client = Box::new(eth_client); @@ -879,7 +879,7 @@ async fn main() -> anyhow::Result<()> { RUST_METRICS.initialize(); EN_METRICS.observe_config( - config.required.l1_chain_id, + config.required.get_settlement_layer_id(), config.required.l2_chain_id, config.postgres.max_connections, ); @@ -985,7 +985,7 @@ async fn run_node( }); let validate_chain_ids_task = ValidateChainIdsTask::new( - config.required.l1_chain_id, + config.required.get_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 70efb7bd3eac..9baa5d7157ba 100644 --- a/core/bin/external_node/src/metrics/framework.rs +++ b/core/bin/external_node/src/metrics/framework.rs @@ -12,7 +12,7 @@ use super::EN_METRICS; #[derive(Debug)] pub struct ExternalNodeMetricsLayer { - pub l1_chain_id: SLChainId, + pub sl_chain_id: SLChainId, pub l2_chain_id: L2ChainId, pub postgres_pool_size: u32, } @@ -39,7 +39,7 @@ 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.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 d020e679e3c6..aa7e7b6b6c1e 100644 --- a/core/bin/external_node/src/metrics/mod.rs +++ b/core/bin/external_node/src/metrics/mod.rs @@ -31,13 +31,13 @@ pub(crate) struct ExternalNodeMetrics { impl ExternalNodeMetrics { pub(crate) fn observe_config( &self, - l1_chain_id: SLChainId, + 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, + l1_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..d6387a57a485 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -120,7 +120,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.get_settlement_layer_id(), l2_chain_id: self.config.required.l2_chain_id, postgres_pool_size: self.config.postgres.max_connections, }); @@ -166,7 +166,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.get_settlement_layer_id(), self.config.required.eth_client_url.clone(), ); self.node.add_layer(query_eth_client_layer); @@ -256,7 +256,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.get_settlement_layer_id(), self.config.required.l2_chain_id, ); self.node.add_layer(layer); diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 3da14c920886..6a0f05de5580 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.get_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.get_settlement_layer_id(), eth_config.l1_rpc_url); self.node.add_layer(query_eth_client_layer); Ok(self) } diff --git a/core/lib/config/src/configs/en_config.rs b/core/lib/config/src/configs/en_config.rs index ed3ebec7bf67..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, L2ChainId, SLChainId, + commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId, L2ChainId, SLChainId, }; /// Temporary config for initializing external node, will be completely replaced by consensus config later @@ -10,7 +10,8 @@ use zksync_basic_types::{ pub struct ENConfig { // Genesis pub l2_chain_id: L2ChainId, - pub l1_chain_id: SLChainId, + pub sl_chain_id: Option, + pub l1_chain_id: L1ChainId, pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, // Main node configuration diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index ee49d21c4186..86720c0e3777 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -6,7 +6,7 @@ use zksync_basic_types::{ commitment::L1BatchCommitmentMode, network::Network, protocol_version::{ProtocolSemanticVersion, ProtocolVersionId, VersionPatch}, - L1BatchNumber, L2ChainId, SLChainId, + L1BatchNumber, L1ChainId, L2ChainId, SLChainId, }; use zksync_consensus_utils::EncodeDist; use zksync_crypto_primitives::K256PrivateKey; @@ -701,7 +701,8 @@ impl Distribution for EncodeDist { bootloader_hash: Some(rng.gen()), default_aa_hash: Some(rng.gen()), fee_account: rng.gen(), - l1_chain_id: SLChainId(self.sample(rng)), + 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(), @@ -873,7 +874,8 @@ impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> configs::en_config::ENConfig { configs::en_config::ENConfig { l2_chain_id: L2ChainId::default(), - l1_chain_id: SLChainId(rng.gen()), + l1_chain_id: L1ChainId(rng.gen()), + sl_chain_id: Some(SLChainId(rng.gen())), 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..543173f8d9e3 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(), + // FIXME: double check whether we can remove it + l1_chain_id: L1ChainId(9), + 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/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index 9c717042af34..542b42420ae3 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -22,7 +22,7 @@ impl PKSigningClient { operator_private_key: K256PrivateKey, diamond_proxy_addr: Address, default_priority_fee_per_gas: u64, - l1_chain_id: SLChainId, + 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, ) } } diff --git a/core/lib/protobuf_config/src/en.rs b/core/lib/protobuf_config/src/en.rs index 0831bc9017a9..2a210a3093cb 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -4,6 +4,7 @@ use anyhow::Context; use zksync_basic_types::{url::SensitiveUrl, L2ChainId, SLChainId}; use zksync_config::configs::en_config::ENConfig; use zksync_protobuf::{required, ProtoRepr}; +use zksync_types::L1ChainId; use crate::proto::en as proto; @@ -16,8 +17,14 @@ impl ProtoRepr for proto::ExternalNode { required(&self.main_node_url).context("main_node_url")?, )?, l1_chain_id: required(&self.l1_chain_id) - .map(|x| SLChainId(*x)) + .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, + // For now, the settlement layer is always the same as the L1 network + sl_chain_id: Some( + required(&self.l1_chain_id) + .map(|x| SLChainId(*x)) + .context("l1_chain_id")?, + ), 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 ed6d00978284..261200af1f40 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -7,6 +7,7 @@ use zksync_basic_types::{ }; use zksync_config::configs; use zksync_protobuf::{repr::ProtoRepr, required}; +use zksync_types::L1ChainId; use crate::{parse_h160, parse_h256, proto::genesis as proto}; @@ -69,8 +70,14 @@ impl ProtoRepr for proto::Genesis { .context("default_aa_hash")?, ), l1_chain_id: required(&self.l1_chain_id) - .map(|x| SLChainId(*x)) + .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, + // For now, the settlement layer is always the same as the L1 network + sl_chain_id: Some( + required(&self.l1_chain_id) + .map(|x| SLChainId(*x)) + .context("l1_chain_id")?, + ), 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 2726599f7b23..82136689d1d0 100644 --- a/core/lib/web3_decl/src/client/network.rs +++ b/core/lib/web3_decl/src/client/network.rs @@ -12,7 +12,8 @@ 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); diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index 17175affa0f6..a55ed0c62ce1 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -150,6 +150,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/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 39c14c34f86d..7c51f9f76919 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}; @@ -174,7 +174,8 @@ pub fn mock_genesis_config() -> GenesisConfig { genesis_commitment: Some(H256::default()), bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), - l1_chain_id: SLChainId(9), + 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 c3be45591040..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 @@ -19,7 +19,7 @@ use crate::{ pub struct PKSigningEthClientLayer { eth_sender_config: EthConfig, contracts_config: ContractsConfig, - l1_chain_id: SLChainId, + 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: SLChainId, + 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/validate_chain_ids.rs b/core/node/node_framework/src/implementations/layers/validate_chain_ids.rs index ef150fc85dca..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 @@ -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: SLChainId, + sl_chain_id: SLChainId, l2_chain_id: L2ChainId, } @@ -43,9 +43,9 @@ pub struct Output { } impl ValidateChainIdsLayer { - pub fn new(l1_chain_id: SLChainId, 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 cfca74695bf8..1ba2c64e270c 100644 --- a/core/node/node_sync/src/validate_chain_ids_task.rs +++ b/core/node/node_sync/src/validate_chain_ids_task.rs @@ -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: SLChainId, + 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: SLChainId, + 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"), @@ -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(); From 289472182bfd7fc1b7b7a45ecea4e23d03d72be0 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 11:53:35 +0200 Subject: [PATCH 03/43] a few small changes --- core/lib/env_config/src/genesis.rs | 4 ++-- core/lib/protobuf_config/src/en.rs | 2 +- core/lib/protobuf_config/src/genesis.rs | 2 +- core/node/node_sync/src/validate_chain_ids_task.rs | 6 +++--- core/tests/loadnext/src/sdk/ethereum/mod.rs | 6 +++--- core/tests/ts-integration/tests/api/web3.test.ts | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/lib/env_config/src/genesis.rs b/core/lib/env_config/src/genesis.rs index 543173f8d9e3..017d1fc46c1e 100644 --- a/core/lib/env_config/src/genesis.rs +++ b/core/lib/env_config/src/genesis.rs @@ -68,8 +68,8 @@ 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, - // FIXME: double check whether we can remove it - l1_chain_id: L1ChainId(9), + // TODO(X): 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, diff --git a/core/lib/protobuf_config/src/en.rs b/core/lib/protobuf_config/src/en.rs index 2a210a3093cb..5e5ff5d5ca5e 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -19,7 +19,7 @@ impl ProtoRepr for proto::ExternalNode { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, - // For now, the settlement layer is always the same as the L1 network + // TODO(X): for now, the settlement layer is always the same as the L1 network sl_chain_id: Some( required(&self.l1_chain_id) .map(|x| SLChainId(*x)) diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 261200af1f40..4bea0fd113e0 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -72,7 +72,7 @@ impl ProtoRepr for proto::Genesis { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, - // For now, the settlement layer is always the same as the L1 network + // TODO(X): for now, the settlement layer is always the same as the L1 network sl_chain_id: Some( required(&self.l1_chain_id) .map(|x| SLChainId(*x)) 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 1ba2c64e270c..0f80bf799b15 100644 --- a/core/node/node_sync/src/validate_chain_ids_task.rs +++ b/core/node/node_sync/src/validate_chain_ids_task.rs @@ -187,7 +187,7 @@ mod tests { .build(); let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_SLChainId", || Ok(U64::from(3))) + .method("zks_L1ChainId", || Ok(U64::from(3))) .build(); let validation_task = ValidateChainIdsTask::new( @@ -225,7 +225,7 @@ mod tests { let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_SLChainId", || Ok(U64::from(9))) + .method("zks_L1ChainId", || Ok(U64::from(9))) .build(); let validation_task = ValidateChainIdsTask::new( @@ -252,7 +252,7 @@ mod tests { .build(); let main_node_client = MockClient::builder(L2::default()) .method("eth_chainId", || Ok(U64::from(270))) - .method("zks_SLChainId", || Ok(U64::from(9))) + .method("zks_L1ChainId", || Ok(U64::from(9))) .build(); let validation_task = ValidateChainIdsTask::new( diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index e5c18510c2ef..31fcc5269774 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -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 = SLChainId(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/core/tests/ts-integration/tests/api/web3.test.ts b/core/tests/ts-integration/tests/api/web3.test.ts index c70ef8b629e4..569321d548ce 100644 --- a/core/tests/ts-integration/tests/api/web3.test.ts +++ b/core/tests/ts-integration/tests/api/web3.test.ts @@ -118,7 +118,7 @@ describe('web3 API compatibility tests', () => { const tokenBalance = await alice.getBalance(l2Token); expect(balances[l2Token.toLowerCase()] == tokenBalance); } - // zks_SLChainId + // zks_L1ChainId const l1ChainId = (await alice.providerL1!.getNetwork()).chainId; const l1ChainIdFromL2Provider = BigInt(await alice.provider.l1ChainId()); expect(l1ChainId).toEqual(l1ChainIdFromL2Provider); From 338eade887ebfb43a12e1765683dadc4b4217539 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 12:55:21 +0200 Subject: [PATCH 04/43] fix lint --- core/lib/protobuf_config/src/genesis.rs | 8 +------- core/node/api_server/src/web3/state.rs | 2 +- core/node/genesis/src/lib.rs | 2 -- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 4bea0fd113e0..aa2b7a6bea4e 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use anyhow::Context as _; use zksync_basic_types::{ commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion, L2ChainId, - SLChainId, }; use zksync_config::configs; use zksync_protobuf::{repr::ProtoRepr, required}; @@ -72,12 +71,7 @@ impl ProtoRepr for proto::Genesis { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, - // TODO(X): for now, the settlement layer is always the same as the L1 network - sl_chain_id: Some( - required(&self.l1_chain_id) - .map(|x| SLChainId(*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/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 41dd4b0c6c0e..b0e74706e523 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -21,7 +21,7 @@ use zksync_metadata_calculator::api_server::TreeApiClient; use zksync_node_sync::SyncState; use zksync_types::{ api, commitment::L1BatchCommitmentMode, l2::L2Tx, transaction_request::CallRequest, Address, - L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId, SLChainId, H256, U256, U64, + L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId, H256, U256, U64, }; use zksync_web3_decl::{error::Web3Error, types::Filter}; diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 7c51f9f76919..dcb9ba2c012f 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -159,8 +159,6 @@ pub struct GenesisBatchParams { } pub fn mock_genesis_config() -> GenesisConfig { - use zksync_types::SLChainId; - let base_system_contracts_hashes = BaseSystemContracts::load_from_disk().hashes(); let first_l1_verifier_config = L1VerifierConfig::default(); From d1d3beb9ecb5e6661afdb55ae31ef3e417153c0a Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 12:59:52 +0200 Subject: [PATCH 05/43] remove inconsistency --- core/lib/protobuf_config/src/en.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/lib/protobuf_config/src/en.rs b/core/lib/protobuf_config/src/en.rs index 5e5ff5d5ca5e..7c0fd73ec602 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -19,12 +19,7 @@ impl ProtoRepr for proto::ExternalNode { l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, - // TODO(X): for now, the settlement layer is always the same as the L1 network - sl_chain_id: Some( - required(&self.l1_chain_id) - .map(|x| SLChainId(*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")?, From e9e8b9e5889a91445b206f2919a32798c0eb47a7 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 15:18:41 +0200 Subject: [PATCH 06/43] upd pr --- core/bin/external_node/src/config/mod.rs | 2 +- core/bin/external_node/src/main.rs | 7 ++++--- core/bin/external_node/src/metrics/framework.rs | 10 ++++++++-- core/bin/external_node/src/metrics/mod.rs | 7 +++++-- core/bin/external_node/src/node_builder.rs | 7 ++++--- core/bin/zksync_server/src/node_builder.rs | 4 ++-- core/lib/config/src/configs/genesis.rs | 2 +- core/lib/protobuf_config/src/en.rs | 3 +-- core/lib/protobuf_config/src/genesis.rs | 4 ++-- 9 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 8d5f28ab5f78..b0f0fa794fa1 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -934,7 +934,7 @@ pub(crate) struct RequiredENConfig { } impl RequiredENConfig { - pub fn get_settlement_layer_id(&self) -> SLChainId { + pub fn settlement_layer_id(&self) -> SLChainId { self.sl_chain_id.unwrap_or(self.l1_chain_id.into()) } diff --git a/core/bin/external_node/src/main.rs b/core/bin/external_node/src/main.rs index e60dca287c78..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.get_settlement_layer_id().into()) + .for_network(config.required.settlement_layer_id().into()) .build(); let eth_client = Box::new(eth_client); @@ -879,7 +879,8 @@ async fn main() -> anyhow::Result<()> { RUST_METRICS.initialize(); EN_METRICS.observe_config( - config.required.get_settlement_layer_id(), + 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.get_settlement_layer_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 9baa5d7157ba..fc9d4fe51345 100644 --- a/core/bin/external_node/src/metrics/framework.rs +++ b/core/bin/external_node/src/metrics/framework.rs @@ -6,12 +6,13 @@ use zksync_node_framework::{ FromContext, IntoContext, StopReceiver, Task, TaskId, WiringError, WiringLayer, }; use zksync_shared_metrics::rustc::RUST_METRICS; -use zksync_types::{L2ChainId, SLChainId}; +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.sl_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 aa7e7b6b6c1e..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::{L2ChainId, SLChainId}; +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, @@ -31,13 +32,15 @@ pub(crate) struct ExternalNodeMetrics { 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: sl_chain_id.0, + 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 d6387a57a485..d71a9f0cdf57 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -120,7 +120,8 @@ impl ExternalNodeBuilder { fn add_external_node_metrics_layer(mut self) -> anyhow::Result { self.node.add_layer(ExternalNodeMetricsLayer { - sl_chain_id: self.config.required.get_settlement_layer_id(), + 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.get_settlement_layer_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.get_settlement_layer_id(), + self.config.required.settlement_layer_id(), self.config.required.l2_chain_id, ); self.node.add_layer(layer); diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 6a0f05de5580..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.get_settlement_layer_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.get_settlement_layer_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/config/src/configs/genesis.rs b/core/lib/config/src/configs/genesis.rs index 1ac4e376a55f..2c5c91128431 100644 --- a/core/lib/config/src/configs/genesis.rs +++ b/core/lib/config/src/configs/genesis.rs @@ -27,7 +27,7 @@ pub struct GenesisConfig { } impl GenesisConfig { - pub fn get_settlement_layer_id(&self) -> SLChainId { + pub fn settlement_layer_id(&self) -> SLChainId { self.sl_chain_id.unwrap_or(self.l1_chain_id.into()) } } diff --git a/core/lib/protobuf_config/src/en.rs b/core/lib/protobuf_config/src/en.rs index 7c0fd73ec602..b006dc61d6b7 100644 --- a/core/lib/protobuf_config/src/en.rs +++ b/core/lib/protobuf_config/src/en.rs @@ -1,10 +1,9 @@ use std::{num::NonZeroUsize, str::FromStr}; use anyhow::Context; -use zksync_basic_types::{url::SensitiveUrl, L2ChainId, SLChainId}; +use zksync_basic_types::{url::SensitiveUrl, L1ChainId, L2ChainId}; use zksync_config::configs::en_config::ENConfig; use zksync_protobuf::{required, ProtoRepr}; -use zksync_types::L1ChainId; use crate::proto::en as proto; diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index aa2b7a6bea4e..92f639aa224e 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -2,11 +2,11 @@ use std::str::FromStr; use anyhow::Context as _; use zksync_basic_types::{ - commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion, L2ChainId, + commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion, L1ChainId, + L2ChainId, }; use zksync_config::configs; use zksync_protobuf::{repr::ProtoRepr, required}; -use zksync_types::L1ChainId; use crate::{parse_h160, parse_h256, proto::genesis as proto}; From d827bbcdc2760a40e8b237030b1f370b8361affe Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 15:48:04 +0200 Subject: [PATCH 07/43] hopefully fix lint --- zk_toolbox/crates/config/src/genesis.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zk_toolbox/crates/config/src/genesis.rs b/zk_toolbox/crates/config/src/genesis.rs index 4f0ca7d3e2c0..6dcc3b3bbb71 100644 --- a/zk_toolbox/crates/config/src/genesis.rs +++ b/zk_toolbox/crates/config/src/genesis.rs @@ -1,7 +1,7 @@ use std::path::Path; use xshell::Shell; -use zksync_basic_types::SLChainId; +use zksync_basic_types::L1ChainId; pub use zksync_config::GenesisConfig; use zksync_protobuf_config::{decode_yaml_repr, encode_yaml_repr}; @@ -13,7 +13,8 @@ use crate::{ pub fn update_from_chain_config(genesis: &mut GenesisConfig, config: &ChainConfig) { genesis.l2_chain_id = config.chain_id; - genesis.l1_chain_id = SLChainId(config.l1_network.chain_id()); + // TODO(X): for now, the settlement layer is always the same as the L1 network + genesis.l1_chain_id = L1ChainId(config.l1_network.chain_id().0); genesis.l1_batch_commit_data_generator_mode = config.l1_batch_commit_data_generator_mode; } From 709b06d5d33c5b95048b02ff18046ac45e0cf179 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 17:04:42 +0200 Subject: [PATCH 08/43] return none on tests --- core/lib/config/src/testonly.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 86720c0e3777..165f08359c75 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -875,7 +875,7 @@ impl Distribution for EncodeDist { configs::en_config::ENConfig { l2_chain_id: L2ChainId::default(), l1_chain_id: L1ChainId(rng.gen()), - sl_chain_id: Some(SLChainId(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, From 2cfffc654198e046f69c31c3c05b539c81b57486 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Wed, 31 Jul 2024 17:09:39 +0200 Subject: [PATCH 09/43] hopefully fix lint --- core/lib/config/src/testonly.rs | 2 +- zk_toolbox/crates/config/src/genesis.rs | 2 +- .../zk_inception/src/commands/external_node/prepare_configs.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 165f08359c75..ca07994cd0f7 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -6,7 +6,7 @@ use zksync_basic_types::{ commitment::L1BatchCommitmentMode, network::Network, protocol_version::{ProtocolSemanticVersion, ProtocolVersionId, VersionPatch}, - L1BatchNumber, L1ChainId, L2ChainId, SLChainId, + L1BatchNumber, L1ChainId, L2ChainId, }; use zksync_consensus_utils::EncodeDist; use zksync_crypto_primitives::K256PrivateKey; diff --git a/zk_toolbox/crates/config/src/genesis.rs b/zk_toolbox/crates/config/src/genesis.rs index 6dcc3b3bbb71..67d6275caba9 100644 --- a/zk_toolbox/crates/config/src/genesis.rs +++ b/zk_toolbox/crates/config/src/genesis.rs @@ -14,7 +14,7 @@ use crate::{ pub fn update_from_chain_config(genesis: &mut GenesisConfig, config: &ChainConfig) { genesis.l2_chain_id = config.chain_id; // TODO(X): for now, the settlement layer is always the same as the L1 network - genesis.l1_chain_id = L1ChainId(config.l1_network.chain_id().0); + 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 From f3d13a2f2df9f883e15a48c136bb3ea8aece20d0 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 15:06:07 +0200 Subject: [PATCH 10/43] apply diff for a new gas adjuster --- core/bin/external_node/src/node_builder.rs | 2 + core/bin/external_node/src/tests/utils.rs | 4 +- core/bin/zksync_server/src/main.rs | 1 + core/bin/zksync_server/src/node_builder.rs | 12 +- core/lib/config/src/configs/eth_sender.rs | 5 + core/lib/config/src/testonly.rs | 1 + ...be1aff592a9f2f102adafba99e1138fb7a6df.json | 29 ++ ...534014b9ab9ca7725e14fb17aa050d9f35eb8.json | 23 -- core/lib/dal/src/blocks_web3_dal.rs | 20 +- core/lib/env_config/src/eth_sender.rs | 1 + core/lib/eth_client/src/clients/http/decl.rs | 22 +- core/lib/eth_client/src/clients/http/mod.rs | 1 + core/lib/eth_client/src/clients/http/query.rs | 92 +++++- .../eth_client/src/clients/http/signing.rs | 17 +- core/lib/eth_client/src/clients/mock.rs | 262 +++++++++++++----- core/lib/eth_client/src/clients/mod.rs | 2 +- core/lib/eth_client/src/lib.rs | 34 ++- .../structures/commit_batch_info.rs | 37 ++- core/lib/protobuf_config/src/eth.rs | 4 + .../src/proto/config/eth_sender.proto | 2 + core/lib/types/src/api/mod.rs | 31 +++ core/lib/types/src/pubdata_da.rs | 3 + core/lib/web3_decl/src/client/mod.rs | 2 +- core/lib/web3_decl/src/namespaces/eth.rs | 7 +- .../web3/backend_jsonrpsee/namespaces/eth.rs | 6 +- .../api_server/src/web3/namespaces/eth.rs | 13 +- core/node/block_reverter/src/lib.rs | 2 +- .../src/validation_task.rs | 4 +- .../node/consistency_checker/src/tests/mod.rs | 8 +- .../eth_sender/src/abstract_l1_interface.rs | 13 +- core/node/eth_sender/src/eth_tx_aggregator.rs | 6 +- core/node/eth_sender/src/eth_tx_manager.rs | 7 +- core/node/eth_sender/src/tests.rs | 15 +- .../src/l1_gas_price/gas_adjuster/metrics.rs | 2 + .../src/l1_gas_price/gas_adjuster/mod.rs | 182 ++++++++++-- .../src/l1_gas_price/gas_adjuster/tests.rs | 163 ++++++++--- core/node/fee_model/src/l1_gas_price/mod.rs | 5 +- core/node/fee_model/src/lib.rs | 19 +- .../src/implementations/layers/l1_gas.rs | 18 +- .../layers/query_eth_client.rs | 55 +++- .../resources/eth_interface.rs | 20 +- core/node/state_keeper/src/io/tests/tester.rs | 17 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 2 +- etc/env/configs/dev2.toml | 21 ++ etc/env/configs/l1-hyperchain.template.toml | 12 + infrastructure/zk/src/database.ts | 2 +- infrastructure/zk/src/init.ts | 9 +- infrastructure/zk/src/setup_en.ts | 2 +- 48 files changed, 944 insertions(+), 273 deletions(-) create mode 100644 core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json delete mode 100644 core/lib/dal/.sqlx/query-83a931ceddf34e1c760649d613f534014b9ab9ca7725e14fb17aa050d9f35eb8.json create mode 100644 etc/env/configs/dev2.toml create mode 100644 etc/env/configs/l1-hyperchain.template.toml diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index d71a9f0cdf57..02372fccf0c6 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -169,6 +169,8 @@ impl ExternalNodeBuilder { let query_eth_client_layer = QueryEthClientLayer::new( self.config.required.settlement_layer_id(), self.config.required.eth_client_url.clone(), + // TODO: add this config for external node + true, ); self.node.add_layer(query_eth_client_layer); Ok(self) diff --git a/core/bin/external_node/src/tests/utils.rs b/core/bin/external_node/src/tests/utils.rs index 3784fea4763b..ee92a4b802a6 100644 --- a/core/bin/external_node/src/tests/utils.rs +++ b/core/bin/external_node/src/tests/utils.rs @@ -1,7 +1,7 @@ use tempfile::TempDir; use zksync_dal::CoreDal; use zksync_db_connection::connection_pool::TestTemplate; -use zksync_eth_client::clients::MockEthereum; +use zksync_eth_client::clients::MockSettlementLayer; use zksync_node_genesis::{insert_genesis_batch, GenesisBatchParams, GenesisParams}; use zksync_types::{ api, block::L2BlockHeader, ethabi, Address, L2BlockNumber, ProtocolVersionId, H256, @@ -119,7 +119,7 @@ pub(super) fn expected_health_components(components: &ComponentsToRun) -> Vec<&' } pub(super) fn mock_eth_client(diamond_proxy_addr: Address) -> MockClient { - let mock = MockEthereum::builder().with_call_handler(move |call, _| { + let mock = MockSettlementLayer::builder().with_call_handler(move |call, _| { tracing::info!("L1 call: {call:?}"); if call.to == Some(diamond_proxy_addr) { let packed_semver = ProtocolVersionId::latest().into_packed_semver_with_patch(0); diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index d9096f6f67df..8915e059dba4 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -26,6 +26,7 @@ use zksync_core_leftovers::{ Component, Components, }; use zksync_env_config::FromEnv; +use zksync_eth_client::clients::{Client, L1}; use crate::node_builder::MainNodeBuilder; diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index c0bf74946609..578f2b6a17aa 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -151,8 +151,16 @@ impl MainNodeBuilder { fn add_query_eth_client_layer(mut self) -> anyhow::Result { let genesis = self.genesis_config.clone(); let eth_config = try_load_config!(self.secrets.l1); - let query_eth_client_layer = - QueryEthClientLayer::new(genesis.settlement_layer_id(), eth_config.l1_rpc_url); + let query_eth_client_layer = QueryEthClientLayer::new( + genesis.l1_chain_id, + eth_config.l1_rpc_url, + self.configs + .eth + .as_ref() + .and_then(|x| x.gas_adjuster) + .and_then(|x| x.l2_mode) + .unwrap_or_default(), + ); self.node.add_layer(query_eth_client_layer); Ok(self) } diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index c0e14dd68a87..c18b2cd9f206 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -54,6 +54,7 @@ impl EthConfig { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, + l2_mode: Some(false), }), watcher: Some(EthWatchConfig { confirmations_for_eth_event: None, @@ -82,6 +83,7 @@ pub enum PubdataSendingMode { Calldata, Blobs, Custom, + RelayedL2Calldata, } #[derive(Debug, Deserialize, Clone, PartialEq)] @@ -181,6 +183,9 @@ pub struct GasAdjusterConfig { pub internal_pubdata_pricing_multiplier: f64, /// Max blob base fee that is allowed to be used. pub max_blob_base_fee: Option, + /// Whether the gas adjuster should require that the L2 node is used as a settlement layer. + /// It offers a runtime check for correctly provided values. + pub l2_mode: Option, } impl GasAdjusterConfig { diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 839853a6bd6a..57a405a6fbdd 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -397,6 +397,7 @@ impl Distribution for EncodeDist { num_samples_for_blob_base_fee_estimate: self.sample(rng), internal_pubdata_pricing_multiplier: self.sample(rng), max_blob_base_fee: self.sample(rng), + l2_mode: self.sample(rng), } } } diff --git a/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json b/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json new file mode 100644 index 000000000000..a5699d0b1ea7 --- /dev/null +++ b/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n base_fee_per_gas,\n gas_per_pubdata_limit\n FROM\n miniblocks\n WHERE\n number <= $1\n ORDER BY\n number DESC\n LIMIT\n $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "base_fee_per_gas", + "type_info": "Numeric" + }, + { + "ordinal": 1, + "name": "gas_per_pubdata_limit", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df" +} diff --git a/core/lib/dal/.sqlx/query-83a931ceddf34e1c760649d613f534014b9ab9ca7725e14fb17aa050d9f35eb8.json b/core/lib/dal/.sqlx/query-83a931ceddf34e1c760649d613f534014b9ab9ca7725e14fb17aa050d9f35eb8.json deleted file mode 100644 index 8d9458dce0a4..000000000000 --- a/core/lib/dal/.sqlx/query-83a931ceddf34e1c760649d613f534014b9ab9ca7725e14fb17aa050d9f35eb8.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n base_fee_per_gas\n FROM\n miniblocks\n WHERE\n number <= $1\n ORDER BY\n number DESC\n LIMIT\n $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "base_fee_per_gas", - "type_info": "Numeric" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - false - ] - }, - "hash": "83a931ceddf34e1c760649d613f534014b9ab9ca7725e14fb17aa050d9f35eb8" -} diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 2957701f9e23..3c9de96763c6 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -564,17 +564,18 @@ impl BlocksWeb3Dal<'_, '_> { .collect()) } - /// Returns `base_fee_per_gas` for L2 block range [min(newest_block - block_count + 1, 0), newest_block] + /// Returns `base_fee_per_gas` and `effective_pubdata_price` for L2 block range [min(newest_block - block_count + 1, 0), newest_block] /// in descending order of L2 block numbers. pub async fn get_fee_history( &mut self, newest_block: L2BlockNumber, block_count: u64, - ) -> DalResult> { + ) -> DalResult<(Vec, Vec)> { let result: Vec<_> = sqlx::query!( r#" SELECT - base_fee_per_gas + base_fee_per_gas, + gas_per_pubdata_limit FROM miniblocks WHERE @@ -593,10 +594,19 @@ impl BlocksWeb3Dal<'_, '_> { .fetch_all(self.storage) .await? .into_iter() - .map(|row| bigdecimal_to_u256(row.base_fee_per_gas)) + .map(|row| { + let base_fee_per_gas = bigdecimal_to_u256(row.base_fee_per_gas); + let effective_pubdata_price = + U256::from(row.gas_per_pubdata_limit as u64) * base_fee_per_gas; + + (base_fee_per_gas, effective_pubdata_price) + }) .collect(); - Ok(result) + let (base_fee_per_gas, effective_pubdata_price): (Vec, Vec) = + result.into_iter().unzip(); + + Ok((base_fee_per_gas, effective_pubdata_price)) } pub async fn get_block_details( diff --git a/core/lib/env_config/src/eth_sender.rs b/core/lib/env_config/src/eth_sender.rs index bd48f80609e8..f3a73bb24728 100644 --- a/core/lib/env_config/src/eth_sender.rs +++ b/core/lib/env_config/src/eth_sender.rs @@ -84,6 +84,7 @@ mod tests { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, + l2_mode: None, }), watcher: Some(EthWatchConfig { confirmations_for_eth_event: Some(0), diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index 77cc1c841e1b..7bb736d72eab 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -1,9 +1,12 @@ use jsonrpsee::proc_macros::rpc; -use zksync_types::{web3, Address, H256, U256, U64}; -use zksync_web3_decl::client::{ForNetwork, L1}; +use zksync_types::{ + api::{BlockDetails, L1BatchDetails}, + web3, Address, L1BatchNumber, L2BlockNumber, H256, U256, U64, +}; +use zksync_web3_decl::client::{ForNetwork, L1, L2}; /// Subset of the L1 `eth` namespace used by the L1 client. -#[rpc(client, namespace = "eth", client_bounds(Self: ForNetwork))] +#[rpc(client, namespace = "eth", client_bounds(Self: ForNetwork))] pub(super) trait L1EthNamespace { #[method(name = "chainId")] async fn chain_id(&self) -> RpcResult; @@ -66,3 +69,16 @@ pub(super) trait L1EthNamespace { hash: H256, ) -> RpcResult>; } + +/// Subset of the L2 `eth` namespace used by an L2 client. It may have the same +/// methods as the L1 `eth` namespace, but with extended return values. +#[rpc(client, namespace = "eth", client_bounds(Self: ForNetwork))] +pub(super) trait L2EthNamespace { + #[method(name = "feeHistory")] + async fn fee_history( + &self, + block_count: U64, + newest_block: web3::BlockNumber, + reward_percentiles: Option>, + ) -> RpcResult; +} diff --git a/core/lib/eth_client/src/clients/http/mod.rs b/core/lib/eth_client/src/clients/http/mod.rs index 2d1ed244afd4..111507c65f05 100644 --- a/core/lib/eth_client/src/clients/http/mod.rs +++ b/core/lib/eth_client/src/clients/http/mod.rs @@ -32,6 +32,7 @@ enum Method { #[metrics(name = "sign_prepared_tx_for_addr")] SignPreparedTx, Allowance, + L2FeeHistory, } #[derive(Debug, Metrics)] diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 65387ff00779..48ce5b0ac2a0 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -2,15 +2,20 @@ use std::fmt; use async_trait::async_trait; use jsonrpsee::core::ClientError; -use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; +use zksync_types::{web3, Address, L1ChainId, L2BlockNumber, H256, U256, U64}; use zksync_web3_decl::error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}; -use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; +use super::{ + decl::{L1EthNamespaceClient, L2EthNamespaceClient}, + Method, COUNTERS, LATENCIES, +}; use crate::{ types::{ExecutedTxStatus, FailureInfo}, - BaseFees, EthInterface, RawTransactionBytes, + BaseFees, EthInterface, L2Fees, RawTransactionBytes, ZkSyncInterface, }; +const FEE_HISTORY_MAX_REQUEST_CHUNK: usize = 1024; + #[async_trait] impl EthInterface for T where @@ -79,16 +84,6 @@ where upto_block: usize, block_count: usize, ) -> EnrichedClientResult> { - // Non-panicking conversion to u64. - fn cast_to_u64(value: U256, tag: &str) -> EnrichedClientResult { - u64::try_from(value).map_err(|_| { - let err = ClientError::Custom(format!("{tag} value does not fit in u64")); - EnrichedClientError::new(err, "cast_to_u64").with_arg("value", &value) - }) - } - - const MAX_REQUEST_CHUNK: usize = 1024; - COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); let mut history = Vec::with_capacity(block_count); @@ -97,8 +92,8 @@ where // Here we are requesting `fee_history` from blocks // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + MAX_REQUEST_CHUNK).min(upto_block); + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); let chunk_size = chunk_end - chunk_start; let fee_history = self @@ -354,6 +349,73 @@ where } } +#[async_trait::async_trait] +impl ZkSyncInterface for T +where + T: L2EthNamespaceClient + fmt::Debug + Send + Sync, +{ + async fn l2_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::L2FeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); + + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `FEE_HISTORY_MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; + + let fee_history = self + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + if fee_history.base_fee_per_gas.len() != fee_history.pubdata_price.len() { + tracing::error!( + "base_fee_per_gas and pubdata_price have different lengths: {} and {}", + fee_history.base_fee_per_gas.len(), + fee_history.pubdata_price.len() + ); + } + + for (base, pubdata_price) in fee_history + .base_fee_per_gas + .into_iter() + .zip(fee_history.pubdata_price) + { + let fees = L2Fees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + pubdata_price, + }; + history.push(fees) + } + } + + latency.observe(); + Ok(history) + } +} + +/// Non-panicking conversion to u64. +fn cast_to_u64(value: U256, tag: &str) -> EnrichedClientResult { + u64::try_from(value).map_err(|_| { + let err = ClientError::Custom(format!("{tag} value does not fit in u64")); + EnrichedClientError::new(err, "cast_to_u64").with_arg("value", &value) + }) +} #[cfg(test)] mod tests { use zksync_web3_decl::client::{Client, L1}; diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index 542b42420ae3..a955b2068854 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -74,6 +74,12 @@ impl fmt::Debug for SigningClient { } } +// impl AsRef for SigningClient { +// fn as_ref(&self) -> &dyn EthInterface { +// self.query_client.as_ref() as &dyn EthInterface +// } +// } + impl AsRef> for SigningClient { fn as_ref(&self) -> &DynClient { self.query_client.as_ref() @@ -81,12 +87,15 @@ impl AsRef> for SigningClient { } #[async_trait] -impl BoundEthInterface for SigningClient { - fn clone_boxed(&self) -> Box { +impl BoundEthInterface for SigningClient { + fn clone_boxed(&self) -> Box> { Box::new(self.clone()) } - fn for_component(self: Box, component_name: &'static str) -> Box { + fn for_component( + self: Box, + component_name: &'static str, + ) -> Box> { Box::new(Self { query_client: self.query_client.for_component(component_name), ..*self @@ -148,7 +157,7 @@ impl BoundEthInterface for SigningClient { let nonce = match options.nonce { Some(nonce) => nonce, - None => ::pending_nonce(self).await?, + None => >::pending_nonce(self).await?, }; let gas = options.gas.unwrap_or_else(|| { diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index d2d6b2108f53..a338e5d07ef5 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -1,20 +1,23 @@ use std::{ collections::{BTreeMap, HashMap}, fmt, + marker::PhantomData, sync::{Arc, RwLock, RwLockWriteGuard}, }; use jsonrpsee::{core::ClientError, types::ErrorObject}; +use zksync_config::configs::api; use zksync_types::{ + api::FeeHistory, ethabi, web3::{self, contract::Tokenize, BlockId}, Address, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, MockClient, L1}; +use zksync_web3_decl::client::{DynClient, MockClient, MockClientBuilder, Network, L1, L2}; use crate::{ types::{ContractCallError, SignedCallResult, SigningError}, - BaseFees, BoundEthInterface, Options, RawTransactionBytes, + BaseFees, BoundEthInterface, L2Fees, Options, RawTransactionBytes, }; #[derive(Debug, Clone)] @@ -131,7 +134,7 @@ impl MockEthereumInner { } fn get_transaction_count(&self, address: Address, block: web3::BlockNumber) -> U256 { - if address != MockEthereum::SENDER_ACCOUNT { + if address != MockSettlementLayer::::SENDER_ACCOUNT { unimplemented!("Getting nonce for custom account is not supported"); } @@ -221,19 +224,45 @@ impl MockExecutedTxHandle<'_> { type CallHandler = dyn Fn(&web3::CallRequest, BlockId) -> Result + Send + Sync; +#[derive(Debug, Clone)] +pub struct MockClientBaseFee { + pub base_fee_per_gas: u64, + pub base_fee_per_blob_gas: U256, + pub pubdata_price: U256, +} + +impl From for BaseFees { + fn from(value: MockClientBaseFee) -> Self { + Self { + base_fee_per_blob_gas: value.base_fee_per_blob_gas, + base_fee_per_gas: value.base_fee_per_gas, + } + } +} + +impl From for L2Fees { + fn from(value: MockClientBaseFee) -> Self { + Self { + base_fee_per_gas: value.base_fee_per_gas, + pubdata_price: value.pubdata_price, + } + } +} + /// Builder for [`MockEthereum`] client. -pub struct MockEthereumBuilder { +pub struct MockEthereumBuilder { max_fee_per_gas: U256, max_priority_fee_per_gas: U256, - base_fee_history: Vec, + base_fee_history: Vec, /// If true, the mock will not check the ordering nonces of the transactions. /// This is useful for testing the cases when the transactions are executed out of order. non_ordering_confirmations: bool, inner: Arc>, call_handler: Box, + _network: PhantomData, } -impl fmt::Debug for MockEthereumBuilder { +impl fmt::Debug for MockEthereumBuilder { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter .debug_struct("MockEthereumBuilder") @@ -249,7 +278,7 @@ impl fmt::Debug for MockEthereumBuilder { } } -impl Default for MockEthereumBuilder { +impl Default for MockEthereumBuilder { fn default() -> Self { Self { max_fee_per_gas: 100.into(), @@ -260,13 +289,14 @@ impl Default for MockEthereumBuilder { call_handler: Box::new(|call, block_id| { panic!("Unexpected eth_call: {call:?}, {block_id:?}"); }), + _network: PhantomData, } } } -impl MockEthereumBuilder { +impl MockEthereumBuilder { /// Sets fee history for each block in the mocked Ethereum network, starting from the 0th block. - pub fn with_fee_history(self, history: Vec) -> Self { + pub fn with_fee_history(self, history: Vec) -> Self { Self { base_fee_history: history, ..self @@ -308,7 +338,7 @@ impl MockEthereumBuilder { } fn get_block_by_number( - fee_history: &[BaseFees], + fee_history: &[MockClientBaseFee], block: web3::BlockNumber, ) -> Option> { let web3::BlockNumber::Number(number) = block else { @@ -330,11 +360,7 @@ impl MockEthereumBuilder { fn build_client(self) -> MockClient { const CHAIN_ID: SLChainId = SLChainId(9); - let base_fee_history = self.base_fee_history.clone(); - let call_handler = self.call_handler; - - MockClient::builder(CHAIN_ID.into()) - .method("eth_chainId", || Ok(U64::from(CHAIN_ID.0))) + MockClient::builder(network) .method("eth_blockNumber", { let inner = self.inner.clone(); move || Ok(U64::from(inner.read().unwrap().block_number)) @@ -355,30 +381,6 @@ impl MockEthereumBuilder { } }) .method("eth_gasPrice", move || Ok(self.max_fee_per_gas)) - .method( - "eth_feeHistory", - move |block_count: U64, newest_block: web3::BlockNumber, _: Option>| { - let web3::BlockNumber::Number(from_block) = newest_block else { - panic!("Non-numeric newest block in `eth_feeHistory`"); - }; - let from_block = from_block.as_usize(); - let start_block = from_block.saturating_sub(block_count.as_usize() - 1); - Ok(web3::FeeHistory { - oldest_block: start_block.into(), - base_fee_per_gas: base_fee_history[start_block..=from_block] - .iter() - .map(|fee| U256::from(fee.base_fee_per_gas)) - .collect(), - base_fee_per_blob_gas: base_fee_history[start_block..=from_block] - .iter() - .map(|fee| fee.base_fee_per_blob_gas) - .collect(), - gas_used_ratio: vec![], // not used - blob_gas_used_ratio: vec![], // not used - reward: None, - }) - }, - ) .method("eth_call", { let inner = self.inner.clone(); move |req, block| { @@ -410,42 +412,127 @@ impl MockEthereumBuilder { Ok(status.map(|status| status.receipt.clone())) } }) + } +} + +pub trait SupportedMockEthNetwork: Network { + fn build_client(builder: MockEthereumBuilder) -> MockClient; +} +impl SupportedMockEthNetwork for L1 { + fn build_client(builder: MockEthereumBuilder) -> MockClient { + const CHAIN_ID: L1ChainId = L1ChainId(9); + + let base_fee_history = builder.base_fee_history.clone(); + + builder + .build_client_inner(CHAIN_ID.0, CHAIN_ID.into()) + .method( + "eth_feeHistory", + move |block_count: U64, newest_block: web3::BlockNumber, _: Option>| { + let web3::BlockNumber::Number(from_block) = newest_block else { + panic!("Non-numeric newest block in `eth_feeHistory`"); + }; + let from_block = from_block.as_usize(); + let start_block = from_block.saturating_sub(block_count.as_usize() - 1); + Ok(web3::FeeHistory { + oldest_block: start_block.into(), + base_fee_per_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| U256::from(fee.base_fee_per_gas)) + .collect(), + base_fee_per_blob_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| fee.base_fee_per_blob_gas) + .collect(), + gas_used_ratio: vec![], // not used + blob_gas_used_ratio: vec![], // not used + reward: None, + }) + }, + ) + .build() + } +} + +impl SupportedMockEthNetwork for L2 { + fn build_client(builder: MockEthereumBuilder) -> MockClient { + const CHAIN_ID: L2ChainId = L2ChainId(9); + + let base_fee_history = builder.base_fee_history.clone(); + + builder + .build_client_inner(CHAIN_ID.0, CHAIN_ID.into()) + .method( + "eth_feeHistory", + move |block_count: U64, newest_block: web3::BlockNumber, _: Option>| { + let web3::BlockNumber::Number(from_block) = newest_block else { + panic!("Non-numeric newest block in `eth_feeHistory`"); + }; + let from_block = from_block.as_usize(); + let start_block = from_block.saturating_sub(block_count.as_usize() - 1); + Ok(FeeHistory { + oldest_block: start_block.into(), + base_fee_per_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| U256::from(fee.base_fee_per_gas)) + .collect(), + base_fee_per_blob_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| fee.base_fee_per_blob_gas) + .collect(), + gas_used_ratio: vec![], // not used + blob_gas_used_ratio: vec![], // not used + pubdata_price: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| fee.pubdata_price) + .collect(), + reward: None, + }) + }, + ) .build() } +} - /// Builds a mock Ethereum client. - pub fn build(self) -> MockEthereum { - MockEthereum { +impl MockEthereumBuilder { + pub fn build(self) -> MockSettlementLayer { + MockSettlementLayer { max_fee_per_gas: self.max_fee_per_gas, max_priority_fee_per_gas: self.max_priority_fee_per_gas, non_ordering_confirmations: self.non_ordering_confirmations, inner: self.inner.clone(), - client: self.build_client(), + client: Net::build_client(self), } } } /// Mock Ethereum client. #[derive(Debug, Clone)] -pub struct MockEthereum { +pub struct MockSettlementLayer { max_fee_per_gas: U256, max_priority_fee_per_gas: U256, non_ordering_confirmations: bool, inner: Arc>, - client: MockClient, + client: MockClient, } -impl Default for MockEthereum { +impl Default for MockSettlementLayer { fn default() -> Self { Self::builder().build() } } -impl MockEthereum { +impl Default for MockSettlementLayer { + fn default() -> Self { + Self::builder().build() + } +} + +impl MockSettlementLayer { const SENDER_ACCOUNT: Address = Address::repeat_byte(0x11); /// Initializes a builder for a [`MockEthereum`] instance. - pub fn builder() -> MockEthereumBuilder { + pub fn builder() -> MockEthereumBuilder { MockEthereumBuilder::default() } @@ -524,24 +611,27 @@ impl MockEthereum { } /// Converts this client into an immutable / contract-agnostic client. - pub fn into_client(self) -> MockClient { + pub fn into_client(self) -> MockClient { self.client } } -impl AsRef> for MockEthereum { - fn as_ref(&self) -> &DynClient { +impl AsRef> for MockSettlementLayer { + fn as_ref(&self) -> &DynClient { &self.client } } #[async_trait::async_trait] -impl BoundEthInterface for MockEthereum { - fn clone_boxed(&self) -> Box { +impl BoundEthInterface for MockSettlementLayer { + fn clone_boxed(&self) -> Box> { Box::new(self.clone()) } - fn for_component(self: Box, _component_name: &'static str) -> Box { + fn for_component( + self: Box, + _component_name: &'static str, + ) -> Box> { self } @@ -588,22 +678,23 @@ mod tests { use super::*; use crate::{CallFunctionArgs, EthInterface}; - fn base_fees(block: u64, blob: u64) -> BaseFees { - BaseFees { + fn base_fees(block: u64, blob: u64, pubdata_price: u64) -> MockClientBaseFee { + MockClientBaseFee { base_fee_per_gas: block, base_fee_per_blob_gas: U256::from(blob), + pubdata_price: U256::from(pubdata_price), } } #[tokio::test] async fn managing_block_number() { - let mock = MockEthereum::builder() + let mock = MockSettlementLayer::::builder() .with_fee_history(vec![ - base_fees(0, 4), - base_fees(1, 3), - base_fees(2, 2), - base_fees(3, 1), - base_fees(4, 0), + base_fees(0, 4, 0), + base_fees(1, 3, 0), + base_fees(2, 2, 0), + base_fees(3, 1, 0), + base_fees(4, 0, 0), ]) .build(); let block_number = mock.client.block_number().await.unwrap(); @@ -628,7 +719,7 @@ mod tests { #[tokio::test] async fn getting_chain_id() { - let mock = MockEthereum::builder().build(); + let mock = MockSettlementLayer::::builder().build(); let chain_id = mock.client.fetch_chain_id().await.unwrap(); assert_eq!(chain_id, SLChainId(9)); } @@ -636,28 +727,49 @@ mod tests { #[tokio::test] async fn managing_fee_history() { let initial_fee_history = vec![ - base_fees(1, 4), - base_fees(2, 3), - base_fees(3, 2), - base_fees(4, 1), - base_fees(5, 0), + base_fees(1, 4, 0), + base_fees(2, 3, 0), + base_fees(3, 2, 0), + base_fees(4, 1, 0), + base_fees(5, 0, 0), ]; - let client = MockEthereum::builder() + let client = MockSettlementLayer::::builder() .with_fee_history(initial_fee_history.clone()) .build(); client.advance_block_number(4); let fee_history = client.as_ref().base_fee_history(4, 4).await.unwrap(); - assert_eq!(fee_history, &initial_fee_history[1..=4]); + assert_eq!( + fee_history, + initial_fee_history[1..=4] + .into_iter() + .cloned() + .map(BaseFees::from) + .collect::>() + ); let fee_history = client.as_ref().base_fee_history(2, 2).await.unwrap(); - assert_eq!(fee_history, &initial_fee_history[1..=2]); + assert_eq!( + fee_history, + initial_fee_history[1..=2] + .into_iter() + .cloned() + .map(BaseFees::from) + .collect::>() + ); let fee_history = client.as_ref().base_fee_history(3, 2).await.unwrap(); - assert_eq!(fee_history, &initial_fee_history[2..=3]); + assert_eq!( + fee_history, + initial_fee_history[2..=3] + .into_iter() + .cloned() + .map(BaseFees::from) + .collect::>() + ); } #[tokio::test] async fn managing_transactions() { - let client = MockEthereum::builder() + let client = MockSettlementLayer::::builder() .with_non_ordering_confirmation(true) .build(); client.advance_block_number(2); @@ -710,7 +822,7 @@ mod tests { #[tokio::test] async fn calling_contracts() { - let client = MockEthereum::builder() + let client = MockSettlementLayer::builder() .with_call_handler(|req, _block_id| { let packed_semver = ProtocolVersionId::latest().into_packed_semver_with_patch(0); let call_signature = &req.data.as_ref().unwrap().0[..4]; @@ -759,7 +871,7 @@ mod tests { #[tokio::test] async fn getting_transaction_failure_reason() { - let client = MockEthereum::default(); + let client = MockSettlementLayer::::default(); let signed_tx = client .sign_prepared_tx( vec![1, 2, 3], diff --git a/core/lib/eth_client/src/clients/mod.rs b/core/lib/eth_client/src/clients/mod.rs index 05b7f852f391..8461ac772fc4 100644 --- a/core/lib/eth_client/src/clients/mod.rs +++ b/core/lib/eth_client/src/clients/mod.rs @@ -7,5 +7,5 @@ pub use zksync_web3_decl::client::{Client, DynClient, L1}; pub use self::{ http::{PKSigningClient, SigningClient}, - mock::{MockEthereum, MockEthereumBuilder}, + mock::{MockClientBaseFee, MockEthereumBuilder, MockSettlementLayer}, }; diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 3e8641845c61..3e15c77f055d 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -10,7 +10,7 @@ use zksync_types::{ }, Address, SLChainId, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, L1}; +use zksync_web3_decl::client::{DynClient, Network, L1}; pub use zksync_web3_decl::{ error::{EnrichedClientError, EnrichedClientResult}, jsonrpsee::core::ClientError, @@ -154,6 +154,23 @@ pub trait EthInterface: Sync + Send { async fn block(&self, block_id: BlockId) -> EnrichedClientResult>>; } +/// Information about the base fees provided by the L1 client. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct L2Fees { + pub base_fee_per_gas: u64, + pub pubdata_price: U256, +} + +#[async_trait] +pub trait ZkSyncInterface: Sync + Send { + /// Returns vector of pubdata prices (in wei) for a zkSync-based network. + async fn l2_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult>; +} + /// An extension of `EthInterface` trait, which is used to perform queries that are bound to /// a certain contract and account. /// @@ -168,13 +185,18 @@ pub trait EthInterface: Sync + Send { /// 2. Consider adding the "unbound" version to the `EthInterface` trait and create a default method /// implementation that invokes `contract` / `contract_addr` / `sender_account` methods. #[async_trait] -pub trait BoundEthInterface: AsRef> + 'static + Sync + Send + fmt::Debug { +pub trait BoundEthInterface: + AsRef> + 'static + Sync + Send + fmt::Debug +{ /// Clones this client. - fn clone_boxed(&self) -> Box; + fn clone_boxed(&self) -> Box>; /// Tags this client as working for a specific component. The component name can be used in logging, /// metrics etc. The component name should be copied to the clones of this client, but should not be passed upstream. - fn for_component(self: Box, component_name: &'static str) -> Box; + fn for_component( + self: Box, + component_name: &'static str, + ) -> Box>; /// ABI of the contract that is used by the implementer. fn contract(&self) -> ðabi::Contract; @@ -209,13 +231,13 @@ pub trait BoundEthInterface: AsRef> + 'static + Sync + Send + fmt: ) -> Result; } -impl Clone for Box { +impl Clone for Box> { fn clone(&self) -> Self { self.clone_boxed() } } -impl dyn BoundEthInterface { +impl dyn BoundEthInterface { /// Returns the nonce of the `Self::sender_account()` at the specified block. pub async fn nonce_at(&self, block: BlockNumber) -> EnrichedClientResult { self.as_ref() diff --git a/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs b/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs index b5d77ff60c16..b3f33a3454b1 100644 --- a/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs +++ b/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs @@ -202,12 +202,21 @@ impl Tokenizable for CommitBatchInfo<'_> { } else { tokens.push(Token::Bytes(match (self.mode, self.pubdata_da) { // Here we're not pushing any pubdata on purpose; no pubdata is sent in Validium mode. - (L1BatchCommitmentMode::Validium, PubdataDA::Calldata) => { - vec![PUBDATA_SOURCE_CALLDATA] - } - (L1BatchCommitmentMode::Validium, PubdataDA::Blobs) => { - vec![PUBDATA_SOURCE_BLOBS] - } + ( + L1BatchCommitmentMode::Validium, + PubdataDA::Calldata | PubdataDA::RelayedL2Calldata, + ) => self + .l1_batch_with_metadata + .metadata + .state_diff_hash + .0 + .into(), + (L1BatchCommitmentMode::Validium, PubdataDA::Blobs) => self + .l1_batch_with_metadata + .metadata + .state_diff_hash + .0 + .into(), (L1BatchCommitmentMode::Rollup, PubdataDA::Custom) => { panic!("Custom pubdata DA is incompatible with Rollup mode") @@ -216,7 +225,21 @@ impl Tokenizable for CommitBatchInfo<'_> { vec![PUBDATA_SOURCE_CUSTOM] } - (L1BatchCommitmentMode::Rollup, PubdataDA::Calldata) => { + ( + L1BatchCommitmentMode::Rollup, + PubdataDA::Calldata | PubdataDA::RelayedL2Calldata, + ) => { + let pubdata = self.pubdata_input(); + + let header = compose_header_for_l1_commit_rollup( + self.l1_batch_with_metadata + .metadata + .state_diff_hash + .0 + .into(), + pubdata.clone(), + ); + // We compute and add the blob commitment to the pubdata payload so that we can verify the proof // even if we are not using blobs. let pubdata = self.pubdata_input(); diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index b713e650d019..1a31ae2bd08e 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -31,6 +31,7 @@ impl proto::PubdataSendingMode { From::Calldata => Self::Calldata, From::Blobs => Self::Blobs, From::Custom => Self::Custom, + From::RelayedL2Calldata => Self::RelayedL2Calldata, } } @@ -40,6 +41,7 @@ impl proto::PubdataSendingMode { Self::Calldata => To::Calldata, Self::Blobs => To::Blobs, Self::Custom => To::Custom, + Self::RelayedL2Calldata => To::RelayedL2Calldata, } } } @@ -174,6 +176,7 @@ impl ProtoRepr for proto::GasAdjuster { ) .context("internal_pubdata_pricing_multiplier")?, max_blob_base_fee: self.max_blob_base_fee, + l2_mode: self.l2_mode, }) } @@ -195,6 +198,7 @@ impl ProtoRepr for proto::GasAdjuster { ), internal_pubdata_pricing_multiplier: Some(this.internal_pubdata_pricing_multiplier), max_blob_base_fee: this.max_blob_base_fee, + l2_mode: this.l2_mode, } } } diff --git a/core/lib/protobuf_config/src/proto/config/eth_sender.proto b/core/lib/protobuf_config/src/proto/config/eth_sender.proto index 839c7f65b973..5af091b8bed2 100644 --- a/core/lib/protobuf_config/src/proto/config/eth_sender.proto +++ b/core/lib/protobuf_config/src/proto/config/eth_sender.proto @@ -24,6 +24,7 @@ enum PubdataSendingMode { CALLDATA = 0; BLOBS = 1; CUSTOM = 2; + RELAYED_L2_CALLDATA = 3; } message Sender { @@ -60,6 +61,7 @@ message GasAdjuster { optional uint64 num_samples_for_blob_base_fee_estimate = 9; // required; optional double internal_pubdata_pricing_multiplier = 10; // required; optional uint64 max_blob_base_fee = 11; // optional; wei + optional bool l2_mode = 13; // optional } message ETHWatch { diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index 751de9bd7040..feaa069d24bb 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -834,6 +834,37 @@ pub struct TransactionExecutionInfo { pub execution_info: Value, } +/// The fee history type returned from `eth_feeHistory` call. +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct FeeHistory { + /// Lowest number block of the returned range. + pub oldest_block: BlockNumber, + /// A vector of block base fees per gas. This includes the next block after the newest of the returned range, + /// because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks. + #[serde(default)] // some node implementations skip empty lists + pub base_fee_per_gas: Vec, + /// A vector of block gas used ratios. These are calculated as the ratio of gas used and gas limit. + #[serde(default)] // some node implementations skip empty lists + pub gas_used_ratio: Vec, + /// A vector of effective priority fee per gas data points from a single block. All zeroes are returned if + /// the block is empty. Returned only if requested. + pub reward: Option>>, + /// An array of base fees per blob gas for blocks. This includes the next block following the newest in the + /// returned range, as this value can be derived from the latest block. For blocks before EIP-4844, zeroes + /// are returned. + #[serde(default)] // some node implementations skip empty lists + pub base_fee_per_blob_gas: Vec, + /// An array showing the ratios of blob gas used in blocks. These ratios are calculated by dividing blobGasUsed + /// by the maximum blob gas per block. + #[serde(default)] // some node implementations skip empty lists + pub blob_gas_used_ratio: Vec, + + /// An array of effective pubdata price. Note, that this field is L2-specific and only provided by L2 nodes. + #[serde(default)] + pub pubdata_price: Vec, +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/lib/types/src/pubdata_da.rs b/core/lib/types/src/pubdata_da.rs index 6705fdc29530..bc7dc55e53de 100644 --- a/core/lib/types/src/pubdata_da.rs +++ b/core/lib/types/src/pubdata_da.rs @@ -15,6 +15,8 @@ pub enum PubdataDA { Blobs, /// Pubdata is sent to the external storage (GCS/DA layers) or not sent at all. Custom, + /// Pubdata is sent to an L2 to be eventually relayed to L1. + RelayedL2Calldata, } impl From for PubdataDA { @@ -23,6 +25,7 @@ impl From for PubdataDA { PubdataSendingMode::Calldata => PubdataDA::Calldata, PubdataSendingMode::Blobs => PubdataDA::Blobs, PubdataSendingMode::Custom => PubdataDA::Custom, + PubdataSendingMode::RelayedL2Calldata => PubdataDA::RelayedL2Calldata, } } } diff --git a/core/lib/web3_decl/src/client/mod.rs b/core/lib/web3_decl/src/client/mod.rs index ca861e77fdfe..9290bad5878f 100644 --- a/core/lib/web3_decl/src/client/mod.rs +++ b/core/lib/web3_decl/src/client/mod.rs @@ -37,7 +37,7 @@ use zksync_types::url::SensitiveUrl; use self::metrics::{L2ClientMetrics, METRICS}; pub use self::{ boxed::{DynClient, ObjectSafeClient}, - mock::MockClient, + mock::{MockClient, MockClientBuilder}, network::{ForNetwork, Network, TaggedClient, L1, L2}, shared::Shared, }; diff --git a/core/lib/web3_decl/src/namespaces/eth.rs b/core/lib/web3_decl/src/namespaces/eth.rs index 10443443958b..b4007006c8e0 100644 --- a/core/lib/web3_decl/src/namespaces/eth.rs +++ b/core/lib/web3_decl/src/namespaces/eth.rs @@ -3,8 +3,8 @@ use jsonrpsee::core::RpcResult; use jsonrpsee::proc_macros::rpc; use zksync_types::{ api::{ - state_override::StateOverride, BlockId, BlockIdVariant, BlockNumber, Transaction, - TransactionVariant, + state_override::StateOverride, BlockId, BlockIdVariant, BlockNumber, FeeHistory, + Transaction, TransactionVariant, }, transaction_request::CallRequest, Address, H256, @@ -13,8 +13,7 @@ use zksync_types::{ use crate::{ client::{ForNetwork, L2}, types::{ - Block, Bytes, FeeHistory, Filter, FilterChanges, Index, Log, SyncState, TransactionReceipt, - U256, U64, + Block, Bytes, Filter, FilterChanges, Index, Log, SyncState, TransactionReceipt, U256, U64, }, }; diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs index ff8ce0356a05..15528c5b309b 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs @@ -1,10 +1,10 @@ use zksync_types::{ api::{ - state_override::StateOverride, Block, BlockId, BlockIdVariant, BlockNumber, Log, - Transaction, TransactionId, TransactionReceipt, TransactionVariant, + state_override::StateOverride, Block, BlockId, BlockIdVariant, BlockNumber, FeeHistory, + Log, Transaction, TransactionId, TransactionReceipt, TransactionVariant, }, transaction_request::CallRequest, - web3::{Bytes, FeeHistory, Index, SyncState}, + web3::{Bytes, Index, SyncState}, Address, H256, U256, U64, }; use zksync_web3_decl::{ diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index 68030763fd60..97adc2fedb5a 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -3,13 +3,13 @@ use zksync_dal::{CoreDal, DalError}; use zksync_system_constants::DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE; use zksync_types::{ api::{ - state_override::StateOverride, BlockId, BlockNumber, GetLogsFilter, Transaction, - TransactionId, TransactionReceipt, TransactionVariant, + state_override::StateOverride, BlockId, BlockNumber, FeeHistory, GetLogsFilter, + Transaction, TransactionId, TransactionReceipt, TransactionVariant, }, l2::{L2Tx, TransactionType}, transaction_request::CallRequest, utils::decompose_full_nonce, - web3::{self, Bytes, FeeHistory, SyncInfo, SyncState}, + web3::{Bytes, SyncInfo, SyncState}, AccountTreeId, L2BlockNumber, StorageKey, H256, L2_BASE_TOKEN_ADDRESS, U256, }; use zksync_utils::u256_to_h256; @@ -678,13 +678,15 @@ impl EthNamespace { .await?; self.set_block_diff(newest_l2_block); - let mut base_fee_per_gas = connection + let (mut base_fee_per_gas, mut effective_pubdata_price_history) = connection .blocks_web3_dal() .get_fee_history(newest_l2_block, block_count) .await .map_err(DalError::generalize)?; + // DAL method returns fees in DESC order while we need ASC. base_fee_per_gas.reverse(); + effective_pubdata_price_history.reverse(); let oldest_block = newest_l2_block.0 + 1 - base_fee_per_gas.len() as u32; // We do not store gas used ratio for blocks, returns array of zeroes as a placeholder. @@ -702,12 +704,13 @@ impl EthNamespace { // `base_fee_per_gas` for next L2 block cannot be calculated, appending last fee as a placeholder. base_fee_per_gas.push(*base_fee_per_gas.last().unwrap()); Ok(FeeHistory { - oldest_block: web3::BlockNumber::Number(oldest_block.into()), + oldest_block: zksync_types::api::BlockNumber::Number(oldest_block.into()), base_fee_per_gas, gas_used_ratio, reward, base_fee_per_blob_gas, blob_gas_used_ratio, + pubdata_price: effective_pubdata_price_history, }) } diff --git a/core/node/block_reverter/src/lib.rs b/core/node/block_reverter/src/lib.rs index da1bf091ea3b..86209f8a9ee6 100644 --- a/core/node/block_reverter/src/lib.rs +++ b/core/node/block_reverter/src/lib.rs @@ -469,7 +469,7 @@ impl BlockReverter { /// Sends a revert transaction to L1. pub async fn send_ethereum_revert_transaction( &self, - eth_client: &dyn BoundEthInterface, + eth_client: &dyn BoundEthInterface, eth_config: &BlockReverterEthConfig, last_l1_batch_to_keep: L1BatchNumber, nonce: u64, diff --git a/core/node/commitment_generator/src/validation_task.rs b/core/node/commitment_generator/src/validation_task.rs index cf93a4899b89..8e18e3493873 100644 --- a/core/node/commitment_generator/src/validation_task.rs +++ b/core/node/commitment_generator/src/validation_task.rs @@ -124,7 +124,7 @@ impl L1BatchCommitmentModeValidationTask { mod tests { use std::{mem, sync::Mutex}; - use zksync_eth_client::clients::MockEthereum; + use zksync_eth_client::clients::MockSettlementLayer; use zksync_types::{ethabi, U256}; use zksync_web3_decl::{client::MockClient, jsonrpsee::types::ErrorObject}; @@ -132,7 +132,7 @@ mod tests { fn mock_ethereum(token: ethabi::Token, err: Option) -> MockClient { let err_mutex = Mutex::new(err); - MockEthereum::builder() + MockSettlementLayer::builder() .with_fallible_call_handler(move |_, _| { let err = mem::take(&mut *err_mutex.lock().unwrap()); if let Some(err) = err { diff --git a/core/node/consistency_checker/src/tests/mod.rs b/core/node/consistency_checker/src/tests/mod.rs index 914e21069bdd..1e8a1fae94c4 100644 --- a/core/node/consistency_checker/src/tests/mod.rs +++ b/core/node/consistency_checker/src/tests/mod.rs @@ -7,7 +7,7 @@ use test_casing::{test_casing, Product}; use tokio::sync::mpsc; use zksync_config::GenesisConfig; use zksync_dal::Connection; -use zksync_eth_client::{clients::MockEthereum, Options}; +use zksync_eth_client::{clients::MockSettlementLayer, Options}; use zksync_l1_contract_interface::{i_executor::methods::CommitBatches, Tokenizable, Tokenize}; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{ @@ -92,7 +92,7 @@ pub(crate) fn build_commit_tx_input_data( } pub(crate) fn create_mock_checker( - client: MockEthereum, + client: MockSettlementLayer, pool: ConnectionPool, commitment_mode: L1BatchCommitmentMode, ) -> ConsistencyChecker { @@ -111,8 +111,8 @@ pub(crate) fn create_mock_checker( } } -fn create_mock_ethereum() -> MockEthereum { - let mock = MockEthereum::builder().with_call_handler(|call, _block_id| { +fn create_mock_ethereum() -> MockSettlementLayer { + let mock = MockSettlementLayer::builder().with_call_handler(|call, _block_id| { assert_eq!(call.to, Some(DIAMOND_PROXY_ADDR)); let packed_semver = ProtocolVersionId::latest().into_packed_semver_with_patch(0); let contract = zksync_contracts::hyperchain_contract(); diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index 9c9af82553e9..b85961086569 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -78,15 +78,15 @@ pub(super) trait AbstractL1Interface: 'static + Sync + Send + fmt::Debug { async fn get_l1_block_numbers(&self) -> Result; - fn ethereum_gateway(&self) -> &dyn BoundEthInterface; + fn ethereum_gateway(&self) -> &dyn BoundEthInterface; - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface>; + fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface>; } #[derive(Debug)] pub(super) struct RealL1Interface { - pub ethereum_gateway: Box, - pub ethereum_gateway_blobs: Option>, + pub ethereum_gateway: Box>, + pub ethereum_gateway_blobs: Option>>, pub wait_confirmations: Option, } @@ -103,6 +103,7 @@ impl RealL1Interface { } } } + #[async_trait] impl AbstractL1Interface for RealL1Interface { async fn failure_reason(&self, tx_hash: H256) -> Option { @@ -260,11 +261,11 @@ impl AbstractL1Interface for RealL1Interface { }) } - fn ethereum_gateway(&self) -> &dyn BoundEthInterface { + fn ethereum_gateway(&self) -> &dyn BoundEthInterface { self.ethereum_gateway.as_ref() } - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface> { + fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface> { self.ethereum_gateway_blobs.as_deref() } } diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 89533432ef83..6144035e79c0 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -2,7 +2,7 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface}; +use zksync_eth_client::{clients::L1, BoundEthInterface, CallFunctionArgs, EthInterface}; use zksync_l1_contract_interface::{ i_executor::{ commit::kzg::{KzgInfo, ZK_SYNC_BYTES_PER_BLOB}, @@ -47,7 +47,7 @@ pub struct MulticallData { #[derive(Debug)] pub struct EthTxAggregator { aggregator: Aggregator, - eth_client: Box, + eth_client: Box>, config: SenderConfig, timelock_contract_address: Address, l1_multicall3_address: Address, @@ -75,7 +75,7 @@ impl EthTxAggregator { pool: ConnectionPool, config: SenderConfig, aggregator: Aggregator, - eth_client: Box, + eth_client: Box>, timelock_contract_address: Address, l1_multicall3_address: Address, state_transition_chain_contract: Address, diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 8014336be262..f5c78443e827 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -4,7 +4,8 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ - encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, RawTransactionBytes, + clients::L1, encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, + RawTransactionBytes, }; use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; @@ -38,8 +39,8 @@ impl EthTxManager { pool: ConnectionPool, config: SenderConfig, gas_adjuster: Arc, - ethereum_gateway: Box, - ethereum_gateway_blobs: Option>, + ethereum_gateway: Box>, + ethereum_gateway_blobs: Option>>, ) -> Self { let ethereum_gateway = ethereum_gateway.for_component("eth_tx_manager"); let ethereum_gateway_blobs = diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index e19ba225b7e1..1514ea3bc25b 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -1,8 +1,17 @@ use assert_matches::assert_matches; use test_casing::{test_casing, Product}; -use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_l1_contract_interface::i_executor::methods::ExecuteBatches; -use zksync_node_test_utils::create_l1_batch; +use zksync_config::{ + configs::eth_sender::{ProofSendingMode, PubdataSendingMode, SenderConfig}, + ContractsConfig, EthConfig, GasAdjusterConfig, +}; +use zksync_contracts::BaseSystemContractsHashes; +use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; +use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; +use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; +use zksync_mini_merkle_tree::SyncMerkleTree; +use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; +use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; +use zksync_object_store::MockObjectStore; use zksync_types::{ aggregated_operations::AggregatedActionType, block::L1BatchHeader, diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs index 0a671179de39..1ce92f2311da 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs @@ -7,9 +7,11 @@ use vise::{Gauge, Metrics}; pub(super) struct GasAdjusterMetrics { pub current_base_fee_per_gas: Gauge, pub current_blob_base_fee: Gauge, + pub current_l2_pubdata_price: Gauge, pub median_base_fee_per_gas: Gauge, pub median_blob_base_fee_per_gas: Gauge, pub median_blob_base_fee: Gauge, + pub median_l2_pubdata_price: Gauge, } #[vise::register] diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 2032cb9c89fd..0ed940c18089 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -7,9 +7,9 @@ use std::{ use tokio::sync::watch; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::EthInterface; -use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U256}; -use zksync_web3_decl::client::{DynClient, L1}; +use zksync_eth_client::{BaseFees, EnrichedClientResult, EthInterface, ZkSyncInterface}; +use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U256, U64}; +use zksync_web3_decl::client::{DynClient, L1, L2}; use self::metrics::METRICS; use super::L1TxParamsProvider; @@ -18,6 +18,103 @@ mod metrics; #[cfg(test)] mod tests; +#[derive(Debug)] +pub enum GasAdjusterClient { + L1(Box>), + L2(Box>), +} + +struct GasAdjusterFee { + pub base_fee_per_gas: u64, + pub base_fee_per_blob_gas: U256, + pub l2_pubdata_price: U256, +} + +impl GasAdjusterClient { + pub fn from_l1(inner: Box>) -> Self { + Self::L1(inner) + } + + pub fn is_l1(&self) -> bool { + matches!(self, Self::L1(_)) + } + + pub fn from_l2(inner: Box>) -> Self { + Self::L2(inner) + } + + pub fn is_l2(&self) -> bool { + matches!(self, Self::L2(_)) + } +} + +impl From>> for GasAdjusterClient { + fn from(inner: Box>) -> Self { + Self::L1(inner) + } +} + +impl From>> for GasAdjusterClient { + fn from(inner: Box>) -> Self { + Self::L2(inner) + } +} + +macro_rules! relay { + ($self:ident, $method:ident $(, $args:expr)*) => { + match $self { + GasAdjusterClient::L1(inner) => inner.$method($($args),*), + GasAdjusterClient::L2(inner) => inner.$method($($args),*), + } + }; +} + +impl GasAdjusterClient { + fn for_component(self, name: &'static str) -> Self { + match self { + GasAdjusterClient::L1(inner) => GasAdjusterClient::L1(inner.for_component(name)), + GasAdjusterClient::L2(inner) => GasAdjusterClient::L2(inner.for_component(name)), + } + } + + async fn block_number(&self) -> EnrichedClientResult { + relay!(self, block_number).await + } + + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + match self { + GasAdjusterClient::L1(inner) => { + let base_fees = inner.base_fee_history(upto_block, block_count).await?; + Ok(base_fees + .into_iter() + .map(|fee| GasAdjusterFee { + base_fee_per_gas: fee.base_fee_per_gas, + base_fee_per_blob_gas: fee.base_fee_per_blob_gas, + // We formally provide it, but we wont use it. + l2_pubdata_price: U256::zero(), + }) + .collect()) + } + GasAdjusterClient::L2(inner) => { + let base_fees = inner.l2_fee_history(upto_block, block_count).await?; + Ok(base_fees + .into_iter() + .map(|fee| GasAdjusterFee { + base_fee_per_gas: fee.base_fee_per_gas, + // We formally provide it, but we wont use it. + base_fee_per_blob_gas: U256::zero(), + l2_pubdata_price: fee.pubdata_price, + }) + .collect()) + } + } + } +} + /// This component keeps track of the median `base_fee` from the last `max_base_fee_samples` blocks /// and of the median `blob_base_fee` from the last `max_blob_base_fee_sample` blocks. /// It is used to adjust the base_fee of transactions sent to L1. @@ -27,31 +124,49 @@ pub struct GasAdjuster { // Type for blob base fee is chosen to be `U256`. // In practice, it's very unlikely to overflow `u64` (if `blob_base_fee_statistics` = 10 ^ 18, then price for one blob is 2 ^ 17 ETH). // But it's still possible and code shouldn't panic if that happens. One more argument is that geth uses big int type for blob prices. + // + // Note, that for L2-based chains it will contains only zeroes. pub(super) blob_base_fee_statistics: GasStatistics, + // Note, that for L1-based chains the following field contains only zeroes. + pub(super) l2_pubdata_price_statistics: GasStatistics, + pub(super) config: GasAdjusterConfig, pubdata_sending_mode: PubdataSendingMode, - eth_client: Box>, + client: GasAdjusterClient, commitment_mode: L1BatchCommitmentMode, } impl GasAdjuster { pub async fn new( - eth_client: Box>, + client: GasAdjusterClient, config: GasAdjusterConfig, pubdata_sending_mode: PubdataSendingMode, commitment_mode: L1BatchCommitmentMode, ) -> anyhow::Result { - let eth_client = eth_client.for_component("gas_adjuster"); + // A runtime check to ensure consistent config. + if config.l2_mode.unwrap_or_default() { + assert!(client.is_l2(), "Must be L2 client in L2 mode"); + + assert!( + matches!(pubdata_sending_mode, PubdataSendingMode::RelayedL2Calldata), + "Only relayed L2 calldata is available for L2 mode" + ); + } else { + assert!(client.is_l1(), "Must be L1 client in L1 mode"); + + assert!( + !matches!(pubdata_sending_mode, PubdataSendingMode::RelayedL2Calldata), + "Relayed L2 calldata is only available in L2 mode" + ); + } + + let client = client.for_component("gas_adjuster"); // Subtracting 1 from the "latest" block number to prevent errors in case // the info about the latest block is not yet present on the node. // This sometimes happens on Infura. - let current_block = eth_client - .block_number() - .await? - .as_usize() - .saturating_sub(1); - let fee_history = eth_client + let current_block = client.block_number().await?.as_usize().saturating_sub(1); + let fee_history = client .base_fee_history(current_block, config.max_base_fee_samples) .await?; @@ -67,12 +182,19 @@ impl GasAdjuster { fee_history.iter().map(|fee| fee.base_fee_per_blob_gas), ); + let l2_pubdata_price_statistics = GasStatistics::new( + config.num_samples_for_blob_base_fee_estimate, + current_block, + fee_history.iter().map(|fee| fee.l2_pubdata_price), + ); + Ok(Self { base_fee_statistics, blob_base_fee_statistics, + l2_pubdata_price_statistics, config, pubdata_sending_mode, - eth_client, + client, commitment_mode, }) } @@ -84,7 +206,7 @@ impl GasAdjuster { // the info about the latest block is not yet present on the node. // This sometimes happens on Infura. let current_block = self - .eth_client + .client .block_number() .await? .as_usize() @@ -94,23 +216,23 @@ impl GasAdjuster { if current_block > last_processed_block { let n_blocks = current_block - last_processed_block; - let base_fees = self - .eth_client + let fee_data = self + .client .base_fee_history(current_block, n_blocks) .await?; // We shouldn't rely on L1 provider to return consistent results, so we check that we have at least one new sample. - if let Some(current_base_fee_per_gas) = base_fees.last().map(|fee| fee.base_fee_per_gas) + if let Some(current_base_fee_per_gas) = fee_data.last().map(|fee| fee.base_fee_per_gas) { METRICS .current_base_fee_per_gas .set(current_base_fee_per_gas); } self.base_fee_statistics - .add_samples(base_fees.iter().map(|fee| fee.base_fee_per_gas)); + .add_samples(fee_data.iter().map(|fee| fee.base_fee_per_gas)); if let Some(current_blob_base_fee) = - base_fees.last().map(|fee| fee.base_fee_per_blob_gas) + fee_data.last().map(|fee| fee.base_fee_per_blob_gas) { // Blob base fee overflows `u64` only in very extreme cases. // It doesn't worth to observe exact value with metric because anyway values that can be used @@ -124,7 +246,23 @@ impl GasAdjuster { } } self.blob_base_fee_statistics - .add_samples(base_fees.iter().map(|fee| fee.base_fee_per_blob_gas)); + .add_samples(fee_data.iter().map(|fee| fee.base_fee_per_blob_gas)); + + if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.l2_pubdata_price) + { + // L2 pubdata price overflows `u64` only in very extreme cases. + // It doesn't worth to observe exact value with metric because anyway values that can be used + // are capped by `self.config.max_blob_base_fee()` of `u64` type. + if current_l2_pubdata_price > U256::from(u64::MAX) { + tracing::error!("Failed to report current_l2_pubdata_price = {current_l2_pubdata_price}, it exceeds u64::MAX"); + } else { + METRICS + .current_l2_pubdata_price + .set(current_l2_pubdata_price.as_u64()); + } + } + self.l2_pubdata_price_statistics + .add_samples(fee_data.iter().map(|fee| fee.l2_pubdata_price)); } Ok(()) } @@ -207,6 +345,9 @@ impl GasAdjuster { // GitHub issue: https://github.com/matter-labs/zksync-era/issues/2105 0 } + PubdataSendingMode::RelayedL2Calldata => { + self.bound_blob_base_fee(self.l2_pubdata_price_statistics.median().as_u64() as f64) + } } } @@ -217,6 +358,7 @@ impl GasAdjuster { } } + // FIXME: shall we rename this method to the `bound_pubdata_fee`? fn bound_blob_base_fee(&self, blob_base_fee: f64) -> u64 { let max_blob_base_fee = self.config.max_blob_base_fee(); match self.commitment_mode { diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs index 200903b6deda..9326d9966f19 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs @@ -2,10 +2,12 @@ use std::{collections::VecDeque, sync::RwLockReadGuard}; use test_casing::test_casing; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::{clients::MockEthereum, BaseFees}; +use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; use zksync_types::commitment::L1BatchCommitmentMode; +use zksync_web3_decl::client::L2; use super::{GasAdjuster, GasStatistics, GasStatisticsInner}; +use crate::l1_gas_price::GasAdjusterClient; /// Check that we compute the median correctly #[test] @@ -28,57 +30,78 @@ fn samples_queue() { assert_eq!(stats.samples, VecDeque::from([4, 5, 18, 18, 18])); } +const TEST_BLOCK_FEES: [u64; 10] = [0, 4, 6, 8, 7, 5, 5, 8, 10, 9]; +const TEST_BLOB_FEES: [u64; 10] = [ + 0, + 393216, + 393216, + 393216 * 2, + 393216, + 393216 * 2, + 393216 * 2, + 393216 * 3, + 393216 * 4, + 393216, +]; +const TEST_PUBDATA_PRICES: [u64; 10] = [ + 0, + 493216, + 493216, + 493216 * 2, + 493216, + 493216 * 2, + 493216 * 2, + 493216 * 3, + 493216 * 4, + 493216, +]; + +fn test_config(l2_mode: Option) -> GasAdjusterConfig { + GasAdjusterConfig { + default_priority_fee_per_gas: 5, + max_base_fee_samples: 5, + pricing_formula_parameter_a: 1.5, + pricing_formula_parameter_b: 1.0005, + internal_l1_pricing_multiplier: 0.8, + internal_enforced_l1_gas_price: None, + internal_enforced_pubdata_price: None, + poll_period: 5, + max_l1_gas_price: None, + num_samples_for_blob_base_fee_estimate: 3, + internal_pubdata_pricing_multiplier: 1.0, + max_blob_base_fee: None, + l2_mode, + } +} + +/// Helper function to read a value from adjuster +fn read(statistics: &GasStatistics) -> RwLockReadGuard> { + statistics.0.read().unwrap() +} + /// Check that we properly fetch base fees as block are mined #[test_casing(2, [L1BatchCommitmentMode::Rollup, L1BatchCommitmentMode::Validium])] #[tokio::test] async fn kept_updated(commitment_mode: L1BatchCommitmentMode) { - // Helper function to read a value from adjuster - fn read(statistics: &GasStatistics) -> RwLockReadGuard> { - statistics.0.read().unwrap() - } - - let block_fees = vec![0, 4, 6, 8, 7, 5, 5, 8, 10, 9]; - let blob_fees = vec![ - 0, - 393216, - 393216, - 393216 * 2, - 393216, - 393216 * 2, - 393216 * 2, - 393216 * 3, - 393216 * 4, - 393216, - ]; - let base_fees = block_fees + let base_fees = TEST_BLOCK_FEES .into_iter() - .zip(blob_fees) - .map(|(block, blob)| BaseFees { + .zip(TEST_BLOB_FEES) + .map(|(block, blob)| MockClientBaseFee { base_fee_per_gas: block, base_fee_per_blob_gas: blob.into(), + pubdata_price: 0.into(), }) .collect(); - let eth_client = MockEthereum::builder().with_fee_history(base_fees).build(); + let eth_client = MockSettlementLayer::builder() + .with_fee_history(base_fees) + .build(); // 5 sampled blocks + additional block to account for latest block subtraction eth_client.advance_block_number(6); - let config = GasAdjusterConfig { - default_priority_fee_per_gas: 5, - max_base_fee_samples: 5, - pricing_formula_parameter_a: 1.5, - pricing_formula_parameter_b: 1.0005, - internal_l1_pricing_multiplier: 0.8, - internal_enforced_l1_gas_price: None, - internal_enforced_pubdata_price: None, - poll_period: 5, - max_l1_gas_price: None, - num_samples_for_blob_base_fee_estimate: 3, - internal_pubdata_pricing_multiplier: 1.0, - max_blob_base_fee: None, - }; + let config = test_config(None); let adjuster = GasAdjuster::new( - Box::new(eth_client.clone().into_client()), + GasAdjusterClient::from_l1(Box::new(eth_client.clone().into_client())), config, PubdataSendingMode::Calldata, commitment_mode, @@ -119,3 +142,67 @@ async fn kept_updated(commitment_mode: L1BatchCommitmentMode) { expected_median_blob_base_fee.into() ); } + +/// Check that we properly fetch base fees as block are mined +#[test_casing(2, [L1BatchCommitmentMode::Rollup, L1BatchCommitmentMode::Validium])] +#[tokio::test] +async fn kept_updated_l2(commitment_mode: L1BatchCommitmentMode) { + let base_fees = TEST_BLOCK_FEES + .into_iter() + .zip(TEST_PUBDATA_PRICES) + .map(|(block, pubdata)| MockClientBaseFee { + base_fee_per_gas: block, + base_fee_per_blob_gas: 0.into(), + pubdata_price: pubdata.into(), + }) + .collect(); + + let eth_client = MockSettlementLayer::::builder() + .with_fee_history(base_fees) + .build(); + // 5 sampled blocks + additional block to account for latest block subtraction + eth_client.advance_block_number(6); + + let config = test_config(Some(true)); + let adjuster = GasAdjuster::new( + GasAdjusterClient::from_l2(Box::new(eth_client.clone().into_client())), + config, + PubdataSendingMode::RelayedL2Calldata, + commitment_mode, + ) + .await + .unwrap(); + + assert_eq!( + read(&adjuster.base_fee_statistics).samples.len(), + config.max_base_fee_samples + ); + assert_eq!(read(&adjuster.base_fee_statistics).median(), 6); + + eprintln!("{:?}", read(&adjuster.l2_pubdata_price_statistics).samples); + let expected_median_blob_base_fee = 493216 * 2; + assert_eq!( + read(&adjuster.l2_pubdata_price_statistics).samples.len(), + config.num_samples_for_blob_base_fee_estimate + ); + assert_eq!( + read(&adjuster.l2_pubdata_price_statistics).median(), + expected_median_blob_base_fee.into() + ); + + eth_client.advance_block_number(3); + adjuster.keep_updated().await.unwrap(); + + assert_eq!( + read(&adjuster.base_fee_statistics).samples.len(), + config.max_base_fee_samples + ); + assert_eq!(read(&adjuster.base_fee_statistics).median(), 7); + + let expected_median_blob_base_fee = 493216 * 3; + assert_eq!(read(&adjuster.l2_pubdata_price_statistics).samples.len(), 3); + assert_eq!( + read(&adjuster.l2_pubdata_price_statistics).median(), + expected_median_blob_base_fee.into() + ); +} diff --git a/core/node/fee_model/src/l1_gas_price/mod.rs b/core/node/fee_model/src/l1_gas_price/mod.rs index 0dab2d921c40..29db21bc1733 100644 --- a/core/node/fee_model/src/l1_gas_price/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/mod.rs @@ -3,13 +3,12 @@ use std::fmt; pub use self::{ - gas_adjuster::GasAdjuster, main_node_fetcher::MainNodeFeeParamsFetcher, - singleton::GasAdjusterSingleton, + gas_adjuster::{GasAdjuster, GasAdjusterClient}, + main_node_fetcher::MainNodeFeeParamsFetcher, }; mod gas_adjuster; mod main_node_fetcher; -mod singleton; /// Abstraction that provides parameters to set the fee for an L1 transaction, taking the desired /// mining time into account. diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index 66a1c07a1c64..8842c18687f6 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -286,9 +286,13 @@ impl BatchFeeModelInputProvider for MockBatchFeeParamsProvider { mod tests { use std::num::NonZeroU64; + use l1_gas_price::GasAdjusterClient; use zksync_base_token_adjuster::NoOpRatioProvider; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; - use zksync_eth_client::{clients::MockEthereum, BaseFees}; + use zksync_eth_client::{ + clients::{MockClientBaseFee, MockSettlementLayer}, + BaseFees, + }; use zksync_types::{commitment::L1BatchCommitmentMode, fee_model::BaseTokenConversionRatio}; use super::*; @@ -744,19 +748,20 @@ mod tests { } // Helper function to create BaseFees. - fn base_fees(block: u64, blob: U256) -> BaseFees { - BaseFees { + fn test_base_fees(block: u64, blob: U256, pubdata: U256) -> MockClientBaseFee { + MockClientBaseFee { base_fee_per_gas: block, base_fee_per_blob_gas: blob, + pubdata_price: pubdata, } } // Helper function to setup the GasAdjuster. async fn setup_gas_adjuster(l1_gas_price: u64, l1_pubdata_price: u64) -> GasAdjuster { - let mock = MockEthereum::builder() + let mock = MockSettlementLayer::builder() .with_fee_history(vec![ - base_fees(0, U256::from(4)), - base_fees(1, U256::from(3)), + test_base_fees(0, U256::from(4), U256::from(0)), + test_base_fees(1, U256::from(3), U256::from(0)), ]) .build(); mock.advance_block_number(2); // Ensure we have enough blocks for the fee history @@ -770,7 +775,7 @@ mod tests { }; GasAdjuster::new( - Box::new(mock.into_client()), + GasAdjusterClient::from_l1(Box::new(mock.into_client())), gas_adjuster_config, PubdataSendingMode::Blobs, L1BatchCommitmentMode::Rollup, diff --git a/core/node/node_framework/src/implementations/layers/l1_gas.rs b/core/node/node_framework/src/implementations/layers/l1_gas.rs index 85e0422cdcb1..41459a4ec6e9 100644 --- a/core/node/node_framework/src/implementations/layers/l1_gas.rs +++ b/core/node/node_framework/src/implementations/layers/l1_gas.rs @@ -5,13 +5,17 @@ use zksync_config::{ configs::{chain::StateKeeperConfig, eth_sender::PubdataSendingMode}, GasAdjusterConfig, GenesisConfig, }; -use zksync_node_fee_model::{l1_gas_price::GasAdjuster, MainNodeFeeInputProvider}; +use zksync_node_fee_model::{ + l1_gas_price::{GasAdjuster, GasAdjusterClient}, + MainNodeFeeInputProvider, +}; use zksync_types::fee_model::FeeModelConfig; use crate::{ implementations::resources::{ base_token_ratio_provider::BaseTokenRatioProviderResource, - eth_interface::EthInterfaceResource, fee_input::FeeInputResource, + eth_interface::{EthInterfaceResource, L2InterfaceResource}, + fee_input::FeeInputResource, l1_tx_params::L1TxParamsResource, }, service::StopReceiver, @@ -33,7 +37,8 @@ pub struct SequencerL1GasLayer { #[derive(Debug, FromContext)] #[context(crate = crate)] pub struct Input { - pub eth_client: EthInterfaceResource, + pub eth_interface_client: EthInterfaceResource, + pub l2_inteface_client: Option, /// If not provided, the base token assumed to be ETH, and the ratio will be constant. #[context(default)] pub base_token_ratio_provider: BaseTokenRatioProviderResource, @@ -75,7 +80,12 @@ impl WiringLayer for SequencerL1GasLayer { } async fn wire(self, input: Self::Input) -> Result { - let client = input.eth_client.0; + let client = if self.gas_adjuster_config.l2_mode.unwrap_or_default() { + GasAdjusterClient::from_l2(input.l2_inteface_client.unwrap().0) + } else { + GasAdjusterClient::from_l1(input.eth_interface_client.0) + }; + let adjuster = GasAdjuster::new( client, self.gas_adjuster_config, 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 b3a9c7d4b275..5cb06f0a8787 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 @@ -3,8 +3,10 @@ use zksync_types::{url::SensitiveUrl, SLChainId}; use zksync_web3_decl::client::Client; use crate::{ - implementations::resources::eth_interface::EthInterfaceResource, + implementations::resources::eth_interface::{EthInterfaceResource, L2InterfaceResource}, + service::ServiceContext, wiring_layer::{WiringError, WiringLayer}, + IntoContext, }; /// Wiring layer for Ethereum client. @@ -12,28 +14,61 @@ use crate::{ pub struct QueryEthClientLayer { chain_id: SLChainId, web3_url: SensitiveUrl, + l2_mode: bool, } impl QueryEthClientLayer { - pub fn new(chain_id: SLChainId, web3_url: SensitiveUrl) -> Self { - Self { chain_id, web3_url } + pub fn new(chain_id: SLChainId, web3_url: SensitiveUrl, l2_mode: bool) -> Self { + Self { + chain_id, + web3_url, + l2_mode, + } + } +} + +#[derive(Debug)] +pub struct Output { + query_client_l1: Client, + query_client_l2: Option>, +} + +impl IntoContext for Output { + fn into_context(self, context: &mut ServiceContext<'_>) -> Result<(), WiringError> { + context.insert_resource(EthInterfaceResource(Box::new(self.query_client_l1)))?; + if let Some(query_client_l2) = self.query_client_l2 { + context.insert_resource(L2InterfaceResource(Box::new(query_client_l2)))?; + } + Ok(()) } } #[async_trait::async_trait] impl WiringLayer for QueryEthClientLayer { type Input = (); - type Output = EthInterfaceResource; + type Output = Output; fn layer_name(&self) -> &'static str { "query_eth_client_layer" } - async fn wire(self, _input: Self::Input) -> Result { - let query_client = Client::http(self.web3_url.clone()) - .context("Client::new()")? - .for_network(self.chain_id.into()) - .build(); - Ok(EthInterfaceResource(Box::new(query_client))) + async fn wire(self, _input: Self::Input) -> Result { + // Both the L1 and L2 client have the same URL, but provide different type guarantees. + Ok(Output { + query_client_l1: Client::http(self.web3_url.clone()) + .context("Client::new()")? + .for_network(self.chain_id.into()) + .build(), + query_client_l2: if self.l2_mode { + Some( + Client::http(self.web3_url.clone()) + .context("Client::new()")? + .for_network(L2ChainId(self.chain_id.0).into()) + .build(), + ) + } else { + None + }, + }) } } diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index cf470c0379da..189cb71d52f0 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -1,5 +1,5 @@ use zksync_eth_client::BoundEthInterface; -use zksync_web3_decl::client::{DynClient, L1}; +use zksync_web3_decl::client::{DynClient, L1, L2}; use crate::resource::Resource; @@ -13,9 +13,23 @@ impl Resource for EthInterfaceResource { } } +/// A resource that provides L2 interface object to the service. +/// It is expected to have the same URL as the `EthInterfaceResource`, but have different capabilities. +/// +/// This resource is provided separately from `EthInterfaceResource`, to provide type safety in places, where the +/// component must work with L1-interface only and should use `EthInterfaceResource` instead. +#[derive(Debug, Clone)] +pub struct L2InterfaceResource(pub Box>); + +impl Resource for L2InterfaceResource { + fn name() -> String { + "common/l2_inteface".into() + } +} + /// A resource that provides L1 interface with signing capabilities to the service. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceResource(pub Box); +pub struct BoundEthInterfaceResource(pub Box>); impl Resource for BoundEthInterfaceResource { fn name() -> String { @@ -25,7 +39,7 @@ impl Resource for BoundEthInterfaceResource { /// Same as `BoundEthInterfaceResource`, but for managing EIP-4844 blobs. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceForBlobsResource(pub Box); +pub struct BoundEthInterfaceForBlobsResource(pub Box>); impl Resource for BoundEthInterfaceForBlobsResource { fn name() -> String { diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 28fcbd51822e..73a9238ad0a2 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -9,9 +9,12 @@ use zksync_config::{ }; use zksync_contracts::BaseSystemContracts; use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{clients::MockEthereum, BaseFees}; +use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; use zksync_multivm::vm_latest::constants::BATCH_COMPUTATIONAL_GAS_LIMIT; -use zksync_node_fee_model::{l1_gas_price::GasAdjuster, MainNodeFeeInputProvider}; +use zksync_node_fee_model::{ + l1_gas_price::{GasAdjuster, GasAdjusterClient}, + MainNodeFeeInputProvider, +}; use zksync_node_genesis::create_genesis_l1_batch; use zksync_node_test_utils::{ create_l1_batch, create_l2_block, create_l2_transaction, execute_l2_transaction, @@ -51,12 +54,15 @@ impl Tester { let block_fees = vec![0, 4, 6, 8, 7, 5, 5, 8, 10, 9]; let base_fees = block_fees .into_iter() - .map(|base_fee_per_gas| BaseFees { + .map(|base_fee_per_gas| MockClientBaseFee { base_fee_per_gas, base_fee_per_blob_gas: 1.into(), // Not relevant for the test + pubdata_price: 0.into(), // Not relevant for the test }) .collect(); - let eth_client = MockEthereum::builder().with_fee_history(base_fees).build(); + let eth_client = MockSettlementLayer::builder() + .with_fee_history(base_fees) + .build(); let gas_adjuster_config = GasAdjusterConfig { default_priority_fee_per_gas: 10, @@ -71,10 +77,11 @@ impl Tester { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, + l2_mode: None, }; GasAdjuster::new( - Box::new(eth_client.into_client()), + GasAdjusterClient::from_l1(Box::new(eth_client.into_client())), gas_adjuster_config, PubdataSendingMode::Calldata, self.commitment_mode, diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 31fcc5269774..3b3516498f89 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -127,7 +127,7 @@ impl EthereumProvider { } /// Exposes Ethereum node `web3` API. - pub fn client(&self) -> &dyn BoundEthInterface { + pub fn client(&self) -> &dyn BoundEthInterface { &self.eth_client } diff --git a/etc/env/configs/dev2.toml b/etc/env/configs/dev2.toml new file mode 100644 index 000000000000..762e058ee954 --- /dev/null +++ b/etc/env/configs/dev2.toml @@ -0,0 +1,21 @@ +__imports__ = ["base", "l1-inits/dev2.init.env", "l2-inits/dev2.init.env" ] + +L1_ENV_NAME="dev2" + +ZKSYNC_DEBUG_LOGS=true + +CONTRACTS_SHARED_BRIDGE_UPGRADE_STORAGE_SWITCH="0" +CHAIN_ETH_ZKSYNC_NETWORK_ID=272 +ZKSYNC_ACTION="dont_ask" +CONTRACTS_ERA_CHAIN_ID="270" + +ETH_SENDER_SENDER_OPERATOR_PRIVATE_KEY="0xf12e28c0eb1ef4ff90478f6805b68d63737b7f33abfa091601140805da450d93" +ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR="0x8002cD98Cfb563492A6fB3E7C8243b7B9Ad4cc92" +ETH_SENDER_SENDER_OPERATOR_BLOBS_PRIVATE_KEY="0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8" +ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR="0xA13c10C0D5bd6f79041B9835c63f91de35A15883" + +ETH_CLIENT_CHAIN_ID="270" +ETH_CLIENT_WEB3_URL="http://127.0.0.1:3050" +CHAIN_ETH_NETWORK="localhostL2" + +CONTRACTS_BASE_NETWORK_ZKSYNC="true" diff --git a/etc/env/configs/l1-hyperchain.template.toml b/etc/env/configs/l1-hyperchain.template.toml new file mode 100644 index 000000000000..e9f504805960 --- /dev/null +++ b/etc/env/configs/l1-hyperchain.template.toml @@ -0,0 +1,12 @@ +__imports__ = ["base", "l1-inits/.init.env", "l2-inits/dev2.init.env" ] +ZKSYNC_DEBUG_LOGS=true + +CONTRACTS_SHARED_BRIDGE_UPGRADE_STORAGE_SWITCH="0" +CHAIN_ETH_ZKSYNC_NETWORK_ID=273 +ZKSYNC_ACTION="dont_ask" +CONTRACTS_ERA_CHAIN_ID="270" + +ETH_SENDER_SENDER_OPERATOR_PRIVATE_KEY="0xf12e28c0eb1ef4ff90478f6805b68d63737b7f33abfa091601140805da450d93" +ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR="0x8002cD98Cfb563492A6fB3E7C8243b7B9Ad4cc92" +ETH_SENDER_SENDER_OPERATOR_BLOBS_PRIVATE_KEY="0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8" +ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR="0xA13c10C0D5bd6f79041B9835c63f91de35A15883" diff --git a/infrastructure/zk/src/database.ts b/infrastructure/zk/src/database.ts index a30d262b8389..3f01bd007feb 100644 --- a/infrastructure/zk/src/database.ts +++ b/infrastructure/zk/src/database.ts @@ -5,7 +5,7 @@ export async function reset(opts: DbOpts) { await utils.confirmAction(); await wait(opts); await drop(opts); - await setup(opts); + await setup(opts, false); } export enum DalPath { diff --git a/infrastructure/zk/src/init.ts b/infrastructure/zk/src/init.ts index 6dbad67b489c..c5ae934607fb 100644 --- a/infrastructure/zk/src/init.ts +++ b/infrastructure/zk/src/init.ts @@ -64,7 +64,9 @@ const initSetup = async ({ await announced('Setting up containers', up(runObservability)); } - await announced('Compiling JS packages', run.yarn()); + if (!skipJsPackages) { + await announced('Compiling JS packages', run.yarn()); + } await Promise.all([ announced('Building L1 L2 contracts', contract.build()), @@ -144,6 +146,8 @@ type InitDevCmdActionOptions = InitSetupOptions & { testTokenOptions?: DeployTestTokensOptions; baseTokenName?: string; validiumMode?: boolean; + skipDbPreparation?: boolean; + skipJsPackages?: boolean; localLegacyBridgeTesting?: boolean; shouldCheckPostgres: boolean; // Whether to perform `cargo sqlx prepare --check` }; @@ -167,7 +171,8 @@ export const initDevCmdAction = async ({ skipEnvSetup, skipSubmodulesCheckout, runObservability, - deploymentMode + deploymentMode, + skipJsPackages }); if (!skipVerifier) { await deployVerifier(); diff --git a/infrastructure/zk/src/setup_en.ts b/infrastructure/zk/src/setup_en.ts index 3d92b326251f..588b59667e21 100644 --- a/infrastructure/zk/src/setup_en.ts +++ b/infrastructure/zk/src/setup_en.ts @@ -189,7 +189,7 @@ async function configExternalNode() { await compileConfig('ext-node'); setEnv('ext-node'); console.log(`Setting up postgres (${cmd('zk db setup')})`); - await setupDb({ prover: false, core: true }); + await setupDb({ prover: false, core: true }, false); console.log(`${success('Everything done!')} You can now run your external node using ${cmd('zk external-node')}`); await runEnIfAskedTo(); From 2e2e368aa2fa002e405da14ae32bb61c111c57be Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 15:21:05 +0200 Subject: [PATCH 11/43] compiles --- core/bin/zksync_server/src/node_builder.rs | 2 +- core/lib/basic_types/src/lib.rs | 2 +- core/lib/eth_client/src/clients/http/query.rs | 2 +- core/lib/eth_client/src/clients/mock.rs | 7 +++-- .../structures/commit_batch_info.rs | 29 ++++--------------- core/lib/web3_decl/src/client/network.rs | 8 ++++- core/node/eth_sender/src/tests.rs | 1 - .../layers/query_eth_client.rs | 4 +-- infrastructure/zk/src/init.ts | 8 ++--- 9 files changed, 24 insertions(+), 39 deletions(-) diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 578f2b6a17aa..9154f4b67b45 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -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, + genesis.settlement_layer_id(), eth_config.l1_rpc_url, self.configs .eth diff --git a/core/lib/basic_types/src/lib.rs b/core/lib/basic_types/src/lib.rs index a9522407222c..2bb9782997fb 100644 --- a/core/lib/basic_types/src/lib.rs +++ b/core/lib/basic_types/src/lib.rs @@ -89,7 +89,7 @@ impl TryFrom for AccountTreeId { /// ChainId in the ZKsync network. #[derive(Copy, Clone, Debug, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct L2ChainId(u64); +pub struct L2ChainId(pub u64); impl<'de> Deserialize<'de> for L2ChainId { fn deserialize(deserializer: D) -> Result diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 48ce5b0ac2a0..4a8a0a16b607 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, L2BlockNumber, H256, U256, U64}; +use zksync_types::{web3, Address, L1ChainId, L2BlockNumber, SLChainId, H256, U256, U64}; use zksync_web3_decl::error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}; use super::{ diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index a338e5d07ef5..a634884e7d4e 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -11,7 +11,7 @@ use zksync_types::{ api::FeeHistory, ethabi, web3::{self, contract::Tokenize, BlockId}, - Address, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, + Address, L1ChainId, L2ChainId, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; use zksync_web3_decl::client::{DynClient, MockClient, MockClientBuilder, Network, L1, L2}; @@ -357,10 +357,11 @@ impl MockEthereumBuilder { }) } - fn build_client(self) -> MockClient { - const CHAIN_ID: SLChainId = SLChainId(9); + fn build_client_inner(self, chaind_id: u64, network: Net) -> MockClientBuilder { + let call_handler = self.call_handler; MockClient::builder(network) + .method("eth_chainId", move || Ok(U64::from(chaind_id))) .method("eth_blockNumber", { let inner = self.inner.clone(); move || Ok(U64::from(inner.read().unwrap().block_number)) diff --git a/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs b/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs index b3f33a3454b1..179c04748d3b 100644 --- a/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs +++ b/core/lib/l1_contract_interface/src/i_executor/structures/commit_batch_info.rs @@ -205,18 +205,12 @@ impl Tokenizable for CommitBatchInfo<'_> { ( L1BatchCommitmentMode::Validium, PubdataDA::Calldata | PubdataDA::RelayedL2Calldata, - ) => self - .l1_batch_with_metadata - .metadata - .state_diff_hash - .0 - .into(), - (L1BatchCommitmentMode::Validium, PubdataDA::Blobs) => self - .l1_batch_with_metadata - .metadata - .state_diff_hash - .0 - .into(), + ) => { + vec![PUBDATA_SOURCE_CALLDATA] + } + (L1BatchCommitmentMode::Validium, PubdataDA::Blobs) => { + vec![PUBDATA_SOURCE_BLOBS] + } (L1BatchCommitmentMode::Rollup, PubdataDA::Custom) => { panic!("Custom pubdata DA is incompatible with Rollup mode") @@ -229,17 +223,6 @@ impl Tokenizable for CommitBatchInfo<'_> { L1BatchCommitmentMode::Rollup, PubdataDA::Calldata | PubdataDA::RelayedL2Calldata, ) => { - let pubdata = self.pubdata_input(); - - let header = compose_header_for_l1_commit_rollup( - self.l1_batch_with_metadata - .metadata - .state_diff_hash - .0 - .into(), - pubdata.clone(), - ); - // We compute and add the blob commitment to the pubdata payload so that we can verify the proof // even if we are not using blobs. let pubdata = self.pubdata_input(); diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 82136689d1d0..632a5ac0e452 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::{L2ChainId, SLChainId}; +use zksync_types::{L1ChainId, L2ChainId, SLChainId}; /// Marker trait for networks. Two standard network kinds are [`L1`] and [`L2`]. /// @@ -33,6 +33,12 @@ impl From for L1 { } } +impl From for L1 { + fn from(chain_id: L1ChainId) -> Self { + Self(Some(chain_id.into())) + } +} + /// L2 network. #[derive(Debug, Clone, Copy, Default)] pub struct L2(Option); diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index 1514ea3bc25b..602073a416c7 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -8,7 +8,6 @@ use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; -use zksync_mini_merkle_tree::SyncMerkleTree; use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; use zksync_object_store::MockObjectStore; 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 5cb06f0a8787..9a067a20e415 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,6 +1,6 @@ use anyhow::Context; -use zksync_types::{url::SensitiveUrl, SLChainId}; -use zksync_web3_decl::client::Client; +use zksync_types::{url::SensitiveUrl, L2ChainId, SLChainId}; +use zksync_web3_decl::client::{Client, L1, L2}; use crate::{ implementations::resources::eth_interface::{EthInterfaceResource, L2InterfaceResource}, diff --git a/infrastructure/zk/src/init.ts b/infrastructure/zk/src/init.ts index c5ae934607fb..775ec7e798d6 100644 --- a/infrastructure/zk/src/init.ts +++ b/infrastructure/zk/src/init.ts @@ -64,9 +64,7 @@ const initSetup = async ({ await announced('Setting up containers', up(runObservability)); } - if (!skipJsPackages) { - await announced('Compiling JS packages', run.yarn()); - } + await announced('Compiling JS packages', run.yarn()); await Promise.all([ announced('Building L1 L2 contracts', contract.build()), @@ -147,7 +145,6 @@ type InitDevCmdActionOptions = InitSetupOptions & { baseTokenName?: string; validiumMode?: boolean; skipDbPreparation?: boolean; - skipJsPackages?: boolean; localLegacyBridgeTesting?: boolean; shouldCheckPostgres: boolean; // Whether to perform `cargo sqlx prepare --check` }; @@ -171,8 +168,7 @@ export const initDevCmdAction = async ({ skipEnvSetup, skipSubmodulesCheckout, runObservability, - deploymentMode, - skipJsPackages + deploymentMode }); if (!skipVerifier) { await deployVerifier(); From 29613464c422ad449fd2cf3ee50d691e200cdff8 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 15:21:19 +0200 Subject: [PATCH 12/43] use the same zk as in main --- infrastructure/zk/src/database.ts | 2 +- infrastructure/zk/src/init.ts | 1 - infrastructure/zk/src/setup_en.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/infrastructure/zk/src/database.ts b/infrastructure/zk/src/database.ts index 3f01bd007feb..a30d262b8389 100644 --- a/infrastructure/zk/src/database.ts +++ b/infrastructure/zk/src/database.ts @@ -5,7 +5,7 @@ export async function reset(opts: DbOpts) { await utils.confirmAction(); await wait(opts); await drop(opts); - await setup(opts, false); + await setup(opts); } export enum DalPath { diff --git a/infrastructure/zk/src/init.ts b/infrastructure/zk/src/init.ts index 775ec7e798d6..6dbad67b489c 100644 --- a/infrastructure/zk/src/init.ts +++ b/infrastructure/zk/src/init.ts @@ -144,7 +144,6 @@ type InitDevCmdActionOptions = InitSetupOptions & { testTokenOptions?: DeployTestTokensOptions; baseTokenName?: string; validiumMode?: boolean; - skipDbPreparation?: boolean; localLegacyBridgeTesting?: boolean; shouldCheckPostgres: boolean; // Whether to perform `cargo sqlx prepare --check` }; diff --git a/infrastructure/zk/src/setup_en.ts b/infrastructure/zk/src/setup_en.ts index 588b59667e21..3d92b326251f 100644 --- a/infrastructure/zk/src/setup_en.ts +++ b/infrastructure/zk/src/setup_en.ts @@ -189,7 +189,7 @@ async function configExternalNode() { await compileConfig('ext-node'); setEnv('ext-node'); console.log(`Setting up postgres (${cmd('zk db setup')})`); - await setupDb({ prover: false, core: true }, false); + await setupDb({ prover: false, core: true }); console.log(`${success('Everything done!')} You can now run your external node using ${cmd('zk external-node')}`); await runEnIfAskedTo(); From b63b26cb18fb359d062a1266d28b5f3bacab9983 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 15:55:16 +0200 Subject: [PATCH 13/43] prettify code --- core/bin/external_node/src/node_builder.rs | 4 +- core/lib/config/src/configs/eth_sender.rs | 2 +- core/lib/config/src/testonly.rs | 3 +- core/lib/dal/src/blocks_web3_dal.rs | 13 ++- core/lib/eth_client/src/clients/http/decl.rs | 6 +- .../eth_client/src/clients/http/signing.rs | 6 -- core/lib/eth_client/src/clients/mock.rs | 93 ++++++++++++++----- core/lib/eth_client/src/lib.rs | 2 +- core/lib/types/src/api/mod.rs | 1 - core/lib/web3_decl/src/client/boxed.rs | 4 +- core/lib/web3_decl/src/client/mock.rs | 4 +- core/lib/web3_decl/src/client/mod.rs | 4 +- core/lib/web3_decl/src/client/network.rs | 8 +- core/lib/web3_decl/src/namespaces/debug.rs | 4 +- core/lib/web3_decl/src/namespaces/en.rs | 4 +- core/lib/web3_decl/src/namespaces/eth.rs | 4 +- core/lib/web3_decl/src/namespaces/net.rs | 4 +- .../lib/web3_decl/src/namespaces/snapshots.rs | 4 +- core/lib/web3_decl/src/namespaces/unstable.rs | 4 +- core/lib/web3_decl/src/namespaces/web3.rs | 4 +- core/lib/web3_decl/src/namespaces/zks.rs | 4 +- .../src/l1_gas_price/gas_adjuster/mod.rs | 41 +++----- etc/env/configs/dev2.toml | 21 ----- etc/env/configs/l1-hyperchain.template.toml | 12 --- 24 files changed, 123 insertions(+), 133 deletions(-) delete mode 100644 etc/env/configs/dev2.toml delete mode 100644 etc/env/configs/l1-hyperchain.template.toml diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index 02372fccf0c6..fc583b5d8dde 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -169,8 +169,8 @@ impl ExternalNodeBuilder { let query_eth_client_layer = QueryEthClientLayer::new( self.config.required.settlement_layer_id(), self.config.required.eth_client_url.clone(), - // TODO: add this config for external node - true, + // TODO(EVM-676): add this config for external node + false, ); self.node.add_layer(query_eth_client_layer); Ok(self) diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index c18b2cd9f206..d1e69c615246 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -54,7 +54,7 @@ impl EthConfig { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, - l2_mode: Some(false), + l2_mode: None, }), watcher: Some(EthWatchConfig { confirmations_for_eth_event: None, diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 57a405a6fbdd..73ae5b1da32b 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -397,7 +397,8 @@ impl Distribution for EncodeDist { num_samples_for_blob_base_fee_estimate: self.sample(rng), internal_pubdata_pricing_multiplier: self.sample(rng), max_blob_base_fee: self.sample(rng), - l2_mode: self.sample(rng), + // TODO(EVM-676): generate it randomly once this value is used + l2_mode: None, } } } diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 3c9de96763c6..706e3b9f3311 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -564,7 +564,7 @@ impl BlocksWeb3Dal<'_, '_> { .collect()) } - /// Returns `base_fee_per_gas` and `effective_pubdata_price` for L2 block range [min(newest_block - block_count + 1, 0), newest_block] + /// Returns `base_fee_per_gas` and `fair_pubdata_price` for L2 block range [min(newest_block - block_count + 1, 0), newest_block] /// in descending order of L2 block numbers. pub async fn get_fee_history( &mut self, @@ -575,7 +575,7 @@ impl BlocksWeb3Dal<'_, '_> { r#" SELECT base_fee_per_gas, - gas_per_pubdata_limit + fair_pubdata_price FROM miniblocks WHERE @@ -595,11 +595,10 @@ impl BlocksWeb3Dal<'_, '_> { .await? .into_iter() .map(|row| { - let base_fee_per_gas = bigdecimal_to_u256(row.base_fee_per_gas); - let effective_pubdata_price = - U256::from(row.gas_per_pubdata_limit as u64) * base_fee_per_gas; - - (base_fee_per_gas, effective_pubdata_price) + ( + bigdecimal_to_u256(row.base_fee_per_gas), + bigdecimal_to_u256(row.fair_pubdata_price), + ) }) .collect(); diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index 7bb736d72eab..c0c6f0c76ac9 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -3,10 +3,10 @@ use zksync_types::{ api::{BlockDetails, L1BatchDetails}, web3, Address, L1BatchNumber, L2BlockNumber, H256, U256, U64, }; -use zksync_web3_decl::client::{ForNetwork, L1, L2}; +use zksync_web3_decl::client::{ForEthereumLikeNetwork, L1, L2}; /// Subset of the L1 `eth` namespace used by the L1 client. -#[rpc(client, namespace = "eth", client_bounds(Self: ForNetwork))] +#[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] pub(super) trait L1EthNamespace { #[method(name = "chainId")] async fn chain_id(&self) -> RpcResult; @@ -72,7 +72,7 @@ pub(super) trait L1EthNamespace { /// Subset of the L2 `eth` namespace used by an L2 client. It may have the same /// methods as the L1 `eth` namespace, but with extended return values. -#[rpc(client, namespace = "eth", client_bounds(Self: ForNetwork))] +#[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] pub(super) trait L2EthNamespace { #[method(name = "feeHistory")] async fn fee_history( diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index a955b2068854..abb3d53ecb05 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -74,12 +74,6 @@ impl fmt::Debug for SigningClient { } } -// impl AsRef for SigningClient { -// fn as_ref(&self) -> &dyn EthInterface { -// self.query_client.as_ref() as &dyn EthInterface -// } -// } - impl AsRef> for SigningClient { fn as_ref(&self) -> &DynClient { self.query_client.as_ref() diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index a634884e7d4e..55b46b2fc014 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -134,7 +134,7 @@ impl MockEthereumInner { } fn get_transaction_count(&self, address: Address, block: web3::BlockNumber) -> U256 { - if address != MockSettlementLayer::::SENDER_ACCOUNT { + if address != MOCK_SENDER_ACCOUNT { unimplemented!("Getting nonce for custom account is not supported"); } @@ -249,8 +249,12 @@ impl From for L2Fees { } } +pub trait SupportedMockEthNetwork: Network { + fn build_client(builder: MockEthereumBuilder) -> MockClient; +} + /// Builder for [`MockEthereum`] client. -pub struct MockEthereumBuilder { +pub struct MockEthereumBuilder { max_fee_per_gas: U256, max_priority_fee_per_gas: U256, base_fee_history: Vec, @@ -262,7 +266,7 @@ pub struct MockEthereumBuilder { _network: PhantomData, } -impl fmt::Debug for MockEthereumBuilder { +impl fmt::Debug for MockEthereumBuilder { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter .debug_struct("MockEthereumBuilder") @@ -278,7 +282,7 @@ impl fmt::Debug for MockEthereumBuilder { } } -impl Default for MockEthereumBuilder { +impl Default for MockEthereumBuilder { fn default() -> Self { Self { max_fee_per_gas: 100.into(), @@ -294,7 +298,7 @@ impl Default for MockEthereumBuilder { } } -impl MockEthereumBuilder { +impl MockEthereumBuilder { /// Sets fee history for each block in the mocked Ethereum network, starting from the 0th block. pub fn with_fee_history(self, history: Vec) -> Self { Self { @@ -414,11 +418,18 @@ impl MockEthereumBuilder { } }) } -} -pub trait SupportedMockEthNetwork: Network { - fn build_client(builder: MockEthereumBuilder) -> MockClient; + pub fn build(self) -> MockSettlementLayer { + MockSettlementLayer { + max_fee_per_gas: self.max_fee_per_gas, + max_priority_fee_per_gas: self.max_priority_fee_per_gas, + non_ordering_confirmations: self.non_ordering_confirmations, + inner: self.inner.clone(), + client: Net::build_client(self), + } + } } + impl SupportedMockEthNetwork for L1 { fn build_client(builder: MockEthereumBuilder) -> MockClient { const CHAIN_ID: L1ChainId = L1ChainId(9); @@ -495,18 +506,6 @@ impl SupportedMockEthNetwork for L2 { } } -impl MockEthereumBuilder { - pub fn build(self) -> MockSettlementLayer { - MockSettlementLayer { - max_fee_per_gas: self.max_fee_per_gas, - max_priority_fee_per_gas: self.max_priority_fee_per_gas, - non_ordering_confirmations: self.non_ordering_confirmations, - inner: self.inner.clone(), - client: Net::build_client(self), - } - } -} - /// Mock Ethereum client. #[derive(Debug, Clone)] pub struct MockSettlementLayer { @@ -529,9 +528,9 @@ impl Default for MockSettlementLayer { } } -impl MockSettlementLayer { - const SENDER_ACCOUNT: Address = Address::repeat_byte(0x11); +const MOCK_SENDER_ACCOUNT: Address = Address::repeat_byte(0x11); +impl MockSettlementLayer { /// Initializes a builder for a [`MockEthereum`] instance. pub fn builder() -> MockEthereumBuilder { MockEthereumBuilder::default() @@ -624,7 +623,7 @@ impl AsRef> for MockSettlementLayer { } #[async_trait::async_trait] -impl BoundEthInterface for MockSettlementLayer { +impl BoundEthInterface for MockSettlementLayer { fn clone_boxed(&self) -> Box> { Box::new(self.clone()) } @@ -649,7 +648,7 @@ impl BoundEthInterface for MockSettlementLayer { } fn sender_account(&self) -> Address { - Self::SENDER_ACCOUNT + MOCK_SENDER_ACCOUNT } async fn sign_prepared_tx_for_addr( @@ -675,9 +674,10 @@ impl BoundEthInterface for MockSettlementLayer { mod tests { use assert_matches::assert_matches; use zksync_types::{commitment::L1BatchCommitmentMode, ProtocolVersionId}; + use zksync_web3_decl::namespaces::EthNamespaceClient; use super::*; - use crate::{CallFunctionArgs, EthInterface}; + use crate::{CallFunctionArgs, EthInterface, ZkSyncInterface}; fn base_fees(block: u64, blob: u64, pubdata_price: u64) -> MockClientBaseFee { MockClientBaseFee { @@ -768,6 +768,49 @@ mod tests { ); } + #[tokio::test] + async fn managing_fee_history_l2() { + let initial_fee_history = vec![ + base_fees(1, 4, 11), + base_fees(2, 3, 12), + base_fees(3, 2, 13), + base_fees(4, 1, 14), + base_fees(5, 0, 15), + ]; + let client = MockSettlementLayer::::builder() + .with_fee_history(initial_fee_history.clone()) + .build(); + client.advance_block_number(4); + + let fee_history = client.as_ref().l2_fee_history(4, 4).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[1..=4] + .into_iter() + .cloned() + .map(L2Fees::from) + .collect::>() + ); + let fee_history = client.as_ref().l2_fee_history(2, 2).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[1..=2] + .into_iter() + .cloned() + .map(L2Fees::from) + .collect::>() + ); + let fee_history = client.as_ref().l2_fee_history(3, 2).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[2..=3] + .into_iter() + .cloned() + .map(L2Fees::from) + .collect::>() + ); + } + #[tokio::test] async fn managing_transactions() { let client = MockSettlementLayer::::builder() diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 3e15c77f055d..f2e14deb9f36 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -163,7 +163,7 @@ pub struct L2Fees { #[async_trait] pub trait ZkSyncInterface: Sync + Send { - /// Returns vector of pubdata prices (in wei) for a zkSync-based network. + /// Returns vector of base fees and pubdata prices (in wei) for a zkSync-based network. async fn l2_fee_history( &self, upto_block: usize, diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index feaa069d24bb..49323b92a7ef 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -859,7 +859,6 @@ pub struct FeeHistory { /// by the maximum blob gas per block. #[serde(default)] // some node implementations skip empty lists pub blob_gas_used_ratio: Vec, - /// An array of effective pubdata price. Note, that this field is L2-specific and only provided by L2 nodes. #[serde(default)] pub pubdata_price: Vec, diff --git a/core/lib/web3_decl/src/client/boxed.rs b/core/lib/web3_decl/src/client/boxed.rs index c49e8aed721c..d83329910981 100644 --- a/core/lib/web3_decl/src/client/boxed.rs +++ b/core/lib/web3_decl/src/client/boxed.rs @@ -9,7 +9,7 @@ use jsonrpsee::core::{ }; use serde::de::DeserializeOwned; -use super::{ForNetwork, Network, TaggedClient}; +use super::{ForEthereumLikeNetwork, Network, TaggedClient}; #[derive(Debug)] pub struct RawParams(pub(super) Option>); @@ -30,7 +30,7 @@ impl ToRpcParams for RawParams { // The implementation is fairly straightforward: [`RawParams`] is used as a catch-all params type, // and `serde_json::Value` is used as a catch-all response type. #[async_trait] -pub trait ObjectSafeClient: 'static + Send + Sync + fmt::Debug + ForNetwork { +pub trait ObjectSafeClient: 'static + Send + Sync + fmt::Debug + ForEthereumLikeNetwork { /// Tags this client as working for a specific component. The component name can be used in logging, /// metrics etc. fn for_component(self: Box, component_name: &'static str) -> Box>; diff --git a/core/lib/web3_decl/src/client/mock.rs b/core/lib/web3_decl/src/client/mock.rs index 75bd037049d4..6d44ebee5756 100644 --- a/core/lib/web3_decl/src/client/mock.rs +++ b/core/lib/web3_decl/src/client/mock.rs @@ -14,7 +14,7 @@ use jsonrpsee::{ }; use serde::{de::DeserializeOwned, Serialize}; -use super::{boxed::RawParams, ForNetwork, Network, TaggedClient}; +use super::{boxed::RawParams, ForEthereumLikeNetwork, Network, TaggedClient}; /// Object-safe counterpart to [`Handler`]. We need it because async closures aren't available on stable Rust. #[async_trait] @@ -177,7 +177,7 @@ impl MockClient { } } -impl ForNetwork for MockClient { +impl ForEthereumLikeNetwork for MockClient { type Net = Net; fn network(&self) -> Self::Net { diff --git a/core/lib/web3_decl/src/client/mod.rs b/core/lib/web3_decl/src/client/mod.rs index 9290bad5878f..5527e6fc86bf 100644 --- a/core/lib/web3_decl/src/client/mod.rs +++ b/core/lib/web3_decl/src/client/mod.rs @@ -38,7 +38,7 @@ use self::metrics::{L2ClientMetrics, METRICS}; pub use self::{ boxed::{DynClient, ObjectSafeClient}, mock::{MockClient, MockClientBuilder}, - network::{ForNetwork, Network, TaggedClient, L1, L2}, + network::{ForEthereumLikeNetwork, Network, TaggedClient, L1, L2}, shared::Shared, }; @@ -227,7 +227,7 @@ impl Client { } } -impl ForNetwork for Client { +impl ForEthereumLikeNetwork for Client { type Net = Net; fn network(&self) -> Self::Net { diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 632a5ac0e452..63e5f9e88d16 100644 --- a/core/lib/web3_decl/src/client/network.rs +++ b/core/lib/web3_decl/src/client/network.rs @@ -61,7 +61,7 @@ impl From for L2 { /// Associates a type with a particular type of RPC networks, such as Ethereum or ZKsync Era. RPC traits created using `jsonrpsee::rpc` /// can use `ForNetwork` as a client boundary to restrict which implementations can call their methods. -pub trait ForNetwork { +pub trait ForEthereumLikeNetwork { /// Network that the type is associated with. type Net: Network; @@ -73,7 +73,7 @@ pub trait ForNetwork { fn component(&self) -> &'static str; } -impl ForNetwork for &T { +impl ForEthereumLikeNetwork for &T { type Net = T::Net; fn network(&self) -> Self::Net { @@ -85,7 +85,7 @@ impl ForNetwork for &T { } } -impl ForNetwork for Box { +impl ForEthereumLikeNetwork for Box { type Net = T::Net; fn network(&self) -> Self::Net { @@ -98,7 +98,7 @@ impl ForNetwork for Box { } /// Client that can be tagged with the component using it. -pub trait TaggedClient: ForNetwork { +pub trait TaggedClient: ForEthereumLikeNetwork { /// Tags this client as working for a specific component. fn set_component(&mut self, component_name: &'static str); } diff --git a/core/lib/web3_decl/src/namespaces/debug.rs b/core/lib/web3_decl/src/namespaces/debug.rs index b06560b47c32..4342660aaf4e 100644 --- a/core/lib/web3_decl/src/namespaces/debug.rs +++ b/core/lib/web3_decl/src/namespaces/debug.rs @@ -8,13 +8,13 @@ use zksync_types::{ }; use crate::{ - client::{ForNetwork, L2}, + client::{ForEthereumLikeNetwork, L2}, types::H256, }; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "debug", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "debug", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/en.rs b/core/lib/web3_decl/src/namespaces/en.rs index 7bb80bccd1c4..7fcaf69f6fe8 100644 --- a/core/lib/web3_decl/src/namespaces/en.rs +++ b/core/lib/web3_decl/src/namespaces/en.rs @@ -4,11 +4,11 @@ use jsonrpsee::proc_macros::rpc; use zksync_config::{configs::EcosystemContracts, GenesisConfig}; use zksync_types::{api::en, tokens::TokenInfo, Address, L2BlockNumber}; -use crate::client::{ForNetwork, L2}; +use crate::client::{ForEthereumLikeNetwork, L2}; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "en", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "en", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/eth.rs b/core/lib/web3_decl/src/namespaces/eth.rs index b4007006c8e0..ec5deefaf3e3 100644 --- a/core/lib/web3_decl/src/namespaces/eth.rs +++ b/core/lib/web3_decl/src/namespaces/eth.rs @@ -11,7 +11,7 @@ use zksync_types::{ }; use crate::{ - client::{ForNetwork, L2}, + client::{ForEthereumLikeNetwork, L2}, types::{ Block, Bytes, Filter, FilterChanges, Index, Log, SyncState, TransactionReceipt, U256, U64, }, @@ -19,7 +19,7 @@ use crate::{ #[cfg_attr( feature = "server", - rpc(server, client, namespace = "eth", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/net.rs b/core/lib/web3_decl/src/namespaces/net.rs index 21e6548e5341..0be546c8200f 100644 --- a/core/lib/web3_decl/src/namespaces/net.rs +++ b/core/lib/web3_decl/src/namespaces/net.rs @@ -3,11 +3,11 @@ use jsonrpsee::core::RpcResult; use jsonrpsee::proc_macros::rpc; use zksync_types::U256; -use crate::client::{ForNetwork, L2}; +use crate::client::{ForEthereumLikeNetwork, L2}; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "net", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "net", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/snapshots.rs b/core/lib/web3_decl/src/namespaces/snapshots.rs index 6b82d5f590d8..e6be578bc046 100644 --- a/core/lib/web3_decl/src/namespaces/snapshots.rs +++ b/core/lib/web3_decl/src/namespaces/snapshots.rs @@ -6,11 +6,11 @@ use zksync_types::{ L1BatchNumber, }; -use crate::client::{ForNetwork, L2}; +use crate::client::{ForEthereumLikeNetwork, L2}; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "snapshots", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "snapshots", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/unstable.rs b/core/lib/web3_decl/src/namespaces/unstable.rs index 4996813a9855..9446862befe1 100644 --- a/core/lib/web3_decl/src/namespaces/unstable.rs +++ b/core/lib/web3_decl/src/namespaces/unstable.rs @@ -3,12 +3,12 @@ use jsonrpsee::core::RpcResult; use jsonrpsee::proc_macros::rpc; use zksync_types::{api::TransactionExecutionInfo, H256}; -use crate::client::{ForNetwork, L2}; +use crate::client::{ForEthereumLikeNetwork, L2}; /// RPCs in this namespace are experimental, and their interface is unstable, and it WILL change. #[cfg_attr( feature = "server", - rpc(server, client, namespace = "unstable", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "unstable", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/web3.rs b/core/lib/web3_decl/src/namespaces/web3.rs index 8851f6d0c3be..ef5feceb4686 100644 --- a/core/lib/web3_decl/src/namespaces/web3.rs +++ b/core/lib/web3_decl/src/namespaces/web3.rs @@ -2,11 +2,11 @@ use jsonrpsee::core::RpcResult; use jsonrpsee::proc_macros::rpc; -use crate::client::{ForNetwork, L2}; +use crate::client::{ForEthereumLikeNetwork, L2}; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "web3", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "web3", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/lib/web3_decl/src/namespaces/zks.rs b/core/lib/web3_decl/src/namespaces/zks.rs index 6f443dbded6a..77fa82d80358 100644 --- a/core/lib/web3_decl/src/namespaces/zks.rs +++ b/core/lib/web3_decl/src/namespaces/zks.rs @@ -15,13 +15,13 @@ use zksync_types::{ }; use crate::{ - client::{ForNetwork, L2}, + client::{ForEthereumLikeNetwork, L2}, types::{Bytes, Token}, }; #[cfg_attr( feature = "server", - rpc(server, client, namespace = "zks", client_bounds(Self: ForNetwork)) + rpc(server, client, namespace = "zks", client_bounds(Self: ForEthereumLikeNetwork)) )] #[cfg_attr( not(feature = "server"), diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 0ed940c18089..8e546de18f74 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -60,15 +60,6 @@ impl From>> for GasAdjusterClient { } } -macro_rules! relay { - ($self:ident, $method:ident $(, $args:expr)*) => { - match $self { - GasAdjusterClient::L1(inner) => inner.$method($($args),*), - GasAdjusterClient::L2(inner) => inner.$method($($args),*), - } - }; -} - impl GasAdjusterClient { fn for_component(self, name: &'static str) -> Self { match self { @@ -78,7 +69,10 @@ impl GasAdjusterClient { } async fn block_number(&self) -> EnrichedClientResult { - relay!(self, block_number).await + match self { + GasAdjusterClient::L1(inner) => inner.block_number().await, + GasAdjusterClient::L2(inner) => inner.block_number().await, + } } async fn base_fee_history( @@ -335,40 +329,33 @@ impl GasAdjuster { * BLOB_GAS_PER_BYTE as f64 * self.config.internal_pubdata_pricing_multiplier; - self.bound_blob_base_fee(calculated_price) - } - PubdataSendingMode::Calldata => { - self.estimate_effective_gas_price() * self.pubdata_byte_gas() + self.bound_pubdata_fee(calculated_price) } + PubdataSendingMode::Calldata => self.bound_pubdata_fee( + self.estimate_effective_gas_price() * L1_GAS_PER_PUBDATA_BYTE.into(), + ), PubdataSendingMode::Custom => { // Fix this when we have a better understanding of dynamic pricing for custom DA layers. // GitHub issue: https://github.com/matter-labs/zksync-era/issues/2105 0 } PubdataSendingMode::RelayedL2Calldata => { - self.bound_blob_base_fee(self.l2_pubdata_price_statistics.median().as_u64() as f64) + self.bound_pubdata_fee(self.l2_pubdata_price_statistics.median().as_u64() as f64) } } } - fn pubdata_byte_gas(&self) -> u64 { - match self.commitment_mode { - L1BatchCommitmentMode::Validium => 0, - L1BatchCommitmentMode::Rollup => L1_GAS_PER_PUBDATA_BYTE.into(), - } - } - - // FIXME: shall we rename this method to the `bound_pubdata_fee`? - fn bound_blob_base_fee(&self, blob_base_fee: f64) -> u64 { + fn bound_pubdata_fee(&self, pubdata_fee: f64) -> u64 { + // We will treat the max blob base fee as the maximal fee that we can take for each byte of pubdata. let max_blob_base_fee = self.config.max_blob_base_fee(); match self.commitment_mode { L1BatchCommitmentMode::Validium => 0, L1BatchCommitmentMode::Rollup => { - if blob_base_fee > max_blob_base_fee as f64 { - tracing::error!("Blob base fee is too high: {blob_base_fee}, using max allowed: {max_blob_base_fee}"); + if pubdata_fee > max_blob_base_fee as f64 { + tracing::error!("Blob base fee is too high: {pubdata_fee}, using max allowed: {max_blob_base_fee}"); return max_blob_base_fee; } - blob_base_fee as u64 + pubdata_fee as u64 } } } diff --git a/etc/env/configs/dev2.toml b/etc/env/configs/dev2.toml deleted file mode 100644 index 762e058ee954..000000000000 --- a/etc/env/configs/dev2.toml +++ /dev/null @@ -1,21 +0,0 @@ -__imports__ = ["base", "l1-inits/dev2.init.env", "l2-inits/dev2.init.env" ] - -L1_ENV_NAME="dev2" - -ZKSYNC_DEBUG_LOGS=true - -CONTRACTS_SHARED_BRIDGE_UPGRADE_STORAGE_SWITCH="0" -CHAIN_ETH_ZKSYNC_NETWORK_ID=272 -ZKSYNC_ACTION="dont_ask" -CONTRACTS_ERA_CHAIN_ID="270" - -ETH_SENDER_SENDER_OPERATOR_PRIVATE_KEY="0xf12e28c0eb1ef4ff90478f6805b68d63737b7f33abfa091601140805da450d93" -ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR="0x8002cD98Cfb563492A6fB3E7C8243b7B9Ad4cc92" -ETH_SENDER_SENDER_OPERATOR_BLOBS_PRIVATE_KEY="0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8" -ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR="0xA13c10C0D5bd6f79041B9835c63f91de35A15883" - -ETH_CLIENT_CHAIN_ID="270" -ETH_CLIENT_WEB3_URL="http://127.0.0.1:3050" -CHAIN_ETH_NETWORK="localhostL2" - -CONTRACTS_BASE_NETWORK_ZKSYNC="true" diff --git a/etc/env/configs/l1-hyperchain.template.toml b/etc/env/configs/l1-hyperchain.template.toml deleted file mode 100644 index e9f504805960..000000000000 --- a/etc/env/configs/l1-hyperchain.template.toml +++ /dev/null @@ -1,12 +0,0 @@ -__imports__ = ["base", "l1-inits/.init.env", "l2-inits/dev2.init.env" ] -ZKSYNC_DEBUG_LOGS=true - -CONTRACTS_SHARED_BRIDGE_UPGRADE_STORAGE_SWITCH="0" -CHAIN_ETH_ZKSYNC_NETWORK_ID=273 -ZKSYNC_ACTION="dont_ask" -CONTRACTS_ERA_CHAIN_ID="270" - -ETH_SENDER_SENDER_OPERATOR_PRIVATE_KEY="0xf12e28c0eb1ef4ff90478f6805b68d63737b7f33abfa091601140805da450d93" -ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR="0x8002cD98Cfb563492A6fB3E7C8243b7B9Ad4cc92" -ETH_SENDER_SENDER_OPERATOR_BLOBS_PRIVATE_KEY="0x850683b40d4a740aa6e745f889a6fdc8327be76e122f5aba645a5b02d0248db8" -ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR="0xA13c10C0D5bd6f79041B9835c63f91de35A15883" From 982b2a0267be56077ebd12e75459a7f7ebdaca42 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 16:02:58 +0200 Subject: [PATCH 14/43] a bit more polishing --- core/lib/protobuf_config/src/eth.rs | 6 ++++-- core/lib/protobuf_config/src/proto/config/eth_sender.proto | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index 1a31ae2bd08e..46fa977bb9aa 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -176,7 +176,8 @@ impl ProtoRepr for proto::GasAdjuster { ) .context("internal_pubdata_pricing_multiplier")?, max_blob_base_fee: self.max_blob_base_fee, - l2_mode: self.l2_mode, + // TODO(EVM-676): support this field + l2_mode: None, }) } @@ -198,7 +199,8 @@ impl ProtoRepr for proto::GasAdjuster { ), internal_pubdata_pricing_multiplier: Some(this.internal_pubdata_pricing_multiplier), max_blob_base_fee: this.max_blob_base_fee, - l2_mode: this.l2_mode, + // TODO(EVM-676): support this field + l2_mode: None, } } } diff --git a/core/lib/protobuf_config/src/proto/config/eth_sender.proto b/core/lib/protobuf_config/src/proto/config/eth_sender.proto index 5af091b8bed2..536ac216863e 100644 --- a/core/lib/protobuf_config/src/proto/config/eth_sender.proto +++ b/core/lib/protobuf_config/src/proto/config/eth_sender.proto @@ -61,7 +61,6 @@ message GasAdjuster { optional uint64 num_samples_for_blob_base_fee_estimate = 9; // required; optional double internal_pubdata_pricing_multiplier = 10; // required; optional uint64 max_blob_base_fee = 11; // optional; wei - optional bool l2_mode = 13; // optional } message ETHWatch { From 86628e3d5e958e59a25f2401a8e7380f82f52d2c Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 17:49:37 +0200 Subject: [PATCH 15/43] resolve more issues --- core/bin/external_node/src/tests/framework.rs | 4 +- ...be1aff592a9f2f102adafba99e1138fb7a6df.json | 29 ------------ ...7517f5d61f7f1472e7d152f575ffd56ad8633.json | 47 +++++++++++++++++++ core/lib/dal/src/blocks_web3_dal.rs | 17 ++++++- core/lib/protobuf_config/src/eth.rs | 2 - .../node/consistency_checker/src/tests/mod.rs | 2 +- core/node/eth_sender/src/tester.rs | 26 ++++++---- .../src/l1_gas_price/gas_adjuster/mod.rs | 2 +- 8 files changed, 83 insertions(+), 46 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json create mode 100644 core/lib/dal/.sqlx/query-1bfcc02ac79958dcbd20f3680df7517f5d61f7f1472e7d152f575ffd56ad8633.json diff --git a/core/bin/external_node/src/tests/framework.rs b/core/bin/external_node/src/tests/framework.rs index 71a6afe503a7..6dfdccdae472 100644 --- a/core/bin/external_node/src/tests/framework.rs +++ b/core/bin/external_node/src/tests/framework.rs @@ -127,7 +127,9 @@ 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(SLChainId(1), "https://example.com".parse().unwrap()).layer_name() + // TODO(EVM-676): configure the `l2_mode` here + QueryEthClientLayer::new(SLChainId(1), "https://example.com".parse().unwrap(), false) + .layer_name() } async fn wire(self, _: Self::Input) -> Result { diff --git a/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json b/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json deleted file mode 100644 index a5699d0b1ea7..000000000000 --- a/core/lib/dal/.sqlx/query-089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n base_fee_per_gas,\n gas_per_pubdata_limit\n FROM\n miniblocks\n WHERE\n number <= $1\n ORDER BY\n number DESC\n LIMIT\n $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "base_fee_per_gas", - "type_info": "Numeric" - }, - { - "ordinal": 1, - "name": "gas_per_pubdata_limit", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - false, - false - ] - }, - "hash": "089698a00ecc3affc2a39e4b779be1aff592a9f2f102adafba99e1138fb7a6df" -} diff --git a/core/lib/dal/.sqlx/query-1bfcc02ac79958dcbd20f3680df7517f5d61f7f1472e7d152f575ffd56ad8633.json b/core/lib/dal/.sqlx/query-1bfcc02ac79958dcbd20f3680df7517f5d61f7f1472e7d152f575ffd56ad8633.json new file mode 100644 index 000000000000..8ae53dc7e6f4 --- /dev/null +++ b/core/lib/dal/.sqlx/query-1bfcc02ac79958dcbd20f3680df7517f5d61f7f1472e7d152f575ffd56ad8633.json @@ -0,0 +1,47 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n base_fee_per_gas,\n l2_fair_gas_price,\n fair_pubdata_price,\n protocol_version,\n l1_gas_price\n FROM\n miniblocks\n WHERE\n number <= $1\n ORDER BY\n number DESC\n LIMIT\n $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "base_fee_per_gas", + "type_info": "Numeric" + }, + { + "ordinal": 1, + "name": "l2_fair_gas_price", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "fair_pubdata_price", + "type_info": "Int8" + }, + { + "ordinal": 3, + "name": "protocol_version", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "l1_gas_price", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + false, + true, + true, + false + ] + }, + "hash": "1bfcc02ac79958dcbd20f3680df7517f5d61f7f1472e7d152f575ffd56ad8633" +} diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 706e3b9f3311..13fa9070f828 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -5,6 +5,7 @@ use zksync_db_connection::{ use zksync_system_constants::EMPTY_UNCLES_HASH; use zksync_types::{ api, + fee_model::BatchFeeInput, l2_to_l1_log::L2ToL1Log, vm_trace::Call, web3::{BlockHeader, Bytes}, @@ -575,7 +576,10 @@ impl BlocksWeb3Dal<'_, '_> { r#" SELECT base_fee_per_gas, - fair_pubdata_price + l2_fair_gas_price, + fair_pubdata_price, + protocol_version, + l1_gas_price FROM miniblocks WHERE @@ -595,9 +599,18 @@ impl BlocksWeb3Dal<'_, '_> { .await? .into_iter() .map(|row| { + let fee_input = BatchFeeInput::for_protocol_version( + row.protocol_version + .map(|x| (x as u16).try_into().unwrap()) + .unwrap_or_else(ProtocolVersionId::last_potentially_undefined), + row.l2_fair_gas_price as u64, + row.fair_pubdata_price.map(|x| x as u64), + row.l1_gas_price as u64, + ); + ( bigdecimal_to_u256(row.base_fee_per_gas), - bigdecimal_to_u256(row.fair_pubdata_price), + U256::from(fee_input.fair_pubdata_price()), ) }) .collect(); diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index 46fa977bb9aa..7e46993fac2e 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -199,8 +199,6 @@ impl ProtoRepr for proto::GasAdjuster { ), internal_pubdata_pricing_multiplier: Some(this.internal_pubdata_pricing_multiplier), max_blob_base_fee: this.max_blob_base_fee, - // TODO(EVM-676): support this field - l2_mode: None, } } } diff --git a/core/node/consistency_checker/src/tests/mod.rs b/core/node/consistency_checker/src/tests/mod.rs index 1e8a1fae94c4..40c447071cf4 100644 --- a/core/node/consistency_checker/src/tests/mod.rs +++ b/core/node/consistency_checker/src/tests/mod.rs @@ -650,7 +650,7 @@ impl IncorrectDataKind { async fn apply( self, - client: &MockEthereum, + client: &MockSettlementLayer, l1_batch: &L1BatchWithMetadata, commitment_mode: L1BatchCommitmentMode, ) -> H256 { diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index cf090e28ea70..bb166a40652e 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -5,9 +5,12 @@ use zksync_config::{ ContractsConfig, EthConfig, GasAdjusterConfig, }; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{clients::MockEthereum, BaseFees, BoundEthInterface}; +use zksync_eth_client::{ + clients::{MockClientBaseFee, MockSettlementLayer}, + BaseFees, BoundEthInterface, +}; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; -use zksync_node_fee_model::l1_gas_price::GasAdjuster; +use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; use zksync_object_store::MockObjectStore; use zksync_types::{ @@ -109,8 +112,8 @@ impl TestL1Batch { #[derive(Debug)] pub(crate) struct EthSenderTester { pub conn: ConnectionPool, - pub gateway: Box, - pub gateway_blobs: Box, + pub gateway: Box, + pub gateway_blobs: Box, pub manager: MockEthTxManager, pub aggregator: EthTxAggregator, pub gas_adjuster: Arc, @@ -149,17 +152,19 @@ impl EthSenderTester { let history: Vec<_> = history .into_iter() - .map(|base_fee_per_gas| BaseFees { + .map(|base_fee_per_gas| MockClientBaseFee { base_fee_per_gas, base_fee_per_blob_gas: 0.into(), + pubdata_price: 0.into(), }) .collect(); - let gateway = MockEthereum::builder() + let gateway = MockSettlementLayer::builder() .with_fee_history( - std::iter::repeat_with(|| BaseFees { + std::iter::repeat_with(|| MockClientBaseFee { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), + pubdata_price: 0.into(), }) .take(Self::WAIT_CONFIRMATIONS as usize) .chain(history.clone()) @@ -174,11 +179,12 @@ impl EthSenderTester { gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); let gateway = Box::new(gateway); - let gateway_blobs = MockEthereum::builder() + let gateway_blobs = MockSettlementLayer::builder() .with_fee_history( - std::iter::repeat_with(|| BaseFees { + std::iter::repeat_with(|| MockClientBaseFee { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), + pubdata_price: 0.into(), }) .take(Self::WAIT_CONFIRMATIONS as usize) .chain(history) @@ -195,7 +201,7 @@ impl EthSenderTester { let gas_adjuster = Arc::new( GasAdjuster::new( - Box::new(gateway.clone().into_client()), + GasAdjusterClient::from_l1(Box::new(gateway.clone().into_client())), GasAdjusterConfig { max_base_fee_samples: Self::MAX_BASE_FEE_SAMPLES, pricing_formula_parameter_a: 3.0, diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 8e546de18f74..834db1465503 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -332,7 +332,7 @@ impl GasAdjuster { self.bound_pubdata_fee(calculated_price) } PubdataSendingMode::Calldata => self.bound_pubdata_fee( - self.estimate_effective_gas_price() * L1_GAS_PER_PUBDATA_BYTE.into(), + (self.estimate_effective_gas_price() * L1_GAS_PER_PUBDATA_BYTE as u64) as f64, ), PubdataSendingMode::Custom => { // Fix this when we have a better understanding of dynamic pricing for custom DA layers. From 5502eca8094a4a8debb7c80a822d3c5c7480b23b Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 1 Aug 2024 19:07:58 +0200 Subject: [PATCH 16/43] hopefully resolve compilation this time --- core/lib/web3_decl/src/namespaces/debug.rs | 2 +- core/lib/web3_decl/src/namespaces/en.rs | 2 +- core/lib/web3_decl/src/namespaces/eth.rs | 2 +- core/lib/web3_decl/src/namespaces/net.rs | 2 +- core/lib/web3_decl/src/namespaces/snapshots.rs | 2 +- core/lib/web3_decl/src/namespaces/unstable.rs | 2 +- core/lib/web3_decl/src/namespaces/web3.rs | 2 +- core/lib/web3_decl/src/namespaces/zks.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/lib/web3_decl/src/namespaces/debug.rs b/core/lib/web3_decl/src/namespaces/debug.rs index 4342660aaf4e..e276d487fb6f 100644 --- a/core/lib/web3_decl/src/namespaces/debug.rs +++ b/core/lib/web3_decl/src/namespaces/debug.rs @@ -18,7 +18,7 @@ use crate::{ )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "debug", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "debug", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait DebugNamespace { #[method(name = "traceBlockByNumber")] diff --git a/core/lib/web3_decl/src/namespaces/en.rs b/core/lib/web3_decl/src/namespaces/en.rs index 7fcaf69f6fe8..6f4cf1ffeaf1 100644 --- a/core/lib/web3_decl/src/namespaces/en.rs +++ b/core/lib/web3_decl/src/namespaces/en.rs @@ -12,7 +12,7 @@ use crate::client::{ForEthereumLikeNetwork, L2}; )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "en", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "en", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait EnNamespace { #[method(name = "syncL2Block")] diff --git a/core/lib/web3_decl/src/namespaces/eth.rs b/core/lib/web3_decl/src/namespaces/eth.rs index ec5deefaf3e3..74ee7845ebc3 100644 --- a/core/lib/web3_decl/src/namespaces/eth.rs +++ b/core/lib/web3_decl/src/namespaces/eth.rs @@ -23,7 +23,7 @@ use crate::{ )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "eth", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait EthNamespace { #[method(name = "blockNumber")] diff --git a/core/lib/web3_decl/src/namespaces/net.rs b/core/lib/web3_decl/src/namespaces/net.rs index 0be546c8200f..750d7c0cd252 100644 --- a/core/lib/web3_decl/src/namespaces/net.rs +++ b/core/lib/web3_decl/src/namespaces/net.rs @@ -11,7 +11,7 @@ use crate::client::{ForEthereumLikeNetwork, L2}; )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "net", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "net", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait NetNamespace { #[method(name = "version")] diff --git a/core/lib/web3_decl/src/namespaces/snapshots.rs b/core/lib/web3_decl/src/namespaces/snapshots.rs index e6be578bc046..947c181cab48 100644 --- a/core/lib/web3_decl/src/namespaces/snapshots.rs +++ b/core/lib/web3_decl/src/namespaces/snapshots.rs @@ -14,7 +14,7 @@ use crate::client::{ForEthereumLikeNetwork, L2}; )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "snapshots", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "snapshots", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait SnapshotsNamespace { #[method(name = "getAllSnapshots")] diff --git a/core/lib/web3_decl/src/namespaces/unstable.rs b/core/lib/web3_decl/src/namespaces/unstable.rs index 9446862befe1..daf5a3a1583f 100644 --- a/core/lib/web3_decl/src/namespaces/unstable.rs +++ b/core/lib/web3_decl/src/namespaces/unstable.rs @@ -12,7 +12,7 @@ use crate::client::{ForEthereumLikeNetwork, L2}; )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "unstable", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "unstable", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait UnstableNamespace { #[method(name = "getTransactionExecutionInfo")] diff --git a/core/lib/web3_decl/src/namespaces/web3.rs b/core/lib/web3_decl/src/namespaces/web3.rs index ef5feceb4686..9ef51363c64e 100644 --- a/core/lib/web3_decl/src/namespaces/web3.rs +++ b/core/lib/web3_decl/src/namespaces/web3.rs @@ -10,7 +10,7 @@ use crate::client::{ForEthereumLikeNetwork, L2}; )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "web3", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "web3", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait Web3Namespace { #[method(name = "clientVersion")] diff --git a/core/lib/web3_decl/src/namespaces/zks.rs b/core/lib/web3_decl/src/namespaces/zks.rs index 77fa82d80358..ca95de0da4e5 100644 --- a/core/lib/web3_decl/src/namespaces/zks.rs +++ b/core/lib/web3_decl/src/namespaces/zks.rs @@ -25,7 +25,7 @@ use crate::{ )] #[cfg_attr( not(feature = "server"), - rpc(client, namespace = "zks", client_bounds(Self: ForNetwork)) + rpc(client, namespace = "zks", client_bounds(Self: ForEthereumLikeNetwork)) )] pub trait ZksNamespace { #[method(name = "estimateFee")] From a85eac25625e4830c662ceaefb65d2b6f3b93774 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 10:25:23 +0200 Subject: [PATCH 17/43] cargo fix --- core/bin/zksync_server/src/main.rs | 1 - core/lib/eth_client/src/clients/http/decl.rs | 7 ++----- core/lib/eth_client/src/clients/http/query.rs | 2 +- core/lib/eth_client/src/clients/mock.rs | 1 - core/lib/eth_client/src/lib.rs | 2 +- core/node/eth_sender/src/tester.rs | 2 +- core/node/eth_sender/src/tests.rs | 14 +++----------- .../fee_model/src/l1_gas_price/gas_adjuster/mod.rs | 2 +- core/node/fee_model/src/lib.rs | 5 +---- 9 files changed, 10 insertions(+), 26 deletions(-) diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index 8915e059dba4..d9096f6f67df 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -26,7 +26,6 @@ use zksync_core_leftovers::{ Component, Components, }; use zksync_env_config::FromEnv; -use zksync_eth_client::clients::{Client, L1}; use crate::node_builder::MainNodeBuilder; diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index c0c6f0c76ac9..3cbc56ede072 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -1,9 +1,6 @@ use jsonrpsee::proc_macros::rpc; -use zksync_types::{ - api::{BlockDetails, L1BatchDetails}, - web3, Address, L1BatchNumber, L2BlockNumber, H256, U256, U64, -}; -use zksync_web3_decl::client::{ForEthereumLikeNetwork, L1, L2}; +use zksync_types::{web3, Address, H256, U256, U64}; +use zksync_web3_decl::client::{ForEthereumLikeNetwork, L2}; /// Subset of the L1 `eth` namespace used by the L1 client. #[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 4ac2c37d3a56..9263caf1f012 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, L2BlockNumber, SLChainId, H256, U256, U64}; +use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}; use super::{ diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 55b46b2fc014..f8a82c7413ca 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -6,7 +6,6 @@ use std::{ }; use jsonrpsee::{core::ClientError, types::ErrorObject}; -use zksync_config::configs::api; use zksync_types::{ api::FeeHistory, ethabi, diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index f2e14deb9f36..80b2764d00f7 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -10,7 +10,7 @@ use zksync_types::{ }, Address, SLChainId, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, Network, L1}; +use zksync_web3_decl::client::{DynClient, Network}; pub use zksync_web3_decl::{ error::{EnrichedClientError, EnrichedClientResult}, jsonrpsee::core::ClientError, diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index bb166a40652e..fd9eca40c983 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -7,7 +7,7 @@ use zksync_config::{ use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ clients::{MockClientBaseFee, MockSettlementLayer}, - BaseFees, BoundEthInterface, + BoundEthInterface, }; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index 602073a416c7..e19ba225b7e1 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -1,16 +1,8 @@ use assert_matches::assert_matches; use test_casing::{test_casing, Product}; -use zksync_config::{ - configs::eth_sender::{ProofSendingMode, PubdataSendingMode, SenderConfig}, - ContractsConfig, EthConfig, GasAdjusterConfig, -}; -use zksync_contracts::BaseSystemContractsHashes; -use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; -use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; -use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; -use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; -use zksync_object_store::MockObjectStore; +use zksync_dal::{ConnectionPool, Core, CoreDal}; +use zksync_l1_contract_interface::i_executor::methods::ExecuteBatches; +use zksync_node_test_utils::create_l1_batch; use zksync_types::{ aggregated_operations::AggregatedActionType, block::L1BatchHeader, diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 834db1465503..160f46697403 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -7,7 +7,7 @@ use std::{ use tokio::sync::watch; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::{BaseFees, EnrichedClientResult, EthInterface, ZkSyncInterface}; +use zksync_eth_client::{EnrichedClientResult, EthInterface, ZkSyncInterface}; use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U256, U64}; use zksync_web3_decl::client::{DynClient, L1, L2}; diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index 8842c18687f6..f3eb8b1f2a77 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -289,10 +289,7 @@ mod tests { use l1_gas_price::GasAdjusterClient; use zksync_base_token_adjuster::NoOpRatioProvider; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; - use zksync_eth_client::{ - clients::{MockClientBaseFee, MockSettlementLayer}, - BaseFees, - }; + use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; use zksync_types::{commitment::L1BatchCommitmentMode, fee_model::BaseTokenConversionRatio}; use super::*; From 5e22a879b3c45c190300e968380bcb89475d8a88 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 10:29:22 +0200 Subject: [PATCH 18/43] fix lint --- core/lib/eth_client/src/clients/mock.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index f8a82c7413ca..a8964d1f0119 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -673,7 +673,6 @@ impl BoundEthInterface for MockSettlementLaye mod tests { use assert_matches::assert_matches; use zksync_types::{commitment::L1BatchCommitmentMode, ProtocolVersionId}; - use zksync_web3_decl::namespaces::EthNamespaceClient; use super::*; use crate::{CallFunctionArgs, EthInterface, ZkSyncInterface}; @@ -742,7 +741,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[1..=4] - .into_iter() + .iter() .cloned() .map(BaseFees::from) .collect::>() @@ -751,7 +750,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[1..=2] - .into_iter() + .iter() .cloned() .map(BaseFees::from) .collect::>() @@ -760,7 +759,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[2..=3] - .into_iter() + .iter() .cloned() .map(BaseFees::from) .collect::>() @@ -785,7 +784,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[1..=4] - .into_iter() + .iter() .cloned() .map(L2Fees::from) .collect::>() @@ -794,7 +793,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[1..=2] - .into_iter() + .iter() .cloned() .map(L2Fees::from) .collect::>() @@ -803,7 +802,7 @@ mod tests { assert_eq!( fee_history, initial_fee_history[2..=3] - .into_iter() + .iter() .cloned() .map(L2Fees::from) .collect::>() From 6fd3ad4fd8626c7d0da2c83f881ff4918f458fb5 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 13:27:33 +0200 Subject: [PATCH 19/43] first round of change --- core/bin/external_node/src/node_builder.rs | 2 +- core/bin/external_node/src/tests/framework.rs | 10 +++++--- core/bin/zksync_server/src/node_builder.rs | 7 +++--- core/lib/basic_types/src/lib.rs | 3 ++- core/lib/basic_types/src/settlement.rs | 16 +++++++++++++ core/lib/config/src/configs/eth_sender.rs | 7 +++--- core/lib/config/src/testonly.rs | 2 +- core/lib/env_config/src/eth_sender.rs | 2 +- core/lib/eth_client/src/clients/http/decl.rs | 24 +++++++++---------- core/lib/eth_client/src/clients/http/query.rs | 14 +++++------ core/lib/eth_client/src/clients/mock.rs | 4 ++-- core/lib/protobuf_config/src/eth.rs | 2 +- core/lib/web3_decl/src/client/boxed.rs | 2 +- core/lib/web3_decl/src/namespaces/eth.rs | 2 +- core/lib/web3_decl/src/namespaces/mod.rs | 6 ++--- core/node/api_server/src/tx_sender/proxy.rs | 2 +- .../web3/backend_jsonrpsee/namespaces/eth.rs | 4 ++-- core/node/api_server/src/web3/mod.rs | 2 +- core/node/api_server/src/web3/tests/mod.rs | 2 +- core/node/api_server/src/web3/tests/ws.rs | 2 +- .../src/l1_gas_price/gas_adjuster/mod.rs | 2 +- .../src/l1_gas_price/gas_adjuster/tests.rs | 10 ++++---- .../src/implementations/layers/l1_gas.rs | 2 +- .../layers/query_eth_client.rs | 16 ++++++++----- core/node/node_sync/src/client.rs | 2 +- core/node/node_sync/src/sync_state.rs | 2 +- .../node_sync/src/validate_chain_ids_task.rs | 2 +- core/node/reorg_detector/src/lib.rs | 2 +- core/node/state_keeper/src/io/tests/tester.rs | 2 +- .../src/account/api_request_executor.rs | 2 +- .../src/account/tx_command_executor.rs | 2 +- core/tests/loadnext/src/command/api.rs | 2 +- core/tests/loadnext/src/executor.rs | 2 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 4 ++-- core/tests/loadnext/src/sdk/mod.rs | 2 +- .../src/sdk/operations/deploy_contract.rs | 5 ++-- .../src/sdk/operations/execute_contract.rs | 4 ++-- core/tests/loadnext/src/sdk/operations/mod.rs | 4 ++-- .../loadnext/src/sdk/operations/transfer.rs | 4 ++-- .../loadnext/src/sdk/operations/withdraw.rs | 4 ++-- core/tests/loadnext/src/sdk/wallet.rs | 6 +++-- 41 files changed, 112 insertions(+), 84 deletions(-) create mode 100644 core/lib/basic_types/src/settlement.rs diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index fc583b5d8dde..844e0120df5a 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -170,7 +170,7 @@ impl ExternalNodeBuilder { self.config.required.settlement_layer_id(), self.config.required.eth_client_url.clone(), // TODO(EVM-676): add this config for external node - false, + Default::default(), ); self.node.add_layer(query_eth_client_layer); Ok(self) diff --git a/core/bin/external_node/src/tests/framework.rs b/core/bin/external_node/src/tests/framework.rs index 6dfdccdae472..e9667f2c05db 100644 --- a/core/bin/external_node/src/tests/framework.rs +++ b/core/bin/external_node/src/tests/framework.rs @@ -127,9 +127,13 @@ impl WiringLayer for MockL1ClientLayer { fn layer_name(&self) -> &'static str { // We don't care about values, we just want to hijack the layer name. - // TODO(EVM-676): configure the `l2_mode` here - QueryEthClientLayer::new(SLChainId(1), "https://example.com".parse().unwrap(), false) - .layer_name() + // TODO(EVM-676): configure the `settlement_mode` here + QueryEthClientLayer::new( + SLChainId(1), + "https://example.com".parse().unwrap(), + Default::default(), + ) + .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 9154f4b67b45..b3df81913e53 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -65,7 +65,7 @@ use zksync_node_framework::{ }, service::{ZkStackService, ZkStackServiceBuilder}, }; -use zksync_types::SHARED_BRIDGE_ETHER_TOKEN_ADDRESS; +use zksync_types::{settlement::SettlementMode, SHARED_BRIDGE_ETHER_TOKEN_ADDRESS}; use zksync_vlog::prometheus::PrometheusExporterConfig; /// Macro that looks into a path to fetch an optional config, @@ -157,9 +157,8 @@ impl MainNodeBuilder { self.configs .eth .as_ref() - .and_then(|x| x.gas_adjuster) - .and_then(|x| x.l2_mode) - .unwrap_or_default(), + .and_then(|x| Some(x.gas_adjuster?.settlement_mode)) + .unwrap_or(SettlementMode::SettlesToL1), ); 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 2bb9782997fb..a25f740ed444 100644 --- a/core/lib/basic_types/src/lib.rs +++ b/core/lib/basic_types/src/lib.rs @@ -26,6 +26,7 @@ pub mod commitment; pub mod network; pub mod protocol_version; pub mod prover_dal; +pub mod settlement; pub mod tee_types; pub mod url; pub mod vm_version; @@ -89,7 +90,7 @@ impl TryFrom for AccountTreeId { /// ChainId in the ZKsync network. #[derive(Copy, Clone, Debug, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct L2ChainId(pub u64); +pub struct L2ChainId(u64); impl<'de> Deserialize<'de> for L2ChainId { fn deserialize(deserializer: D) -> Result diff --git a/core/lib/basic_types/src/settlement.rs b/core/lib/basic_types/src/settlement.rs new file mode 100644 index 000000000000..89ffe488bf30 --- /dev/null +++ b/core/lib/basic_types/src/settlement.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +/// An enum which is used to describe whether a zkSync network settles to L1 or to the gateway. +/// Gateway is an Ethereum-compatible L2 and so it requires different treatment with regards to DA handling. +#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum SettlementMode { + #[default] + SettlesToL1, + Gateway, +} + +impl SettlementMode { + pub fn is_gateway(&self) -> bool { + matches!(self, Self::Gateway) + } +} diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index d1e69c615246..e932cd9819b9 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -2,7 +2,7 @@ use std::time::Duration; use anyhow::Context as _; use serde::Deserialize; -use zksync_basic_types::H256; +use zksync_basic_types::{settlement::SettlementMode, H256}; use zksync_crypto_primitives::K256PrivateKey; use crate::EthWatchConfig; @@ -54,7 +54,7 @@ impl EthConfig { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, - l2_mode: None, + settlement_mode: Default::default(), }), watcher: Some(EthWatchConfig { confirmations_for_eth_event: None, @@ -185,7 +185,8 @@ pub struct GasAdjusterConfig { pub max_blob_base_fee: Option, /// Whether the gas adjuster should require that the L2 node is used as a settlement layer. /// It offers a runtime check for correctly provided values. - pub l2_mode: Option, + #[serde(default)] + pub settlement_mode: SettlementMode, } impl GasAdjusterConfig { diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 73ae5b1da32b..ff388ccd3257 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -398,7 +398,7 @@ impl Distribution for EncodeDist { internal_pubdata_pricing_multiplier: self.sample(rng), max_blob_base_fee: self.sample(rng), // TODO(EVM-676): generate it randomly once this value is used - l2_mode: None, + settlement_mode: Default::default(), } } } diff --git a/core/lib/env_config/src/eth_sender.rs b/core/lib/env_config/src/eth_sender.rs index f3a73bb24728..18a661099b61 100644 --- a/core/lib/env_config/src/eth_sender.rs +++ b/core/lib/env_config/src/eth_sender.rs @@ -84,7 +84,7 @@ mod tests { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, - l2_mode: None, + settlement_mode: Default::default(), }), watcher: Some(EthWatchConfig { confirmations_for_eth_event: Some(0), diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index 3cbc56ede072..8437ab289eb7 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -67,15 +67,15 @@ pub(super) trait L1EthNamespace { ) -> RpcResult>; } -/// Subset of the L2 `eth` namespace used by an L2 client. It may have the same -/// methods as the L1 `eth` namespace, but with extended return values. -#[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] -pub(super) trait L2EthNamespace { - #[method(name = "feeHistory")] - async fn fee_history( - &self, - block_count: U64, - newest_block: web3::BlockNumber, - reward_percentiles: Option>, - ) -> RpcResult; -} +// /// Subset of the L2 `eth` namespace used by an L2 client. It may have the same +// /// methods as the L1 `eth` namespace, but with extended return values. +// #[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] +// pub(super) trait L2EthNamespace { +// #[method(name = "feeHistory")] +// async fn fee_history( +// &self, +// block_count: U64, +// newest_block: web3::BlockNumber, +// reward_percentiles: Option>, +// ) -> RpcResult; +// } diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 9263caf1f012..5b4400843e92 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -3,12 +3,12 @@ use std::fmt; use async_trait::async_trait; use jsonrpsee::core::ClientError; use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; -use zksync_web3_decl::error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}; - -use super::{ - decl::{L1EthNamespaceClient, L2EthNamespaceClient}, - Method, COUNTERS, LATENCIES, +use zksync_web3_decl::{ + error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, + namespaces::L2EthNamespaceClient, }; + +use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; use crate::{ types::{ExecutedTxStatus, FailureInfo}, BaseFees, EthInterface, L2Fees, RawTransactionBytes, ZkSyncInterface, @@ -374,8 +374,8 @@ where let fee_history = self .fee_history( U64::from(chunk_size), - web3::BlockNumber::from(chunk_end), - None, + zksync_types::api::BlockNumber::from(chunk_end), + vec![], ) .rpc_context("fee_history") .with_arg("chunk_size", &chunk_size) diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index a8964d1f0119..c63d4fa25c31 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -467,12 +467,12 @@ impl SupportedMockEthNetwork for L1 { impl SupportedMockEthNetwork for L2 { fn build_client(builder: MockEthereumBuilder) -> MockClient { - const CHAIN_ID: L2ChainId = L2ChainId(9); + let chain_id: L2ChainId = 9u64.try_into().unwrap(); let base_fee_history = builder.base_fee_history.clone(); builder - .build_client_inner(CHAIN_ID.0, CHAIN_ID.into()) + .build_client_inner(chain_id.as_u64(), chain_id.into()) .method( "eth_feeHistory", move |block_count: U64, newest_block: web3::BlockNumber, _: Option>| { diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index 7e46993fac2e..c605e6d2cccb 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -177,7 +177,7 @@ impl ProtoRepr for proto::GasAdjuster { .context("internal_pubdata_pricing_multiplier")?, max_blob_base_fee: self.max_blob_base_fee, // TODO(EVM-676): support this field - l2_mode: None, + settlement_mode: Default::default(), }) } diff --git a/core/lib/web3_decl/src/client/boxed.rs b/core/lib/web3_decl/src/client/boxed.rs index d83329910981..58db3c9ae8be 100644 --- a/core/lib/web3_decl/src/client/boxed.rs +++ b/core/lib/web3_decl/src/client/boxed.rs @@ -187,7 +187,7 @@ mod tests { use super::*; use crate::{ client::{MockClient, L2}, - namespaces::EthNamespaceClient, + namespaces::L2EthNamespaceClient, }; #[tokio::test] diff --git a/core/lib/web3_decl/src/namespaces/eth.rs b/core/lib/web3_decl/src/namespaces/eth.rs index 74ee7845ebc3..37a54601eba0 100644 --- a/core/lib/web3_decl/src/namespaces/eth.rs +++ b/core/lib/web3_decl/src/namespaces/eth.rs @@ -25,7 +25,7 @@ use crate::{ not(feature = "server"), rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork)) )] -pub trait EthNamespace { +pub trait L2EthNamespace { #[method(name = "blockNumber")] async fn get_block_number(&self) -> RpcResult; diff --git a/core/lib/web3_decl/src/namespaces/mod.rs b/core/lib/web3_decl/src/namespaces/mod.rs index f3b5c8a9aaee..b145d7cfac93 100644 --- a/core/lib/web3_decl/src/namespaces/mod.rs +++ b/core/lib/web3_decl/src/namespaces/mod.rs @@ -1,12 +1,12 @@ pub use self::{ - debug::DebugNamespaceClient, en::EnNamespaceClient, eth::EthNamespaceClient, + debug::DebugNamespaceClient, en::EnNamespaceClient, eth::L2EthNamespaceClient, net::NetNamespaceClient, snapshots::SnapshotsNamespaceClient, unstable::UnstableNamespaceClient, web3::Web3NamespaceClient, zks::ZksNamespaceClient, }; #[cfg(feature = "server")] pub use self::{ - debug::DebugNamespaceServer, en::EnNamespaceServer, eth::EthNamespaceServer, - eth::EthPubSubServer, net::NetNamespaceServer, snapshots::SnapshotsNamespaceServer, + debug::DebugNamespaceServer, en::EnNamespaceServer, eth::EthPubSubServer, + eth::L2EthNamespaceServer, net::NetNamespaceServer, snapshots::SnapshotsNamespaceServer, unstable::UnstableNamespaceServer, web3::Web3NamespaceServer, zks::ZksNamespaceServer, }; diff --git a/core/node/api_server/src/tx_sender/proxy.rs b/core/node/api_server/src/tx_sender/proxy.rs index e179cdcb7748..7786e3280ee3 100644 --- a/core/node/api_server/src/tx_sender/proxy.rs +++ b/core/node/api_server/src/tx_sender/proxy.rs @@ -16,7 +16,7 @@ use zksync_types::{api, fee::TransactionExecutionMetrics, l2::L2Tx, Address, Non use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientResult, Web3Error}, - namespaces::EthNamespaceClient, + namespaces::L2EthNamespaceClient, }; use super::{tx_sink::TxSink, SubmitTxError}; diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs index 15528c5b309b..cc864309ec28 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs @@ -9,14 +9,14 @@ use zksync_types::{ }; use zksync_web3_decl::{ jsonrpsee::core::{async_trait, RpcResult}, - namespaces::EthNamespaceServer, + namespaces::L2EthNamespaceServer, types::{Filter, FilterChanges}, }; use crate::web3::EthNamespace; #[async_trait] -impl EthNamespaceServer for EthNamespace { +impl L2EthNamespaceServer for EthNamespace { async fn get_block_number(&self) -> RpcResult { self.get_block_number_impl() .await diff --git a/core/node/api_server/src/web3/mod.rs b/core/node/api_server/src/web3/mod.rs index bad1b493a5fd..5480c57cbd6b 100644 --- a/core/node/api_server/src/web3/mod.rs +++ b/core/node/api_server/src/web3/mod.rs @@ -23,7 +23,7 @@ use zksync_web3_decl::{ MethodCallback, Methods, RpcModule, }, namespaces::{ - DebugNamespaceServer, EnNamespaceServer, EthNamespaceServer, EthPubSubServer, + DebugNamespaceServer, EnNamespaceServer, EthPubSubServer, L2EthNamespaceServer, NetNamespaceServer, SnapshotsNamespaceServer, UnstableNamespaceServer, Web3NamespaceServer, ZksNamespaceServer, }, diff --git a/core/node/api_server/src/web3/tests/mod.rs b/core/node/api_server/src/web3/tests/mod.rs index d136971734aa..969728e0008f 100644 --- a/core/node/api_server/src/web3/tests/mod.rs +++ b/core/node/api_server/src/web3/tests/mod.rs @@ -51,7 +51,7 @@ use zksync_web3_decl::{ ErrorObjectOwned, }, }, - namespaces::{EnNamespaceClient, EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EnNamespaceClient, L2EthNamespaceClient, ZksNamespaceClient}, }; use super::*; diff --git a/core/node/api_server/src/web3/tests/ws.rs b/core/node/api_server/src/web3/tests/ws.rs index cccebdd6ddd1..57441f9040d6 100644 --- a/core/node/api_server/src/web3/tests/ws.rs +++ b/core/node/api_server/src/web3/tests/ws.rs @@ -19,7 +19,7 @@ use zksync_web3_decl::{ }, rpc_params, }, - namespaces::{EthNamespaceClient, ZksNamespaceClient}, + namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, types::{BlockHeader, Bytes, PubSubFilter}, }; diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 160f46697403..b80ae8101f6a 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -138,7 +138,7 @@ impl GasAdjuster { commitment_mode: L1BatchCommitmentMode, ) -> anyhow::Result { // A runtime check to ensure consistent config. - if config.l2_mode.unwrap_or_default() { + if config.settlement_mode.is_gateway() { assert!(client.is_l2(), "Must be L2 client in L2 mode"); assert!( diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs index 9326d9966f19..dfd55f947993 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs @@ -3,7 +3,7 @@ use std::{collections::VecDeque, sync::RwLockReadGuard}; use test_casing::test_casing; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; -use zksync_types::commitment::L1BatchCommitmentMode; +use zksync_types::{commitment::L1BatchCommitmentMode, settlement::SettlementMode}; use zksync_web3_decl::client::L2; use super::{GasAdjuster, GasStatistics, GasStatisticsInner}; @@ -56,7 +56,7 @@ const TEST_PUBDATA_PRICES: [u64; 10] = [ 493216, ]; -fn test_config(l2_mode: Option) -> GasAdjusterConfig { +fn test_config(settlement_mode: SettlementMode) -> GasAdjusterConfig { GasAdjusterConfig { default_priority_fee_per_gas: 5, max_base_fee_samples: 5, @@ -70,7 +70,7 @@ fn test_config(l2_mode: Option) -> GasAdjusterConfig { num_samples_for_blob_base_fee_estimate: 3, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, - l2_mode, + settlement_mode, } } @@ -99,7 +99,7 @@ async fn kept_updated(commitment_mode: L1BatchCommitmentMode) { // 5 sampled blocks + additional block to account for latest block subtraction eth_client.advance_block_number(6); - let config = test_config(None); + let config = test_config(SettlementMode::SettlesToL1); let adjuster = GasAdjuster::new( GasAdjusterClient::from_l1(Box::new(eth_client.clone().into_client())), config, @@ -163,7 +163,7 @@ async fn kept_updated_l2(commitment_mode: L1BatchCommitmentMode) { // 5 sampled blocks + additional block to account for latest block subtraction eth_client.advance_block_number(6); - let config = test_config(Some(true)); + let config = test_config(SettlementMode::Gateway); let adjuster = GasAdjuster::new( GasAdjusterClient::from_l2(Box::new(eth_client.clone().into_client())), config, diff --git a/core/node/node_framework/src/implementations/layers/l1_gas.rs b/core/node/node_framework/src/implementations/layers/l1_gas.rs index 41459a4ec6e9..fe3eb860eb48 100644 --- a/core/node/node_framework/src/implementations/layers/l1_gas.rs +++ b/core/node/node_framework/src/implementations/layers/l1_gas.rs @@ -80,7 +80,7 @@ impl WiringLayer for SequencerL1GasLayer { } async fn wire(self, input: Self::Input) -> Result { - let client = if self.gas_adjuster_config.l2_mode.unwrap_or_default() { + let client = if self.gas_adjuster_config.settlement_mode.is_gateway() { GasAdjusterClient::from_l2(input.l2_inteface_client.unwrap().0) } else { GasAdjusterClient::from_l1(input.eth_interface_client.0) 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 9a067a20e415..ae3dd6f2b14f 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, L2ChainId, SLChainId}; +use zksync_types::{settlement::SettlementMode, url::SensitiveUrl, L2ChainId, SLChainId}; use zksync_web3_decl::client::{Client, L1, L2}; use crate::{ @@ -14,15 +14,19 @@ use crate::{ pub struct QueryEthClientLayer { chain_id: SLChainId, web3_url: SensitiveUrl, - l2_mode: bool, + settlement_mode: SettlementMode, } impl QueryEthClientLayer { - pub fn new(chain_id: SLChainId, web3_url: SensitiveUrl, l2_mode: bool) -> Self { + pub fn new( + chain_id: SLChainId, + web3_url: SensitiveUrl, + settlement_mode: SettlementMode, + ) -> Self { Self { chain_id, web3_url, - l2_mode, + settlement_mode, } } } @@ -59,11 +63,11 @@ impl WiringLayer for QueryEthClientLayer { .context("Client::new()")? .for_network(self.chain_id.into()) .build(), - query_client_l2: if self.l2_mode { + query_client_l2: if self.settlement_mode.is_gateway() { Some( Client::http(self.web3_url.clone()) .context("Client::new()")? - .for_network(L2ChainId(self.chain_id.0).into()) + .for_network(L2ChainId::try_from(self.chain_id.0).unwrap().into()) .build(), ) } else { diff --git a/core/node/node_sync/src/client.rs b/core/node/node_sync/src/client.rs index d064803eab59..b171742f6aa4 100644 --- a/core/node/node_sync/src/client.rs +++ b/core/node/node_sync/src/client.rs @@ -13,7 +13,7 @@ use zksync_types::{ use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, - namespaces::{EnNamespaceClient, EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EnNamespaceClient, L2EthNamespaceClient, ZksNamespaceClient}, }; /// Client abstracting connection to the main node. diff --git a/core/node/node_sync/src/sync_state.rs b/core/node/node_sync/src/sync_state.rs index e061ff7da012..ae4b32fbb7bd 100644 --- a/core/node/node_sync/src/sync_state.rs +++ b/core/node/node_sync/src/sync_state.rs @@ -11,7 +11,7 @@ use zksync_state_keeper::{io::IoCursor, updates::UpdatesManager, StateKeeperOutp use zksync_types::L2BlockNumber; use zksync_web3_decl::{ client::{DynClient, L2}, - namespaces::EthNamespaceClient, + namespaces::L2EthNamespaceClient, }; /// `SyncState` is a structure that holds the state of the syncing process. 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 0f80bf799b15..af021a02e25c 100644 --- a/core/node/node_sync/src/validate_chain_ids_task.rs +++ b/core/node/node_sync/src/validate_chain_ids_task.rs @@ -9,7 +9,7 @@ use zksync_types::{L2ChainId, SLChainId}; use zksync_web3_decl::{ client::{DynClient, L1, L2}, error::ClientRpcContext, - namespaces::{EthNamespaceClient, ZksNamespaceClient}, + namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, }; /// Task that validates chain IDs using main node and Ethereum clients. diff --git a/core/node/reorg_detector/src/lib.rs b/core/node/reorg_detector/src/lib.rs index 5945b201c16c..6361425238bd 100644 --- a/core/node/reorg_detector/src/lib.rs +++ b/core/node/reorg_detector/src/lib.rs @@ -10,7 +10,7 @@ use zksync_types::{L1BatchNumber, L2BlockNumber, H256}; use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, - namespaces::{EthNamespaceClient, ZksNamespaceClient}, + namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, }; #[cfg(test)] diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 73a9238ad0a2..8bcbc82c5cee 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -77,7 +77,7 @@ impl Tester { num_samples_for_blob_base_fee_estimate: 10, internal_pubdata_pricing_multiplier: 1.0, max_blob_base_fee: None, - l2_mode: None, + settlement_mode: Default::default(), }; GasAdjuster::new( diff --git a/core/tests/loadnext/src/account/api_request_executor.rs b/core/tests/loadnext/src/account/api_request_executor.rs index 20c4bc2f5970..6eb72fbd2f70 100644 --- a/core/tests/loadnext/src/account/api_request_executor.rs +++ b/core/tests/loadnext/src/account/api_request_executor.rs @@ -14,7 +14,7 @@ use crate::{ sdk::{ error::{ClientError, RpcError}, types::FilterBuilder, - EthNamespaceClient, + L2EthNamespaceClient, }, }; diff --git a/core/tests/loadnext/src/account/tx_command_executor.rs b/core/tests/loadnext/src/account/tx_command_executor.rs index b085219060b7..a8a62d5d52d6 100644 --- a/core/tests/loadnext/src/account/tx_command_executor.rs +++ b/core/tests/loadnext/src/account/tx_command_executor.rs @@ -23,7 +23,7 @@ use crate::{ utils::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, - EthNamespaceClient, + L2EthNamespaceClient, }, utils::format_gwei, }; diff --git a/core/tests/loadnext/src/command/api.rs b/core/tests/loadnext/src/command/api.rs index 2f5628f5759b..feacf53227fa 100644 --- a/core/tests/loadnext/src/command/api.rs +++ b/core/tests/loadnext/src/command/api.rs @@ -6,7 +6,7 @@ use crate::{ account_pool::SyncWallet, all::AllWeighted, rng::{LoadtestRng, WeightedRandom}, - sdk::EthNamespaceClient, + sdk::L2EthNamespaceClient, }; /// Helper enum for generating random block number. diff --git a/core/tests/loadnext/src/executor.rs b/core/tests/loadnext/src/executor.rs index 48d90f19c1d7..2e07aa65b118 100644 --- a/core/tests/loadnext/src/executor.rs +++ b/core/tests/loadnext/src/executor.rs @@ -24,7 +24,7 @@ use crate::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, web3::TransactionReceipt, - EthNamespaceClient, EthereumProvider, ZksNamespaceClient, + EthereumProvider, L2EthNamespaceClient, ZksNamespaceClient, }, utils::format_eth, }; diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 3b3516498f89..2c42179fcaa2 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -19,7 +19,7 @@ use zksync_types::{ }; use zksync_web3_decl::{ client::{Client, DynClient, L1}, - namespaces::{EthNamespaceClient, ZksNamespaceClient}, + namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, }; use crate::sdk::{ @@ -608,7 +608,7 @@ pub trait PriorityOpHolder { /// Returns the handle for the priority operation. fn priority_op_handle<'a, P>(&self, provider: &'a P) -> Option> where - P: EthNamespaceClient + Sync, + P: L2EthNamespaceClient + Sync, { self.priority_op() .map(|op| SyncTransactionHandle::new(op.hash(), provider)) diff --git a/core/tests/loadnext/src/sdk/mod.rs b/core/tests/loadnext/src/sdk/mod.rs index 26c11eb7a2a6..d5cdc0fff4c2 100644 --- a/core/tests/loadnext/src/sdk/mod.rs +++ b/core/tests/loadnext/src/sdk/mod.rs @@ -1,6 +1,6 @@ pub use zksync_types::{self, ethabi, web3}; pub use zksync_web3_decl::{ - namespaces::{EthNamespaceClient, ZksNamespaceClient}, + namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, types, }; diff --git a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs index 3b4c7a5eb53f..a91b26a44c07 100644 --- a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs @@ -3,10 +3,11 @@ use zksync_types::{ l2::L2Tx, transaction_request::PaymasterParams, Execute, Nonce, CONTRACT_DEPLOYER_ADDRESS, U256, }; use zksync_utils::bytecode::hash_bytecode; +use zksync_web3_decl::namespaces::L2EthNamespaceClient; use crate::sdk::{ error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, zksync_types::fee::Fee, - EthNamespaceClient, ZksNamespaceClient, + ZksNamespaceClient, }; pub struct DeployContractBuilder<'a, S: EthereumSigner, P> { @@ -23,7 +24,7 @@ pub struct DeployContractBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> DeployContractBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + EthNamespaceClient + Sync, + P: ZksNamespaceClient + L2EthNamespaceClient + Sync, { /// Initializes a change public key transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/execute_contract.rs b/core/tests/loadnext/src/sdk/operations/execute_contract.rs index d5fe57c7b79f..28e84ec98b7c 100644 --- a/core/tests/loadnext/src/sdk/operations/execute_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/execute_contract.rs @@ -4,7 +4,7 @@ use zksync_types::{ }; use crate::sdk::{ - error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, EthNamespaceClient, + error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, L2EthNamespaceClient, ZksNamespaceClient, }; @@ -22,7 +22,7 @@ pub struct ExecuteContractBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> ExecuteContractBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + EthNamespaceClient + Sync, + P: ZksNamespaceClient + L2EthNamespaceClient + Sync, { /// Initializes a change public key transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/mod.rs b/core/tests/loadnext/src/sdk/operations/mod.rs index 757758ef501e..b6bdfa200209 100644 --- a/core/tests/loadnext/src/sdk/operations/mod.rs +++ b/core/tests/loadnext/src/sdk/operations/mod.rs @@ -13,7 +13,7 @@ pub use self::{ transfer::{create_transfer_calldata, TransferBuilder}, withdraw::WithdrawBuilder, }; -use crate::sdk::{error::ClientError, EthNamespaceClient}; +use crate::sdk::{error::ClientError, L2EthNamespaceClient}; mod deploy_contract; mod execute_contract; @@ -37,7 +37,7 @@ pub struct SyncTransactionHandle<'a, P> { impl<'a, P> SyncTransactionHandle<'a, P> where - P: EthNamespaceClient + Sync, + P: L2EthNamespaceClient + Sync, { pub fn new(hash: H256, provider: &'a P) -> Self { Self { diff --git a/core/tests/loadnext/src/sdk/operations/transfer.rs b/core/tests/loadnext/src/sdk/operations/transfer.rs index 94ee3aeb6082..035b92edb025 100644 --- a/core/tests/loadnext/src/sdk/operations/transfer.rs +++ b/core/tests/loadnext/src/sdk/operations/transfer.rs @@ -8,7 +8,7 @@ use crate::sdk::{ wallet::Wallet, web3::contract::Tokenize, zksync_types::{transaction_request::PaymasterParams, Execute, L2TxCommonData}, - EthNamespaceClient, ZksNamespaceClient, + L2EthNamespaceClient, ZksNamespaceClient, }; pub struct TransferBuilder<'a, S: EthereumSigner, P> { @@ -24,7 +24,7 @@ pub struct TransferBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> TransferBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + EthNamespaceClient + Sync, + P: ZksNamespaceClient + L2EthNamespaceClient + Sync, { /// Initializes a transfer transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/withdraw.rs b/core/tests/loadnext/src/sdk/operations/withdraw.rs index 89a8f40713a8..4f03a797dcb4 100644 --- a/core/tests/loadnext/src/sdk/operations/withdraw.rs +++ b/core/tests/loadnext/src/sdk/operations/withdraw.rs @@ -8,7 +8,7 @@ use crate::sdk::{ error::ClientError, operations::{ExecuteContractBuilder, SyncTransactionHandle}, wallet::Wallet, - EthNamespaceClient, ZksNamespaceClient, + L2EthNamespaceClient, ZksNamespaceClient, }; pub struct WithdrawBuilder<'a, S: EthereumSigner, P> { @@ -25,7 +25,7 @@ pub struct WithdrawBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> WithdrawBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + EthNamespaceClient + Sync, + P: ZksNamespaceClient + L2EthNamespaceClient + Sync, { /// Initializes a withdraw transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/wallet.rs b/core/tests/loadnext/src/sdk/wallet.rs index 9d3bd73a9bf2..41a607e4ed36 100644 --- a/core/tests/loadnext/src/sdk/wallet.rs +++ b/core/tests/loadnext/src/sdk/wallet.rs @@ -9,7 +9,9 @@ use zksync_types::{ }; use zksync_web3_decl::{ client::{Client, L2}, - namespaces::{EthNamespaceClient, NetNamespaceClient, Web3NamespaceClient, ZksNamespaceClient}, + namespaces::{ + L2EthNamespaceClient, NetNamespaceClient, Web3NamespaceClient, ZksNamespaceClient, + }, }; use crate::sdk::{ @@ -57,7 +59,7 @@ where impl Wallet where S: EthereumSigner, - P: EthNamespaceClient + ZksNamespaceClient + NetNamespaceClient + Web3NamespaceClient + Sync, + P: L2EthNamespaceClient + ZksNamespaceClient + NetNamespaceClient + Web3NamespaceClient + Sync, { pub fn new(provider: P, signer: Signer) -> Self { Self { provider, signer } From 26a2eeeb212bf3a90d0e62425be7d87fb2151ea1 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 14:39:17 +0200 Subject: [PATCH 20/43] more changes --- core/lib/eth_client/src/clients/http/decl.rs | 13 ---------- core/lib/eth_client/src/clients/http/query.rs | 5 ++-- core/lib/eth_client/src/clients/mock.rs | 26 ++++++++++--------- core/lib/types/src/api/mod.rs | 23 ++-------------- .../api_server/src/web3/namespaces/eth.rs | 16 +++++++----- .../src/l1_gas_price/gas_adjuster/metrics.rs | 1 - .../src/l1_gas_price/gas_adjuster/mod.rs | 20 +++++++------- .../src/implementations/layers/l1_gas.rs | 4 +-- .../resources/eth_interface.rs | 2 +- 9 files changed, 41 insertions(+), 69 deletions(-) diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index 8437ab289eb7..c5ce3acd2eb0 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -66,16 +66,3 @@ pub(super) trait L1EthNamespace { hash: H256, ) -> RpcResult>; } - -// /// Subset of the L2 `eth` namespace used by an L2 client. It may have the same -// /// methods as the L1 `eth` namespace, but with extended return values. -// #[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] -// pub(super) trait L2EthNamespace { -// #[method(name = "feeHistory")] -// async fn fee_history( -// &self, -// block_count: U64, -// newest_block: web3::BlockNumber, -// reward_percentiles: Option>, -// ) -> RpcResult; -// } diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 5b4400843e92..b058ba9d5610 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -383,15 +383,16 @@ where .await?; // Check that the lengths are the same. - if fee_history.base_fee_per_gas.len() != fee_history.pubdata_price.len() { + if fee_history.inner.base_fee_per_gas.len() != fee_history.pubdata_price.len() { tracing::error!( "base_fee_per_gas and pubdata_price have different lengths: {} and {}", - fee_history.base_fee_per_gas.len(), + fee_history.inner.base_fee_per_gas.len(), fee_history.pubdata_price.len() ); } for (base, pubdata_price) in fee_history + .inner .base_fee_per_gas .into_iter() .zip(fee_history.pubdata_price) diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index c63d4fa25c31..f5e3120ee769 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -482,22 +482,24 @@ impl SupportedMockEthNetwork for L2 { let from_block = from_block.as_usize(); let start_block = from_block.saturating_sub(block_count.as_usize() - 1); Ok(FeeHistory { - oldest_block: start_block.into(), - base_fee_per_gas: base_fee_history[start_block..=from_block] - .iter() - .map(|fee| U256::from(fee.base_fee_per_gas)) - .collect(), - base_fee_per_blob_gas: base_fee_history[start_block..=from_block] - .iter() - .map(|fee| fee.base_fee_per_blob_gas) - .collect(), - gas_used_ratio: vec![], // not used - blob_gas_used_ratio: vec![], // not used + inner: web3::FeeHistory { + oldest_block: start_block.into(), + base_fee_per_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| U256::from(fee.base_fee_per_gas)) + .collect(), + base_fee_per_blob_gas: base_fee_history[start_block..=from_block] + .iter() + .map(|fee| fee.base_fee_per_blob_gas) + .collect(), + gas_used_ratio: vec![], // not used + blob_gas_used_ratio: vec![], // not used + reward: None, + }, pubdata_price: base_fee_history[start_block..=from_block] .iter() .map(|fee| fee.pubdata_price) .collect(), - reward: None, }) }, ) diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index 49323b92a7ef..714ecd91c91f 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -838,27 +838,8 @@ pub struct TransactionExecutionInfo { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct FeeHistory { - /// Lowest number block of the returned range. - pub oldest_block: BlockNumber, - /// A vector of block base fees per gas. This includes the next block after the newest of the returned range, - /// because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks. - #[serde(default)] // some node implementations skip empty lists - pub base_fee_per_gas: Vec, - /// A vector of block gas used ratios. These are calculated as the ratio of gas used and gas limit. - #[serde(default)] // some node implementations skip empty lists - pub gas_used_ratio: Vec, - /// A vector of effective priority fee per gas data points from a single block. All zeroes are returned if - /// the block is empty. Returned only if requested. - pub reward: Option>>, - /// An array of base fees per blob gas for blocks. This includes the next block following the newest in the - /// returned range, as this value can be derived from the latest block. For blocks before EIP-4844, zeroes - /// are returned. - #[serde(default)] // some node implementations skip empty lists - pub base_fee_per_blob_gas: Vec, - /// An array showing the ratios of blob gas used in blocks. These ratios are calculated by dividing blobGasUsed - /// by the maximum blob gas per block. - #[serde(default)] // some node implementations skip empty lists - pub blob_gas_used_ratio: Vec, + #[serde(flatten)] + pub inner: zksync_basic_types::web3::FeeHistory, /// An array of effective pubdata price. Note, that this field is L2-specific and only provided by L2 nodes. #[serde(default)] pub pubdata_price: Vec, diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index 97adc2fedb5a..76dc2c91cd69 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -9,7 +9,7 @@ use zksync_types::{ l2::{L2Tx, TransactionType}, transaction_request::CallRequest, utils::decompose_full_nonce, - web3::{Bytes, SyncInfo, SyncState}, + web3::{self, Bytes, SyncInfo, SyncState}, AccountTreeId, L2BlockNumber, StorageKey, H256, L2_BASE_TOKEN_ADDRESS, U256, }; use zksync_utils::u256_to_h256; @@ -704,12 +704,14 @@ impl EthNamespace { // `base_fee_per_gas` for next L2 block cannot be calculated, appending last fee as a placeholder. base_fee_per_gas.push(*base_fee_per_gas.last().unwrap()); Ok(FeeHistory { - oldest_block: zksync_types::api::BlockNumber::Number(oldest_block.into()), - base_fee_per_gas, - gas_used_ratio, - reward, - base_fee_per_blob_gas, - blob_gas_used_ratio, + inner: web3::FeeHistory { + oldest_block: zksync_types::web3::BlockNumber::Number(oldest_block.into()), + base_fee_per_gas, + gas_used_ratio, + reward, + base_fee_per_blob_gas, + blob_gas_used_ratio, + }, pubdata_price: effective_pubdata_price_history, }) } diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs index 1ce92f2311da..f75c1796037f 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/metrics.rs @@ -11,7 +11,6 @@ pub(super) struct GasAdjusterMetrics { pub median_base_fee_per_gas: Gauge, pub median_blob_base_fee_per_gas: Gauge, pub median_blob_base_fee: Gauge, - pub median_l2_pubdata_price: Gauge, } #[vise::register] diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index b80ae8101f6a..499af24fdb04 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -139,16 +139,16 @@ impl GasAdjuster { ) -> anyhow::Result { // A runtime check to ensure consistent config. if config.settlement_mode.is_gateway() { - assert!(client.is_l2(), "Must be L2 client in L2 mode"); + anyhow::ensure!(client.is_l2(), "Must be L2 client in L2 mode"); - assert!( + anyhow::ensure!( matches!(pubdata_sending_mode, PubdataSendingMode::RelayedL2Calldata), "Only relayed L2 calldata is available for L2 mode" ); } else { - assert!(client.is_l1(), "Must be L1 client in L1 mode"); + anyhow::ensure!(client.is_l1(), "Must be L1 client in L1 mode"); - assert!( + anyhow::ensure!( !matches!(pubdata_sending_mode, PubdataSendingMode::RelayedL2Calldata), "Relayed L2 calldata is only available in L2 mode" ); @@ -229,7 +229,7 @@ impl GasAdjuster { fee_data.last().map(|fee| fee.base_fee_per_blob_gas) { // Blob base fee overflows `u64` only in very extreme cases. - // It doesn't worth to observe exact value with metric because anyway values that can be used + // It isn't worth to observe exact value with metric because anyway values that can be used // are capped by `self.config.max_blob_base_fee()` of `u64` type. if current_blob_base_fee > U256::from(u64::MAX) { tracing::error!("Failed to report current_blob_base_fee = {current_blob_base_fee}, it exceeds u64::MAX"); @@ -245,7 +245,7 @@ impl GasAdjuster { if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.l2_pubdata_price) { // L2 pubdata price overflows `u64` only in very extreme cases. - // It doesn't worth to observe exact value with metric because anyway values that can be used + // It isn't worth to observe exact value with metric because anyway values that can be used // are capped by `self.config.max_blob_base_fee()` of `u64` type. if current_l2_pubdata_price > U256::from(u64::MAX) { tracing::error!("Failed to report current_l2_pubdata_price = {current_l2_pubdata_price}, it exceeds u64::MAX"); @@ -329,9 +329,9 @@ impl GasAdjuster { * BLOB_GAS_PER_BYTE as f64 * self.config.internal_pubdata_pricing_multiplier; - self.bound_pubdata_fee(calculated_price) + self.cap_pubdata_fee(calculated_price) } - PubdataSendingMode::Calldata => self.bound_pubdata_fee( + PubdataSendingMode::Calldata => self.cap_pubdata_fee( (self.estimate_effective_gas_price() * L1_GAS_PER_PUBDATA_BYTE as u64) as f64, ), PubdataSendingMode::Custom => { @@ -340,12 +340,12 @@ impl GasAdjuster { 0 } PubdataSendingMode::RelayedL2Calldata => { - self.bound_pubdata_fee(self.l2_pubdata_price_statistics.median().as_u64() as f64) + self.cap_pubdata_fee(self.l2_pubdata_price_statistics.median().as_u64() as f64) } } } - fn bound_pubdata_fee(&self, pubdata_fee: f64) -> u64 { + fn cap_pubdata_fee(&self, pubdata_fee: f64) -> u64 { // We will treat the max blob base fee as the maximal fee that we can take for each byte of pubdata. let max_blob_base_fee = self.config.max_blob_base_fee(); match self.commitment_mode { diff --git a/core/node/node_framework/src/implementations/layers/l1_gas.rs b/core/node/node_framework/src/implementations/layers/l1_gas.rs index fe3eb860eb48..8575ac08bec3 100644 --- a/core/node/node_framework/src/implementations/layers/l1_gas.rs +++ b/core/node/node_framework/src/implementations/layers/l1_gas.rs @@ -81,9 +81,9 @@ impl WiringLayer for SequencerL1GasLayer { async fn wire(self, input: Self::Input) -> Result { let client = if self.gas_adjuster_config.settlement_mode.is_gateway() { - GasAdjusterClient::from_l2(input.l2_inteface_client.unwrap().0) + input.l2_inteface_client.unwrap().0.into() } else { - GasAdjusterClient::from_l1(input.eth_interface_client.0) + input.eth_interface_client.0.into() }; let adjuster = GasAdjuster::new( diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index 189cb71d52f0..c8c566816b97 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -23,7 +23,7 @@ pub struct L2InterfaceResource(pub Box>); impl Resource for L2InterfaceResource { fn name() -> String { - "common/l2_inteface".into() + "common/l2_interface".into() } } From 8ffaf5f2f395c90c63f40882404457b80f4568fe Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 14:48:48 +0200 Subject: [PATCH 21/43] nit --- .../layers/query_eth_client.rs | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) 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 ae3dd6f2b14f..fc06aed32fe1 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 @@ -31,20 +31,11 @@ impl QueryEthClientLayer { } } -#[derive(Debug)] +#[derive(Debug, IntoContext)] +#[context(crate = crate)] pub struct Output { - query_client_l1: Client, - query_client_l2: Option>, -} - -impl IntoContext for Output { - fn into_context(self, context: &mut ServiceContext<'_>) -> Result<(), WiringError> { - context.insert_resource(EthInterfaceResource(Box::new(self.query_client_l1)))?; - if let Some(query_client_l2) = self.query_client_l2 { - context.insert_resource(L2InterfaceResource(Box::new(query_client_l2)))?; - } - Ok(()) - } + query_client_l1: EthInterfaceResource, + query_client_l2: Option, } #[async_trait::async_trait] @@ -59,17 +50,19 @@ impl WiringLayer for QueryEthClientLayer { async fn wire(self, _input: Self::Input) -> Result { // Both the L1 and L2 client have the same URL, but provide different type guarantees. Ok(Output { - query_client_l1: Client::http(self.web3_url.clone()) - .context("Client::new()")? - .for_network(self.chain_id.into()) - .build(), + query_client_l1: EthInterfaceResource(Box::new( + Client::http(self.web3_url.clone()) + .context("Client::new()")? + .for_network(self.chain_id.into()) + .build(), + )), query_client_l2: if self.settlement_mode.is_gateway() { - Some( + Some(L2InterfaceResource(Box::new( Client::http(self.web3_url.clone()) .context("Client::new()")? .for_network(L2ChainId::try_from(self.chain_id.0).unwrap().into()) .build(), - ) + ))) } else { None }, From c4091e94cf44a996c84aa3c08f1b5585fb505e59 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 2 Aug 2024 15:10:58 +0200 Subject: [PATCH 22/43] return back old naming for smaller diff --- core/lib/eth_client/src/clients/http/query.rs | 4 ++-- core/lib/web3_decl/src/client/boxed.rs | 2 +- core/lib/web3_decl/src/namespaces/eth.rs | 2 +- core/lib/web3_decl/src/namespaces/mod.rs | 6 +++--- core/node/api_server/src/tx_sender/proxy.rs | 2 +- .../api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs | 4 ++-- core/node/api_server/src/web3/mod.rs | 2 +- core/node/api_server/src/web3/tests/mod.rs | 2 +- core/node/api_server/src/web3/tests/ws.rs | 2 +- core/node/node_sync/src/client.rs | 2 +- core/node/node_sync/src/sync_state.rs | 2 +- core/node/node_sync/src/validate_chain_ids_task.rs | 2 +- core/node/reorg_detector/src/lib.rs | 2 +- core/tests/loadnext/src/account/api_request_executor.rs | 2 +- core/tests/loadnext/src/account/tx_command_executor.rs | 2 +- core/tests/loadnext/src/command/api.rs | 2 +- core/tests/loadnext/src/executor.rs | 2 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 4 ++-- core/tests/loadnext/src/sdk/mod.rs | 2 +- core/tests/loadnext/src/sdk/operations/deploy_contract.rs | 4 ++-- core/tests/loadnext/src/sdk/operations/execute_contract.rs | 4 ++-- core/tests/loadnext/src/sdk/operations/mod.rs | 4 ++-- core/tests/loadnext/src/sdk/operations/transfer.rs | 4 ++-- core/tests/loadnext/src/sdk/operations/withdraw.rs | 4 ++-- core/tests/loadnext/src/sdk/wallet.rs | 6 ++---- 25 files changed, 36 insertions(+), 38 deletions(-) diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index b058ba9d5610..12966a5664d6 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -5,7 +5,7 @@ use jsonrpsee::core::ClientError; use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::{ error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, - namespaces::L2EthNamespaceClient, + namespaces::EthNamespaceClient, }; use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; @@ -352,7 +352,7 @@ where #[async_trait::async_trait] impl ZkSyncInterface for T where - T: L2EthNamespaceClient + fmt::Debug + Send + Sync, + T: EthNamespaceClient + fmt::Debug + Send + Sync, { async fn l2_fee_history( &self, diff --git a/core/lib/web3_decl/src/client/boxed.rs b/core/lib/web3_decl/src/client/boxed.rs index 58db3c9ae8be..d83329910981 100644 --- a/core/lib/web3_decl/src/client/boxed.rs +++ b/core/lib/web3_decl/src/client/boxed.rs @@ -187,7 +187,7 @@ mod tests { use super::*; use crate::{ client::{MockClient, L2}, - namespaces::L2EthNamespaceClient, + namespaces::EthNamespaceClient, }; #[tokio::test] diff --git a/core/lib/web3_decl/src/namespaces/eth.rs b/core/lib/web3_decl/src/namespaces/eth.rs index 37a54601eba0..74ee7845ebc3 100644 --- a/core/lib/web3_decl/src/namespaces/eth.rs +++ b/core/lib/web3_decl/src/namespaces/eth.rs @@ -25,7 +25,7 @@ use crate::{ not(feature = "server"), rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork)) )] -pub trait L2EthNamespace { +pub trait EthNamespace { #[method(name = "blockNumber")] async fn get_block_number(&self) -> RpcResult; diff --git a/core/lib/web3_decl/src/namespaces/mod.rs b/core/lib/web3_decl/src/namespaces/mod.rs index b145d7cfac93..f3b5c8a9aaee 100644 --- a/core/lib/web3_decl/src/namespaces/mod.rs +++ b/core/lib/web3_decl/src/namespaces/mod.rs @@ -1,12 +1,12 @@ pub use self::{ - debug::DebugNamespaceClient, en::EnNamespaceClient, eth::L2EthNamespaceClient, + debug::DebugNamespaceClient, en::EnNamespaceClient, eth::EthNamespaceClient, net::NetNamespaceClient, snapshots::SnapshotsNamespaceClient, unstable::UnstableNamespaceClient, web3::Web3NamespaceClient, zks::ZksNamespaceClient, }; #[cfg(feature = "server")] pub use self::{ - debug::DebugNamespaceServer, en::EnNamespaceServer, eth::EthPubSubServer, - eth::L2EthNamespaceServer, net::NetNamespaceServer, snapshots::SnapshotsNamespaceServer, + debug::DebugNamespaceServer, en::EnNamespaceServer, eth::EthNamespaceServer, + eth::EthPubSubServer, net::NetNamespaceServer, snapshots::SnapshotsNamespaceServer, unstable::UnstableNamespaceServer, web3::Web3NamespaceServer, zks::ZksNamespaceServer, }; diff --git a/core/node/api_server/src/tx_sender/proxy.rs b/core/node/api_server/src/tx_sender/proxy.rs index 7786e3280ee3..e179cdcb7748 100644 --- a/core/node/api_server/src/tx_sender/proxy.rs +++ b/core/node/api_server/src/tx_sender/proxy.rs @@ -16,7 +16,7 @@ use zksync_types::{api, fee::TransactionExecutionMetrics, l2::L2Tx, Address, Non use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientResult, Web3Error}, - namespaces::L2EthNamespaceClient, + namespaces::EthNamespaceClient, }; use super::{tx_sink::TxSink, SubmitTxError}; diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs index cc864309ec28..15528c5b309b 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs @@ -9,14 +9,14 @@ use zksync_types::{ }; use zksync_web3_decl::{ jsonrpsee::core::{async_trait, RpcResult}, - namespaces::L2EthNamespaceServer, + namespaces::EthNamespaceServer, types::{Filter, FilterChanges}, }; use crate::web3::EthNamespace; #[async_trait] -impl L2EthNamespaceServer for EthNamespace { +impl EthNamespaceServer for EthNamespace { async fn get_block_number(&self) -> RpcResult { self.get_block_number_impl() .await diff --git a/core/node/api_server/src/web3/mod.rs b/core/node/api_server/src/web3/mod.rs index 5480c57cbd6b..bad1b493a5fd 100644 --- a/core/node/api_server/src/web3/mod.rs +++ b/core/node/api_server/src/web3/mod.rs @@ -23,7 +23,7 @@ use zksync_web3_decl::{ MethodCallback, Methods, RpcModule, }, namespaces::{ - DebugNamespaceServer, EnNamespaceServer, EthPubSubServer, L2EthNamespaceServer, + DebugNamespaceServer, EnNamespaceServer, EthNamespaceServer, EthPubSubServer, NetNamespaceServer, SnapshotsNamespaceServer, UnstableNamespaceServer, Web3NamespaceServer, ZksNamespaceServer, }, diff --git a/core/node/api_server/src/web3/tests/mod.rs b/core/node/api_server/src/web3/tests/mod.rs index 969728e0008f..d136971734aa 100644 --- a/core/node/api_server/src/web3/tests/mod.rs +++ b/core/node/api_server/src/web3/tests/mod.rs @@ -51,7 +51,7 @@ use zksync_web3_decl::{ ErrorObjectOwned, }, }, - namespaces::{EnNamespaceClient, L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EnNamespaceClient, EthNamespaceClient, ZksNamespaceClient}, }; use super::*; diff --git a/core/node/api_server/src/web3/tests/ws.rs b/core/node/api_server/src/web3/tests/ws.rs index 57441f9040d6..cccebdd6ddd1 100644 --- a/core/node/api_server/src/web3/tests/ws.rs +++ b/core/node/api_server/src/web3/tests/ws.rs @@ -19,7 +19,7 @@ use zksync_web3_decl::{ }, rpc_params, }, - namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, types::{BlockHeader, Bytes, PubSubFilter}, }; diff --git a/core/node/node_sync/src/client.rs b/core/node/node_sync/src/client.rs index b171742f6aa4..d064803eab59 100644 --- a/core/node/node_sync/src/client.rs +++ b/core/node/node_sync/src/client.rs @@ -13,7 +13,7 @@ use zksync_types::{ use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, - namespaces::{EnNamespaceClient, L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EnNamespaceClient, EthNamespaceClient, ZksNamespaceClient}, }; /// Client abstracting connection to the main node. diff --git a/core/node/node_sync/src/sync_state.rs b/core/node/node_sync/src/sync_state.rs index ae4b32fbb7bd..e061ff7da012 100644 --- a/core/node/node_sync/src/sync_state.rs +++ b/core/node/node_sync/src/sync_state.rs @@ -11,7 +11,7 @@ use zksync_state_keeper::{io::IoCursor, updates::UpdatesManager, StateKeeperOutp use zksync_types::L2BlockNumber; use zksync_web3_decl::{ client::{DynClient, L2}, - namespaces::L2EthNamespaceClient, + namespaces::EthNamespaceClient, }; /// `SyncState` is a structure that holds the state of the syncing process. 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 af021a02e25c..0f80bf799b15 100644 --- a/core/node/node_sync/src/validate_chain_ids_task.rs +++ b/core/node/node_sync/src/validate_chain_ids_task.rs @@ -9,7 +9,7 @@ use zksync_types::{L2ChainId, SLChainId}; use zksync_web3_decl::{ client::{DynClient, L1, L2}, error::ClientRpcContext, - namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, }; /// Task that validates chain IDs using main node and Ethereum clients. diff --git a/core/node/reorg_detector/src/lib.rs b/core/node/reorg_detector/src/lib.rs index 6361425238bd..5945b201c16c 100644 --- a/core/node/reorg_detector/src/lib.rs +++ b/core/node/reorg_detector/src/lib.rs @@ -10,7 +10,7 @@ use zksync_types::{L1BatchNumber, L2BlockNumber, H256}; use zksync_web3_decl::{ client::{DynClient, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, - namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, }; #[cfg(test)] diff --git a/core/tests/loadnext/src/account/api_request_executor.rs b/core/tests/loadnext/src/account/api_request_executor.rs index 6eb72fbd2f70..20c4bc2f5970 100644 --- a/core/tests/loadnext/src/account/api_request_executor.rs +++ b/core/tests/loadnext/src/account/api_request_executor.rs @@ -14,7 +14,7 @@ use crate::{ sdk::{ error::{ClientError, RpcError}, types::FilterBuilder, - L2EthNamespaceClient, + EthNamespaceClient, }, }; diff --git a/core/tests/loadnext/src/account/tx_command_executor.rs b/core/tests/loadnext/src/account/tx_command_executor.rs index a8a62d5d52d6..b085219060b7 100644 --- a/core/tests/loadnext/src/account/tx_command_executor.rs +++ b/core/tests/loadnext/src/account/tx_command_executor.rs @@ -23,7 +23,7 @@ use crate::{ utils::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, - L2EthNamespaceClient, + EthNamespaceClient, }, utils::format_gwei, }; diff --git a/core/tests/loadnext/src/command/api.rs b/core/tests/loadnext/src/command/api.rs index feacf53227fa..2f5628f5759b 100644 --- a/core/tests/loadnext/src/command/api.rs +++ b/core/tests/loadnext/src/command/api.rs @@ -6,7 +6,7 @@ use crate::{ account_pool::SyncWallet, all::AllWeighted, rng::{LoadtestRng, WeightedRandom}, - sdk::L2EthNamespaceClient, + sdk::EthNamespaceClient, }; /// Helper enum for generating random block number. diff --git a/core/tests/loadnext/src/executor.rs b/core/tests/loadnext/src/executor.rs index 2e07aa65b118..48d90f19c1d7 100644 --- a/core/tests/loadnext/src/executor.rs +++ b/core/tests/loadnext/src/executor.rs @@ -24,7 +24,7 @@ use crate::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, web3::TransactionReceipt, - EthereumProvider, L2EthNamespaceClient, ZksNamespaceClient, + EthNamespaceClient, EthereumProvider, ZksNamespaceClient, }, utils::format_eth, }; diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 2c42179fcaa2..3b3516498f89 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -19,7 +19,7 @@ use zksync_types::{ }; use zksync_web3_decl::{ client::{Client, DynClient, L1}, - namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, }; use crate::sdk::{ @@ -608,7 +608,7 @@ pub trait PriorityOpHolder { /// Returns the handle for the priority operation. fn priority_op_handle<'a, P>(&self, provider: &'a P) -> Option> where - P: L2EthNamespaceClient + Sync, + P: EthNamespaceClient + Sync, { self.priority_op() .map(|op| SyncTransactionHandle::new(op.hash(), provider)) diff --git a/core/tests/loadnext/src/sdk/mod.rs b/core/tests/loadnext/src/sdk/mod.rs index d5cdc0fff4c2..26c11eb7a2a6 100644 --- a/core/tests/loadnext/src/sdk/mod.rs +++ b/core/tests/loadnext/src/sdk/mod.rs @@ -1,6 +1,6 @@ pub use zksync_types::{self, ethabi, web3}; pub use zksync_web3_decl::{ - namespaces::{L2EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, types, }; diff --git a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs index a91b26a44c07..161d156a53e9 100644 --- a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs @@ -3,7 +3,7 @@ use zksync_types::{ l2::L2Tx, transaction_request::PaymasterParams, Execute, Nonce, CONTRACT_DEPLOYER_ADDRESS, U256, }; use zksync_utils::bytecode::hash_bytecode; -use zksync_web3_decl::namespaces::L2EthNamespaceClient; +use zksync_web3_decl::namespaces::EthNamespaceClient; use crate::sdk::{ error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, zksync_types::fee::Fee, @@ -24,7 +24,7 @@ pub struct DeployContractBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> DeployContractBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + L2EthNamespaceClient + Sync, + P: ZksNamespaceClient + EthNamespaceClient + Sync, { /// Initializes a change public key transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/execute_contract.rs b/core/tests/loadnext/src/sdk/operations/execute_contract.rs index 28e84ec98b7c..d5fe57c7b79f 100644 --- a/core/tests/loadnext/src/sdk/operations/execute_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/execute_contract.rs @@ -4,7 +4,7 @@ use zksync_types::{ }; use crate::sdk::{ - error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, L2EthNamespaceClient, + error::ClientError, operations::SyncTransactionHandle, wallet::Wallet, EthNamespaceClient, ZksNamespaceClient, }; @@ -22,7 +22,7 @@ pub struct ExecuteContractBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> ExecuteContractBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + L2EthNamespaceClient + Sync, + P: ZksNamespaceClient + EthNamespaceClient + Sync, { /// Initializes a change public key transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/mod.rs b/core/tests/loadnext/src/sdk/operations/mod.rs index b6bdfa200209..757758ef501e 100644 --- a/core/tests/loadnext/src/sdk/operations/mod.rs +++ b/core/tests/loadnext/src/sdk/operations/mod.rs @@ -13,7 +13,7 @@ pub use self::{ transfer::{create_transfer_calldata, TransferBuilder}, withdraw::WithdrawBuilder, }; -use crate::sdk::{error::ClientError, L2EthNamespaceClient}; +use crate::sdk::{error::ClientError, EthNamespaceClient}; mod deploy_contract; mod execute_contract; @@ -37,7 +37,7 @@ pub struct SyncTransactionHandle<'a, P> { impl<'a, P> SyncTransactionHandle<'a, P> where - P: L2EthNamespaceClient + Sync, + P: EthNamespaceClient + Sync, { pub fn new(hash: H256, provider: &'a P) -> Self { Self { diff --git a/core/tests/loadnext/src/sdk/operations/transfer.rs b/core/tests/loadnext/src/sdk/operations/transfer.rs index 035b92edb025..94ee3aeb6082 100644 --- a/core/tests/loadnext/src/sdk/operations/transfer.rs +++ b/core/tests/loadnext/src/sdk/operations/transfer.rs @@ -8,7 +8,7 @@ use crate::sdk::{ wallet::Wallet, web3::contract::Tokenize, zksync_types::{transaction_request::PaymasterParams, Execute, L2TxCommonData}, - L2EthNamespaceClient, ZksNamespaceClient, + EthNamespaceClient, ZksNamespaceClient, }; pub struct TransferBuilder<'a, S: EthereumSigner, P> { @@ -24,7 +24,7 @@ pub struct TransferBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> TransferBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + L2EthNamespaceClient + Sync, + P: ZksNamespaceClient + EthNamespaceClient + Sync, { /// Initializes a transfer transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/operations/withdraw.rs b/core/tests/loadnext/src/sdk/operations/withdraw.rs index 4f03a797dcb4..89a8f40713a8 100644 --- a/core/tests/loadnext/src/sdk/operations/withdraw.rs +++ b/core/tests/loadnext/src/sdk/operations/withdraw.rs @@ -8,7 +8,7 @@ use crate::sdk::{ error::ClientError, operations::{ExecuteContractBuilder, SyncTransactionHandle}, wallet::Wallet, - L2EthNamespaceClient, ZksNamespaceClient, + EthNamespaceClient, ZksNamespaceClient, }; pub struct WithdrawBuilder<'a, S: EthereumSigner, P> { @@ -25,7 +25,7 @@ pub struct WithdrawBuilder<'a, S: EthereumSigner, P> { impl<'a, S, P> WithdrawBuilder<'a, S, P> where S: EthereumSigner, - P: ZksNamespaceClient + L2EthNamespaceClient + Sync, + P: ZksNamespaceClient + EthNamespaceClient + Sync, { /// Initializes a withdraw transaction building process. pub fn new(wallet: &'a Wallet) -> Self { diff --git a/core/tests/loadnext/src/sdk/wallet.rs b/core/tests/loadnext/src/sdk/wallet.rs index 41a607e4ed36..9d3bd73a9bf2 100644 --- a/core/tests/loadnext/src/sdk/wallet.rs +++ b/core/tests/loadnext/src/sdk/wallet.rs @@ -9,9 +9,7 @@ use zksync_types::{ }; use zksync_web3_decl::{ client::{Client, L2}, - namespaces::{ - L2EthNamespaceClient, NetNamespaceClient, Web3NamespaceClient, ZksNamespaceClient, - }, + namespaces::{EthNamespaceClient, NetNamespaceClient, Web3NamespaceClient, ZksNamespaceClient}, }; use crate::sdk::{ @@ -59,7 +57,7 @@ where impl Wallet where S: EthereumSigner, - P: L2EthNamespaceClient + ZksNamespaceClient + NetNamespaceClient + Web3NamespaceClient + Sync, + P: EthNamespaceClient + ZksNamespaceClient + NetNamespaceClient + Web3NamespaceClient + Sync, { pub fn new(provider: P, signer: Signer) -> Self { Self { provider, signer } From 91b38a3af2a4282ab116e586a78cbe6e00e21362 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 10:54:12 +0200 Subject: [PATCH 23/43] impl review --- core/bin/block_reverter/src/main.rs | 4 +- core/lib/eth_client/src/clients/http/query.rs | 998 +++++++++++++++++- .../eth_client/src/clients/http/signing.rs | 17 +- core/lib/eth_client/src/clients/mock.rs | 109 +- core/lib/eth_client/src/lib.rs | 24 +- core/lib/eth_client/src/types.rs | 2 +- core/lib/web3_decl/src/client/mock.rs | 2 +- core/lib/web3_decl/src/client/mod.rs | 2 +- core/lib/web3_decl/src/client/network.rs | 5 + core/node/block_reverter/src/lib.rs | 10 +- .../src/validation_task.rs | 8 +- core/node/consistency_checker/src/lib.rs | 2 +- .../node/consistency_checker/src/tests/mod.rs | 2 +- .../eth_sender/src/abstract_l1_interface.rs | 23 +- core/node/eth_sender/src/eth_tx_aggregator.rs | 8 +- core/node/eth_sender/src/eth_tx_manager.rs | 6 +- core/node/eth_watch/src/client.rs | 2 +- .../resources/eth_interface.rs | 6 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 6 +- 19 files changed, 1115 insertions(+), 121 deletions(-) diff --git a/core/bin/block_reverter/src/main.rs b/core/bin/block_reverter/src/main.rs index 1be006cfb3d1..93833f8e699e 100644 --- a/core/bin/block_reverter/src/main.rs +++ b/core/bin/block_reverter/src/main.rs @@ -5,7 +5,7 @@ use clap::{Parser, Subcommand}; use tokio::io::{self, AsyncReadExt}; use zksync_block_reverter::{ eth_client::{ - clients::{Client, PKSigningClient}, + clients::{Client, DynClient, PKSigningClient, L1}, EthInterface, }, BlockReverter, BlockReverterEthConfig, NodeRole, @@ -229,7 +229,7 @@ async fn main() -> anyhow::Result<()> { json, operator_address, } => { - let eth_client = Client::http(l1_secrets.l1_rpc_url.clone()) + let eth_client = Client::::http(l1_secrets.l1_rpc_url.clone()) .context("Ethereum client")? .build(); diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 12966a5664d6..8f9323e5ca51 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -4,6 +4,7 @@ use async_trait::async_trait; use jsonrpsee::core::ClientError; use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::{ + client::{Client, DynClient, EthereumLikeNetwork, ForEthereumLikeNetwork, MockClient, L1}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, namespaces::EthNamespaceClient, }; @@ -16,11 +17,998 @@ use crate::{ const FEE_HISTORY_MAX_REQUEST_CHUNK: usize = 1024; -#[async_trait] -impl EthInterface for T -where - T: L1EthNamespaceClient + fmt::Debug + Send + Sync, -{ +#[async_trait::async_trait] +impl EthInterface for Box> { + 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?; + latency.observe(); + let chain_id = u64::try_from(raw_chain_id).map_err(|err| { + let err = ClientError::Custom(format!("invalid chainId: {err}")); + EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) + })?; + Ok(SLChainId(chain_id)) + } + + async fn nonce_at_for_account( + &self, + account: Address, + block: web3::BlockNumber, + ) -> EnrichedClientResult { + COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); + let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); + let nonce = self + .get_transaction_count(account, block) + .rpc_context("get_transaction_count") + .with_arg("account", &account) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(nonce) + } + + async fn block_number(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BlockNumber].start(); + let block_number = self + .get_block_number() + .rpc_context("get_block_number") + .await?; + latency.observe(); + Ok(block_number) + } + + async fn get_gas_price(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetGasPrice].start(); + let network_gas_price = self.gas_price().rpc_context("gas_price").await?; + latency.observe(); + Ok(network_gas_price) + } + + async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::SendRawTx].start(); + let tx = self + .send_raw_transaction(web3::Bytes(tx.0)) + .rpc_context("send_raw_transaction") + .await?; + latency.observe(); + Ok(tx) + } + + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); + + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; + + let fee_history = self + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + // Per specification, the values should always be provided, and must be 0 for blocks + // prior to EIP-4844. + // https://ethereum.github.io/execution-apis/api-documentation/ + if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { + tracing::error!( + "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", + fee_history.base_fee_per_gas.len(), + fee_history.base_fee_per_blob_gas.len() + ); + } + + for (base, blob) in fee_history + .base_fee_per_gas + .into_iter() + .zip(fee_history.base_fee_per_blob_gas) + { + let fees = BaseFees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: blob, + }; + history.push(fees) + } + } + + latency.observe(); + Ok(history) + } + + async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); + let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); + + let block = self + .get_block_by_number(web3::BlockNumber::Pending, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Pending) + .with_arg("with_transactions", &false) + .await?; + let block = if let Some(block) = block { + block + } else { + // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup + // there may be no pending block + self.get_block_by_number(web3::BlockNumber::Latest, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Latest) + .with_arg("with_transactions", &false) + .await? + .expect("Latest block always exists") + }; + + latency.observe(); + + // base_fee_per_gas always exists after London fork + Ok(block.base_fee_per_gas.unwrap()) + } + + async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetTxStatus].start(); + + let receipt = self.tx_receipt(hash).await?; + let res = receipt.and_then(|receipt| match receipt.status { + Some(status) if receipt.block_number.is_some() => { + let success = status.as_u64() == 1; + + Some(ExecutedTxStatus { + tx_hash: receipt.transaction_hash, + success, + receipt, + }) + } + _ => None, + }); + + latency.observe(); + Ok(res) + } + + async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { + let latency = LATENCIES.direct[&Method::FailureReason].start(); + let transaction = self + .get_transaction_by_hash(tx_hash) + .rpc_context("failure_reason#get_transaction_by_hash") + .with_arg("hash", &tx_hash) + .await?; + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("failure_reason#get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + + match (transaction, receipt) { + (Some(transaction), Some(receipt)) => { + let gas_limit = transaction.gas; + let gas_used = receipt.gas_used; + + let call_request = web3::CallRequest { + from: transaction.from, + to: transaction.to, + gas: Some(transaction.gas), + gas_price: transaction.gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + value: Some(transaction.value), + data: Some(transaction.input), + transaction_type: None, + access_list: None, + }; + + let block_number = receipt + .block_number + .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); + let result = self + .call(call_request.clone(), block_number) + .rpc_context("failure_reason#call") + .with_arg("call_request", &call_request) + .with_arg("block_number", &block_number) + .await; + + let failure_info = match result { + Err(err) => { + if let ClientError::Call(call_err) = err.as_ref() { + let revert_code = call_err.code().into(); + let message_len = + "execution reverted: ".len().min(call_err.message().len()); + let revert_reason = call_err.message()[message_len..].to_string(); + + Ok(Some(FailureInfo { + revert_code, + revert_reason, + gas_used, + gas_limit, + })) + } else { + Err(err) + } + } + Ok(_) => Ok(None), + }; + + latency.observe(); + failure_info + } + _ => Ok(None), + } + } + + async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTx, self.component())].inc(); + let tx = self + .get_transaction_by_hash(hash) + .rpc_context("get_transaction_by_hash") + .with_arg("hash", &hash) + .await?; + Ok(tx) + } + + async fn call_contract_function( + &self, + request: web3::CallRequest, + block: Option, + ) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::CallContractFunction].start(); + let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); + let output_bytes = self + .call(request.clone(), block) + .rpc_context("call") + .with_arg("request", &request) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(output_bytes) + } + + async fn tx_receipt( + &self, + tx_hash: H256, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); + let latency = LATENCIES.direct[&Method::TxReceipt].start(); + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + latency.observe(); + Ok(receipt) + } + + async fn eth_balance(&self, address: Address) -> EnrichedClientResult { + COUNTERS.call[&(Method::EthBalance, self.component())].inc(); + let latency = LATENCIES.direct[&Method::EthBalance].start(); + let balance = self + .get_balance(address, web3::BlockNumber::Latest) + .rpc_context("get_balance") + .with_arg("address", &address) + .await?; + latency.observe(); + Ok(balance) + } + + async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { + COUNTERS.call[&(Method::Logs, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Logs].start(); + let logs = self + .get_logs(filter.clone()) + .rpc_context("get_logs") + .with_arg("filter", filter) + .await?; + latency.observe(); + Ok(logs) + } + + async fn block( + &self, + block_id: web3::BlockId, + ) -> EnrichedClientResult>> { + COUNTERS.call[&(Method::Block, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Block].start(); + let block = match block_id { + web3::BlockId::Hash(hash) => { + self.get_block_by_hash(hash, false) + .rpc_context("get_block_by_hash") + .with_arg("hash", &hash) + .with_arg("with_transactions", &false) + .await? + } + web3::BlockId::Number(num) => { + self.get_block_by_number(num, false) + .rpc_context("get_block_by_number") + .with_arg("number", &num) + .with_arg("with_transactions", &false) + .await? + } + }; + latency.observe(); + Ok(block) + } +} + +#[async_trait::async_trait] +impl EthInterface for DynClient { + 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?; + latency.observe(); + let chain_id = u64::try_from(raw_chain_id).map_err(|err| { + let err = ClientError::Custom(format!("invalid chainId: {err}")); + EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) + })?; + Ok(SLChainId(chain_id)) + } + + async fn nonce_at_for_account( + &self, + account: Address, + block: web3::BlockNumber, + ) -> EnrichedClientResult { + COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); + let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); + let nonce = self + .get_transaction_count(account, block) + .rpc_context("get_transaction_count") + .with_arg("account", &account) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(nonce) + } + + async fn block_number(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BlockNumber].start(); + let block_number = self + .get_block_number() + .rpc_context("get_block_number") + .await?; + latency.observe(); + Ok(block_number) + } + + async fn get_gas_price(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetGasPrice].start(); + let network_gas_price = self.gas_price().rpc_context("gas_price").await?; + latency.observe(); + Ok(network_gas_price) + } + + async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::SendRawTx].start(); + let tx = self + .send_raw_transaction(web3::Bytes(tx.0)) + .rpc_context("send_raw_transaction") + .await?; + latency.observe(); + Ok(tx) + } + + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); + + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; + + let fee_history = self + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + // Per specification, the values should always be provided, and must be 0 for blocks + // prior to EIP-4844. + // https://ethereum.github.io/execution-apis/api-documentation/ + if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { + tracing::error!( + "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", + fee_history.base_fee_per_gas.len(), + fee_history.base_fee_per_blob_gas.len() + ); + } + + for (base, blob) in fee_history + .base_fee_per_gas + .into_iter() + .zip(fee_history.base_fee_per_blob_gas) + { + let fees = BaseFees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: blob, + }; + history.push(fees) + } + } + + latency.observe(); + Ok(history) + } + + async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); + let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); + + let block = self + .get_block_by_number(web3::BlockNumber::Pending, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Pending) + .with_arg("with_transactions", &false) + .await?; + let block = if let Some(block) = block { + block + } else { + // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup + // there may be no pending block + self.get_block_by_number(web3::BlockNumber::Latest, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Latest) + .with_arg("with_transactions", &false) + .await? + .expect("Latest block always exists") + }; + + latency.observe(); + + // base_fee_per_gas always exists after London fork + Ok(block.base_fee_per_gas.unwrap()) + } + + async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetTxStatus].start(); + + let receipt = self.tx_receipt(hash).await?; + let res = receipt.and_then(|receipt| match receipt.status { + Some(status) if receipt.block_number.is_some() => { + let success = status.as_u64() == 1; + + Some(ExecutedTxStatus { + tx_hash: receipt.transaction_hash, + success, + receipt, + }) + } + _ => None, + }); + + latency.observe(); + Ok(res) + } + + async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { + let latency = LATENCIES.direct[&Method::FailureReason].start(); + let transaction = self + .get_transaction_by_hash(tx_hash) + .rpc_context("failure_reason#get_transaction_by_hash") + .with_arg("hash", &tx_hash) + .await?; + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("failure_reason#get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + + match (transaction, receipt) { + (Some(transaction), Some(receipt)) => { + let gas_limit = transaction.gas; + let gas_used = receipt.gas_used; + + let call_request = web3::CallRequest { + from: transaction.from, + to: transaction.to, + gas: Some(transaction.gas), + gas_price: transaction.gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + value: Some(transaction.value), + data: Some(transaction.input), + transaction_type: None, + access_list: None, + }; + + let block_number = receipt + .block_number + .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); + let result = self + .call(call_request.clone(), block_number) + .rpc_context("failure_reason#call") + .with_arg("call_request", &call_request) + .with_arg("block_number", &block_number) + .await; + + let failure_info = match result { + Err(err) => { + if let ClientError::Call(call_err) = err.as_ref() { + let revert_code = call_err.code().into(); + let message_len = + "execution reverted: ".len().min(call_err.message().len()); + let revert_reason = call_err.message()[message_len..].to_string(); + + Ok(Some(FailureInfo { + revert_code, + revert_reason, + gas_used, + gas_limit, + })) + } else { + Err(err) + } + } + Ok(_) => Ok(None), + }; + + latency.observe(); + failure_info + } + _ => Ok(None), + } + } + + async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTx, self.component())].inc(); + let tx = self + .get_transaction_by_hash(hash) + .rpc_context("get_transaction_by_hash") + .with_arg("hash", &hash) + .await?; + Ok(tx) + } + + async fn call_contract_function( + &self, + request: web3::CallRequest, + block: Option, + ) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::CallContractFunction].start(); + let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); + let output_bytes = self + .call(request.clone(), block) + .rpc_context("call") + .with_arg("request", &request) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(output_bytes) + } + + async fn tx_receipt( + &self, + tx_hash: H256, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); + let latency = LATENCIES.direct[&Method::TxReceipt].start(); + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + latency.observe(); + Ok(receipt) + } + + async fn eth_balance(&self, address: Address) -> EnrichedClientResult { + COUNTERS.call[&(Method::EthBalance, self.component())].inc(); + let latency = LATENCIES.direct[&Method::EthBalance].start(); + let balance = self + .get_balance(address, web3::BlockNumber::Latest) + .rpc_context("get_balance") + .with_arg("address", &address) + .await?; + latency.observe(); + Ok(balance) + } + + async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { + COUNTERS.call[&(Method::Logs, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Logs].start(); + let logs = self + .get_logs(filter.clone()) + .rpc_context("get_logs") + .with_arg("filter", filter) + .await?; + latency.observe(); + Ok(logs) + } + + async fn block( + &self, + block_id: web3::BlockId, + ) -> EnrichedClientResult>> { + COUNTERS.call[&(Method::Block, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Block].start(); + let block = match block_id { + web3::BlockId::Hash(hash) => { + self.get_block_by_hash(hash, false) + .rpc_context("get_block_by_hash") + .with_arg("hash", &hash) + .with_arg("with_transactions", &false) + .await? + } + web3::BlockId::Number(num) => { + self.get_block_by_number(num, false) + .rpc_context("get_block_by_number") + .with_arg("number", &num) + .with_arg("with_transactions", &false) + .await? + } + }; + latency.observe(); + Ok(block) + } +} + +#[async_trait::async_trait] +impl EthInterface for Client { + 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?; + latency.observe(); + let chain_id = u64::try_from(raw_chain_id).map_err(|err| { + let err = ClientError::Custom(format!("invalid chainId: {err}")); + EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) + })?; + Ok(SLChainId(chain_id)) + } + + async fn nonce_at_for_account( + &self, + account: Address, + block: web3::BlockNumber, + ) -> EnrichedClientResult { + COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); + let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); + let nonce = self + .get_transaction_count(account, block) + .rpc_context("get_transaction_count") + .with_arg("account", &account) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(nonce) + } + + async fn block_number(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BlockNumber].start(); + let block_number = self + .get_block_number() + .rpc_context("get_block_number") + .await?; + latency.observe(); + Ok(block_number) + } + + async fn get_gas_price(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetGasPrice].start(); + let network_gas_price = self.gas_price().rpc_context("gas_price").await?; + latency.observe(); + Ok(network_gas_price) + } + + async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::SendRawTx].start(); + let tx = self + .send_raw_transaction(web3::Bytes(tx.0)) + .rpc_context("send_raw_transaction") + .await?; + latency.observe(); + Ok(tx) + } + + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); + + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; + + let fee_history = self + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + // Per specification, the values should always be provided, and must be 0 for blocks + // prior to EIP-4844. + // https://ethereum.github.io/execution-apis/api-documentation/ + if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { + tracing::error!( + "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", + fee_history.base_fee_per_gas.len(), + fee_history.base_fee_per_blob_gas.len() + ); + } + + for (base, blob) in fee_history + .base_fee_per_gas + .into_iter() + .zip(fee_history.base_fee_per_blob_gas) + { + let fees = BaseFees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: blob, + }; + history.push(fees) + } + } + + latency.observe(); + Ok(history) + } + + async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { + COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); + let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); + + let block = self + .get_block_by_number(web3::BlockNumber::Pending, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Pending) + .with_arg("with_transactions", &false) + .await?; + let block = if let Some(block) = block { + block + } else { + // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup + // there may be no pending block + self.get_block_by_number(web3::BlockNumber::Latest, false) + .rpc_context("get_block_by_number") + .with_arg("number", &web3::BlockNumber::Latest) + .with_arg("with_transactions", &false) + .await? + .expect("Latest block always exists") + }; + + latency.observe(); + + // base_fee_per_gas always exists after London fork + Ok(block.base_fee_per_gas.unwrap()) + } + + async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); + let latency = LATENCIES.direct[&Method::GetTxStatus].start(); + + let receipt = self.tx_receipt(hash).await?; + let res = receipt.and_then(|receipt| match receipt.status { + Some(status) if receipt.block_number.is_some() => { + let success = status.as_u64() == 1; + + Some(ExecutedTxStatus { + tx_hash: receipt.transaction_hash, + success, + receipt, + }) + } + _ => None, + }); + + latency.observe(); + Ok(res) + } + + async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { + let latency = LATENCIES.direct[&Method::FailureReason].start(); + let transaction = self + .get_transaction_by_hash(tx_hash) + .rpc_context("failure_reason#get_transaction_by_hash") + .with_arg("hash", &tx_hash) + .await?; + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("failure_reason#get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + + match (transaction, receipt) { + (Some(transaction), Some(receipt)) => { + let gas_limit = transaction.gas; + let gas_used = receipt.gas_used; + + let call_request = web3::CallRequest { + from: transaction.from, + to: transaction.to, + gas: Some(transaction.gas), + gas_price: transaction.gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + value: Some(transaction.value), + data: Some(transaction.input), + transaction_type: None, + access_list: None, + }; + + let block_number = receipt + .block_number + .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); + let result = self + .call(call_request.clone(), block_number) + .rpc_context("failure_reason#call") + .with_arg("call_request", &call_request) + .with_arg("block_number", &block_number) + .await; + + let failure_info = match result { + Err(err) => { + if let ClientError::Call(call_err) = err.as_ref() { + let revert_code = call_err.code().into(); + let message_len = + "execution reverted: ".len().min(call_err.message().len()); + let revert_reason = call_err.message()[message_len..].to_string(); + + Ok(Some(FailureInfo { + revert_code, + revert_reason, + gas_used, + gas_limit, + })) + } else { + Err(err) + } + } + Ok(_) => Ok(None), + }; + + latency.observe(); + failure_info + } + _ => Ok(None), + } + } + + async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { + COUNTERS.call[&(Method::GetTx, self.component())].inc(); + let tx = self + .get_transaction_by_hash(hash) + .rpc_context("get_transaction_by_hash") + .with_arg("hash", &hash) + .await?; + Ok(tx) + } + + async fn call_contract_function( + &self, + request: web3::CallRequest, + block: Option, + ) -> EnrichedClientResult { + let latency = LATENCIES.direct[&Method::CallContractFunction].start(); + let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); + let output_bytes = self + .call(request.clone(), block) + .rpc_context("call") + .with_arg("request", &request) + .with_arg("block", &block) + .await?; + latency.observe(); + Ok(output_bytes) + } + + async fn tx_receipt( + &self, + tx_hash: H256, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); + let latency = LATENCIES.direct[&Method::TxReceipt].start(); + let receipt = self + .get_transaction_receipt(tx_hash) + .rpc_context("get_transaction_receipt") + .with_arg("hash", &tx_hash) + .await?; + latency.observe(); + Ok(receipt) + } + + async fn eth_balance(&self, address: Address) -> EnrichedClientResult { + COUNTERS.call[&(Method::EthBalance, self.component())].inc(); + let latency = LATENCIES.direct[&Method::EthBalance].start(); + let balance = self + .get_balance(address, web3::BlockNumber::Latest) + .rpc_context("get_balance") + .with_arg("address", &address) + .await?; + latency.observe(); + Ok(balance) + } + + async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { + COUNTERS.call[&(Method::Logs, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Logs].start(); + let logs = self + .get_logs(filter.clone()) + .rpc_context("get_logs") + .with_arg("filter", filter) + .await?; + latency.observe(); + Ok(logs) + } + + async fn block( + &self, + block_id: web3::BlockId, + ) -> EnrichedClientResult>> { + COUNTERS.call[&(Method::Block, self.component())].inc(); + let latency = LATENCIES.direct[&Method::Block].start(); + let block = match block_id { + web3::BlockId::Hash(hash) => { + self.get_block_by_hash(hash, false) + .rpc_context("get_block_by_hash") + .with_arg("hash", &hash) + .with_arg("with_transactions", &false) + .await? + } + web3::BlockId::Number(num) => { + self.get_block_by_number(num, false) + .rpc_context("get_block_by_number") + .with_arg("number", &num) + .with_arg("with_transactions", &false) + .await? + } + }; + latency.observe(); + Ok(block) + } +} + +#[async_trait::async_trait] +impl EthInterface for MockClient { async fn fetch_chain_id(&self) -> EnrichedClientResult { COUNTERS.call[&(Method::ChainId, self.component())].inc(); let latency = LATENCIES.direct[&Method::ChainId].start(); diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index abb3d53ecb05..eae3f645894d 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -74,22 +74,19 @@ impl fmt::Debug for SigningClient { } } -impl AsRef> for SigningClient { - fn as_ref(&self) -> &DynClient { - self.query_client.as_ref() +impl AsRef for SigningClient { + fn as_ref(&self) -> &(dyn EthInterface + 'static) { + &self.query_client as &dyn EthInterface } } #[async_trait] -impl BoundEthInterface for SigningClient { - fn clone_boxed(&self) -> Box> { +impl BoundEthInterface for SigningClient { + fn clone_boxed(&self) -> Box { Box::new(self.clone()) } - fn for_component( - self: Box, - component_name: &'static str, - ) -> Box> { + fn for_component(self: Box, component_name: &'static str) -> Box { Box::new(Self { query_client: self.query_client.for_component(component_name), ..*self @@ -151,7 +148,7 @@ impl BoundEthInterface for SigningClient { let nonce = match options.nonce { Some(nonce) => nonce, - None => >::pending_nonce(self).await?, + None => ::pending_nonce(self).await?, }; let gas = options.gas.unwrap_or_else(|| { diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index f5e3120ee769..b09ac4e61248 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -12,11 +12,13 @@ use zksync_types::{ web3::{self, contract::Tokenize, BlockId}, Address, L1ChainId, L2ChainId, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, MockClient, MockClientBuilder, Network, L1, L2}; +use zksync_web3_decl::client::{ + DynClient, EthereumLikeNetwork, MockClient, MockClientBuilder, Network, L1, L2, +}; use crate::{ types::{ContractCallError, SignedCallResult, SigningError}, - BaseFees, BoundEthInterface, L2Fees, Options, RawTransactionBytes, + BaseFees, BoundEthInterface, EthInterface, L2Fees, Options, RawTransactionBytes, }; #[derive(Debug, Clone)] @@ -617,22 +619,21 @@ impl MockSettlementLayer { } } -impl AsRef> for MockSettlementLayer { - fn as_ref(&self) -> &DynClient { - &self.client +impl AsRef for MockSettlementLayer { + fn as_ref(&self) -> &(dyn EthInterface + 'static) { + &self.client as &dyn EthInterface } } #[async_trait::async_trait] -impl BoundEthInterface for MockSettlementLayer { - fn clone_boxed(&self) -> Box> { +impl BoundEthInterface + for MockSettlementLayer +{ + fn clone_boxed(&self) -> Box { Box::new(self.clone()) } - fn for_component( - self: Box, - _component_name: &'static str, - ) -> Box> { + fn for_component(self: Box, _component_name: &'static str) -> Box { self } @@ -768,48 +769,48 @@ mod tests { ); } - #[tokio::test] - async fn managing_fee_history_l2() { - let initial_fee_history = vec![ - base_fees(1, 4, 11), - base_fees(2, 3, 12), - base_fees(3, 2, 13), - base_fees(4, 1, 14), - base_fees(5, 0, 15), - ]; - let client = MockSettlementLayer::::builder() - .with_fee_history(initial_fee_history.clone()) - .build(); - client.advance_block_number(4); - - let fee_history = client.as_ref().l2_fee_history(4, 4).await.unwrap(); - assert_eq!( - fee_history, - initial_fee_history[1..=4] - .iter() - .cloned() - .map(L2Fees::from) - .collect::>() - ); - let fee_history = client.as_ref().l2_fee_history(2, 2).await.unwrap(); - assert_eq!( - fee_history, - initial_fee_history[1..=2] - .iter() - .cloned() - .map(L2Fees::from) - .collect::>() - ); - let fee_history = client.as_ref().l2_fee_history(3, 2).await.unwrap(); - assert_eq!( - fee_history, - initial_fee_history[2..=3] - .iter() - .cloned() - .map(L2Fees::from) - .collect::>() - ); - } + // #[tokio::test] + // async fn managing_fee_history_l2() { + // let initial_fee_history = vec![ + // base_fees(1, 4, 11), + // base_fees(2, 3, 12), + // base_fees(3, 2, 13), + // base_fees(4, 1, 14), + // base_fees(5, 0, 15), + // ]; + // let client = MockSettlementLayer::::builder() + // .with_fee_history(initial_fee_history.clone()) + // .build(); + // client.advance_block_number(4); + + // let fee_history = client.as_ref().l2_fee_history(4, 4).await.unwrap(); + // assert_eq!( + // fee_history, + // initial_fee_history[1..=4] + // .iter() + // .cloned() + // .map(L2Fees::from) + // .collect::>() + // ); + // let fee_history = client.as_ref().l2_fee_history(2, 2).await.unwrap(); + // assert_eq!( + // fee_history, + // initial_fee_history[1..=2] + // .iter() + // .cloned() + // .map(L2Fees::from) + // .collect::>() + // ); + // let fee_history = client.as_ref().l2_fee_history(3, 2).await.unwrap(); + // assert_eq!( + // fee_history, + // initial_fee_history[2..=3] + // .iter() + // .cloned() + // .map(L2Fees::from) + // .collect::>() + // ); + // } #[tokio::test] async fn managing_transactions() { @@ -866,7 +867,7 @@ mod tests { #[tokio::test] async fn calling_contracts() { - let client = MockSettlementLayer::builder() + let client = MockSettlementLayer::::builder() .with_call_handler(|req, _block_id| { let packed_semver = ProtocolVersionId::latest().into_packed_semver_with_patch(0); let call_signature = &req.data.as_ref().unwrap().0[..4]; diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 80b2764d00f7..63ed9a0493fb 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::fmt::{self, Debug}; use async_trait::async_trait; use zksync_types::{ @@ -10,7 +10,7 @@ use zksync_types::{ }, Address, SLChainId, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, Network}; +use zksync_web3_decl::client::{DynClient, Network, L1}; pub use zksync_web3_decl::{ error::{EnrichedClientError, EnrichedClientResult}, jsonrpsee::core::ClientError, @@ -70,6 +70,7 @@ impl Options { pub struct BaseFees { pub base_fee_per_gas: u64, pub base_fee_per_blob_gas: U256, + // pub pubdata_price: U256, } /// Common Web3 interface, as seen by the core applications. @@ -83,7 +84,7 @@ pub struct BaseFees { /// If you want to add a method to this trait, make sure that it doesn't depend on any particular /// contract or account address. For that, you can use the `BoundEthInterface` trait. #[async_trait] -pub trait EthInterface: Sync + Send { +pub trait EthInterface: Sync + Send + Debug { /// 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; @@ -185,18 +186,13 @@ pub trait ZkSyncInterface: Sync + Send { /// 2. Consider adding the "unbound" version to the `EthInterface` trait and create a default method /// implementation that invokes `contract` / `contract_addr` / `sender_account` methods. #[async_trait] -pub trait BoundEthInterface: - AsRef> + 'static + Sync + Send + fmt::Debug -{ +pub trait BoundEthInterface: 'static + Sync + Send + fmt::Debug + AsRef { /// Clones this client. - fn clone_boxed(&self) -> Box>; + fn clone_boxed(&self) -> Box; /// Tags this client as working for a specific component. The component name can be used in logging, /// metrics etc. The component name should be copied to the clones of this client, but should not be passed upstream. - fn for_component( - self: Box, - component_name: &'static str, - ) -> Box>; + fn for_component(self: Box, component_name: &'static str) -> Box; /// ABI of the contract that is used by the implementer. fn contract(&self) -> ðabi::Contract; @@ -231,13 +227,15 @@ pub trait BoundEthInterface: ) -> Result; } -impl Clone for Box> { +pub type L1EthBoundInterface = dyn BoundEthInterface; + +impl Clone for Box { fn clone(&self) -> Self { self.clone_boxed() } } -impl dyn BoundEthInterface { +impl dyn BoundEthInterface { /// Returns the nonce of the `Self::sender_account()` at the specified block. pub async fn nonce_at(&self, block: BlockNumber) -> EnrichedClientResult { self.as_ref() diff --git a/core/lib/eth_client/src/types.rs b/core/lib/eth_client/src/types.rs index 8ac5ff427fb8..b5477cae159c 100644 --- a/core/lib/eth_client/src/types.rs +++ b/core/lib/eth_client/src/types.rs @@ -81,7 +81,7 @@ impl ContractCall<'_> { pub async fn call( &self, - client: &DynClient, + client: &dyn EthInterface, ) -> Result { let func = self .contract_abi diff --git a/core/lib/web3_decl/src/client/mock.rs b/core/lib/web3_decl/src/client/mock.rs index 6d44ebee5756..2f49e0d88af2 100644 --- a/core/lib/web3_decl/src/client/mock.rs +++ b/core/lib/web3_decl/src/client/mock.rs @@ -14,7 +14,7 @@ use jsonrpsee::{ }; use serde::{de::DeserializeOwned, Serialize}; -use super::{boxed::RawParams, ForEthereumLikeNetwork, Network, TaggedClient}; +use super::{boxed::RawParams, EthereumLikeNetwork, ForEthereumLikeNetwork, Network, TaggedClient}; /// Object-safe counterpart to [`Handler`]. We need it because async closures aren't available on stable Rust. #[async_trait] diff --git a/core/lib/web3_decl/src/client/mod.rs b/core/lib/web3_decl/src/client/mod.rs index 5527e6fc86bf..b3b8deeb0aa4 100644 --- a/core/lib/web3_decl/src/client/mod.rs +++ b/core/lib/web3_decl/src/client/mod.rs @@ -38,7 +38,7 @@ use self::metrics::{L2ClientMetrics, METRICS}; pub use self::{ boxed::{DynClient, ObjectSafeClient}, mock::{MockClient, MockClientBuilder}, - network::{ForEthereumLikeNetwork, Network, TaggedClient, L1, L2}, + network::{EthereumLikeNetwork, ForEthereumLikeNetwork, Network, TaggedClient, L1, L2}, shared::Shared, }; diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 63e5f9e88d16..2cabbaafbd0b 100644 --- a/core/lib/web3_decl/src/client/network.rs +++ b/core/lib/web3_decl/src/client/network.rs @@ -39,6 +39,11 @@ impl From for L1 { } } +pub trait EthereumLikeNetwork: Network {} + +impl EthereumLikeNetwork for L1 {} +impl EthereumLikeNetwork for L2 {} + /// L2 network. #[derive(Debug, Clone, Copy, Default)] pub struct L2(Option); diff --git a/core/node/block_reverter/src/lib.rs b/core/node/block_reverter/src/lib.rs index 86209f8a9ee6..d622e541e26d 100644 --- a/core/node/block_reverter/src/lib.rs +++ b/core/node/block_reverter/src/lib.rs @@ -10,7 +10,7 @@ use zksync_dal::{ConnectionPool, Core, CoreDal}; pub use zksync_eth_client as eth_client; use zksync_eth_client::{ clients::{DynClient, L1}, - BoundEthInterface, CallFunctionArgs, EthInterface, Options, + BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface, Options, }; use zksync_merkle_tree::domain::ZkSyncTree; use zksync_object_store::{ObjectStore, ObjectStoreError}; @@ -469,7 +469,7 @@ impl BlockReverter { /// Sends a revert transaction to L1. pub async fn send_ethereum_revert_transaction( &self, - eth_client: &dyn BoundEthInterface, + eth_client: &L1EthBoundInterface, eth_config: &BlockReverterEthConfig, last_l1_batch_to_keep: L1BatchNumber, nonce: u64, @@ -531,7 +531,7 @@ impl BlockReverter { #[tracing::instrument(err)] async fn get_l1_batch_number_from_contract( - eth_client: &DynClient, + eth_client: &dyn EthInterface, contract_address: Address, op: AggregatedActionType, ) -> anyhow::Result { @@ -542,7 +542,7 @@ impl BlockReverter { }; let block_number: U256 = CallFunctionArgs::new(function_name, ()) .for_contract(contract_address, &hyperchain_contract()) - .call(eth_client) + .call(eth_client as &dyn EthInterface) .await .with_context(|| { format!("failed calling `{function_name}` for contract {contract_address:?}") @@ -553,7 +553,7 @@ impl BlockReverter { /// Returns suggested values for a reversion. pub async fn suggested_values( &self, - eth_client: &DynClient, + eth_client: &dyn EthInterface, eth_config: &BlockReverterEthConfig, reverter_address: Address, ) -> anyhow::Result { diff --git a/core/node/commitment_generator/src/validation_task.rs b/core/node/commitment_generator/src/validation_task.rs index 8e18e3493873..bde0819ebfbb 100644 --- a/core/node/commitment_generator/src/validation_task.rs +++ b/core/node/commitment_generator/src/validation_task.rs @@ -3,7 +3,7 @@ use std::time::Duration; use tokio::sync::watch; use zksync_eth_client::{ clients::{DynClient, L1}, - CallFunctionArgs, ClientError, ContractCallError, + CallFunctionArgs, ClientError, ContractCallError, EthInterface, }; use zksync_types::{commitment::L1BatchCommitmentMode, Address}; @@ -46,9 +46,9 @@ impl L1BatchCommitmentModeValidationTask { async fn validate_commitment_mode(self) -> anyhow::Result<()> { let expected_mode = self.expected_mode; let diamond_proxy_address = self.diamond_proxy_address; - let eth_client = self.eth_client.as_ref(); loop { - let result = Self::get_pubdata_pricing_mode(diamond_proxy_address, eth_client).await; + let result = + Self::get_pubdata_pricing_mode(diamond_proxy_address, &self.eth_client).await; match result { Ok(mode) => { anyhow::ensure!( @@ -91,7 +91,7 @@ impl L1BatchCommitmentModeValidationTask { async fn get_pubdata_pricing_mode( diamond_proxy_address: Address, - eth_client: &DynClient, + eth_client: &dyn EthInterface, ) -> Result { CallFunctionArgs::new("getPubdataPricingMode", ()) .for_contract( diff --git a/core/node/consistency_checker/src/lib.rs b/core/node/consistency_checker/src/lib.rs index ba8085333a4c..9944d5112437 100644 --- a/core/node/consistency_checker/src/lib.rs +++ b/core/node/consistency_checker/src/lib.rs @@ -518,7 +518,7 @@ impl ConsistencyChecker { let version: U256 = CallFunctionArgs::new("getProtocolVersion", ()) .for_contract(address, &self.contract) - .call(self.l1_client.as_ref()) + .call(&self.l1_client) .await?; tracing::info!("Checked diamond proxy {address:?} (protocol version: {version})"); Ok(()) diff --git a/core/node/consistency_checker/src/tests/mod.rs b/core/node/consistency_checker/src/tests/mod.rs index 40c447071cf4..8664bde74ca8 100644 --- a/core/node/consistency_checker/src/tests/mod.rs +++ b/core/node/consistency_checker/src/tests/mod.rs @@ -7,7 +7,7 @@ use test_casing::{test_casing, Product}; use tokio::sync::mpsc; use zksync_config::GenesisConfig; use zksync_dal::Connection; -use zksync_eth_client::{clients::MockSettlementLayer, Options}; +use zksync_eth_client::{clients::MockSettlementLayer, BoundEthInterface, Options}; use zksync_l1_contract_interface::{i_executor::methods::CommitBatches, Tokenizable, Tokenize}; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{ diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index b85961086569..9f17386478d2 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use vise::{EncodeLabelSet, EncodeLabelValue}; use zksync_eth_client::{ clients::{DynClient, L1}, - BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, Options, - RawTransactionBytes, SignedCallResult, + BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, + L1EthBoundInterface, Options, RawTransactionBytes, SignedCallResult, }; #[cfg(test)] use zksync_types::web3; @@ -78,24 +78,27 @@ pub(super) trait AbstractL1Interface: 'static + Sync + Send + fmt::Debug { async fn get_l1_block_numbers(&self) -> Result; - fn ethereum_gateway(&self) -> &dyn BoundEthInterface; + fn ethereum_gateway(&self) -> &L1EthBoundInterface; - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface>; + fn ethereum_gateway_blobs(&self) -> Option<&L1EthBoundInterface>; } #[derive(Debug)] pub(super) struct RealL1Interface { - pub ethereum_gateway: Box>, - pub ethereum_gateway_blobs: Option>>, + pub ethereum_gateway: Box, + pub ethereum_gateway_blobs: Option>, pub wait_confirmations: Option, } impl RealL1Interface { - pub(crate) fn query_client(&self) -> &DynClient { + pub(crate) fn query_client(&self) -> &dyn EthInterface { self.ethereum_gateway().as_ref() } - pub(crate) fn query_client_for_operator(&self, operator_type: OperatorType) -> &DynClient { + pub(crate) fn query_client_for_operator( + &self, + operator_type: OperatorType, + ) -> &dyn EthInterface { if operator_type == OperatorType::Blob { self.ethereum_gateway_blobs().unwrap().as_ref() } else { @@ -261,11 +264,11 @@ impl AbstractL1Interface for RealL1Interface { }) } - fn ethereum_gateway(&self) -> &dyn BoundEthInterface { + fn ethereum_gateway(&self) -> &L1EthBoundInterface { self.ethereum_gateway.as_ref() } - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface> { + fn ethereum_gateway_blobs(&self) -> Option<&L1EthBoundInterface> { self.ethereum_gateway_blobs.as_deref() } } diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 6144035e79c0..d30a77067f6d 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -2,7 +2,9 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{clients::L1, BoundEthInterface, CallFunctionArgs, EthInterface}; +use zksync_eth_client::{ + clients::L1, BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface, +}; use zksync_l1_contract_interface::{ i_executor::{ commit::kzg::{KzgInfo, ZK_SYNC_BYTES_PER_BLOB}, @@ -47,7 +49,7 @@ pub struct MulticallData { #[derive(Debug)] pub struct EthTxAggregator { aggregator: Aggregator, - eth_client: Box>, + eth_client: Box, config: SenderConfig, timelock_contract_address: Address, l1_multicall3_address: Address, @@ -75,7 +77,7 @@ impl EthTxAggregator { pool: ConnectionPool, config: SenderConfig, aggregator: Aggregator, - eth_client: Box>, + eth_client: Box, timelock_contract_address: Address, l1_multicall3_address: Address, state_transition_chain_contract: Address, diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 5165c89b3daa..78180baa01ea 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -5,7 +5,7 @@ use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ clients::L1, encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, - RawTransactionBytes, + L1EthBoundInterface, RawTransactionBytes, }; use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; @@ -39,8 +39,8 @@ impl EthTxManager { pool: ConnectionPool, config: SenderConfig, gas_adjuster: Arc, - ethereum_gateway: Box>, - ethereum_gateway_blobs: Option>>, + ethereum_gateway: Box, + ethereum_gateway_blobs: Option>, ) -> Self { let ethereum_gateway = ethereum_gateway.for_component("eth_tx_manager"); let ethereum_gateway_blobs = diff --git a/core/node/eth_watch/src/client.rs b/core/node/eth_watch/src/client.rs index 39b9b5e9f6b1..8be556b42889 100644 --- a/core/node/eth_watch/src/client.rs +++ b/core/node/eth_watch/src/client.rs @@ -122,7 +122,7 @@ impl EthClient for EthHttpQueryClient { // New verifier returns the hash of the verification key. CallFunctionArgs::new("verificationKeyHash", ()) .for_contract(verifier_address, &self.verifier_contract_abi) - .call(self.client.as_ref()) + .call(&self.client) .await } diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index c8c566816b97..72a782ca278c 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -1,4 +1,4 @@ -use zksync_eth_client::BoundEthInterface; +use zksync_eth_client::{BoundEthInterface, L1EthBoundInterface}; use zksync_web3_decl::client::{DynClient, L1, L2}; use crate::resource::Resource; @@ -29,7 +29,7 @@ impl Resource for L2InterfaceResource { /// A resource that provides L1 interface with signing capabilities to the service. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceResource(pub Box>); +pub struct BoundEthInterfaceResource(pub Box); impl Resource for BoundEthInterfaceResource { fn name() -> String { @@ -39,7 +39,7 @@ impl Resource for BoundEthInterfaceResource { /// Same as `BoundEthInterfaceResource`, but for managing EIP-4844 blobs. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceForBlobsResource(pub Box>); +pub struct BoundEthInterfaceForBlobsResource(pub Box); impl Resource for BoundEthInterfaceForBlobsResource { fn name() -> String { diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 3b3516498f89..5b23dc59f66b 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use serde_json::{Map, Value}; use zksync_eth_client::{ clients::SigningClient, BoundEthInterface, CallFunctionArgs, ContractCallError, EthInterface, - Options, + L1EthBoundInterface, Options, }; use zksync_eth_signer::EthereumSigner; use zksync_types::{ @@ -127,11 +127,11 @@ impl EthereumProvider { } /// Exposes Ethereum node `web3` API. - pub fn client(&self) -> &dyn BoundEthInterface { + pub fn client(&self) -> &L1EthBoundInterface { &self.eth_client } - pub fn query_client(&self) -> &DynClient { + pub fn query_client(&self) -> &dyn EthInterface { self.eth_client.as_ref() } From 31edada0f5eff18641264d7f38c201cbc45b70d3 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 11:19:09 +0200 Subject: [PATCH 24/43] remove most of copypaste --- core/lib/eth_client/src/clients/http/query.rs | 1012 +---------------- core/lib/eth_client/src/clients/mock.rs | 8 +- core/lib/eth_client/src/lib.rs | 23 +- .../src/l1_gas_price/gas_adjuster/mod.rs | 2 +- .../src/tree_data_fetcher/provider/mod.rs | 12 +- 5 files changed, 39 insertions(+), 1018 deletions(-) diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index 8f9323e5ca51..f8c83ef7f6fd 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use jsonrpsee::core::ClientError; use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::{ - client::{Client, DynClient, EthereumLikeNetwork, ForEthereumLikeNetwork, MockClient, L1}, + client::{Client, DynClient, EthereumLikeNetwork, ForEthereumLikeNetwork, MockClient, L1, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, namespaces::EthNamespaceClient, }; @@ -12,13 +12,16 @@ use zksync_web3_decl::{ use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; use crate::{ types::{ExecutedTxStatus, FailureInfo}, - BaseFees, EthInterface, L2Fees, RawTransactionBytes, ZkSyncInterface, + BaseFees, EthFeeInterface, EthInterface, L2Fees, RawTransactionBytes, ZkSyncInterface, }; const FEE_HISTORY_MAX_REQUEST_CHUNK: usize = 1024; -#[async_trait::async_trait] -impl EthInterface for Box> { +#[async_trait] +impl EthInterface for T +where + T: L1EthNamespaceClient + fmt::Debug + Send + Sync, +{ async fn fetch_chain_id(&self) -> EnrichedClientResult { COUNTERS.call[&(Method::ChainId, self.component())].inc(); let latency = LATENCIES.direct[&Method::ChainId].start(); @@ -77,63 +80,6 @@ impl EthInterface for Box> { Ok(tx) } - async fn base_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); - let mut history = Vec::with_capacity(block_count); - let from_block = upto_block.saturating_sub(block_count); - - // Here we are requesting `fee_history` from blocks - // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` - // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); - let chunk_size = chunk_end - chunk_start; - - let fee_history = self - .fee_history( - U64::from(chunk_size), - web3::BlockNumber::from(chunk_end), - None, - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; - - // Check that the lengths are the same. - // Per specification, the values should always be provided, and must be 0 for blocks - // prior to EIP-4844. - // https://ethereum.github.io/execution-apis/api-documentation/ - if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { - tracing::error!( - "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", - fee_history.base_fee_per_gas.len(), - fee_history.base_fee_per_blob_gas.len() - ); - } - - for (base, blob) in fee_history - .base_fee_per_gas - .into_iter() - .zip(fee_history.base_fee_per_blob_gas) - { - let fees = BaseFees { - base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, - base_fee_per_blob_gas: blob, - }; - history.push(fees) - } - } - - latency.observe(); - Ok(history) - } - async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); @@ -347,66 +293,12 @@ impl EthInterface for Box> { } } -#[async_trait::async_trait] -impl EthInterface for DynClient { - 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?; - latency.observe(); - let chain_id = u64::try_from(raw_chain_id).map_err(|err| { - let err = ClientError::Custom(format!("invalid chainId: {err}")); - EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) - })?; - Ok(SLChainId(chain_id)) - } - - async fn nonce_at_for_account( - &self, - account: Address, - block: web3::BlockNumber, - ) -> EnrichedClientResult { - COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); - let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); - let nonce = self - .get_transaction_count(account, block) - .rpc_context("get_transaction_count") - .with_arg("account", &account) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(nonce) - } - - async fn block_number(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BlockNumber].start(); - let block_number = self - .get_block_number() - .rpc_context("get_block_number") - .await?; - latency.observe(); - Ok(block_number) - } - - async fn get_gas_price(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetGasPrice].start(); - let network_gas_price = self.gas_price().rpc_context("gas_price").await?; - latency.observe(); - Ok(network_gas_price) - } - - async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::SendRawTx].start(); - let tx = self - .send_raw_transaction(web3::Bytes(tx.0)) - .rpc_context("send_raw_transaction") - .await?; - latency.observe(); - Ok(tx) - } +pub trait L1Client: L1EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} +impl L1Client for Box> {} +impl L1Client for MockClient {} +#[async_trait::async_trait] +impl EthFeeInterface for T { async fn base_fee_history( &self, upto_block: usize, @@ -463,885 +355,13 @@ impl EthInterface for DynClient { latency.observe(); Ok(history) } +} - async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); - let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); - - let block = self - .get_block_by_number(web3::BlockNumber::Pending, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Pending) - .with_arg("with_transactions", &false) - .await?; - let block = if let Some(block) = block { - block - } else { - // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup - // there may be no pending block - self.get_block_by_number(web3::BlockNumber::Latest, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Latest) - .with_arg("with_transactions", &false) - .await? - .expect("Latest block always exists") - }; - - latency.observe(); - - // base_fee_per_gas always exists after London fork - Ok(block.base_fee_per_gas.unwrap()) - } - - async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetTxStatus].start(); - - let receipt = self.tx_receipt(hash).await?; - let res = receipt.and_then(|receipt| match receipt.status { - Some(status) if receipt.block_number.is_some() => { - let success = status.as_u64() == 1; - - Some(ExecutedTxStatus { - tx_hash: receipt.transaction_hash, - success, - receipt, - }) - } - _ => None, - }); - - latency.observe(); - Ok(res) - } - - async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { - let latency = LATENCIES.direct[&Method::FailureReason].start(); - let transaction = self - .get_transaction_by_hash(tx_hash) - .rpc_context("failure_reason#get_transaction_by_hash") - .with_arg("hash", &tx_hash) - .await?; - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("failure_reason#get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - - match (transaction, receipt) { - (Some(transaction), Some(receipt)) => { - let gas_limit = transaction.gas; - let gas_used = receipt.gas_used; - - let call_request = web3::CallRequest { - from: transaction.from, - to: transaction.to, - gas: Some(transaction.gas), - gas_price: transaction.gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - value: Some(transaction.value), - data: Some(transaction.input), - transaction_type: None, - access_list: None, - }; - - let block_number = receipt - .block_number - .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); - let result = self - .call(call_request.clone(), block_number) - .rpc_context("failure_reason#call") - .with_arg("call_request", &call_request) - .with_arg("block_number", &block_number) - .await; - - let failure_info = match result { - Err(err) => { - if let ClientError::Call(call_err) = err.as_ref() { - let revert_code = call_err.code().into(); - let message_len = - "execution reverted: ".len().min(call_err.message().len()); - let revert_reason = call_err.message()[message_len..].to_string(); - - Ok(Some(FailureInfo { - revert_code, - revert_reason, - gas_used, - gas_limit, - })) - } else { - Err(err) - } - } - Ok(_) => Ok(None), - }; - - latency.observe(); - failure_info - } - _ => Ok(None), - } - } - - async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTx, self.component())].inc(); - let tx = self - .get_transaction_by_hash(hash) - .rpc_context("get_transaction_by_hash") - .with_arg("hash", &hash) - .await?; - Ok(tx) - } - - async fn call_contract_function( - &self, - request: web3::CallRequest, - block: Option, - ) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::CallContractFunction].start(); - let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); - let output_bytes = self - .call(request.clone(), block) - .rpc_context("call") - .with_arg("request", &request) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(output_bytes) - } - - async fn tx_receipt( - &self, - tx_hash: H256, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); - let latency = LATENCIES.direct[&Method::TxReceipt].start(); - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - latency.observe(); - Ok(receipt) - } - - async fn eth_balance(&self, address: Address) -> EnrichedClientResult { - COUNTERS.call[&(Method::EthBalance, self.component())].inc(); - let latency = LATENCIES.direct[&Method::EthBalance].start(); - let balance = self - .get_balance(address, web3::BlockNumber::Latest) - .rpc_context("get_balance") - .with_arg("address", &address) - .await?; - latency.observe(); - Ok(balance) - } - - async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { - COUNTERS.call[&(Method::Logs, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Logs].start(); - let logs = self - .get_logs(filter.clone()) - .rpc_context("get_logs") - .with_arg("filter", filter) - .await?; - latency.observe(); - Ok(logs) - } - - async fn block( - &self, - block_id: web3::BlockId, - ) -> EnrichedClientResult>> { - COUNTERS.call[&(Method::Block, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Block].start(); - let block = match block_id { - web3::BlockId::Hash(hash) => { - self.get_block_by_hash(hash, false) - .rpc_context("get_block_by_hash") - .with_arg("hash", &hash) - .with_arg("with_transactions", &false) - .await? - } - web3::BlockId::Number(num) => { - self.get_block_by_number(num, false) - .rpc_context("get_block_by_number") - .with_arg("number", &num) - .with_arg("with_transactions", &false) - .await? - } - }; - latency.observe(); - Ok(block) - } -} - -#[async_trait::async_trait] -impl EthInterface for Client { - 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?; - latency.observe(); - let chain_id = u64::try_from(raw_chain_id).map_err(|err| { - let err = ClientError::Custom(format!("invalid chainId: {err}")); - EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) - })?; - Ok(SLChainId(chain_id)) - } - - async fn nonce_at_for_account( - &self, - account: Address, - block: web3::BlockNumber, - ) -> EnrichedClientResult { - COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); - let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); - let nonce = self - .get_transaction_count(account, block) - .rpc_context("get_transaction_count") - .with_arg("account", &account) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(nonce) - } - - async fn block_number(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BlockNumber].start(); - let block_number = self - .get_block_number() - .rpc_context("get_block_number") - .await?; - latency.observe(); - Ok(block_number) - } - - async fn get_gas_price(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetGasPrice].start(); - let network_gas_price = self.gas_price().rpc_context("gas_price").await?; - latency.observe(); - Ok(network_gas_price) - } - - async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::SendRawTx].start(); - let tx = self - .send_raw_transaction(web3::Bytes(tx.0)) - .rpc_context("send_raw_transaction") - .await?; - latency.observe(); - Ok(tx) - } - - async fn base_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); - let mut history = Vec::with_capacity(block_count); - let from_block = upto_block.saturating_sub(block_count); - - // Here we are requesting `fee_history` from blocks - // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` - // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); - let chunk_size = chunk_end - chunk_start; - - let fee_history = self - .fee_history( - U64::from(chunk_size), - web3::BlockNumber::from(chunk_end), - None, - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; - - // Check that the lengths are the same. - // Per specification, the values should always be provided, and must be 0 for blocks - // prior to EIP-4844. - // https://ethereum.github.io/execution-apis/api-documentation/ - if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { - tracing::error!( - "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", - fee_history.base_fee_per_gas.len(), - fee_history.base_fee_per_blob_gas.len() - ); - } - - for (base, blob) in fee_history - .base_fee_per_gas - .into_iter() - .zip(fee_history.base_fee_per_blob_gas) - { - let fees = BaseFees { - base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, - base_fee_per_blob_gas: blob, - }; - history.push(fees) - } - } - - latency.observe(); - Ok(history) - } - - async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); - let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); - - let block = self - .get_block_by_number(web3::BlockNumber::Pending, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Pending) - .with_arg("with_transactions", &false) - .await?; - let block = if let Some(block) = block { - block - } else { - // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup - // there may be no pending block - self.get_block_by_number(web3::BlockNumber::Latest, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Latest) - .with_arg("with_transactions", &false) - .await? - .expect("Latest block always exists") - }; - - latency.observe(); - - // base_fee_per_gas always exists after London fork - Ok(block.base_fee_per_gas.unwrap()) - } - - async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetTxStatus].start(); - - let receipt = self.tx_receipt(hash).await?; - let res = receipt.and_then(|receipt| match receipt.status { - Some(status) if receipt.block_number.is_some() => { - let success = status.as_u64() == 1; - - Some(ExecutedTxStatus { - tx_hash: receipt.transaction_hash, - success, - receipt, - }) - } - _ => None, - }); - - latency.observe(); - Ok(res) - } - - async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { - let latency = LATENCIES.direct[&Method::FailureReason].start(); - let transaction = self - .get_transaction_by_hash(tx_hash) - .rpc_context("failure_reason#get_transaction_by_hash") - .with_arg("hash", &tx_hash) - .await?; - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("failure_reason#get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - - match (transaction, receipt) { - (Some(transaction), Some(receipt)) => { - let gas_limit = transaction.gas; - let gas_used = receipt.gas_used; - - let call_request = web3::CallRequest { - from: transaction.from, - to: transaction.to, - gas: Some(transaction.gas), - gas_price: transaction.gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - value: Some(transaction.value), - data: Some(transaction.input), - transaction_type: None, - access_list: None, - }; - - let block_number = receipt - .block_number - .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); - let result = self - .call(call_request.clone(), block_number) - .rpc_context("failure_reason#call") - .with_arg("call_request", &call_request) - .with_arg("block_number", &block_number) - .await; - - let failure_info = match result { - Err(err) => { - if let ClientError::Call(call_err) = err.as_ref() { - let revert_code = call_err.code().into(); - let message_len = - "execution reverted: ".len().min(call_err.message().len()); - let revert_reason = call_err.message()[message_len..].to_string(); - - Ok(Some(FailureInfo { - revert_code, - revert_reason, - gas_used, - gas_limit, - })) - } else { - Err(err) - } - } - Ok(_) => Ok(None), - }; - - latency.observe(); - failure_info - } - _ => Ok(None), - } - } - - async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTx, self.component())].inc(); - let tx = self - .get_transaction_by_hash(hash) - .rpc_context("get_transaction_by_hash") - .with_arg("hash", &hash) - .await?; - Ok(tx) - } - - async fn call_contract_function( - &self, - request: web3::CallRequest, - block: Option, - ) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::CallContractFunction].start(); - let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); - let output_bytes = self - .call(request.clone(), block) - .rpc_context("call") - .with_arg("request", &request) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(output_bytes) - } - - async fn tx_receipt( - &self, - tx_hash: H256, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); - let latency = LATENCIES.direct[&Method::TxReceipt].start(); - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - latency.observe(); - Ok(receipt) - } - - async fn eth_balance(&self, address: Address) -> EnrichedClientResult { - COUNTERS.call[&(Method::EthBalance, self.component())].inc(); - let latency = LATENCIES.direct[&Method::EthBalance].start(); - let balance = self - .get_balance(address, web3::BlockNumber::Latest) - .rpc_context("get_balance") - .with_arg("address", &address) - .await?; - latency.observe(); - Ok(balance) - } - - async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { - COUNTERS.call[&(Method::Logs, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Logs].start(); - let logs = self - .get_logs(filter.clone()) - .rpc_context("get_logs") - .with_arg("filter", filter) - .await?; - latency.observe(); - Ok(logs) - } - - async fn block( - &self, - block_id: web3::BlockId, - ) -> EnrichedClientResult>> { - COUNTERS.call[&(Method::Block, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Block].start(); - let block = match block_id { - web3::BlockId::Hash(hash) => { - self.get_block_by_hash(hash, false) - .rpc_context("get_block_by_hash") - .with_arg("hash", &hash) - .with_arg("with_transactions", &false) - .await? - } - web3::BlockId::Number(num) => { - self.get_block_by_number(num, false) - .rpc_context("get_block_by_number") - .with_arg("number", &num) - .with_arg("with_transactions", &false) - .await? - } - }; - latency.observe(); - Ok(block) - } -} - -#[async_trait::async_trait] -impl EthInterface for MockClient { - 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?; - latency.observe(); - let chain_id = u64::try_from(raw_chain_id).map_err(|err| { - let err = ClientError::Custom(format!("invalid chainId: {err}")); - EnrichedClientError::new(err, "chain_id").with_arg("chain_id", &raw_chain_id) - })?; - Ok(SLChainId(chain_id)) - } - - async fn nonce_at_for_account( - &self, - account: Address, - block: web3::BlockNumber, - ) -> EnrichedClientResult { - COUNTERS.call[&(Method::NonceAtForAccount, self.component())].inc(); - let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); - let nonce = self - .get_transaction_count(account, block) - .rpc_context("get_transaction_count") - .with_arg("account", &account) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(nonce) - } - - async fn block_number(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::BlockNumber, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BlockNumber].start(); - let block_number = self - .get_block_number() - .rpc_context("get_block_number") - .await?; - latency.observe(); - Ok(block_number) - } - - async fn get_gas_price(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::GetGasPrice, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetGasPrice].start(); - let network_gas_price = self.gas_price().rpc_context("gas_price").await?; - latency.observe(); - Ok(network_gas_price) - } - - async fn send_raw_tx(&self, tx: RawTransactionBytes) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::SendRawTx].start(); - let tx = self - .send_raw_transaction(web3::Bytes(tx.0)) - .rpc_context("send_raw_transaction") - .await?; - latency.observe(); - Ok(tx) - } - - async fn base_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); - let mut history = Vec::with_capacity(block_count); - let from_block = upto_block.saturating_sub(block_count); - - // Here we are requesting `fee_history` from blocks - // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` - // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); - let chunk_size = chunk_end - chunk_start; - - let fee_history = self - .fee_history( - U64::from(chunk_size), - web3::BlockNumber::from(chunk_end), - None, - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; - - // Check that the lengths are the same. - // Per specification, the values should always be provided, and must be 0 for blocks - // prior to EIP-4844. - // https://ethereum.github.io/execution-apis/api-documentation/ - if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { - tracing::error!( - "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", - fee_history.base_fee_per_gas.len(), - fee_history.base_fee_per_blob_gas.len() - ); - } - - for (base, blob) in fee_history - .base_fee_per_gas - .into_iter() - .zip(fee_history.base_fee_per_blob_gas) - { - let fees = BaseFees { - base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, - base_fee_per_blob_gas: blob, - }; - history.push(fees) - } - } - - latency.observe(); - Ok(history) - } - - async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult { - COUNTERS.call[&(Method::PendingBlockBaseFee, self.component())].inc(); - let latency = LATENCIES.direct[&Method::PendingBlockBaseFee].start(); - - let block = self - .get_block_by_number(web3::BlockNumber::Pending, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Pending) - .with_arg("with_transactions", &false) - .await?; - let block = if let Some(block) = block { - block - } else { - // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup - // there may be no pending block - self.get_block_by_number(web3::BlockNumber::Latest, false) - .rpc_context("get_block_by_number") - .with_arg("number", &web3::BlockNumber::Latest) - .with_arg("with_transactions", &false) - .await? - .expect("Latest block always exists") - }; - - latency.observe(); - - // base_fee_per_gas always exists after London fork - Ok(block.base_fee_per_gas.unwrap()) - } - - async fn get_tx_status(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTxStatus, self.component())].inc(); - let latency = LATENCIES.direct[&Method::GetTxStatus].start(); - - let receipt = self.tx_receipt(hash).await?; - let res = receipt.and_then(|receipt| match receipt.status { - Some(status) if receipt.block_number.is_some() => { - let success = status.as_u64() == 1; - - Some(ExecutedTxStatus { - tx_hash: receipt.transaction_hash, - success, - receipt, - }) - } - _ => None, - }); - - latency.observe(); - Ok(res) - } - - async fn failure_reason(&self, tx_hash: H256) -> EnrichedClientResult> { - let latency = LATENCIES.direct[&Method::FailureReason].start(); - let transaction = self - .get_transaction_by_hash(tx_hash) - .rpc_context("failure_reason#get_transaction_by_hash") - .with_arg("hash", &tx_hash) - .await?; - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("failure_reason#get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - - match (transaction, receipt) { - (Some(transaction), Some(receipt)) => { - let gas_limit = transaction.gas; - let gas_used = receipt.gas_used; - - let call_request = web3::CallRequest { - from: transaction.from, - to: transaction.to, - gas: Some(transaction.gas), - gas_price: transaction.gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - value: Some(transaction.value), - data: Some(transaction.input), - transaction_type: None, - access_list: None, - }; - - let block_number = receipt - .block_number - .map_or_else(|| web3::BlockNumber::Latest.into(), Into::into); - let result = self - .call(call_request.clone(), block_number) - .rpc_context("failure_reason#call") - .with_arg("call_request", &call_request) - .with_arg("block_number", &block_number) - .await; - - let failure_info = match result { - Err(err) => { - if let ClientError::Call(call_err) = err.as_ref() { - let revert_code = call_err.code().into(); - let message_len = - "execution reverted: ".len().min(call_err.message().len()); - let revert_reason = call_err.message()[message_len..].to_string(); - - Ok(Some(FailureInfo { - revert_code, - revert_reason, - gas_used, - gas_limit, - })) - } else { - Err(err) - } - } - Ok(_) => Ok(None), - }; - - latency.observe(); - failure_info - } - _ => Ok(None), - } - } - - async fn get_tx(&self, hash: H256) -> EnrichedClientResult> { - COUNTERS.call[&(Method::GetTx, self.component())].inc(); - let tx = self - .get_transaction_by_hash(hash) - .rpc_context("get_transaction_by_hash") - .with_arg("hash", &hash) - .await?; - Ok(tx) - } - - async fn call_contract_function( - &self, - request: web3::CallRequest, - block: Option, - ) -> EnrichedClientResult { - let latency = LATENCIES.direct[&Method::CallContractFunction].start(); - let block = block.unwrap_or_else(|| web3::BlockNumber::Latest.into()); - let output_bytes = self - .call(request.clone(), block) - .rpc_context("call") - .with_arg("request", &request) - .with_arg("block", &block) - .await?; - latency.observe(); - Ok(output_bytes) - } - - async fn tx_receipt( - &self, - tx_hash: H256, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::TxReceipt, self.component())].inc(); - let latency = LATENCIES.direct[&Method::TxReceipt].start(); - let receipt = self - .get_transaction_receipt(tx_hash) - .rpc_context("get_transaction_receipt") - .with_arg("hash", &tx_hash) - .await?; - latency.observe(); - Ok(receipt) - } - - async fn eth_balance(&self, address: Address) -> EnrichedClientResult { - COUNTERS.call[&(Method::EthBalance, self.component())].inc(); - let latency = LATENCIES.direct[&Method::EthBalance].start(); - let balance = self - .get_balance(address, web3::BlockNumber::Latest) - .rpc_context("get_balance") - .with_arg("address", &address) - .await?; - latency.observe(); - Ok(balance) - } - - async fn logs(&self, filter: &web3::Filter) -> EnrichedClientResult> { - COUNTERS.call[&(Method::Logs, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Logs].start(); - let logs = self - .get_logs(filter.clone()) - .rpc_context("get_logs") - .with_arg("filter", filter) - .await?; - latency.observe(); - Ok(logs) - } - - async fn block( - &self, - block_id: web3::BlockId, - ) -> EnrichedClientResult>> { - COUNTERS.call[&(Method::Block, self.component())].inc(); - let latency = LATENCIES.direct[&Method::Block].start(); - let block = match block_id { - web3::BlockId::Hash(hash) => { - self.get_block_by_hash(hash, false) - .rpc_context("get_block_by_hash") - .with_arg("hash", &hash) - .with_arg("with_transactions", &false) - .await? - } - web3::BlockId::Number(num) => { - self.get_block_by_number(num, false) - .rpc_context("get_block_by_number") - .with_arg("number", &num) - .with_arg("with_transactions", &false) - .await? - } - }; - latency.observe(); - Ok(block) - } -} +pub trait L2Client: EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} +impl L2Client for Box> {} #[async_trait::async_trait] -impl ZkSyncInterface for T -where - T: EthNamespaceClient + fmt::Debug + Send + Sync, -{ +impl ZkSyncInterface for T { async fn l2_fee_history( &self, upto_block: usize, diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index b09ac4e61248..5d0db0dca034 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -678,7 +678,7 @@ mod tests { use zksync_types::{commitment::L1BatchCommitmentMode, ProtocolVersionId}; use super::*; - use crate::{CallFunctionArgs, EthInterface, ZkSyncInterface}; + use crate::{CallFunctionArgs, EthFeeInterface, EthInterface, ZkSyncInterface}; fn base_fees(block: u64, blob: u64, pubdata_price: u64) -> MockClientBaseFee { MockClientBaseFee { @@ -740,7 +740,7 @@ mod tests { .build(); client.advance_block_number(4); - let fee_history = client.as_ref().base_fee_history(4, 4).await.unwrap(); + let fee_history = client.client.base_fee_history(4, 4).await.unwrap(); assert_eq!( fee_history, initial_fee_history[1..=4] @@ -749,7 +749,7 @@ mod tests { .map(BaseFees::from) .collect::>() ); - let fee_history = client.as_ref().base_fee_history(2, 2).await.unwrap(); + let fee_history = client.client.base_fee_history(2, 2).await.unwrap(); assert_eq!( fee_history, initial_fee_history[1..=2] @@ -758,7 +758,7 @@ mod tests { .map(BaseFees::from) .collect::>() ); - let fee_history = client.as_ref().base_fee_history(3, 2).await.unwrap(); + let fee_history = client.client.base_fee_history(3, 2).await.unwrap(); assert_eq!( fee_history, initial_fee_history[2..=3] diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 63ed9a0493fb..be3b444803b3 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -96,16 +96,6 @@ pub trait EthInterface: Sync + Send + Debug { block: BlockNumber, ) -> EnrichedClientResult; - /// Collects the base fee history for the specified block range. - /// - /// Returns 1 value for each block in range, assuming that these blocks exist. - /// Will return an error if the `from_block + block_count` is beyond the head block. - async fn base_fee_history( - &self, - from_block: usize, - block_count: usize, - ) -> EnrichedClientResult>; - /// Returns the `base_fee_per_gas` value for the currently pending L1 block. async fn get_pending_block_base_fee_per_gas(&self) -> EnrichedClientResult; @@ -155,6 +145,19 @@ pub trait EthInterface: Sync + Send + Debug { async fn block(&self, block_id: BlockId) -> EnrichedClientResult>>; } +#[async_trait::async_trait] +pub trait EthFeeInterface: EthInterface { + /// Collects the base fee history for the specified block range. + /// + /// Returns 1 value for each block in range, assuming that these blocks exist. + /// Will return an error if the `from_block + block_count` is beyond the head block. + async fn base_fee_history( + &self, + from_block: usize, + block_count: usize, + ) -> EnrichedClientResult>; +} + /// Information about the base fees provided by the L1 client. #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct L2Fees { diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 499af24fdb04..7181206336ba 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -7,7 +7,7 @@ use std::{ use tokio::sync::watch; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::{EnrichedClientResult, EthInterface, ZkSyncInterface}; +use zksync_eth_client::{EnrichedClientResult, EthFeeInterface, EthInterface, ZkSyncInterface}; use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U256, U64}; use zksync_web3_decl::client::{DynClient, L1, L2}; diff --git a/core/node/node_sync/src/tree_data_fetcher/provider/mod.rs b/core/node/node_sync/src/tree_data_fetcher/provider/mod.rs index 867ea2427541..5e28bfe8baff 100644 --- a/core/node/node_sync/src/tree_data_fetcher/provider/mod.rs +++ b/core/node/node_sync/src/tree_data_fetcher/provider/mod.rs @@ -135,7 +135,7 @@ impl L1DataProvider { /// Guesses the number of an L1 block with a `BlockCommit` event for the specified L1 batch. /// The guess is based on the L1 batch seal timestamp. async fn guess_l1_commit_block_number( - eth_client: &DynClient, + eth_client: &dyn EthInterface, l1_batch_seal_timestamp: u64, ) -> EnrichedClientResult<(U64, usize)> { let l1_batch_seal_timestamp = U256::from(l1_batch_seal_timestamp); @@ -171,7 +171,7 @@ impl L1DataProvider { /// Gets a block that should be present on L1. async fn get_block( - eth_client: &DynClient, + eth_client: &dyn EthInterface, number: web3::BlockNumber, ) -> EnrichedClientResult<(U64, U256)> { let block = eth_client.block(number.into()).await?.ok_or_else(|| { @@ -218,11 +218,9 @@ impl TreeDataProvider for L1DataProvider { let from_block = match from_block { Some(number) => number, None => { - let (approximate_block, steps) = Self::guess_l1_commit_block_number( - self.eth_client.as_ref(), - l1_batch_seal_timestamp, - ) - .await?; + let (approximate_block, steps) = + Self::guess_l1_commit_block_number(&self.eth_client, l1_batch_seal_timestamp) + .await?; tracing::debug!( number = number.0, "Guessed L1 block number for L1 batch #{number} commit in {steps} binary search steps: {approximate_block}" From 19054b0c3e1ee626c01e3fbf34e92e40bfb5f3ef Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 11:57:42 +0200 Subject: [PATCH 25/43] almost finalize --- core/lib/eth_client/src/clients/http/query.rs | 196 ++++++++++++------ core/lib/eth_client/src/clients/mock.rs | 39 +--- core/lib/eth_client/src/clients/mod.rs | 2 +- core/lib/eth_client/src/lib.rs | 21 +- core/node/eth_sender/src/tester.rs | 11 +- .../src/l1_gas_price/gas_adjuster/mod.rs | 39 +--- .../src/l1_gas_price/gas_adjuster/tests.rs | 6 +- core/node/fee_model/src/lib.rs | 6 +- core/node/state_keeper/src/io/tests/tester.rs | 4 +- 9 files changed, 164 insertions(+), 160 deletions(-) diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index f8c83ef7f6fd..f959c266a7f4 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -12,7 +12,7 @@ use zksync_web3_decl::{ use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; use crate::{ types::{ExecutedTxStatus, FailureInfo}, - BaseFees, EthFeeInterface, EthInterface, L2Fees, RawTransactionBytes, ZkSyncInterface, + BaseFees, EthFeeInterface, EthInterface, RawTransactionBytes, }; const FEE_HISTORY_MAX_REQUEST_CHUNK: usize = 1024; @@ -293,80 +293,149 @@ where } } -pub trait L1Client: L1EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} -impl L1Client for Box> {} -impl L1Client for MockClient {} - -#[async_trait::async_trait] -impl EthFeeInterface for T { - async fn base_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); - let mut history = Vec::with_capacity(block_count); - let from_block = upto_block.saturating_sub(block_count); - - // Here we are requesting `fee_history` from blocks - // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` - // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); - let chunk_size = chunk_end - chunk_start; - - let fee_history = self - .fee_history( - U64::from(chunk_size), - web3::BlockNumber::from(chunk_end), - None, - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; +// pub trait L1Client: L1EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} + +// impl L1Client for Box> {} +// impl L1Client for MockClient {} + +macro_rules! impl_l1_eth_fee_interface { + ($type:ty) => { + #[async_trait::async_trait] + impl EthFeeInterface for $type { + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); + + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; + + let fee_history = self + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + // Per specification, the values should always be provided, and must be 0 for blocks + // prior to EIP-4844. + // https://ethereum.github.io/execution-apis/api-documentation/ + if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { + tracing::error!( + "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", + fee_history.base_fee_per_gas.len(), + fee_history.base_fee_per_blob_gas.len() + ); + } - // Check that the lengths are the same. - // Per specification, the values should always be provided, and must be 0 for blocks - // prior to EIP-4844. - // https://ethereum.github.io/execution-apis/api-documentation/ - if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { - tracing::error!( - "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", - fee_history.base_fee_per_gas.len(), - fee_history.base_fee_per_blob_gas.len() - ); - } + for (base, blob) in fee_history + .base_fee_per_gas + .into_iter() + .zip(fee_history.base_fee_per_blob_gas) + { + let fees = BaseFees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: blob, + pubdata_price: 0.into() + }; + history.push(fees) + } + } - for (base, blob) in fee_history - .base_fee_per_gas - .into_iter() - .zip(fee_history.base_fee_per_blob_gas) - { - let fees = BaseFees { - base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, - base_fee_per_blob_gas: blob, - }; - history.push(fees) + latency.observe(); + Ok(history) } } - - latency.observe(); - Ok(history) - } + }; } +impl_l1_eth_fee_interface!(Box::>); +impl_l1_eth_fee_interface!(MockClient::); + +// #[async_trait::async_trait] +// impl EthFeeInterface for T { +// async fn base_fee_history( +// &self, +// upto_block: usize, +// block_count: usize, +// ) -> EnrichedClientResult> { +// COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); +// let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); +// let mut history = Vec::with_capacity(block_count); +// let from_block = upto_block.saturating_sub(block_count); + +// // Here we are requesting `fee_history` from blocks +// // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` +// // starting from the oldest block. +// for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { +// let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); +// let chunk_size = chunk_end - chunk_start; + +// let fee_history = self +// .fee_history( +// U64::from(chunk_size), +// web3::BlockNumber::from(chunk_end), +// None, +// ) +// .rpc_context("fee_history") +// .with_arg("chunk_size", &chunk_size) +// .with_arg("block", &chunk_end) +// .await?; + +// // Check that the lengths are the same. +// // Per specification, the values should always be provided, and must be 0 for blocks +// // prior to EIP-4844. +// // https://ethereum.github.io/execution-apis/api-documentation/ +// if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { +// tracing::error!( +// "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", +// fee_history.base_fee_per_gas.len(), +// fee_history.base_fee_per_blob_gas.len() +// ); +// } + +// for (base, blob) in fee_history +// .base_fee_per_gas +// .into_iter() +// .zip(fee_history.base_fee_per_blob_gas) +// { +// let fees = BaseFees { +// base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, +// base_fee_per_blob_gas: blob, +// }; +// history.push(fees) +// } +// } + +// latency.observe(); +// Ok(history) +// } +// } + pub trait L2Client: EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} impl L2Client for Box> {} #[async_trait::async_trait] -impl ZkSyncInterface for T { - async fn l2_fee_history( +impl EthFeeInterface for T { + async fn base_fee_history( &self, upto_block: usize, block_count: usize, - ) -> EnrichedClientResult> { + ) -> EnrichedClientResult> { COUNTERS.call[&(Method::L2FeeHistory, self.component())].inc(); let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); let mut history = Vec::with_capacity(block_count); @@ -405,8 +474,9 @@ impl ZkSyncInterface for T { .into_iter() .zip(fee_history.pubdata_price) { - let fees = L2Fees { + let fees = BaseFees { base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: 0.into(), pubdata_price, }; history.push(fees) diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 5d0db0dca034..5cf0ae906fb9 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -18,7 +18,7 @@ use zksync_web3_decl::client::{ use crate::{ types::{ContractCallError, SignedCallResult, SigningError}, - BaseFees, BoundEthInterface, EthInterface, L2Fees, Options, RawTransactionBytes, + BaseFees, BoundEthInterface, EthInterface, Options, RawTransactionBytes, }; #[derive(Debug, Clone)] @@ -225,31 +225,6 @@ impl MockExecutedTxHandle<'_> { type CallHandler = dyn Fn(&web3::CallRequest, BlockId) -> Result + Send + Sync; -#[derive(Debug, Clone)] -pub struct MockClientBaseFee { - pub base_fee_per_gas: u64, - pub base_fee_per_blob_gas: U256, - pub pubdata_price: U256, -} - -impl From for BaseFees { - fn from(value: MockClientBaseFee) -> Self { - Self { - base_fee_per_blob_gas: value.base_fee_per_blob_gas, - base_fee_per_gas: value.base_fee_per_gas, - } - } -} - -impl From for L2Fees { - fn from(value: MockClientBaseFee) -> Self { - Self { - base_fee_per_gas: value.base_fee_per_gas, - pubdata_price: value.pubdata_price, - } - } -} - pub trait SupportedMockEthNetwork: Network { fn build_client(builder: MockEthereumBuilder) -> MockClient; } @@ -258,7 +233,7 @@ pub trait SupportedMockEthNetwork: Network { pub struct MockEthereumBuilder { max_fee_per_gas: U256, max_priority_fee_per_gas: U256, - base_fee_history: Vec, + base_fee_history: Vec, /// If true, the mock will not check the ordering nonces of the transactions. /// This is useful for testing the cases when the transactions are executed out of order. non_ordering_confirmations: bool, @@ -301,7 +276,7 @@ impl Default for MockEthereumBuilder { impl MockEthereumBuilder { /// Sets fee history for each block in the mocked Ethereum network, starting from the 0th block. - pub fn with_fee_history(self, history: Vec) -> Self { + pub fn with_fee_history(self, history: Vec) -> Self { Self { base_fee_history: history, ..self @@ -343,7 +318,7 @@ impl MockEthereumBuilder { } fn get_block_by_number( - fee_history: &[MockClientBaseFee], + fee_history: &[BaseFees], block: web3::BlockNumber, ) -> Option> { let web3::BlockNumber::Number(number) = block else { @@ -678,10 +653,10 @@ mod tests { use zksync_types::{commitment::L1BatchCommitmentMode, ProtocolVersionId}; use super::*; - use crate::{CallFunctionArgs, EthFeeInterface, EthInterface, ZkSyncInterface}; + use crate::{CallFunctionArgs, EthFeeInterface, EthInterface}; - fn base_fees(block: u64, blob: u64, pubdata_price: u64) -> MockClientBaseFee { - MockClientBaseFee { + fn base_fees(block: u64, blob: u64, pubdata_price: u64) -> BaseFees { + BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: U256::from(blob), pubdata_price: U256::from(pubdata_price), diff --git a/core/lib/eth_client/src/clients/mod.rs b/core/lib/eth_client/src/clients/mod.rs index 8461ac772fc4..4d48229c573f 100644 --- a/core/lib/eth_client/src/clients/mod.rs +++ b/core/lib/eth_client/src/clients/mod.rs @@ -7,5 +7,5 @@ pub use zksync_web3_decl::client::{Client, DynClient, L1}; pub use self::{ http::{PKSigningClient, SigningClient}, - mock::{MockClientBaseFee, MockEthereumBuilder, MockSettlementLayer}, + mock::{MockEthereumBuilder, MockSettlementLayer}, }; diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index be3b444803b3..93488b2708fa 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -69,8 +69,10 @@ impl Options { #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct BaseFees { pub base_fee_per_gas: u64, + // Base fee per blob gas. It is zero on networks that do not support blob transactions (e.g. L2s). pub base_fee_per_blob_gas: U256, - // pub pubdata_price: U256, + // The price (in wei) for relaying the pubdata to L1. It is non-zero only for L2 settlement layers. + pub pubdata_price: U256, } /// Common Web3 interface, as seen by the core applications. @@ -158,23 +160,6 @@ pub trait EthFeeInterface: EthInterface { ) -> EnrichedClientResult>; } -/// Information about the base fees provided by the L1 client. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct L2Fees { - pub base_fee_per_gas: u64, - pub pubdata_price: U256, -} - -#[async_trait] -pub trait ZkSyncInterface: Sync + Send { - /// Returns vector of base fees and pubdata prices (in wei) for a zkSync-based network. - async fn l2_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult>; -} - /// An extension of `EthInterface` trait, which is used to perform queries that are bound to /// a certain contract and account. /// diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index 1729ef4c08ef..b98d96dc1267 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -5,10 +5,7 @@ use zksync_config::{ ContractsConfig, EthConfig, GasAdjusterConfig, }; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{ - clients::{MockClientBaseFee, MockSettlementLayer}, - BoundEthInterface, -}; +use zksync_eth_client::{clients::MockSettlementLayer, BaseFees, BoundEthInterface}; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; @@ -152,7 +149,7 @@ impl EthSenderTester { let history: Vec<_> = history .into_iter() - .map(|base_fee_per_gas| MockClientBaseFee { + .map(|base_fee_per_gas| BaseFees { base_fee_per_gas, base_fee_per_blob_gas: 0.into(), pubdata_price: 0.into(), @@ -161,7 +158,7 @@ impl EthSenderTester { let gateway = MockSettlementLayer::builder() .with_fee_history( - std::iter::repeat_with(|| MockClientBaseFee { + std::iter::repeat_with(|| BaseFees { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), pubdata_price: 0.into(), @@ -181,7 +178,7 @@ impl EthSenderTester { let gateway_blobs = MockSettlementLayer::builder() .with_fee_history( - std::iter::repeat_with(|| MockClientBaseFee { + std::iter::repeat_with(|| BaseFees { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), pubdata_price: 0.into(), diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 7181206336ba..1e353acca089 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -7,7 +7,7 @@ use std::{ use tokio::sync::watch; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::{EnrichedClientResult, EthFeeInterface, EthInterface, ZkSyncInterface}; +use zksync_eth_client::{BaseFees, EnrichedClientResult, EthFeeInterface, EthInterface}; use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U256, U64}; use zksync_web3_decl::client::{DynClient, L1, L2}; @@ -24,12 +24,6 @@ pub enum GasAdjusterClient { L2(Box>), } -struct GasAdjusterFee { - pub base_fee_per_gas: u64, - pub base_fee_per_blob_gas: U256, - pub l2_pubdata_price: U256, -} - impl GasAdjusterClient { pub fn from_l1(inner: Box>) -> Self { Self::L1(inner) @@ -79,31 +73,15 @@ impl GasAdjusterClient { &self, upto_block: usize, block_count: usize, - ) -> EnrichedClientResult> { + ) -> EnrichedClientResult> { match self { GasAdjusterClient::L1(inner) => { let base_fees = inner.base_fee_history(upto_block, block_count).await?; - Ok(base_fees - .into_iter() - .map(|fee| GasAdjusterFee { - base_fee_per_gas: fee.base_fee_per_gas, - base_fee_per_blob_gas: fee.base_fee_per_blob_gas, - // We formally provide it, but we wont use it. - l2_pubdata_price: U256::zero(), - }) - .collect()) + Ok(base_fees) } GasAdjusterClient::L2(inner) => { - let base_fees = inner.l2_fee_history(upto_block, block_count).await?; - Ok(base_fees - .into_iter() - .map(|fee| GasAdjusterFee { - base_fee_per_gas: fee.base_fee_per_gas, - // We formally provide it, but we wont use it. - base_fee_per_blob_gas: U256::zero(), - l2_pubdata_price: fee.pubdata_price, - }) - .collect()) + let base_fees = inner.base_fee_history(upto_block, block_count).await?; + Ok(base_fees) } } } @@ -179,7 +157,7 @@ impl GasAdjuster { let l2_pubdata_price_statistics = GasStatistics::new( config.num_samples_for_blob_base_fee_estimate, current_block, - fee_history.iter().map(|fee| fee.l2_pubdata_price), + fee_history.iter().map(|fee| fee.pubdata_price), ); Ok(Self { @@ -242,8 +220,7 @@ impl GasAdjuster { self.blob_base_fee_statistics .add_samples(fee_data.iter().map(|fee| fee.base_fee_per_blob_gas)); - if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.l2_pubdata_price) - { + if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.pubdata_price) { // L2 pubdata price overflows `u64` only in very extreme cases. // It isn't worth to observe exact value with metric because anyway values that can be used // are capped by `self.config.max_blob_base_fee()` of `u64` type. @@ -256,7 +233,7 @@ impl GasAdjuster { } } self.l2_pubdata_price_statistics - .add_samples(fee_data.iter().map(|fee| fee.l2_pubdata_price)); + .add_samples(fee_data.iter().map(|fee| fee.pubdata_price)); } Ok(()) } diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs index dfd55f947993..e39b699b4daa 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs @@ -2,7 +2,7 @@ use std::{collections::VecDeque, sync::RwLockReadGuard}; use test_casing::test_casing; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; -use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; +use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; use zksync_types::{commitment::L1BatchCommitmentMode, settlement::SettlementMode}; use zksync_web3_decl::client::L2; @@ -86,7 +86,7 @@ async fn kept_updated(commitment_mode: L1BatchCommitmentMode) { let base_fees = TEST_BLOCK_FEES .into_iter() .zip(TEST_BLOB_FEES) - .map(|(block, blob)| MockClientBaseFee { + .map(|(block, blob)| BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: blob.into(), pubdata_price: 0.into(), @@ -150,7 +150,7 @@ async fn kept_updated_l2(commitment_mode: L1BatchCommitmentMode) { let base_fees = TEST_BLOCK_FEES .into_iter() .zip(TEST_PUBDATA_PRICES) - .map(|(block, pubdata)| MockClientBaseFee { + .map(|(block, pubdata)| BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: 0.into(), pubdata_price: pubdata.into(), diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index f3eb8b1f2a77..abc1ee1c2767 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -289,7 +289,7 @@ mod tests { use l1_gas_price::GasAdjusterClient; use zksync_base_token_adjuster::NoOpRatioProvider; use zksync_config::{configs::eth_sender::PubdataSendingMode, GasAdjusterConfig}; - use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; + use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; use zksync_types::{commitment::L1BatchCommitmentMode, fee_model::BaseTokenConversionRatio}; use super::*; @@ -745,8 +745,8 @@ mod tests { } // Helper function to create BaseFees. - fn test_base_fees(block: u64, blob: U256, pubdata: U256) -> MockClientBaseFee { - MockClientBaseFee { + fn test_base_fees(block: u64, blob: U256, pubdata: U256) -> BaseFees { + BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: blob, pubdata_price: pubdata, diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 8bcbc82c5cee..6b18df3fcce6 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -9,7 +9,7 @@ use zksync_config::{ }; use zksync_contracts::BaseSystemContracts; use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_eth_client::clients::{MockClientBaseFee, MockSettlementLayer}; +use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; use zksync_multivm::vm_latest::constants::BATCH_COMPUTATIONAL_GAS_LIMIT; use zksync_node_fee_model::{ l1_gas_price::{GasAdjuster, GasAdjusterClient}, @@ -54,7 +54,7 @@ impl Tester { let block_fees = vec![0, 4, 6, 8, 7, 5, 5, 8, 10, 9]; let base_fees = block_fees .into_iter() - .map(|base_fee_per_gas| MockClientBaseFee { + .map(|base_fee_per_gas| BaseFees { base_fee_per_gas, base_fee_per_blob_gas: 1.into(), // Not relevant for the test pubdata_price: 0.into(), // Not relevant for the test From 1fac151f95a3dd558f22dd6ff77643da1338e189 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 12:46:00 +0200 Subject: [PATCH 26/43] some final fixes --- core/lib/eth_client/src/clients/http/query.rs | 97 ++++--------------- core/lib/eth_client/src/clients/mock.rs | 6 +- core/lib/eth_client/src/lib.rs | 2 +- core/lib/types/src/api/mod.rs | 2 +- .../api_server/src/web3/namespaces/eth.rs | 2 +- core/node/eth_sender/src/tester.rs | 6 +- .../src/l1_gas_price/gas_adjuster/mod.rs | 7 +- .../src/l1_gas_price/gas_adjuster/tests.rs | 4 +- core/node/fee_model/src/lib.rs | 2 +- core/node/state_keeper/src/io/tests/tester.rs | 2 +- 10 files changed, 34 insertions(+), 96 deletions(-) diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index f959c266a7f4..b72ff6bbbca8 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -350,7 +350,7 @@ macro_rules! impl_l1_eth_fee_interface { let fees = BaseFees { base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, base_fee_per_blob_gas: blob, - pubdata_price: 0.into() + l2_pubdata_price: 0.into() }; history.push(fees) } @@ -366,71 +366,8 @@ macro_rules! impl_l1_eth_fee_interface { impl_l1_eth_fee_interface!(Box::>); impl_l1_eth_fee_interface!(MockClient::); -// #[async_trait::async_trait] -// impl EthFeeInterface for T { -// async fn base_fee_history( -// &self, -// upto_block: usize, -// block_count: usize, -// ) -> EnrichedClientResult> { -// COUNTERS.call[&(Method::BaseFeeHistory, self.component())].inc(); -// let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); -// let mut history = Vec::with_capacity(block_count); -// let from_block = upto_block.saturating_sub(block_count); - -// // Here we are requesting `fee_history` from blocks -// // `(from_block; upto_block)` in chunks of size `MAX_REQUEST_CHUNK` -// // starting from the oldest block. -// for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { -// let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); -// let chunk_size = chunk_end - chunk_start; - -// let fee_history = self -// .fee_history( -// U64::from(chunk_size), -// web3::BlockNumber::from(chunk_end), -// None, -// ) -// .rpc_context("fee_history") -// .with_arg("chunk_size", &chunk_size) -// .with_arg("block", &chunk_end) -// .await?; - -// // Check that the lengths are the same. -// // Per specification, the values should always be provided, and must be 0 for blocks -// // prior to EIP-4844. -// // https://ethereum.github.io/execution-apis/api-documentation/ -// if fee_history.base_fee_per_gas.len() != fee_history.base_fee_per_blob_gas.len() { -// tracing::error!( -// "base_fee_per_gas and base_fee_per_blob_gas have different lengths: {} and {}", -// fee_history.base_fee_per_gas.len(), -// fee_history.base_fee_per_blob_gas.len() -// ); -// } - -// for (base, blob) in fee_history -// .base_fee_per_gas -// .into_iter() -// .zip(fee_history.base_fee_per_blob_gas) -// { -// let fees = BaseFees { -// base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, -// base_fee_per_blob_gas: blob, -// }; -// history.push(fees) -// } -// } - -// latency.observe(); -// Ok(history) -// } -// } - -pub trait L2Client: EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} -impl L2Client for Box> {} - #[async_trait::async_trait] -impl EthFeeInterface for T { +impl EthFeeInterface for Box> { async fn base_fee_history( &self, upto_block: usize, @@ -448,36 +385,36 @@ impl EthFeeInterface for T { let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); let chunk_size = chunk_end - chunk_start; - let fee_history = self - .fee_history( - U64::from(chunk_size), - zksync_types::api::BlockNumber::from(chunk_end), - vec![], - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; + let fee_history = EthNamespaceClient::fee_history( + self, + U64::from(chunk_size), + zksync_types::api::BlockNumber::from(chunk_end), + vec![], + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; // Check that the lengths are the same. - if fee_history.inner.base_fee_per_gas.len() != fee_history.pubdata_price.len() { + if fee_history.inner.base_fee_per_gas.len() != fee_history.l2_pubdata_price.len() { tracing::error!( "base_fee_per_gas and pubdata_price have different lengths: {} and {}", fee_history.inner.base_fee_per_gas.len(), - fee_history.pubdata_price.len() + fee_history.l2_pubdata_price.len() ); } - for (base, pubdata_price) in fee_history + for (base, l2_pubdata_price) in fee_history .inner .base_fee_per_gas .into_iter() - .zip(fee_history.pubdata_price) + .zip(fee_history.l2_pubdata_price) { let fees = BaseFees { base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, base_fee_per_blob_gas: 0.into(), - pubdata_price, + l2_pubdata_price, }; history.push(fees) } diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 5cf0ae906fb9..52d036ccd113 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -473,9 +473,9 @@ impl SupportedMockEthNetwork for L2 { blob_gas_used_ratio: vec![], // not used reward: None, }, - pubdata_price: base_fee_history[start_block..=from_block] + l2_pubdata_price: base_fee_history[start_block..=from_block] .iter() - .map(|fee| fee.pubdata_price) + .map(|fee| fee.l2_pubdata_price) .collect(), }) }, @@ -659,7 +659,7 @@ mod tests { BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: U256::from(blob), - pubdata_price: U256::from(pubdata_price), + l2_pubdata_price: U256::from(pubdata_price), } } diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 93488b2708fa..e85dc41a13ec 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -72,7 +72,7 @@ pub struct BaseFees { // Base fee per blob gas. It is zero on networks that do not support blob transactions (e.g. L2s). pub base_fee_per_blob_gas: U256, // The price (in wei) for relaying the pubdata to L1. It is non-zero only for L2 settlement layers. - pub pubdata_price: U256, + pub l2_pubdata_price: U256, } /// Common Web3 interface, as seen by the core applications. diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index 714ecd91c91f..5739ccd5309f 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -842,7 +842,7 @@ pub struct FeeHistory { pub inner: zksync_basic_types::web3::FeeHistory, /// An array of effective pubdata price. Note, that this field is L2-specific and only provided by L2 nodes. #[serde(default)] - pub pubdata_price: Vec, + pub l2_pubdata_price: Vec, } #[cfg(test)] diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index 76dc2c91cd69..c3bed64a1468 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -712,7 +712,7 @@ impl EthNamespace { base_fee_per_blob_gas, blob_gas_used_ratio, }, - pubdata_price: effective_pubdata_price_history, + l2_pubdata_price: effective_pubdata_price_history, }) } diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index b98d96dc1267..5bd5181ed8c7 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -152,7 +152,7 @@ impl EthSenderTester { .map(|base_fee_per_gas| BaseFees { base_fee_per_gas, base_fee_per_blob_gas: 0.into(), - pubdata_price: 0.into(), + l2_pubdata_price: 0.into(), }) .collect(); @@ -161,7 +161,7 @@ impl EthSenderTester { std::iter::repeat_with(|| BaseFees { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), - pubdata_price: 0.into(), + l2_pubdata_price: 0.into(), }) .take(Self::WAIT_CONFIRMATIONS as usize) .chain(history.clone()) @@ -181,7 +181,7 @@ impl EthSenderTester { std::iter::repeat_with(|| BaseFees { base_fee_per_gas: 0, base_fee_per_blob_gas: 0.into(), - pubdata_price: 0.into(), + l2_pubdata_price: 0.into(), }) .take(Self::WAIT_CONFIRMATIONS as usize) .chain(history) diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 1e353acca089..cf8aa81439db 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -157,7 +157,7 @@ impl GasAdjuster { let l2_pubdata_price_statistics = GasStatistics::new( config.num_samples_for_blob_base_fee_estimate, current_block, - fee_history.iter().map(|fee| fee.pubdata_price), + fee_history.iter().map(|fee| fee.l2_pubdata_price), ); Ok(Self { @@ -220,7 +220,8 @@ impl GasAdjuster { self.blob_base_fee_statistics .add_samples(fee_data.iter().map(|fee| fee.base_fee_per_blob_gas)); - if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.pubdata_price) { + if let Some(current_l2_pubdata_price) = fee_data.last().map(|fee| fee.l2_pubdata_price) + { // L2 pubdata price overflows `u64` only in very extreme cases. // It isn't worth to observe exact value with metric because anyway values that can be used // are capped by `self.config.max_blob_base_fee()` of `u64` type. @@ -233,7 +234,7 @@ impl GasAdjuster { } } self.l2_pubdata_price_statistics - .add_samples(fee_data.iter().map(|fee| fee.pubdata_price)); + .add_samples(fee_data.iter().map(|fee| fee.l2_pubdata_price)); } Ok(()) } diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs index e39b699b4daa..2643e4b3c424 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/tests.rs @@ -89,7 +89,7 @@ async fn kept_updated(commitment_mode: L1BatchCommitmentMode) { .map(|(block, blob)| BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: blob.into(), - pubdata_price: 0.into(), + l2_pubdata_price: 0.into(), }) .collect(); @@ -153,7 +153,7 @@ async fn kept_updated_l2(commitment_mode: L1BatchCommitmentMode) { .map(|(block, pubdata)| BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: 0.into(), - pubdata_price: pubdata.into(), + l2_pubdata_price: pubdata.into(), }) .collect(); diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index abc1ee1c2767..f65239912523 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -749,7 +749,7 @@ mod tests { BaseFees { base_fee_per_gas: block, base_fee_per_blob_gas: blob, - pubdata_price: pubdata, + l2_pubdata_price: pubdata, } } diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 6b18df3fcce6..dc5e5f345d5a 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -57,7 +57,7 @@ impl Tester { .map(|base_fee_per_gas| BaseFees { base_fee_per_gas, base_fee_per_blob_gas: 1.into(), // Not relevant for the test - pubdata_price: 0.into(), // Not relevant for the test + l2_pubdata_price: 0.into(), // Not relevant for the test }) .collect(); let eth_client = MockSettlementLayer::builder() From 789f271cde536bd577e495a2f2804116b2f16463 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 12:56:14 +0200 Subject: [PATCH 27/43] some more fixing --- core/bin/block_reverter/src/main.rs | 2 +- core/lib/eth_client/src/clients/http/decl.rs | 2 +- core/lib/eth_client/src/clients/http/query.rs | 123 +++++++++--------- .../eth_client/src/clients/http/signing.rs | 2 +- core/lib/eth_client/src/clients/mock.rs | 88 ++++++------- core/lib/eth_client/src/lib.rs | 1 - core/lib/eth_client/src/types.rs | 5 +- core/lib/web3_decl/src/client/mock.rs | 2 +- core/node/block_reverter/src/lib.rs | 3 +- .../node/consistency_checker/src/tests/mod.rs | 2 +- .../eth_sender/src/abstract_l1_interface.rs | 1 - core/node/eth_sender/src/eth_tx_aggregator.rs | 4 +- core/node/eth_sender/src/eth_tx_manager.rs | 4 +- .../src/implementations/layers/l1_gas.rs | 5 +- .../layers/query_eth_client.rs | 3 +- .../resources/eth_interface.rs | 2 +- core/node/node_framework/src/service/mod.rs | 2 +- 17 files changed, 119 insertions(+), 132 deletions(-) diff --git a/core/bin/block_reverter/src/main.rs b/core/bin/block_reverter/src/main.rs index 93833f8e699e..4342a70048c0 100644 --- a/core/bin/block_reverter/src/main.rs +++ b/core/bin/block_reverter/src/main.rs @@ -5,7 +5,7 @@ use clap::{Parser, Subcommand}; use tokio::io::{self, AsyncReadExt}; use zksync_block_reverter::{ eth_client::{ - clients::{Client, DynClient, PKSigningClient, L1}, + clients::{Client, PKSigningClient, L1}, EthInterface, }, BlockReverter, BlockReverterEthConfig, NodeRole, diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs index c5ce3acd2eb0..38f532bf7bba 100644 --- a/core/lib/eth_client/src/clients/http/decl.rs +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -1,6 +1,6 @@ use jsonrpsee::proc_macros::rpc; use zksync_types::{web3, Address, H256, U256, U64}; -use zksync_web3_decl::client::{ForEthereumLikeNetwork, L2}; +use zksync_web3_decl::client::ForEthereumLikeNetwork; /// Subset of the L1 `eth` namespace used by the L1 client. #[rpc(client, namespace = "eth", client_bounds(Self: ForEthereumLikeNetwork))] diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index b72ff6bbbca8..1d864ed75254 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use jsonrpsee::core::ClientError; use zksync_types::{web3, Address, SLChainId, H256, U256, U64}; use zksync_web3_decl::{ - client::{Client, DynClient, EthereumLikeNetwork, ForEthereumLikeNetwork, MockClient, L1, L2}, + client::{DynClient, ForEthereumLikeNetwork, MockClient, L1, L2}, error::{ClientRpcContext, EnrichedClientError, EnrichedClientResult}, namespaces::EthNamespaceClient, }; @@ -293,11 +293,6 @@ where } } -// pub trait L1Client: L1EthNamespaceClient + EthInterface + ForEthereumLikeNetwork {} - -// impl L1Client for Box> {} -// impl L1Client for MockClient {} - macro_rules! impl_l1_eth_fee_interface { ($type:ty) => { #[async_trait::async_trait] @@ -366,65 +361,75 @@ macro_rules! impl_l1_eth_fee_interface { impl_l1_eth_fee_interface!(Box::>); impl_l1_eth_fee_interface!(MockClient::); -#[async_trait::async_trait] -impl EthFeeInterface for Box> { - async fn base_fee_history( - &self, - upto_block: usize, - block_count: usize, - ) -> EnrichedClientResult> { - COUNTERS.call[&(Method::L2FeeHistory, self.component())].inc(); - let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); - let mut history = Vec::with_capacity(block_count); - let from_block = upto_block.saturating_sub(block_count); - - // Here we are requesting `fee_history` from blocks - // `(from_block; upto_block)` in chunks of size `FEE_HISTORY_MAX_REQUEST_CHUNK` - // starting from the oldest block. - for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) { - let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); - let chunk_size = chunk_end - chunk_start; - - let fee_history = EthNamespaceClient::fee_history( - self, - U64::from(chunk_size), - zksync_types::api::BlockNumber::from(chunk_end), - vec![], - ) - .rpc_context("fee_history") - .with_arg("chunk_size", &chunk_size) - .with_arg("block", &chunk_end) - .await?; +macro_rules! impl_l2_eth_fee_interface { + ($type:ty) => { + #[async_trait::async_trait] + impl EthFeeInterface for $type { + async fn base_fee_history( + &self, + upto_block: usize, + block_count: usize, + ) -> EnrichedClientResult> { + COUNTERS.call[&(Method::L2FeeHistory, self.component())].inc(); + let latency = LATENCIES.direct[&Method::BaseFeeHistory].start(); + let mut history = Vec::with_capacity(block_count); + let from_block = upto_block.saturating_sub(block_count); - // Check that the lengths are the same. - if fee_history.inner.base_fee_per_gas.len() != fee_history.l2_pubdata_price.len() { - tracing::error!( - "base_fee_per_gas and pubdata_price have different lengths: {} and {}", - fee_history.inner.base_fee_per_gas.len(), - fee_history.l2_pubdata_price.len() - ); - } + // Here we are requesting `fee_history` from blocks + // `(from_block; upto_block)` in chunks of size `FEE_HISTORY_MAX_REQUEST_CHUNK` + // starting from the oldest block. + for chunk_start in (from_block..=upto_block).step_by(FEE_HISTORY_MAX_REQUEST_CHUNK) + { + let chunk_end = (chunk_start + FEE_HISTORY_MAX_REQUEST_CHUNK).min(upto_block); + let chunk_size = chunk_end - chunk_start; - for (base, l2_pubdata_price) in fee_history - .inner - .base_fee_per_gas - .into_iter() - .zip(fee_history.l2_pubdata_price) - { - let fees = BaseFees { - base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, - base_fee_per_blob_gas: 0.into(), - l2_pubdata_price, - }; - history.push(fees) + let fee_history = EthNamespaceClient::fee_history( + self, + U64::from(chunk_size), + zksync_types::api::BlockNumber::from(chunk_end), + vec![], + ) + .rpc_context("fee_history") + .with_arg("chunk_size", &chunk_size) + .with_arg("block", &chunk_end) + .await?; + + // Check that the lengths are the same. + if fee_history.inner.base_fee_per_gas.len() + != fee_history.l2_pubdata_price.len() + { + tracing::error!( + "base_fee_per_gas and pubdata_price have different lengths: {} and {}", + fee_history.inner.base_fee_per_gas.len(), + fee_history.l2_pubdata_price.len() + ); + } + + for (base, l2_pubdata_price) in fee_history + .inner + .base_fee_per_gas + .into_iter() + .zip(fee_history.l2_pubdata_price) + { + let fees = BaseFees { + base_fee_per_gas: cast_to_u64(base, "base_fee_per_gas")?, + base_fee_per_blob_gas: 0.into(), + l2_pubdata_price, + }; + history.push(fees) + } + } + + latency.observe(); + Ok(history) } } - - latency.observe(); - Ok(history) - } + }; } +impl_l2_eth_fee_interface!(Box::>); +impl_l2_eth_fee_interface!(MockClient::); + /// Non-panicking conversion to u64. fn cast_to_u64(value: U256, tag: &str) -> EnrichedClientResult { u64::try_from(value).map_err(|_| { diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index eae3f645894d..e602f98a35e9 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -76,7 +76,7 @@ impl fmt::Debug for SigningClient { impl AsRef for SigningClient { fn as_ref(&self) -> &(dyn EthInterface + 'static) { - &self.query_client as &dyn EthInterface + &self.query_client } } diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 52d036ccd113..b40d7837e27f 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -13,7 +13,7 @@ use zksync_types::{ Address, L1ChainId, L2ChainId, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; use zksync_web3_decl::client::{ - DynClient, EthereumLikeNetwork, MockClient, MockClientBuilder, Network, L1, L2, + EthereumLikeNetwork, MockClient, MockClientBuilder, Network, L1, L2, }; use crate::{ @@ -596,7 +596,7 @@ impl MockSettlementLayer { impl AsRef for MockSettlementLayer { fn as_ref(&self) -> &(dyn EthInterface + 'static) { - &self.client as &dyn EthInterface + &self.client } } @@ -721,7 +721,6 @@ mod tests { initial_fee_history[1..=4] .iter() .cloned() - .map(BaseFees::from) .collect::>() ); let fee_history = client.client.base_fee_history(2, 2).await.unwrap(); @@ -730,7 +729,6 @@ mod tests { initial_fee_history[1..=2] .iter() .cloned() - .map(BaseFees::from) .collect::>() ); let fee_history = client.client.base_fee_history(3, 2).await.unwrap(); @@ -739,53 +737,49 @@ mod tests { initial_fee_history[2..=3] .iter() .cloned() - .map(BaseFees::from) .collect::>() ); } - // #[tokio::test] - // async fn managing_fee_history_l2() { - // let initial_fee_history = vec![ - // base_fees(1, 4, 11), - // base_fees(2, 3, 12), - // base_fees(3, 2, 13), - // base_fees(4, 1, 14), - // base_fees(5, 0, 15), - // ]; - // let client = MockSettlementLayer::::builder() - // .with_fee_history(initial_fee_history.clone()) - // .build(); - // client.advance_block_number(4); - - // let fee_history = client.as_ref().l2_fee_history(4, 4).await.unwrap(); - // assert_eq!( - // fee_history, - // initial_fee_history[1..=4] - // .iter() - // .cloned() - // .map(L2Fees::from) - // .collect::>() - // ); - // let fee_history = client.as_ref().l2_fee_history(2, 2).await.unwrap(); - // assert_eq!( - // fee_history, - // initial_fee_history[1..=2] - // .iter() - // .cloned() - // .map(L2Fees::from) - // .collect::>() - // ); - // let fee_history = client.as_ref().l2_fee_history(3, 2).await.unwrap(); - // assert_eq!( - // fee_history, - // initial_fee_history[2..=3] - // .iter() - // .cloned() - // .map(L2Fees::from) - // .collect::>() - // ); - // } + #[tokio::test] + async fn managing_fee_history_l2() { + let initial_fee_history = vec![ + base_fees(1, 0, 11), + base_fees(2, 0, 12), + base_fees(3, 0, 13), + base_fees(4, 0, 14), + base_fees(5, 0, 15), + ]; + let client = MockSettlementLayer::::builder() + .with_fee_history(initial_fee_history.clone()) + .build(); + client.advance_block_number(4); + + let fee_history = client.client.base_fee_history(4, 4).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[1..=4] + .iter() + .cloned() + .collect::>() + ); + let fee_history = client.client.base_fee_history(2, 2).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[1..=2] + .iter() + .cloned() + .collect::>() + ); + let fee_history = client.client.base_fee_history(3, 2).await.unwrap(); + assert_eq!( + fee_history, + initial_fee_history[2..=3] + .iter() + .cloned() + .collect::>() + ); + } #[tokio::test] async fn managing_transactions() { diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index e85dc41a13ec..0c899383072f 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -10,7 +10,6 @@ use zksync_types::{ }, Address, SLChainId, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{DynClient, Network, L1}; pub use zksync_web3_decl::{ error::{EnrichedClientError, EnrichedClientResult}, jsonrpsee::core::ClientError, diff --git a/core/lib/eth_client/src/types.rs b/core/lib/eth_client/src/types.rs index b5477cae159c..59fb1cdeddcc 100644 --- a/core/lib/eth_client/src/types.rs +++ b/core/lib/eth_client/src/types.rs @@ -8,10 +8,7 @@ use zksync_types::{ }, Address, EIP_4844_TX_TYPE, H256, U256, }; -use zksync_web3_decl::{ - client::{DynClient, L1}, - error::EnrichedClientError, -}; +use zksync_web3_decl::error::EnrichedClientError; use crate::EthInterface; diff --git a/core/lib/web3_decl/src/client/mock.rs b/core/lib/web3_decl/src/client/mock.rs index 2f49e0d88af2..6d44ebee5756 100644 --- a/core/lib/web3_decl/src/client/mock.rs +++ b/core/lib/web3_decl/src/client/mock.rs @@ -14,7 +14,7 @@ use jsonrpsee::{ }; use serde::{de::DeserializeOwned, Serialize}; -use super::{boxed::RawParams, EthereumLikeNetwork, ForEthereumLikeNetwork, Network, TaggedClient}; +use super::{boxed::RawParams, ForEthereumLikeNetwork, Network, TaggedClient}; /// Object-safe counterpart to [`Handler`]. We need it because async closures aren't available on stable Rust. #[async_trait] diff --git a/core/node/block_reverter/src/lib.rs b/core/node/block_reverter/src/lib.rs index d622e541e26d..5a9484853826 100644 --- a/core/node/block_reverter/src/lib.rs +++ b/core/node/block_reverter/src/lib.rs @@ -9,7 +9,6 @@ use zksync_dal::{ConnectionPool, Core, CoreDal}; // Public re-export to simplify the API use. pub use zksync_eth_client as eth_client; use zksync_eth_client::{ - clients::{DynClient, L1}, BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface, Options, }; use zksync_merkle_tree::domain::ZkSyncTree; @@ -542,7 +541,7 @@ impl BlockReverter { }; let block_number: U256 = CallFunctionArgs::new(function_name, ()) .for_contract(contract_address, &hyperchain_contract()) - .call(eth_client as &dyn EthInterface) + .call(eth_client) .await .with_context(|| { format!("failed calling `{function_name}` for contract {contract_address:?}") diff --git a/core/node/consistency_checker/src/tests/mod.rs b/core/node/consistency_checker/src/tests/mod.rs index 8664bde74ca8..40c447071cf4 100644 --- a/core/node/consistency_checker/src/tests/mod.rs +++ b/core/node/consistency_checker/src/tests/mod.rs @@ -7,7 +7,7 @@ use test_casing::{test_casing, Product}; use tokio::sync::mpsc; use zksync_config::GenesisConfig; use zksync_dal::Connection; -use zksync_eth_client::{clients::MockSettlementLayer, BoundEthInterface, Options}; +use zksync_eth_client::{clients::MockSettlementLayer, Options}; use zksync_l1_contract_interface::{i_executor::methods::CommitBatches, Tokenizable, Tokenize}; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{ diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index 9f17386478d2..2ab9642d66c2 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -3,7 +3,6 @@ use std::fmt; use async_trait::async_trait; use vise::{EncodeLabelSet, EncodeLabelValue}; use zksync_eth_client::{ - clients::{DynClient, L1}, BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, L1EthBoundInterface, Options, RawTransactionBytes, SignedCallResult, }; diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index d30a77067f6d..ffe93fdb4c2d 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -2,9 +2,7 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{ - clients::L1, BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface, -}; +use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface}; use zksync_l1_contract_interface::{ i_executor::{ commit::kzg::{KzgInfo, ZK_SYNC_BYTES_PER_BLOB}, diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 78180baa01ea..b1d0a5b31f89 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -4,8 +4,8 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ - clients::L1, encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, - L1EthBoundInterface, RawTransactionBytes, + encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, L1EthBoundInterface, + RawTransactionBytes, }; use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; diff --git a/core/node/node_framework/src/implementations/layers/l1_gas.rs b/core/node/node_framework/src/implementations/layers/l1_gas.rs index 8575ac08bec3..3293d1750125 100644 --- a/core/node/node_framework/src/implementations/layers/l1_gas.rs +++ b/core/node/node_framework/src/implementations/layers/l1_gas.rs @@ -5,10 +5,7 @@ use zksync_config::{ configs::{chain::StateKeeperConfig, eth_sender::PubdataSendingMode}, GasAdjusterConfig, GenesisConfig, }; -use zksync_node_fee_model::{ - l1_gas_price::{GasAdjuster, GasAdjusterClient}, - MainNodeFeeInputProvider, -}; +use zksync_node_fee_model::{l1_gas_price::GasAdjuster, MainNodeFeeInputProvider}; use zksync_types::fee_model::FeeModelConfig; use crate::{ 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 fc06aed32fe1..116823d92d8a 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,10 +1,9 @@ use anyhow::Context; use zksync_types::{settlement::SettlementMode, url::SensitiveUrl, L2ChainId, SLChainId}; -use zksync_web3_decl::client::{Client, L1, L2}; +use zksync_web3_decl::client::Client; use crate::{ implementations::resources::eth_interface::{EthInterfaceResource, L2InterfaceResource}, - service::ServiceContext, wiring_layer::{WiringError, WiringLayer}, IntoContext, }; diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index 72a782ca278c..495d39ae257e 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -1,4 +1,4 @@ -use zksync_eth_client::{BoundEthInterface, L1EthBoundInterface}; +use zksync_eth_client::L1EthBoundInterface; use zksync_web3_decl::client::{DynClient, L1, L2}; use crate::resource::Resource; diff --git a/core/node/node_framework/src/service/mod.rs b/core/node/node_framework/src/service/mod.rs index b6bbaa2e4d28..f7b360893b49 100644 --- a/core/node/node_framework/src/service/mod.rs +++ b/core/node/node_framework/src/service/mod.rs @@ -153,7 +153,7 @@ impl ZkStackService { tracing::info!("Exiting the service"); - if let Some(mut observability_guard) = observability_guard.into() { + if let Some(observability_guard) = observability_guard.into() { // Make sure that the shutdown happens in the `tokio` context. let _guard = self.runtime.enter(); observability_guard.shutdown(); From 1a9b42eef271057f312fc6c007a4f8a0db9a028a Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 13:32:11 +0200 Subject: [PATCH 28/43] remove more unneeded things --- core/lib/eth_client/src/clients/mock.rs | 8 +++----- core/lib/eth_client/src/lib.rs | 2 -- core/lib/web3_decl/src/client/mod.rs | 2 +- core/lib/web3_decl/src/client/network.rs | 5 ----- core/node/block_reverter/src/lib.rs | 6 ++---- .../node/eth_sender/src/abstract_l1_interface.rs | 16 ++++++++-------- core/node/eth_sender/src/eth_tx_aggregator.rs | 6 +++--- core/node/eth_sender/src/eth_tx_manager.rs | 7 +++---- .../implementations/resources/eth_interface.rs | 6 +++--- core/node/node_framework/src/service/mod.rs | 2 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 4 ++-- 11 files changed, 26 insertions(+), 38 deletions(-) diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index b40d7837e27f..450446832a27 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -12,9 +12,7 @@ use zksync_types::{ web3::{self, contract::Tokenize, BlockId}, Address, L1ChainId, L2ChainId, SLChainId, EIP_4844_TX_TYPE, H160, H256, U256, U64, }; -use zksync_web3_decl::client::{ - EthereumLikeNetwork, MockClient, MockClientBuilder, Network, L1, L2, -}; +use zksync_web3_decl::client::{MockClient, MockClientBuilder, Network, L1, L2}; use crate::{ types::{ContractCallError, SignedCallResult, SigningError}, @@ -594,14 +592,14 @@ impl MockSettlementLayer { } } -impl AsRef for MockSettlementLayer { +impl AsRef for MockSettlementLayer { fn as_ref(&self) -> &(dyn EthInterface + 'static) { &self.client } } #[async_trait::async_trait] -impl BoundEthInterface +impl BoundEthInterface for MockSettlementLayer { fn clone_boxed(&self) -> Box { diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 0c899383072f..d1a326949c6d 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -214,8 +214,6 @@ pub trait BoundEthInterface: 'static + Sync + Send + fmt::Debug + AsRef Result; } -pub type L1EthBoundInterface = dyn BoundEthInterface; - impl Clone for Box { fn clone(&self) -> Self { self.clone_boxed() diff --git a/core/lib/web3_decl/src/client/mod.rs b/core/lib/web3_decl/src/client/mod.rs index b3b8deeb0aa4..5527e6fc86bf 100644 --- a/core/lib/web3_decl/src/client/mod.rs +++ b/core/lib/web3_decl/src/client/mod.rs @@ -38,7 +38,7 @@ use self::metrics::{L2ClientMetrics, METRICS}; pub use self::{ boxed::{DynClient, ObjectSafeClient}, mock::{MockClient, MockClientBuilder}, - network::{EthereumLikeNetwork, ForEthereumLikeNetwork, Network, TaggedClient, L1, L2}, + network::{ForEthereumLikeNetwork, Network, TaggedClient, L1, L2}, shared::Shared, }; diff --git a/core/lib/web3_decl/src/client/network.rs b/core/lib/web3_decl/src/client/network.rs index 2cabbaafbd0b..63e5f9e88d16 100644 --- a/core/lib/web3_decl/src/client/network.rs +++ b/core/lib/web3_decl/src/client/network.rs @@ -39,11 +39,6 @@ impl From for L1 { } } -pub trait EthereumLikeNetwork: Network {} - -impl EthereumLikeNetwork for L1 {} -impl EthereumLikeNetwork for L2 {} - /// L2 network. #[derive(Debug, Clone, Copy, Default)] pub struct L2(Option); diff --git a/core/node/block_reverter/src/lib.rs b/core/node/block_reverter/src/lib.rs index 5a9484853826..bf147f13eeb9 100644 --- a/core/node/block_reverter/src/lib.rs +++ b/core/node/block_reverter/src/lib.rs @@ -8,9 +8,7 @@ use zksync_contracts::hyperchain_contract; use zksync_dal::{ConnectionPool, Core, CoreDal}; // Public re-export to simplify the API use. pub use zksync_eth_client as eth_client; -use zksync_eth_client::{ - BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface, Options, -}; +use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface, Options}; use zksync_merkle_tree::domain::ZkSyncTree; use zksync_object_store::{ObjectStore, ObjectStoreError}; use zksync_state::RocksdbStorage; @@ -468,7 +466,7 @@ impl BlockReverter { /// Sends a revert transaction to L1. pub async fn send_ethereum_revert_transaction( &self, - eth_client: &L1EthBoundInterface, + eth_client: &dyn BoundEthInterface, eth_config: &BlockReverterEthConfig, last_l1_batch_to_keep: L1BatchNumber, nonce: u64, diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index 2ab9642d66c2..1f1956c9dd84 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -3,8 +3,8 @@ use std::fmt; use async_trait::async_trait; use vise::{EncodeLabelSet, EncodeLabelValue}; use zksync_eth_client::{ - BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, - L1EthBoundInterface, Options, RawTransactionBytes, SignedCallResult, + BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, Options, + RawTransactionBytes, SignedCallResult, }; #[cfg(test)] use zksync_types::web3; @@ -77,15 +77,15 @@ pub(super) trait AbstractL1Interface: 'static + Sync + Send + fmt::Debug { async fn get_l1_block_numbers(&self) -> Result; - fn ethereum_gateway(&self) -> &L1EthBoundInterface; + fn ethereum_gateway(&self) -> &dyn BoundEthInterface; - fn ethereum_gateway_blobs(&self) -> Option<&L1EthBoundInterface>; + fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface>; } #[derive(Debug)] pub(super) struct RealL1Interface { - pub ethereum_gateway: Box, - pub ethereum_gateway_blobs: Option>, + pub ethereum_gateway: Box, + pub ethereum_gateway_blobs: Option>, pub wait_confirmations: Option, } @@ -263,11 +263,11 @@ impl AbstractL1Interface for RealL1Interface { }) } - fn ethereum_gateway(&self) -> &L1EthBoundInterface { + fn ethereum_gateway(&self) -> &dyn BoundEthInterface { self.ethereum_gateway.as_ref() } - fn ethereum_gateway_blobs(&self) -> Option<&L1EthBoundInterface> { + fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface> { self.ethereum_gateway_blobs.as_deref() } } diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index ffe93fdb4c2d..89533432ef83 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -2,7 +2,7 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface, L1EthBoundInterface}; +use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface}; use zksync_l1_contract_interface::{ i_executor::{ commit::kzg::{KzgInfo, ZK_SYNC_BYTES_PER_BLOB}, @@ -47,7 +47,7 @@ pub struct MulticallData { #[derive(Debug)] pub struct EthTxAggregator { aggregator: Aggregator, - eth_client: Box, + eth_client: Box, config: SenderConfig, timelock_contract_address: Address, l1_multicall3_address: Address, @@ -75,7 +75,7 @@ impl EthTxAggregator { pool: ConnectionPool, config: SenderConfig, aggregator: Aggregator, - eth_client: Box, + eth_client: Box, timelock_contract_address: Address, l1_multicall3_address: Address, state_transition_chain_contract: Address, diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index b1d0a5b31f89..9f41bfde8b4d 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -4,8 +4,7 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ - encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, L1EthBoundInterface, - RawTransactionBytes, + encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, RawTransactionBytes, }; use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; @@ -39,8 +38,8 @@ impl EthTxManager { pool: ConnectionPool, config: SenderConfig, gas_adjuster: Arc, - ethereum_gateway: Box, - ethereum_gateway_blobs: Option>, + ethereum_gateway: Box, + ethereum_gateway_blobs: Option>, ) -> Self { let ethereum_gateway = ethereum_gateway.for_component("eth_tx_manager"); let ethereum_gateway_blobs = diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index 495d39ae257e..5879610b75ed 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -1,4 +1,4 @@ -use zksync_eth_client::L1EthBoundInterface; +use zksync_eth_client::BoundEthInterface; use zksync_web3_decl::client::{DynClient, L1, L2}; use crate::resource::Resource; @@ -29,7 +29,7 @@ impl Resource for L2InterfaceResource { /// A resource that provides L1 interface with signing capabilities to the service. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceResource(pub Box); +pub struct BoundEthInterfaceResource(pub Box); impl Resource for BoundEthInterfaceResource { fn name() -> String { @@ -39,7 +39,7 @@ impl Resource for BoundEthInterfaceResource { /// Same as `BoundEthInterfaceResource`, but for managing EIP-4844 blobs. #[derive(Debug, Clone)] -pub struct BoundEthInterfaceForBlobsResource(pub Box); +pub struct BoundEthInterfaceForBlobsResource(pub Box); impl Resource for BoundEthInterfaceForBlobsResource { fn name() -> String { diff --git a/core/node/node_framework/src/service/mod.rs b/core/node/node_framework/src/service/mod.rs index f7b360893b49..b4cb5857bbab 100644 --- a/core/node/node_framework/src/service/mod.rs +++ b/core/node/node_framework/src/service/mod.rs @@ -153,7 +153,7 @@ impl ZkStackService { tracing::info!("Exiting the service"); - if let Some(observability_guard) = observability_guard.into() { + if let Some(observability_guard) = &mut observability_guard.into() { // Make sure that the shutdown happens in the `tokio` context. let _guard = self.runtime.enter(); observability_guard.shutdown(); diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 5b23dc59f66b..4b7bb00a3080 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use serde_json::{Map, Value}; use zksync_eth_client::{ clients::SigningClient, BoundEthInterface, CallFunctionArgs, ContractCallError, EthInterface, - L1EthBoundInterface, Options, + Options, }; use zksync_eth_signer::EthereumSigner; use zksync_types::{ @@ -127,7 +127,7 @@ impl EthereumProvider { } /// Exposes Ethereum node `web3` API. - pub fn client(&self) -> &L1EthBoundInterface { + pub fn client(&self) -> &dyn BoundEthInterface { &self.eth_client } From 690a0aeb403032492da7abfeb1195395947bdf4d Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Mon, 5 Aug 2024 13:35:21 +0200 Subject: [PATCH 29/43] same contracts as main --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 63e360600715..8670004d6daa 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 63e3606007158701f47c2532dd585c7d13741271 +Subproject commit 8670004d6daa7e8c299087d62f1451a3dec4f899 From 09031d96ef52594360fca7b68ee7a2c2dfb7ab41 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 5 Aug 2024 16:38:06 +0200 Subject: [PATCH 30/43] first version Signed-off-by: tomg10 --- core/lib/config/src/configs/eth_sender.rs | 2 +- ...f9654c06dfef57863281601c947830ad448a.json} | 15 +- ...c67d2c7f06d507747f7b03350a7b7efed2b1.json} | 17 +- ...3ce80f9b2b27758651ccfc09df61a4ae8a363.json | 8 +- ...f65ff83204ebab2ea31847ae305a098823b0.json} | 15 +- ...5ac6758a0a4e367f93a9bd48ec82c51e09755.json | 108 +++++++++ ..._add_is_gateway_column_to_eth_txs.down.sql | 1 + ...14_add_is_gateway_column_to_eth_txs.up.sql | 1 + core/lib/dal/src/blocks_dal.rs | 11 +- core/lib/dal/src/blocks_web3_dal.rs | 1 + core/lib/dal/src/eth_sender_dal.rs | 35 ++- core/lib/dal/src/models/storage_eth_tx.rs | 2 + core/lib/eth_client/src/clients/mock.rs | 2 +- core/lib/eth_client/src/clients/mod.rs | 2 +- core/lib/types/src/eth_sender.rs | 1 + .../eth_sender/src/abstract_l1_interface.rs | 206 ++++++++++-------- core/node/eth_sender/src/eth_fees_oracle.rs | 27 ++- core/node/eth_sender/src/eth_tx_aggregator.rs | 4 +- core/node/eth_sender/src/eth_tx_manager.rs | 102 ++++++--- core/node/eth_sender/src/tester.rs | 126 ++++++++--- core/node/eth_sender/src/tests.rs | 76 ++++++- .../src/l1_gas_price/gas_adjuster/mod.rs | 27 +-- core/node/fee_model/src/l1_gas_price/mod.rs | 11 +- .../layers/eth_sender/manager.rs | 7 +- 24 files changed, 596 insertions(+), 211 deletions(-) rename core/lib/dal/.sqlx/{query-2a2680234c38904e5c19df45193a8c13d04079683e09c65f7f4e76a9987e2ab4.json => query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json} (81%) rename core/lib/dal/.sqlx/{query-4570e9ffd0b2973d0bc2986c391d0a59076dda4aa572ade2492f37e537fdf6ed.json => query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json} (70%) rename core/lib/dal/.sqlx/{query-6bb5eab89be2b08a08c00b5cd8d725208b0ecfe8065c8f893ff38c49072a21fc.json => query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json} (70%) create mode 100644 core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json create mode 100644 core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.down.sql create mode 100644 core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.up.sql diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index e932cd9819b9..89f8d459a1d9 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -24,7 +24,7 @@ impl EthConfig { Self { sender: Some(SenderConfig { aggregated_proof_sizes: vec![1], - wait_confirmations: Some(1), + wait_confirmations: Some(10), tx_poll_period: 1, aggregate_tx_poll_period: 1, max_txs_in_flight: 30, diff --git a/core/lib/dal/.sqlx/query-2a2680234c38904e5c19df45193a8c13d04079683e09c65f7f4e76a9987e2ab4.json b/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json similarity index 81% rename from core/lib/dal/.sqlx/query-2a2680234c38904e5c19df45193a8c13d04079683e09c65f7f4e76a9987e2ab4.json rename to core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json index 8b984f4939a8..cdf425de713b 100644 --- a/core/lib/dal/.sqlx/query-2a2680234c38904e5c19df45193a8c13d04079683e09c65f7f4e76a9987e2ab4.json +++ b/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n eth_txs (\n raw_tx,\n nonce,\n tx_type,\n contract_address,\n predicted_gas_cost,\n created_at,\n updated_at,\n from_addr,\n blob_sidecar\n )\n VALUES\n ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7)\n RETURNING\n *\n ", + "query": "\n INSERT INTO\n eth_txs (\n raw_tx,\n nonce,\n tx_type,\n contract_address,\n predicted_gas_cost,\n created_at,\n updated_at,\n from_addr,\n blob_sidecar,\n is_gateway\n )\n VALUES\n ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7, $8)\n RETURNING\n *\n ", "describe": { "columns": [ { @@ -72,6 +72,11 @@ "ordinal": 13, "name": "blob_sidecar", "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "is_gateway", + "type_info": "Bool" } ], "parameters": { @@ -82,7 +87,8 @@ "Text", "Int8", "Bytea", - "Bytea" + "Bytea", + "Bool" ] }, "nullable": [ @@ -99,8 +105,9 @@ true, false, true, - true + true, + false ] }, - "hash": "2a2680234c38904e5c19df45193a8c13d04079683e09c65f7f4e76a9987e2ab4" + "hash": "0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a" } diff --git a/core/lib/dal/.sqlx/query-4570e9ffd0b2973d0bc2986c391d0a59076dda4aa572ade2492f37e537fdf6ed.json b/core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json similarity index 70% rename from core/lib/dal/.sqlx/query-4570e9ffd0b2973d0bc2986c391d0a59076dda4aa572ade2492f37e537fdf6ed.json rename to core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json index 7297bcdcad23..7038a138dae7 100644 --- a/core/lib/dal/.sqlx/query-4570e9ffd0b2973d0bc2986c391d0a59076dda4aa572ade2492f37e537fdf6ed.json +++ b/core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n from_addr IS NOT DISTINCT FROM $2 -- can't just use equality as NULL != NULL\n AND id > (\n SELECT\n COALESCE(MAX(eth_tx_id), 0)\n FROM\n eth_txs_history\n JOIN eth_txs ON eth_txs.id = eth_txs_history.eth_tx_id\n WHERE\n eth_txs_history.sent_at_block IS NOT NULL\n AND eth_txs.from_addr IS NOT DISTINCT FROM $2\n )\n ORDER BY\n id\n LIMIT\n $1\n ", + "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n confirmed_eth_tx_history_id IS NULL\n AND is_gateway = FALSE\n ", "describe": { "columns": [ { @@ -72,13 +72,15 @@ "ordinal": 13, "name": "blob_sidecar", "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "is_gateway", + "type_info": "Bool" } ], "parameters": { - "Left": [ - "Int8", - "Bytea" - ] + "Left": [] }, "nullable": [ false, @@ -94,8 +96,9 @@ true, false, true, - true + true, + false ] }, - "hash": "4570e9ffd0b2973d0bc2986c391d0a59076dda4aa572ade2492f37e537fdf6ed" + "hash": "1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1" } diff --git a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json index 985f998b439a..49578cd67bec 100644 --- a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json +++ b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json @@ -72,6 +72,11 @@ "ordinal": 13, "name": "blob_sidecar", "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "is_gateway", + "type_info": "Bool" } ], "parameters": { @@ -93,7 +98,8 @@ true, false, true, - true + true, + false ] }, "hash": "6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363" diff --git a/core/lib/dal/.sqlx/query-6bb5eab89be2b08a08c00b5cd8d725208b0ecfe8065c8f893ff38c49072a21fc.json b/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json similarity index 70% rename from core/lib/dal/.sqlx/query-6bb5eab89be2b08a08c00b5cd8d725208b0ecfe8065c8f893ff38c49072a21fc.json rename to core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json index 71318c9a1023..28058b9e42a7 100644 --- a/core/lib/dal/.sqlx/query-6bb5eab89be2b08a08c00b5cd8d725208b0ecfe8065c8f893ff38c49072a21fc.json +++ b/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n from_addr IS NOT DISTINCT FROM $1 -- can't just use equality as NULL != NULL\n AND confirmed_eth_tx_history_id IS NULL\n AND id <= (\n SELECT\n COALESCE(MAX(eth_tx_id), 0)\n FROM\n eth_txs_history\n JOIN eth_txs ON eth_txs.id = eth_txs_history.eth_tx_id\n WHERE\n eth_txs_history.sent_at_block IS NOT NULL\n AND eth_txs.from_addr IS NOT DISTINCT FROM $1\n )\n ORDER BY\n id\n ", + "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n from_addr IS NOT DISTINCT FROM $1 -- can't just use equality as NULL != NULL\n AND confirmed_eth_tx_history_id IS NULL\n AND is_gateway = $2\n AND id <= (\n SELECT\n COALESCE(MAX(eth_tx_id), 0)\n FROM\n eth_txs_history\n JOIN eth_txs ON eth_txs.id = eth_txs_history.eth_tx_id\n WHERE\n eth_txs_history.sent_at_block IS NOT NULL\n AND eth_txs.from_addr IS NOT DISTINCT FROM $1\n AND is_gateway = $2\n )\n ORDER BY\n id\n ", "describe": { "columns": [ { @@ -72,11 +72,17 @@ "ordinal": 13, "name": "blob_sidecar", "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "is_gateway", + "type_info": "Bool" } ], "parameters": { "Left": [ - "Bytea" + "Bytea", + "Bool" ] }, "nullable": [ @@ -93,8 +99,9 @@ true, false, true, - true + true, + false ] }, - "hash": "6bb5eab89be2b08a08c00b5cd8d725208b0ecfe8065c8f893ff38c49072a21fc" + "hash": "a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0" } diff --git a/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json b/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json new file mode 100644 index 000000000000..fb6ea1d2d3e5 --- /dev/null +++ b/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json @@ -0,0 +1,108 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n from_addr IS NOT DISTINCT FROM $2 -- can't just use equality as NULL != NULL\n AND is_gateway = $3\n AND id > (\n SELECT\n COALESCE(MAX(eth_tx_id), 0)\n FROM\n eth_txs_history\n JOIN eth_txs ON eth_txs.id = eth_txs_history.eth_tx_id\n WHERE\n eth_txs_history.sent_at_block IS NOT NULL\n AND eth_txs.from_addr IS NOT DISTINCT FROM $2\n AND is_gateway = $3\n )\n ORDER BY\n id\n LIMIT\n $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "nonce", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "raw_tx", + "type_info": "Bytea" + }, + { + "ordinal": 3, + "name": "contract_address", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "tx_type", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "gas_used", + "type_info": "Int8" + }, + { + "ordinal": 6, + "name": "created_at", + "type_info": "Timestamp" + }, + { + "ordinal": 7, + "name": "updated_at", + "type_info": "Timestamp" + }, + { + "ordinal": 8, + "name": "has_failed", + "type_info": "Bool" + }, + { + "ordinal": 9, + "name": "sent_at_block", + "type_info": "Int4" + }, + { + "ordinal": 10, + "name": "confirmed_eth_tx_history_id", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "predicted_gas_cost", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "from_addr", + "type_info": "Bytea" + }, + { + "ordinal": 13, + "name": "blob_sidecar", + "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "is_gateway", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8", + "Bytea", + "Bool" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + true, + true, + false, + true, + true, + false + ] + }, + "hash": "eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755" +} diff --git a/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.down.sql b/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.down.sql new file mode 100644 index 000000000000..02fbc8cb075d --- /dev/null +++ b/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.down.sql @@ -0,0 +1 @@ +ALTER TABLE eth_txs DROP COLUMN is_gateway; diff --git a/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.up.sql b/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.up.sql new file mode 100644 index 000000000000..af1ef835cf37 --- /dev/null +++ b/core/lib/dal/migrations/20240803083814_add_is_gateway_column_to_eth_txs.up.sql @@ -0,0 +1 @@ +ALTER TABLE eth_txs ADD COLUMN is_gateway BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 4f4b3e99ff7b..1418c5398427 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -2431,7 +2431,16 @@ mod tests { async fn save_mock_eth_tx(action_type: AggregatedActionType, conn: &mut Connection<'_, Core>) { conn.eth_sender_dal() - .save_eth_tx(1, vec![], action_type, Address::default(), 1, None, None) + .save_eth_tx( + 1, + vec![], + action_type, + Address::default(), + 1, + None, + None, + false, + ) .await .unwrap(); } diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 13fa9070f828..dc96ba7bb463 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -968,6 +968,7 @@ mod tests { 0, None, None, + false, ) .await .unwrap(); diff --git a/core/lib/dal/src/eth_sender_dal.rs b/core/lib/dal/src/eth_sender_dal.rs index f1ff515f506e..116dbe88e40f 100644 --- a/core/lib/dal/src/eth_sender_dal.rs +++ b/core/lib/dal/src/eth_sender_dal.rs @@ -25,6 +25,7 @@ impl EthSenderDal<'_, '_> { pub async fn get_inflight_txs( &mut self, operator_address: Option
, + is_gateway: bool, ) -> sqlx::Result> { let txs = sqlx::query_as!( StorageEthTx, @@ -36,6 +37,7 @@ impl EthSenderDal<'_, '_> { WHERE from_addr IS NOT DISTINCT FROM $1 -- can't just use equality as NULL != NULL AND confirmed_eth_tx_history_id IS NULL + AND is_gateway = $2 AND id <= ( SELECT COALESCE(MAX(eth_tx_id), 0) @@ -45,17 +47,39 @@ impl EthSenderDal<'_, '_> { WHERE eth_txs_history.sent_at_block IS NOT NULL AND eth_txs.from_addr IS NOT DISTINCT FROM $1 + AND is_gateway = $2 ) ORDER BY id "#, operator_address.as_ref().map(|h160| h160.as_bytes()), + is_gateway ) .fetch_all(self.storage.conn()) .await?; Ok(txs.into_iter().map(|tx| tx.into()).collect()) } + pub async fn get_non_gateway_inflight_txs_count_for_gateway_migration( + &mut self, + ) -> sqlx::Result { + let txs = sqlx::query_as!( + StorageEthTx, + r#" + SELECT + * + FROM + eth_txs + WHERE + confirmed_eth_tx_history_id IS NULL + AND is_gateway = FALSE + "# + ) + .fetch_all(self.storage.conn()) + .await?; + Ok(txs.len()) + } + pub async fn get_eth_l1_batches(&mut self) -> sqlx::Result { struct EthTxRow { number: i64, @@ -132,6 +156,7 @@ impl EthSenderDal<'_, '_> { &mut self, limit: u64, operator_address: &Option
, + is_gateway: bool, ) -> sqlx::Result> { let txs = sqlx::query_as!( StorageEthTx, @@ -142,6 +167,7 @@ impl EthSenderDal<'_, '_> { eth_txs WHERE from_addr IS NOT DISTINCT FROM $2 -- can't just use equality as NULL != NULL + AND is_gateway = $3 AND id > ( SELECT COALESCE(MAX(eth_tx_id), 0) @@ -151,6 +177,7 @@ impl EthSenderDal<'_, '_> { WHERE eth_txs_history.sent_at_block IS NOT NULL AND eth_txs.from_addr IS NOT DISTINCT FROM $2 + AND is_gateway = $3 ) ORDER BY id @@ -159,6 +186,7 @@ impl EthSenderDal<'_, '_> { "#, limit as i64, operator_address.as_ref().map(|h160| h160.as_bytes()), + is_gateway ) .fetch_all(self.storage.conn()) .await?; @@ -202,6 +230,7 @@ impl EthSenderDal<'_, '_> { predicted_gas_cost: u32, from_address: Option
, blob_sidecar: Option, + is_gateway: bool, ) -> sqlx::Result { let address = format!("{:#x}", contract_address); let eth_tx = sqlx::query_as!( @@ -217,10 +246,11 @@ impl EthSenderDal<'_, '_> { created_at, updated_at, from_addr, - blob_sidecar + blob_sidecar, + is_gateway ) VALUES - ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7) + ($1, $2, $3, $4, $5, NOW(), NOW(), $6, $7, $8) RETURNING * "#, @@ -232,6 +262,7 @@ impl EthSenderDal<'_, '_> { from_address.as_ref().map(Address::as_bytes), blob_sidecar.map(|sidecar| bincode::serialize(&sidecar) .expect("can always bincode serialize EthTxBlobSidecar; qed")), + is_gateway, ) .fetch_one(self.storage.conn()) .await?; diff --git a/core/lib/dal/src/models/storage_eth_tx.rs b/core/lib/dal/src/models/storage_eth_tx.rs index 2654ffe0e0a7..c721f938838e 100644 --- a/core/lib/dal/src/models/storage_eth_tx.rs +++ b/core/lib/dal/src/models/storage_eth_tx.rs @@ -29,6 +29,7 @@ pub struct StorageEthTx { // // Format a `bincode`-encoded `EthTxBlobSidecar` enum. pub blob_sidecar: Option>, + pub is_gateway: bool, } #[derive(Debug, Default)] @@ -83,6 +84,7 @@ impl From for EthTx { blob_sidecar: tx.blob_sidecar.map(|b| { bincode::deserialize(&b).expect("EthTxBlobSidecar is encoded correctly; qed") }), + is_gateway: tx.is_gateway, } } } diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 450446832a27..233dc76f3a55 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -107,7 +107,7 @@ impl MockEthereumInner { self.block_number += confirmations; let nonce = self.current_nonce; self.current_nonce += 1; - tracing::info!("Executing tx with hash {tx_hash:?}, success: {success}, current nonce: {}, confirmations: {confirmations}", self.current_nonce); + tracing::info!("Executing tx with hash {tx_hash:?} at block {}, success: {success}, current nonce: {}, confirmations: {confirmations}", self.block_number - confirmations, self.current_nonce); let tx_nonce = self.sent_txs[&tx_hash].nonce; if non_ordering_confirmations { diff --git a/core/lib/eth_client/src/clients/mod.rs b/core/lib/eth_client/src/clients/mod.rs index 4d48229c573f..867ac170b0f8 100644 --- a/core/lib/eth_client/src/clients/mod.rs +++ b/core/lib/eth_client/src/clients/mod.rs @@ -3,7 +3,7 @@ mod http; mod mock; -pub use zksync_web3_decl::client::{Client, DynClient, L1}; +pub use zksync_web3_decl::client::{Client, DynClient, ForEthereumLikeNetwork, L1, L2}; pub use self::{ http::{PKSigningClient, SigningClient}, diff --git a/core/lib/types/src/eth_sender.rs b/core/lib/types/src/eth_sender.rs index bab57165b3dc..09ea915283eb 100644 --- a/core/lib/types/src/eth_sender.rs +++ b/core/lib/types/src/eth_sender.rs @@ -51,6 +51,7 @@ pub struct EthTx { /// this transaction. If it is set to `None` this transaction was sent by the main operator. pub from_addr: Option
, pub blob_sidecar: Option, + pub is_gateway: bool, } impl std::fmt::Debug for EthTx { diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index 1f1956c9dd84..d3a64a73abc7 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -3,13 +3,13 @@ use std::fmt; use async_trait::async_trait; use vise::{EncodeLabelSet, EncodeLabelValue}; use zksync_eth_client::{ + clients::{L1, L2}, BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, Options, RawTransactionBytes, SignedCallResult, }; #[cfg(test)] use zksync_types::web3; use zksync_types::{ - aggregated_operations::AggregatedActionType, eth_sender::{EthTx, EthTxBlobSidecar}, web3::{BlockId, BlockNumber}, Address, L1BlockNumber, Nonce, EIP_1559_TX_TYPE, EIP_4844_TX_TYPE, H256, U256, @@ -37,14 +37,25 @@ pub(crate) struct L1BlockNumbers { pub(crate) enum OperatorType { NonBlob, Blob, + Gateway, } #[async_trait] pub(super) trait AbstractL1Interface: 'static + Sync + Send + fmt::Debug { - async fn failure_reason(&self, tx_hash: H256) -> Option; + fn supported_operator_types(&self) -> Vec; + + async fn failure_reason( + &self, + tx_hash: H256, + operator_type: OperatorType, + ) -> Option; #[cfg(test)] - async fn get_tx(&self, tx_hash: H256) -> EnrichedClientResult>; + async fn get_tx( + &self, + tx_hash: H256, + operator_type: OperatorType, + ) -> EnrichedClientResult>; async fn get_tx_status( &self, @@ -73,50 +84,77 @@ pub(super) trait AbstractL1Interface: 'static + Sync + Send + fmt::Debug { priority_fee_per_gas: u64, blob_gas_price: Option, max_aggregated_tx_gas: U256, + operator_type: OperatorType, ) -> SignedCallResult; - async fn get_l1_block_numbers(&self) -> Result; - - fn ethereum_gateway(&self) -> &dyn BoundEthInterface; - - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface>; + async fn get_l1_block_numbers( + &self, + operator_type: OperatorType, + ) -> Result; } #[derive(Debug)] pub(super) struct RealL1Interface { - pub ethereum_gateway: Box, + pub ethereum_gateway: Option>, pub ethereum_gateway_blobs: Option>, + pub l2_gateway: Option>, pub wait_confirmations: Option, } impl RealL1Interface { - pub(crate) fn query_client(&self) -> &dyn EthInterface { - self.ethereum_gateway().as_ref() + fn query_client(&self, operator_type: OperatorType) -> &dyn EthInterface { + match operator_type { + OperatorType::NonBlob => self.ethereum_gateway.as_deref().unwrap().as_ref(), + OperatorType::Blob => self.ethereum_gateway_blobs.as_deref().unwrap().as_ref(), + OperatorType::Gateway => self.l2_gateway.as_deref().unwrap().as_ref(), + } } - pub(crate) fn query_client_for_operator( - &self, - operator_type: OperatorType, - ) -> &dyn EthInterface { - if operator_type == OperatorType::Blob { - self.ethereum_gateway_blobs().unwrap().as_ref() - } else { - self.ethereum_gateway().as_ref() + fn bound_query_client(&self, operator_type: OperatorType) -> &dyn BoundEthInterface { + match operator_type { + OperatorType::NonBlob => self.ethereum_gateway.as_deref().unwrap(), + OperatorType::Blob => self.ethereum_gateway_blobs.as_deref().unwrap(), + OperatorType::Gateway => self.l2_gateway.as_deref().unwrap(), } } } #[async_trait] impl AbstractL1Interface for RealL1Interface { - async fn failure_reason(&self, tx_hash: H256) -> Option { - self.query_client().failure_reason(tx_hash).await.expect( - "Tx is already failed, it's safe to fail here and apply the status on the next run", - ) + fn supported_operator_types(&self) -> Vec { + let mut result = vec![]; + if self.l2_gateway.is_some() { + result.push(OperatorType::Gateway); + } + if self.ethereum_gateway_blobs.is_some() { + result.push(OperatorType::Blob) + } + if self.ethereum_gateway.is_some() { + result.push(OperatorType::NonBlob); + } + result + } + + async fn failure_reason( + &self, + tx_hash: H256, + operator_type: OperatorType, + ) -> Option { + self.query_client(operator_type) + .failure_reason(tx_hash) + .await + .expect( + "Tx is already failed, it's safe to fail here and apply the status on the next run", + ) } #[cfg(test)] - async fn get_tx(&self, tx_hash: H256) -> EnrichedClientResult> { - self.query_client().get_tx(tx_hash).await + async fn get_tx( + &self, + tx_hash: H256, + operator_type: OperatorType, + ) -> EnrichedClientResult> { + self.query_client(operator_type).get_tx(tx_hash).await } async fn get_tx_status( @@ -124,7 +162,7 @@ impl AbstractL1Interface for RealL1Interface { tx_hash: H256, operator_type: OperatorType, ) -> Result, EthSenderError> { - self.query_client_for_operator(operator_type) + self.query_client(operator_type) .get_tx_status(tx_hash) .await .map_err(Into::into) @@ -135,13 +173,12 @@ impl AbstractL1Interface for RealL1Interface { tx_bytes: RawTransactionBytes, operator_type: OperatorType, ) -> EnrichedClientResult { - self.query_client_for_operator(operator_type) - .send_raw_tx(tx_bytes) - .await + self.query_client(operator_type).send_raw_tx(tx_bytes).await } fn get_blobs_operator_account(&self) -> Option
{ - self.ethereum_gateway_blobs() + self.ethereum_gateway_blobs + .as_deref() .as_ref() .map(|s| s.sender_account()) } @@ -151,27 +188,20 @@ impl AbstractL1Interface for RealL1Interface { block_numbers: L1BlockNumbers, operator_type: OperatorType, ) -> Result, EthSenderError> { - let gateway = match operator_type { - OperatorType::NonBlob => Some(self.ethereum_gateway()), - OperatorType::Blob => self.ethereum_gateway_blobs(), - }; - match gateway { - None => Ok(None), - Some(gateway) => { - let finalized = gateway - .nonce_at(block_numbers.finalized.0.into()) - .await? - .as_u32() - .into(); - - let latest = gateway - .nonce_at(block_numbers.latest.0.into()) - .await? - .as_u32() - .into(); - Ok(Some(OperatorNonce { finalized, latest })) - } - } + let finalized = self + .bound_query_client(operator_type) + .nonce_at(block_numbers.finalized.0.into()) + .await? + .as_u32() + .into(); + + let latest = self + .bound_query_client(operator_type) + .nonce_at(block_numbers.latest.0.into()) + .await? + .as_u32() + .into(); + Ok(Some(OperatorNonce { finalized, latest })) } async fn sign_tx( @@ -181,22 +211,9 @@ impl AbstractL1Interface for RealL1Interface { priority_fee_per_gas: u64, blob_gas_price: Option, max_aggregated_tx_gas: U256, + operator_type: OperatorType, ) -> SignedCallResult { - // Chose the signing gateway. Use a custom one in case - // the operator is in 4844 mode and the operation at hand is Commit. - // then the optional gateway is used to send this transaction from a - // custom sender account. - let signing_gateway = if let Some(blobs_gateway) = self.ethereum_gateway_blobs() { - if tx.tx_type == AggregatedActionType::Commit { - blobs_gateway - } else { - self.ethereum_gateway() - } - } else { - self.ethereum_gateway() - }; - - signing_gateway + self.bound_query_client(operator_type) .sign_prepared_tx_for_addr( tx.raw_tx.clone(), tx.contract_address, @@ -206,34 +223,44 @@ impl AbstractL1Interface for RealL1Interface { opt.max_fee_per_gas = Some(U256::from(base_fee_per_gas + priority_fee_per_gas)); opt.max_priority_fee_per_gas = Some(U256::from(priority_fee_per_gas)); opt.nonce = Some(tx.nonce.0.into()); - opt.transaction_type = if tx.blob_sidecar.is_some() { - opt.max_fee_per_blob_gas = blob_gas_price; - Some(EIP_4844_TX_TYPE.into()) - } else { - Some(EIP_1559_TX_TYPE.into()) + opt.transaction_type = match operator_type { + OperatorType::NonBlob => Some(EIP_1559_TX_TYPE.into()), + OperatorType::Blob => Some(EIP_4844_TX_TYPE.into()), + OperatorType::Gateway => Some(EIP_1559_TX_TYPE.into()), }; - opt.blob_versioned_hashes = tx.blob_sidecar.as_ref().map(|s| match s { - EthTxBlobSidecar::EthTxBlobSidecarV1(s) => s - .blobs - .iter() - .map(|blob| H256::from_slice(&blob.versioned_hash)) - .collect(), - }); + if tx.blob_sidecar.is_some() { + opt.max_fee_per_blob_gas = blob_gas_price; + opt.blob_versioned_hashes = tx.blob_sidecar.as_ref().map(|s| match s { + EthTxBlobSidecar::EthTxBlobSidecarV1(s) => s + .blobs + .iter() + .map(|blob| H256::from_slice(&blob.versioned_hash)) + .collect(), + }); + } }), ) .await .expect("Failed to sign transaction") } - async fn get_l1_block_numbers(&self) -> Result { + async fn get_l1_block_numbers( + &self, + operator_type: OperatorType, + ) -> Result { let (finalized, safe) = if let Some(confirmations) = self.wait_confirmations { - let latest_block_number = self.query_client().block_number().await?.as_u64(); + let latest_block_number: u64 = self + .query_client(operator_type) + .block_number() + .await? + .as_u64() + .into(); let finalized = (latest_block_number.saturating_sub(confirmations) as u32).into(); (finalized, finalized) } else { let finalized = self - .query_client() + .query_client(operator_type) .block(BlockId::Number(BlockNumber::Finalized)) .await? .expect("Finalized block must be present on L1") @@ -243,7 +270,7 @@ impl AbstractL1Interface for RealL1Interface { .into(); let safe = self - .query_client() + .query_client(operator_type) .block(BlockId::Number(BlockNumber::Safe)) .await? .expect("Safe block must be present on L1") @@ -254,7 +281,12 @@ impl AbstractL1Interface for RealL1Interface { (finalized, safe) }; - let latest = self.query_client().block_number().await?.as_u32().into(); + let latest = self + .query_client(operator_type) + .block_number() + .await? + .as_u32() + .into(); Ok(L1BlockNumbers { finalized, @@ -262,12 +294,4 @@ impl AbstractL1Interface for RealL1Interface { safe, }) } - - fn ethereum_gateway(&self) -> &dyn BoundEthInterface { - self.ethereum_gateway.as_ref() - } - - fn ethereum_gateway_blobs(&self) -> Option<&dyn BoundEthInterface> { - self.ethereum_gateway_blobs.as_deref() - } } diff --git a/core/node/eth_sender/src/eth_fees_oracle.rs b/core/node/eth_sender/src/eth_fees_oracle.rs index 89d10bc2b1e5..b7385f18dd07 100644 --- a/core/node/eth_sender/src/eth_fees_oracle.rs +++ b/core/node/eth_sender/src/eth_fees_oracle.rs @@ -5,30 +5,31 @@ use std::{ }; use zksync_eth_client::{ClientError, EnrichedClientError}; -use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; +use zksync_node_fee_model::l1_gas_price::TxParamsProvider; use zksync_types::eth_sender::TxHistory; -use crate::EthSenderError; +use crate::{abstract_l1_interface::OperatorType, EthSenderError}; #[derive(Debug)] pub(crate) struct EthFees { pub(crate) base_fee_per_gas: u64, pub(crate) priority_fee_per_gas: u64, pub(crate) blob_base_fee_per_gas: Option, + pub(crate) pubdata_price: Option, } pub(crate) trait EthFeesOracle: 'static + Sync + Send + fmt::Debug { fn calculate_fees( &self, previous_sent_tx: &Option, - has_blob_sidecar: bool, time_in_mempool: u32, + operator_type: OperatorType, ) -> Result; } #[derive(Debug)] pub(crate) struct GasAdjusterFeesOracle { - pub gas_adjuster: Arc, + pub l1_gas_adjuster: Arc, pub max_acceptable_priority_fee_in_gwei: u64, } @@ -37,9 +38,9 @@ impl GasAdjusterFeesOracle { &self, previous_sent_tx: &Option, ) -> Result { - let base_fee_per_gas = self.gas_adjuster.get_blob_tx_base_fee(); - let priority_fee_per_gas = self.gas_adjuster.get_blob_tx_priority_fee(); - let blob_base_fee_per_gas = Some(self.gas_adjuster.get_blob_tx_blob_base_fee()); + let base_fee_per_gas = self.l1_gas_adjuster.get_blob_tx_base_fee(); + let priority_fee_per_gas = self.l1_gas_adjuster.get_blob_tx_priority_fee(); + let blob_base_fee_per_gas = Some(self.l1_gas_adjuster.get_blob_tx_blob_base_fee()); if let Some(previous_sent_tx) = previous_sent_tx { // for blob transactions on re-sending need to double all gas prices @@ -53,12 +54,14 @@ impl GasAdjusterFeesOracle { previous_sent_tx.blob_base_fee_per_gas.map(|v| v * 2), blob_base_fee_per_gas, ), + pubdata_price: None, }); } Ok(EthFees { base_fee_per_gas, priority_fee_per_gas, blob_base_fee_per_gas, + pubdata_price: None, }) } @@ -67,7 +70,7 @@ impl GasAdjusterFeesOracle { previous_sent_tx: &Option, time_in_mempool: u32, ) -> Result { - let mut base_fee_per_gas = self.gas_adjuster.get_base_fee(time_in_mempool); + let mut base_fee_per_gas = self.l1_gas_adjuster.get_base_fee(time_in_mempool); if let Some(previous_sent_tx) = previous_sent_tx { self.verify_base_fee_not_too_low_on_resend( previous_sent_tx.id, @@ -76,7 +79,7 @@ impl GasAdjusterFeesOracle { )?; } - let mut priority_fee_per_gas = self.gas_adjuster.get_priority_fee(); + let mut priority_fee_per_gas = self.l1_gas_adjuster.get_priority_fee(); if let Some(previous_sent_tx) = previous_sent_tx { // Increase `priority_fee_per_gas` by at least 20% to prevent "replacement transaction under-priced" error. @@ -105,6 +108,7 @@ impl GasAdjusterFeesOracle { base_fee_per_gas, blob_base_fee_per_gas: None, priority_fee_per_gas, + pubdata_price: None, }) } @@ -114,7 +118,7 @@ impl GasAdjusterFeesOracle { previous_base_fee: u64, base_fee_to_use: u64, ) -> Result<(), EthSenderError> { - let next_block_minimal_base_fee = self.gas_adjuster.get_next_block_minimal_base_fee(); + let next_block_minimal_base_fee = self.l1_gas_adjuster.get_next_block_minimal_base_fee(); if base_fee_to_use < min(next_block_minimal_base_fee, previous_base_fee) { // If the base fee is lower than the previous used one // or is lower than the minimal possible value for the next block, sending is skipped. @@ -143,9 +147,10 @@ impl EthFeesOracle for GasAdjusterFeesOracle { fn calculate_fees( &self, previous_sent_tx: &Option, - has_blob_sidecar: bool, time_in_mempool: u32, + operator_type: OperatorType, ) -> Result { + let has_blob_sidecar = operator_type == OperatorType::Blob; if has_blob_sidecar { self.calculate_fees_with_blob_sidecar(previous_sent_tx) } else { diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 89533432ef83..681c2192d45b 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -356,7 +356,7 @@ impl EthTxAggregator { .await { let tx = self - .save_eth_tx(storage, &agg_op, contracts_are_pre_shared_bridge) + .save_eth_tx(storage, &agg_op, contracts_are_pre_shared_bridge, false) .await?; Self::report_eth_tx_saving(storage, &agg_op, &tx).await; } @@ -521,6 +521,7 @@ impl EthTxAggregator { storage: &mut Connection<'_, Core>, aggregated_op: &AggregatedOperation, contracts_are_pre_shared_bridge: bool, + is_gateway: bool, ) -> Result { let mut transaction = storage.start_transaction().await.unwrap(); let op_type = aggregated_op.get_action_type(); @@ -553,6 +554,7 @@ impl EthTxAggregator { eth_tx_predicted_gas, sender_addr, encoded_aggregated_op.sidecar, + is_gateway, ) .await .unwrap(); diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 9f41bfde8b4d..527b6698c727 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -4,9 +4,10 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ + clients::{L1, L2}, encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, RawTransactionBytes, }; -use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; +use zksync_node_fee_model::l1_gas_price::TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; use zksync_types::{eth_sender::EthTx, Address, L1BlockNumber, H256, U256}; use zksync_utils::time::seconds_since_epoch; @@ -37,21 +38,23 @@ impl EthTxManager { pub fn new( pool: ConnectionPool, config: SenderConfig, - gas_adjuster: Arc, - ethereum_gateway: Box, + gas_adjuster: Arc, + ethereum_gateway: Option>, ethereum_gateway_blobs: Option>, + l2_gateway: Option>, ) -> Self { - let ethereum_gateway = ethereum_gateway.for_component("eth_tx_manager"); + let ethereum_gateway = ethereum_gateway.map(|eth| eth.for_component("eth_tx_manager")); let ethereum_gateway_blobs = ethereum_gateway_blobs.map(|eth| eth.for_component("eth_tx_manager")); let fees_oracle = GasAdjusterFeesOracle { - gas_adjuster, + l1_gas_adjuster: gas_adjuster, max_acceptable_priority_fee_in_gwei: config.max_acceptable_priority_fee_in_gwei, }; Self { l1_interface: Box::new(RealL1Interface { ethereum_gateway, ethereum_gateway_blobs, + l2_gateway, wait_confirmations: config.wait_confirmations, }), config, @@ -77,18 +80,12 @@ impl EthTxManager { .await .unwrap() { - let operator_type = if op.blob_sidecar.is_some() { - OperatorType::Blob - } else { - OperatorType::NonBlob - }; - // `status` is a Result here and we don't unwrap it with `?` // because if we do and get an `Err`, we won't finish the for loop, // which means we might miss the transaction that actually succeeded. match self .l1_interface - .get_tx_status(history_item.tx_hash, operator_type) + .get_tx_status(history_item.tx_hash, self.operator_type(op)) .await { Ok(Some(s)) => return Ok(Some(s)), @@ -124,17 +121,14 @@ impl EthTxManager { base_fee_per_gas, priority_fee_per_gas, blob_base_fee_per_gas, + pubdata_price: _, } = self.fees_oracle.calculate_fees( &previous_sent_tx, - has_blob_sidecar, time_in_mempool, + self.operator_type(tx), )?; - let operator_type = if tx.blob_sidecar.is_some() { - OperatorType::Blob - } else { - OperatorType::NonBlob - }; + let operator_type = self.operator_type(tx); if let Some(previous_sent_tx) = previous_sent_tx { METRICS.transaction_resent.inc(); @@ -195,6 +189,7 @@ impl EthTxManager { priority_fee_per_gas, blob_gas_price, self.config.max_aggregated_tx_gas.into(), + operator_type, ) .await; @@ -286,7 +281,10 @@ impl EthTxManager { if let Some(operator_nonce) = operator_nonce { let inflight_txs = storage .eth_sender_dal() - .get_inflight_txs(self.operator_address(operator_type)) + .get_inflight_txs( + self.operator_address(operator_type), + operator_type == OperatorType::Gateway, + ) .await .unwrap(); METRICS.number_of_inflight_txs[&operator_type].set(inflight_txs.len()); @@ -427,6 +425,16 @@ impl EthTxManager { } } + fn operator_type(&self, tx: &EthTx) -> OperatorType { + if tx.blob_sidecar.is_some() { + OperatorType::Blob + } else if tx.is_gateway { + OperatorType::Gateway + } else { + OperatorType::NonBlob + } + } + pub async fn fail_tx( &self, storage: &mut Connection<'_, Core>, @@ -440,7 +448,7 @@ impl EthTxManager { .unwrap(); let failure_reason = self .l1_interface - .failure_reason(tx_status.receipt.transaction_hash) + .failure_reason(tx_status.receipt.transaction_hash, self.operator_type(tx)) .await; tracing::error!( @@ -513,10 +521,13 @@ impl EthTxManager { tracing::info!("Stop signal received, eth_tx_manager is shutting down"); break; } - let l1_block_numbers = self.l1_interface.get_l1_block_numbers().await?; + let l1_block_numbers = self + .l1_interface + .get_l1_block_numbers(OperatorType::Blob) + .await?; METRICS.track_block_numbers(&l1_block_numbers); - self.loop_iteration(&mut storage, l1_block_numbers).await; + self.loop_iteration(&mut storage).await; tokio::time::sleep(self.config.tx_poll_period()).await; } Ok(()) @@ -530,7 +541,10 @@ impl EthTxManager { ) { let number_inflight_txs = storage .eth_sender_dal() - .get_inflight_txs(self.operator_address(operator_type)) + .get_inflight_txs( + self.operator_address(operator_type), + operator_type == OperatorType::Gateway, + ) .await .unwrap() .len(); @@ -546,6 +560,7 @@ impl EthTxManager { .get_new_eth_txs( number_of_available_slots_for_eth_txs, &self.operator_address(operator_type), + operator_type == OperatorType::Gateway, ) .await .unwrap(); @@ -594,17 +609,46 @@ impl EthTxManager { Ok(()) } - #[tracing::instrument(skip_all, name = "EthTxManager::loop_iteration")] - pub async fn loop_iteration( + pub async fn assert_there_are_no_pre_gateway_txs_with_gateway_enabled( &mut self, storage: &mut Connection<'_, Core>, - l1_block_numbers: L1BlockNumbers, ) { - tracing::debug!("Loop iteration at block {}", l1_block_numbers.latest); - // We can treat those two operators independently as they have different nonces and + if !self + .l1_interface + .supported_operator_types() + .contains(&OperatorType::Gateway) + { + return; + } + + let inflight_count = storage + .eth_sender_dal() + .get_non_gateway_inflight_txs_count_for_gateway_migration() + .await + .unwrap(); + if inflight_count != 0 { + panic!("eth-sender was switched to gateway, but there are still {inflight_count} pre-gateway transactions in-flight!") + } + } + + #[tracing::instrument(skip_all, name = "EthTxManager::loop_iteration")] + pub async fn loop_iteration(&mut self, storage: &mut Connection<'_, Core>) { + self.assert_there_are_no_pre_gateway_txs_with_gateway_enabled(storage) + .await; + + // We can treat blob and non-blob operators independently as they have different nonces and // aggregator makes sure that corresponding Commit transaction is confirmed before creating // a PublishProof transaction - for operator_type in [OperatorType::NonBlob, OperatorType::Blob] { + for operator_type in self.l1_interface.supported_operator_types() { + let l1_block_numbers = self + .l1_interface + .get_l1_block_numbers(operator_type) + .await + .unwrap(); + tracing::info!( + "Loop iteration at block {} for {operator_type:?} operator", + l1_block_numbers.latest + ); self.send_new_eth_txs(storage, l1_block_numbers.latest, operator_type) .await; let result = self diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index 5bd5181ed8c7..28a6d856ce2a 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -5,7 +5,10 @@ use zksync_config::{ ContractsConfig, EthConfig, GasAdjusterConfig, }; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{clients::MockSettlementLayer, BaseFees, BoundEthInterface}; +use zksync_eth_client::{ + clients::{MockSettlementLayer, L2}, + BaseFees, BoundEthInterface, +}; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; @@ -17,7 +20,7 @@ use zksync_types::{ }; use crate::{ - abstract_l1_interface::{L1BlockNumbers, OperatorType}, + abstract_l1_interface::{L1BlockNumbers, OperatorType, RealL1Interface}, aggregated_operations::AggregatedOperation, tests::{default_l1_batch_metadata, l1_batch_with_metadata}, Aggregator, EthTxAggregator, EthTxManager, @@ -111,6 +114,7 @@ pub(crate) struct EthSenderTester { pub conn: ConnectionPool, pub gateway: Box, pub gateway_blobs: Box, + pub l2_gateway: Box, pub manager: MockEthTxManager, pub aggregator: EthTxAggregator, pub gas_adjuster: Arc, @@ -120,6 +124,7 @@ pub(crate) struct EthSenderTester { next_l1_batch_number_to_prove: L1BatchNumber, next_l1_batch_number_to_execute: L1BatchNumber, tx_sent_in_last_iteration_count: usize, + pub is_gateway: bool, } impl EthSenderTester { @@ -176,6 +181,26 @@ impl EthSenderTester { gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); let gateway = Box::new(gateway); + let l2_gateway: MockSettlementLayer = MockSettlementLayer::builder() + .with_fee_history( + std::iter::repeat_with(|| BaseFees { + base_fee_per_gas: 0, + base_fee_per_blob_gas: 0.into(), + l2_pubdata_price: 0.into(), + }) + .take(Self::WAIT_CONFIRMATIONS as usize) + .chain(history.clone()) + .collect(), + ) + .with_non_ordering_confirmation(non_ordering_confirmations) + .with_call_handler(move |call, _| { + assert_eq!(call.to, Some(contracts_config.l1_multicall3_addr)); + crate::tests::mock_multicall_response() + }) + .build(); + l2_gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); + let l2_gateway = Box::new(l2_gateway); + let gateway_blobs = MockSettlementLayer::builder() .with_fee_history( std::iter::repeat_with(|| BaseFees { @@ -249,8 +274,9 @@ impl EthSenderTester { connection_pool.clone(), eth_sender.clone(), gas_adjuster.clone(), - gateway.clone(), + Some(gateway.clone()), Some(gateway_blobs.clone()), + None, ); let connection_pool_clone = connection_pool.clone(); @@ -264,6 +290,7 @@ impl EthSenderTester { Self { gateway, gateway_blobs, + l2_gateway, manager, aggregator, gas_adjuster, @@ -274,9 +301,23 @@ impl EthSenderTester { next_l1_batch_number_to_execute: L1BatchNumber(1), next_l1_batch_number_to_prove: L1BatchNumber(1), tx_sent_in_last_iteration_count: 0, + is_gateway: false, } } + pub fn switch_to_gateway(&mut self) { + self.manager = EthTxManager::new( + self.conn.clone(), + EthConfig::for_tests().sender.unwrap(), + self.gas_adjuster.clone(), + None, + None, + Some(self.l2_gateway.clone()), + ); + self.is_gateway = true; + tracing::info!("Switched eth-sender tester to use Gateway!"); + } + pub async fn storage(&self) -> Connection<'_, Core> { self.conn.connection().await.unwrap() } @@ -285,7 +326,7 @@ impl EthSenderTester { let latest = self .manager .l1_interface() - .get_l1_block_numbers() + .get_l1_block_numbers(OperatorType::NonBlob) .await .unwrap() .latest; @@ -341,13 +382,18 @@ impl EthSenderTester { .get_last_sent_eth_tx_hash(l1_batch_number, operation_type) .await .unwrap(); - let (gateway, other) = if tx.blob_base_fee_per_gas.is_some() { - (self.gateway_blobs.as_ref(), self.gateway.as_ref()) + if !self.is_gateway { + let (gateway, other) = if tx.blob_base_fee_per_gas.is_some() { + (self.gateway_blobs.as_ref(), self.gateway.as_ref()) + } else { + (self.gateway.as_ref(), self.gateway_blobs.as_ref()) + }; + gateway.execute_tx(tx.tx_hash, success, confirmations); + other.advance_block_number(confirmations); } else { - (self.gateway.as_ref(), self.gateway_blobs.as_ref()) - }; - gateway.execute_tx(tx.tx_hash, success, confirmations); - other.advance_block_number(confirmations); + self.l2_gateway + .execute_tx(tx.tx_hash, success, confirmations); + } } pub async fn seal_l1_batch(&mut self) -> L1BatchHeader { @@ -407,15 +453,17 @@ impl EthSenderTester { pub async fn run_eth_sender_tx_manager_iteration_after_n_blocks(&mut self, n: u64) { self.gateway.advance_block_number(n); self.gateway_blobs.advance_block_number(n); - let tx_sent_before = self.gateway.sent_tx_count() + self.gateway_blobs.sent_tx_count(); + self.l2_gateway.advance_block_number(n); + let tx_sent_before = self.gateway.sent_tx_count() + + self.gateway_blobs.sent_tx_count() + + self.l2_gateway.sent_tx_count(); self.manager - .loop_iteration( - &mut self.conn.connection().await.unwrap(), - self.get_block_numbers().await, - ) + .loop_iteration(&mut self.conn.connection().await.unwrap()) .await; - self.tx_sent_in_last_iteration_count = - (self.gateway.sent_tx_count() + self.gateway_blobs.sent_tx_count()) - tx_sent_before; + self.tx_sent_in_last_iteration_count = (self.gateway.sent_tx_count() + + self.gateway_blobs.sent_tx_count() + + self.l2_gateway.sent_tx_count()) + - tx_sent_before; } pub async fn run_eth_sender_tx_manager_iteration(&mut self) { @@ -467,6 +515,7 @@ impl EthSenderTester { &mut self.conn.connection().await.unwrap(), &aggregated_operation, false, + self.is_gateway, ) .await .unwrap() @@ -491,14 +540,18 @@ impl EthSenderTester { } pub async fn confirm_tx(&mut self, hash: H256, is_blob: bool) { - let (gateway, other) = if is_blob { - (self.gateway_blobs.as_ref(), self.gateway.as_ref()) + if !self.is_gateway { + let (gateway, other) = if is_blob { + (self.gateway_blobs.as_ref(), self.gateway.as_ref()) + } else { + (self.gateway.as_ref(), self.gateway_blobs.as_ref()) + }; + gateway.execute_tx(hash, true, EthSenderTester::WAIT_CONFIRMATIONS); + other.advance_block_number(EthSenderTester::WAIT_CONFIRMATIONS); } else { - (self.gateway.as_ref(), self.gateway_blobs.as_ref()) - }; - gateway.execute_tx(hash, true, EthSenderTester::WAIT_CONFIRMATIONS); - other.advance_block_number(EthSenderTester::WAIT_CONFIRMATIONS); - + self.l2_gateway + .execute_tx(hash, true, EthSenderTester::WAIT_CONFIRMATIONS); + } self.run_eth_sender_tx_manager_iteration().await; } @@ -543,13 +596,13 @@ impl EthSenderTester { } pub async fn assert_inflight_txs_count_equals(&mut self, value: usize) { - //sanity check - assert!(self.manager.operator_address(OperatorType::Blob).is_some()); - assert_eq!( + let inflight_count = if !self.is_gateway { + //sanity check + assert!(self.manager.operator_address(OperatorType::Blob).is_some()); self.storage() .await .eth_sender_dal() - .get_inflight_txs(self.manager.operator_address(OperatorType::NonBlob)) + .get_inflight_txs(self.manager.operator_address(OperatorType::NonBlob), false) .await .unwrap() .len() @@ -557,11 +610,22 @@ impl EthSenderTester { .storage() .await .eth_sender_dal() - .get_inflight_txs(self.manager.operator_address(OperatorType::Blob)) + .get_inflight_txs(self.manager.operator_address(OperatorType::Blob), false) .await .unwrap() - .len(), - value, + .len() + } else { + self.storage() + .await + .eth_sender_dal() + .get_inflight_txs(None, true) + .await + .unwrap() + .len() + }; + + assert_eq!( + inflight_count, value, "Unexpected number of in-flight transactions" ); } diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index 83c37dd5d0a5..bc053b8c6299 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -160,6 +160,7 @@ async fn resend_each_block(commitment_mode: L1BatchCommitmentMode) -> anyhow::Re &mut tester.conn.connection().await.unwrap(), &get_dummy_operation(0), false, + false, ) .await?; @@ -175,7 +176,10 @@ async fn resend_each_block(commitment_mode: L1BatchCommitmentMode) -> anyhow::Re .storage() .await .eth_sender_dal() - .get_inflight_txs(tester.manager.operator_address(OperatorType::NonBlob)) + .get_inflight_txs( + tester.manager.operator_address(OperatorType::NonBlob), + false + ) .await .unwrap() .len(), @@ -185,7 +189,7 @@ async fn resend_each_block(commitment_mode: L1BatchCommitmentMode) -> anyhow::Re let sent_tx = tester .manager .l1_interface() - .get_tx(hash) + .get_tx(hash, OperatorType::NonBlob) .await .unwrap() .expect("no transaction"); @@ -228,7 +232,10 @@ async fn resend_each_block(commitment_mode: L1BatchCommitmentMode) -> anyhow::Re .storage() .await .eth_sender_dal() - .get_inflight_txs(tester.manager.operator_address(OperatorType::NonBlob)) + .get_inflight_txs( + tester.manager.operator_address(OperatorType::NonBlob), + false + ) .await .unwrap() .len(), @@ -238,7 +245,7 @@ async fn resend_each_block(commitment_mode: L1BatchCommitmentMode) -> anyhow::Re let resent_tx = tester .manager .l1_interface() - .get_tx(resent_hash) + .get_tx(resent_hash, OperatorType::NonBlob) .await .unwrap() .expect("no transaction"); @@ -425,6 +432,67 @@ async fn transactions_are_not_resent_on_the_same_block() { tester.assert_just_sent_tx_count_equals(0).await; } +#[should_panic( + expected = "eth-sender was switched to gateway, but there are still 1 pre-gateway transactions in-flight!" +)] +#[test_log::test(tokio::test)] +async fn switching_to_gateway_while_some_transactions_were_in_flight_should_cause_panic() { + let mut tester = EthSenderTester::new( + ConnectionPool::::test_pool().await, + vec![100; 100], + true, + true, + L1BatchCommitmentMode::Rollup, + ) + .await; + + let _genesis_l1_batch = TestL1Batch::sealed(&mut tester).await; + let first_l1_batch = TestL1Batch::sealed(&mut tester).await; + + first_l1_batch.save_commit_tx(&mut tester).await; + tester.run_eth_sender_tx_manager_iteration().await; + + // sanity check + tester.assert_inflight_txs_count_equals(1).await; + + tester.switch_to_gateway(); + tester.run_eth_sender_tx_manager_iteration().await; +} + +#[test_log::test(tokio::test)] +async fn switching_to_gateway_works_for_most_basic_scenario() { + let mut tester = EthSenderTester::new( + ConnectionPool::::test_pool().await, + vec![100; 100], + true, + true, + L1BatchCommitmentMode::Rollup, + ) + .await; + + let _genesis_l1_batch = TestL1Batch::sealed(&mut tester).await; + let first_l1_batch = TestL1Batch::sealed(&mut tester).await; + + first_l1_batch.save_commit_tx(&mut tester).await; + tester.run_eth_sender_tx_manager_iteration().await; + + first_l1_batch.execute_commit_tx(&mut tester).await; + tester.run_eth_sender_tx_manager_iteration().await; + // sanity check + tester.assert_inflight_txs_count_equals(0).await; + + tester.switch_to_gateway(); + tester.run_eth_sender_tx_manager_iteration().await; + + first_l1_batch.save_prove_tx(&mut tester).await; + tester.run_eth_sender_tx_manager_iteration().await; + tester.assert_inflight_txs_count_equals(1).await; + + first_l1_batch.execute_prove_tx(&mut tester).await; + tester.run_eth_sender_tx_manager_iteration().await; + tester.assert_inflight_txs_count_equals(0).await; +} + #[test_casing(2, COMMITMENT_MODES)] #[test_log::test(tokio::test)] async fn correct_order_for_confirmations( diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index cf8aa81439db..ee05875cf167 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -12,7 +12,7 @@ use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U use zksync_web3_decl::client::{DynClient, L1, L2}; use self::metrics::METRICS; -use super::L1TxParamsProvider; +use crate::l1_gas_price::TxParamsProvider; mod metrics; #[cfg(test)] @@ -339,7 +339,7 @@ impl GasAdjuster { } } -impl L1TxParamsProvider for GasAdjuster { +impl TxParamsProvider for GasAdjuster { // This is the method where we decide how much we are ready to pay for the // base_fee based on the number of L1 blocks the transaction has been in the mempool. // This is done in order to avoid base_fee spikes (e.g. during NFT drops) and @@ -360,21 +360,6 @@ impl L1TxParamsProvider for GasAdjuster { new_fee as u64 } - fn get_blob_base_fee(&self) -> u64 { - let a = self.config.pricing_formula_parameter_a; - let b = self.config.pricing_formula_parameter_b; - - // Use the single evaluation at zero of the following: - // Currently we use an exponential formula. - // The alternative is a linear one: - // `let scale_factor = a + b * time_in_mempool as f64;` - let scale_factor = a * b.powf(0.0); - let median = self.blob_base_fee_statistics.median(); - METRICS.median_blob_base_fee_per_gas.set(median.as_u64()); - let new_fee = median.as_u64() as f64 * scale_factor; - new_fee as u64 - } - fn get_next_block_minimal_base_fee(&self) -> u64 { let last_block_base_fee = self.base_fee_statistics.last_added_value(); @@ -408,6 +393,14 @@ impl L1TxParamsProvider for GasAdjuster { fn get_blob_tx_priority_fee(&self) -> u64 { self.get_priority_fee() * 2 } + + fn get_gateway_tx_base_fee(&self) -> u64 { + todo!() + } + + fn get_gateway_tx_pubdata_price(&self) -> u64 { + todo!() + } } /// Helper structure responsible for collecting the data about recent transactions, diff --git a/core/node/fee_model/src/l1_gas_price/mod.rs b/core/node/fee_model/src/l1_gas_price/mod.rs index 29db21bc1733..2a5d63089ca1 100644 --- a/core/node/fee_model/src/l1_gas_price/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/mod.rs @@ -14,13 +14,10 @@ mod main_node_fetcher; /// mining time into account. /// /// This trait, as a bound, should only be used in components that actually sign and send transactions. -pub trait L1TxParamsProvider: fmt::Debug + 'static + Send + Sync { +pub trait TxParamsProvider: fmt::Debug + 'static + Send + Sync { /// Returns the recommended `max_fee_per_gas` value (EIP1559). fn get_base_fee(&self, time_in_mempool: u32) -> u64; - /// Returns the recommended `max_blob_fee_per_gas` value (EIP4844). - fn get_blob_base_fee(&self) -> u64; - /// Returns the recommended `max_priority_fee_per_gas` value (EIP1559). fn get_priority_fee(&self) -> u64; @@ -35,4 +32,10 @@ pub trait L1TxParamsProvider: fmt::Debug + 'static + Send + Sync { /// Returns the recommended `max_priority_fee_per_gas` value (EIP1559) for blob transaction. fn get_blob_tx_priority_fee(&self) -> u64; + + /// Returns the recommended `max_fee_per_gas` value for gateway transactions. + fn get_gateway_tx_base_fee(&self) -> u64; + + /// Returns the recommended `max_fee_per_gas` value for gateway transactions. + fn get_gateway_tx_pubdata_price(&self) -> u64; } diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs index e979c372d8e8..c6697e71b8a6 100644 --- a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs +++ b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs @@ -6,7 +6,9 @@ use zksync_eth_sender::EthTxManager; use crate::{ implementations::resources::{ circuit_breakers::CircuitBreakersResource, - eth_interface::{BoundEthInterfaceForBlobsResource, BoundEthInterfaceResource}, + eth_interface::{ + BoundEthInterfaceForBlobsResource, BoundEthInterfaceResource, L2InterfaceResource, + }, l1_tx_params::L1TxParamsResource, pools::{MasterPool, PoolResource, ReplicaPool}, }, @@ -45,6 +47,7 @@ pub struct Input { pub replica_pool: PoolResource, pub eth_client: BoundEthInterfaceResource, pub eth_client_blobs: Option, + pub l2_client: Option, pub l1_tx_params: L1TxParamsResource, #[context(default)] pub circuit_breakers: CircuitBreakersResource, @@ -79,6 +82,7 @@ impl WiringLayer for EthTxManagerLayer { let eth_client = input.eth_client.0; let eth_client_blobs = input.eth_client_blobs.map(|c| c.0); + let l2_client = input.l2_client; let config = self.eth_sender_config.sender.context("sender")?; @@ -90,6 +94,7 @@ impl WiringLayer for EthTxManagerLayer { gas_adjuster, eth_client, eth_client_blobs, + l2_client, ); // Insert circuit breaker. From 91d93d040702642e9ddb88369f6e6c150f41d786 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 5 Aug 2024 21:58:50 +0200 Subject: [PATCH 31/43] fix compilation issue Signed-off-by: tomg10 --- .../src/implementations/resources/l1_tx_params.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/node/node_framework/src/implementations/resources/l1_tx_params.rs b/core/node/node_framework/src/implementations/resources/l1_tx_params.rs index 676828c39885..7d2525603225 100644 --- a/core/node/node_framework/src/implementations/resources/l1_tx_params.rs +++ b/core/node/node_framework/src/implementations/resources/l1_tx_params.rs @@ -1,20 +1,20 @@ use std::sync::Arc; -use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; +use zksync_node_fee_model::l1_gas_price::TxParamsProvider; use crate::resource::Resource; /// A resource that provides [`L1TxParamsProvider`] implementation to the service. #[derive(Debug, Clone)] -pub struct L1TxParamsResource(pub Arc); +pub struct L1TxParamsResource(pub Arc); impl Resource for L1TxParamsResource { fn name() -> String { - "common/l1_tx_params".into() + "common/tx_params".into() } } -impl From> for L1TxParamsResource { +impl From> for L1TxParamsResource { fn from(provider: Arc) -> Self { Self(provider) } From 0d9f8cf435da65828239bb7cc3a183423557dd52 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 5 Aug 2024 22:25:54 +0200 Subject: [PATCH 32/43] fix compilation issue, PR feedback Signed-off-by: tomg10 --- ...cc67d2c7f06d507747f7b03350a7b7efed2b1.json | 104 ------------------ core/lib/dal/src/eth_sender_dal.rs | 13 ++- .../eth_sender/src/abstract_l1_interface.rs | 2 + core/node/eth_sender/src/tester.rs | 16 +-- core/node/eth_sender/src/tests.rs | 4 +- 5 files changed, 19 insertions(+), 120 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json diff --git a/core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json b/core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json deleted file mode 100644 index 7038a138dae7..000000000000 --- a/core/lib/dal/.sqlx/query-1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n *\n FROM\n eth_txs\n WHERE\n confirmed_eth_tx_history_id IS NULL\n AND is_gateway = FALSE\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "nonce", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "raw_tx", - "type_info": "Bytea" - }, - { - "ordinal": 3, - "name": "contract_address", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "tx_type", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "gas_used", - "type_info": "Int8" - }, - { - "ordinal": 6, - "name": "created_at", - "type_info": "Timestamp" - }, - { - "ordinal": 7, - "name": "updated_at", - "type_info": "Timestamp" - }, - { - "ordinal": 8, - "name": "has_failed", - "type_info": "Bool" - }, - { - "ordinal": 9, - "name": "sent_at_block", - "type_info": "Int4" - }, - { - "ordinal": 10, - "name": "confirmed_eth_tx_history_id", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "predicted_gas_cost", - "type_info": "Int8" - }, - { - "ordinal": 12, - "name": "from_addr", - "type_info": "Bytea" - }, - { - "ordinal": 13, - "name": "blob_sidecar", - "type_info": "Bytea" - }, - { - "ordinal": 14, - "name": "is_gateway", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - false, - false, - false, - false, - true, - false, - false, - false, - true, - true, - false, - true, - true, - false - ] - }, - "hash": "1045c6ee11551ffb5ac53102b59cc67d2c7f06d507747f7b03350a7b7efed2b1" -} diff --git a/core/lib/dal/src/eth_sender_dal.rs b/core/lib/dal/src/eth_sender_dal.rs index 116dbe88e40f..eb7e1cd642c1 100644 --- a/core/lib/dal/src/eth_sender_dal.rs +++ b/core/lib/dal/src/eth_sender_dal.rs @@ -63,11 +63,10 @@ impl EthSenderDal<'_, '_> { pub async fn get_non_gateway_inflight_txs_count_for_gateway_migration( &mut self, ) -> sqlx::Result { - let txs = sqlx::query_as!( - StorageEthTx, + let count = sqlx::query!( r#" SELECT - * + COUNT(*) FROM eth_txs WHERE @@ -75,9 +74,11 @@ impl EthSenderDal<'_, '_> { AND is_gateway = FALSE "# ) - .fetch_all(self.storage.conn()) - .await?; - Ok(txs.len()) + .fetch_one(self.storage.conn()) + .await? + .count + .unwrap(); + Ok(count.try_into().unwrap()) } pub async fn get_eth_l1_batches(&mut self) -> sqlx::Result { diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index d3a64a73abc7..fd8992ef2b7c 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -229,6 +229,8 @@ impl AbstractL1Interface for RealL1Interface { OperatorType::Gateway => Some(EIP_1559_TX_TYPE.into()), }; if tx.blob_sidecar.is_some() { + //sanity check + assert_eq!(opt.transaction_type, Some(EIP_4844_TX_TYPE.into())); opt.max_fee_per_blob_gas = blob_gas_price; opt.blob_versioned_hashes = tx.blob_sidecar.as_ref().map(|s| match s { EthTxBlobSidecar::EthTxBlobSidecarV1(s) => s diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index 28a6d856ce2a..3766fec25cf5 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -124,7 +124,7 @@ pub(crate) struct EthSenderTester { next_l1_batch_number_to_prove: L1BatchNumber, next_l1_batch_number_to_execute: L1BatchNumber, tx_sent_in_last_iteration_count: usize, - pub is_gateway: bool, + pub is_l2: bool, } impl EthSenderTester { @@ -301,11 +301,11 @@ impl EthSenderTester { next_l1_batch_number_to_execute: L1BatchNumber(1), next_l1_batch_number_to_prove: L1BatchNumber(1), tx_sent_in_last_iteration_count: 0, - is_gateway: false, + is_l2: false, } } - pub fn switch_to_gateway(&mut self) { + pub fn switch_to_using_gateway(&mut self) { self.manager = EthTxManager::new( self.conn.clone(), EthConfig::for_tests().sender.unwrap(), @@ -314,7 +314,7 @@ impl EthSenderTester { None, Some(self.l2_gateway.clone()), ); - self.is_gateway = true; + self.is_l2 = true; tracing::info!("Switched eth-sender tester to use Gateway!"); } @@ -382,7 +382,7 @@ impl EthSenderTester { .get_last_sent_eth_tx_hash(l1_batch_number, operation_type) .await .unwrap(); - if !self.is_gateway { + if !self.is_l2 { let (gateway, other) = if tx.blob_base_fee_per_gas.is_some() { (self.gateway_blobs.as_ref(), self.gateway.as_ref()) } else { @@ -515,7 +515,7 @@ impl EthSenderTester { &mut self.conn.connection().await.unwrap(), &aggregated_operation, false, - self.is_gateway, + self.is_l2, ) .await .unwrap() @@ -540,7 +540,7 @@ impl EthSenderTester { } pub async fn confirm_tx(&mut self, hash: H256, is_blob: bool) { - if !self.is_gateway { + if !self.is_l2 { let (gateway, other) = if is_blob { (self.gateway_blobs.as_ref(), self.gateway.as_ref()) } else { @@ -596,7 +596,7 @@ impl EthSenderTester { } pub async fn assert_inflight_txs_count_equals(&mut self, value: usize) { - let inflight_count = if !self.is_gateway { + let inflight_count = if !self.is_l2 { //sanity check assert!(self.manager.operator_address(OperatorType::Blob).is_some()); self.storage() diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index bc053b8c6299..e03532458f18 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -455,7 +455,7 @@ async fn switching_to_gateway_while_some_transactions_were_in_flight_should_caus // sanity check tester.assert_inflight_txs_count_equals(1).await; - tester.switch_to_gateway(); + tester.switch_to_using_gateway(); tester.run_eth_sender_tx_manager_iteration().await; } @@ -481,7 +481,7 @@ async fn switching_to_gateway_works_for_most_basic_scenario() { // sanity check tester.assert_inflight_txs_count_equals(0).await; - tester.switch_to_gateway(); + tester.switch_to_using_gateway(); tester.run_eth_sender_tx_manager_iteration().await; first_l1_batch.save_prove_tx(&mut tester).await; From 7ac6f9bcb5050df5bca74cbd3b3b4f3a6ec6906a Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 5 Aug 2024 23:44:24 +0200 Subject: [PATCH 33/43] missing sqlx file Signed-off-by: tomg10 --- ...9754ed7219a77459ef40cd99d7d4d0749e538.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 core/lib/dal/.sqlx/query-5b7d2612dd2dd064ea0095b40669754ed7219a77459ef40cd99d7d4d0749e538.json diff --git a/core/lib/dal/.sqlx/query-5b7d2612dd2dd064ea0095b40669754ed7219a77459ef40cd99d7d4d0749e538.json b/core/lib/dal/.sqlx/query-5b7d2612dd2dd064ea0095b40669754ed7219a77459ef40cd99d7d4d0749e538.json new file mode 100644 index 000000000000..88bac1a36022 --- /dev/null +++ b/core/lib/dal/.sqlx/query-5b7d2612dd2dd064ea0095b40669754ed7219a77459ef40cd99d7d4d0749e538.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n COUNT(*)\n FROM\n eth_txs\n WHERE\n confirmed_eth_tx_history_id IS NULL\n AND is_gateway = FALSE\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null + ] + }, + "hash": "5b7d2612dd2dd064ea0095b40669754ed7219a77459ef40cd99d7d4d0749e538" +} From 97e14ebe2c5cff71b44c3d7c77eac20b92fed191 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Tue, 6 Aug 2024 00:39:21 +0200 Subject: [PATCH 34/43] missing bound l2 resource Signed-off-by: tomg10 --- .../src/implementations/layers/eth_sender/manager.rs | 9 +++++---- .../src/implementations/resources/eth_interface.rs | 9 +++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs index c6697e71b8a6..8093ad64cc2b 100644 --- a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs +++ b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs @@ -7,7 +7,8 @@ use crate::{ implementations::resources::{ circuit_breakers::CircuitBreakersResource, eth_interface::{ - BoundEthInterfaceForBlobsResource, BoundEthInterfaceResource, L2InterfaceResource, + BoundEthInterfaceForBlobsResource, BoundEthInterfaceForL2Resource, + BoundEthInterfaceResource, }, l1_tx_params::L1TxParamsResource, pools::{MasterPool, PoolResource, ReplicaPool}, @@ -47,7 +48,7 @@ pub struct Input { pub replica_pool: PoolResource, pub eth_client: BoundEthInterfaceResource, pub eth_client_blobs: Option, - pub l2_client: Option, + pub l2_client: Option, pub l1_tx_params: L1TxParamsResource, #[context(default)] pub circuit_breakers: CircuitBreakersResource, @@ -82,7 +83,7 @@ impl WiringLayer for EthTxManagerLayer { let eth_client = input.eth_client.0; let eth_client_blobs = input.eth_client_blobs.map(|c| c.0); - let l2_client = input.l2_client; + let l2_client = input.l2_client.map(|c| c.0); let config = self.eth_sender_config.sender.context("sender")?; @@ -92,7 +93,7 @@ impl WiringLayer for EthTxManagerLayer { master_pool, config, gas_adjuster, - eth_client, + Some(eth_client), eth_client_blobs, l2_client, ); diff --git a/core/node/node_framework/src/implementations/resources/eth_interface.rs b/core/node/node_framework/src/implementations/resources/eth_interface.rs index 5879610b75ed..24b7df327f63 100644 --- a/core/node/node_framework/src/implementations/resources/eth_interface.rs +++ b/core/node/node_framework/src/implementations/resources/eth_interface.rs @@ -46,3 +46,12 @@ impl Resource for BoundEthInterfaceForBlobsResource { "common/bound_eth_interface_for_blobs".into() } } + +#[derive(Debug, Clone)] +pub struct BoundEthInterfaceForL2Resource(pub Box); + +impl Resource for BoundEthInterfaceForL2Resource { + fn name() -> String { + "common/bound_eth_interface_for_l2".into() + } +} From 5aa7d076bd3c3e07e5bb49a5cac1b15bb61fe70e Mon Sep 17 00:00:00 2001 From: tomg10 Date: Tue, 6 Aug 2024 01:40:19 +0200 Subject: [PATCH 35/43] missing bound l2 resource Signed-off-by: tomg10 --- core/node/eth_sender/src/abstract_l1_interface.rs | 9 ++------- core/node/eth_sender/src/eth_tx_manager.rs | 11 +++++------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index fd8992ef2b7c..5c18476b8b0e 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -223,14 +223,9 @@ impl AbstractL1Interface for RealL1Interface { opt.max_fee_per_gas = Some(U256::from(base_fee_per_gas + priority_fee_per_gas)); opt.max_priority_fee_per_gas = Some(U256::from(priority_fee_per_gas)); opt.nonce = Some(tx.nonce.0.into()); - opt.transaction_type = match operator_type { - OperatorType::NonBlob => Some(EIP_1559_TX_TYPE.into()), - OperatorType::Blob => Some(EIP_4844_TX_TYPE.into()), - OperatorType::Gateway => Some(EIP_1559_TX_TYPE.into()), - }; + opt.transaction_type = Some(EIP_1559_TX_TYPE.into()); if tx.blob_sidecar.is_some() { - //sanity check - assert_eq!(opt.transaction_type, Some(EIP_4844_TX_TYPE.into())); + opt.transaction_type = Some(EIP_4844_TX_TYPE.into()); opt.max_fee_per_blob_gas = blob_gas_price; opt.blob_versioned_hashes = tx.blob_sidecar.as_ref().map(|s| match s { EthTxBlobSidecar::EthTxBlobSidecarV1(s) => s diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 527b6698c727..3493213ac5f9 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -115,7 +115,6 @@ impl EthTxManager { .get_last_sent_eth_tx(tx.id) .await .unwrap(); - let has_blob_sidecar = tx.blob_sidecar.is_some(); let EthFees { base_fee_per_gas, @@ -171,7 +170,7 @@ impl EthTxManager { .observe(priority_fee_per_gas); } - let blob_gas_price = if has_blob_sidecar { + let blob_gas_price = if tx.blob_sidecar.is_some() { Some( blob_base_fee_per_gas .expect("always ready to query blob gas price for blob transactions; qed") @@ -426,12 +425,12 @@ impl EthTxManager { } fn operator_type(&self, tx: &EthTx) -> OperatorType { - if tx.blob_sidecar.is_some() { - OperatorType::Blob - } else if tx.is_gateway { + if tx.is_gateway { OperatorType::Gateway - } else { + } else if tx.from_addr == None { OperatorType::NonBlob + } else { + OperatorType::Blob } } From 7d4dd5762376315eea8d60f9d3d3354cdf5640ae Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 14:18:06 +0200 Subject: [PATCH 36/43] merge fix Signed-off-by: tomg10 --- .../zk_inception/src/commands/ecosystem/args/create.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs index 4063f4ccdcd2..24cf4e3b4a10 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs @@ -65,9 +65,9 @@ impl EcosystemCreateArgs { } }); - let l1_network = self - .l1_network - .unwrap_or_else(|| PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask()); + let l1_network = self.l1_network.unwrap_or_else(|| { + PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask() + }); // Make the only chain as a default one self.chain.set_as_default = Some(true); From 072e495b666ee0c98e1f3f98e62c1cc61ded59f8 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 14:19:48 +0200 Subject: [PATCH 37/43] merge fix Signed-off-by: tomg10 --- .../zk_inception/src/commands/ecosystem/args/create.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs index 24cf4e3b4a10..4063f4ccdcd2 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs @@ -65,9 +65,9 @@ impl EcosystemCreateArgs { } }); - let l1_network = self.l1_network.unwrap_or_else(|| { - PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask() - }); + let l1_network = self + .l1_network + .unwrap_or_else(|| PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask()); // Make the only chain as a default one self.chain.set_as_default = Some(true); From 3c1019b6997ebee509755343e45e3cf65095055f Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 14:27:47 +0200 Subject: [PATCH 38/43] fix Signed-off-by: tomg10 --- core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs | 2 +- .../src/implementations/layers/eth_sender/manager.rs | 4 ++-- .../node_framework/src/implementations/layers/l1_gas.rs | 4 ++-- .../src/implementations/resources/l1_tx_params.rs | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs index 23750f458f03..4ed9cf1330ea 100644 --- a/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs +++ b/core/node/fee_model/src/l1_gas_price/gas_adjuster/mod.rs @@ -12,7 +12,7 @@ use zksync_types::{commitment::L1BatchCommitmentMode, L1_GAS_PER_PUBDATA_BYTE, U use zksync_web3_decl::client::{DynClient, L1, L2}; use self::metrics::METRICS; -use super::L1TxParamsProvider; +use super::TxParamsProvider; mod metrics; #[cfg(test)] diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs index 03c43f70a5cf..4bb2bdcfabd9 100644 --- a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs +++ b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs @@ -11,7 +11,7 @@ use crate::{ BoundEthInterfaceResource, }, gas_adjuster::GasAdjusterResource, - l1_tx_params::L1TxParamsResource, + l1_tx_params::TxParamsResource, pools::{MasterPool, PoolResource, ReplicaPool}, }, service::StopReceiver, @@ -31,7 +31,7 @@ use crate::{ /// - `PoolResource` /// - `BoundEthInterfaceResource` /// - `BoundEthInterfaceForBlobsResource` (optional) -/// - `L1TxParamsResource` +/// - `TxParamsResource` /// - `CircuitBreakersResource` (adds a circuit breaker) /// /// ## Adds tasks diff --git a/core/node/node_framework/src/implementations/layers/l1_gas.rs b/core/node/node_framework/src/implementations/layers/l1_gas.rs index 9a4ccb8264f6..35c4bc3fc205 100644 --- a/core/node/node_framework/src/implementations/layers/l1_gas.rs +++ b/core/node/node_framework/src/implementations/layers/l1_gas.rs @@ -9,7 +9,7 @@ use crate::{ base_token_ratio_provider::BaseTokenRatioProviderResource, fee_input::{ApiFeeInputResource, SequencerFeeInputResource}, gas_adjuster::GasAdjusterResource, - l1_tx_params::L1TxParamsResource, + l1_tx_params::TxParamsResource, pools::{PoolResource, ReplicaPool}, }, wiring_layer::{WiringError, WiringLayer}, @@ -38,7 +38,7 @@ pub struct Input { pub struct Output { pub sequencer_fee_input: SequencerFeeInputResource, pub api_fee_input: ApiFeeInputResource, - pub l1_tx_params: L1TxParamsResource, + pub l1_tx_params: TxParamsResource, } impl L1GasLayer { diff --git a/core/node/node_framework/src/implementations/resources/l1_tx_params.rs b/core/node/node_framework/src/implementations/resources/l1_tx_params.rs index 7d2525603225..5cb8af5ed44c 100644 --- a/core/node/node_framework/src/implementations/resources/l1_tx_params.rs +++ b/core/node/node_framework/src/implementations/resources/l1_tx_params.rs @@ -4,17 +4,17 @@ use zksync_node_fee_model::l1_gas_price::TxParamsProvider; use crate::resource::Resource; -/// A resource that provides [`L1TxParamsProvider`] implementation to the service. +/// A resource that provides [`TxParamsProvider`] implementation to the service. #[derive(Debug, Clone)] -pub struct L1TxParamsResource(pub Arc); +pub struct TxParamsResource(pub Arc); -impl Resource for L1TxParamsResource { +impl Resource for TxParamsResource { fn name() -> String { "common/tx_params".into() } } -impl From> for L1TxParamsResource { +impl From> for TxParamsResource { fn from(provider: Arc) -> Self { Self(provider) } From 5ca14a82b321787f15968431742c71d2d5779443 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 15:49:29 +0200 Subject: [PATCH 39/43] fix Signed-off-by: tomg10 --- core/node/eth_sender/src/abstract_l1_interface.rs | 1 - core/node/eth_sender/src/eth_fees_oracle.rs | 1 + core/node/eth_sender/src/eth_tx_manager.rs | 1 - core/node/eth_sender/src/tester.rs | 7 ++----- .../src/implementations/layers/eth_sender/manager.rs | 1 - 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index 5c18476b8b0e..bac95c725773 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -3,7 +3,6 @@ use std::fmt; use async_trait::async_trait; use vise::{EncodeLabelSet, EncodeLabelValue}; use zksync_eth_client::{ - clients::{L1, L2}, BoundEthInterface, EnrichedClientResult, EthInterface, ExecutedTxStatus, FailureInfo, Options, RawTransactionBytes, SignedCallResult, }; diff --git a/core/node/eth_sender/src/eth_fees_oracle.rs b/core/node/eth_sender/src/eth_fees_oracle.rs index b7385f18dd07..c875da404fdb 100644 --- a/core/node/eth_sender/src/eth_fees_oracle.rs +++ b/core/node/eth_sender/src/eth_fees_oracle.rs @@ -15,6 +15,7 @@ pub(crate) struct EthFees { pub(crate) base_fee_per_gas: u64, pub(crate) priority_fee_per_gas: u64, pub(crate) blob_base_fee_per_gas: Option, + #[allow(dead_code)] pub(crate) pubdata_price: Option, } diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index f674f708a235..dc54683c19ac 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -4,7 +4,6 @@ use tokio::sync::watch; use zksync_config::configs::eth_sender::SenderConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_eth_client::{ - clients::{L1, L2}, encode_blob_tx_with_sidecar, BoundEthInterface, ExecutedTxStatus, RawTransactionBytes, }; use zksync_node_fee_model::l1_gas_price::TxParamsProvider; diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index 3766fec25cf5..508a38e61732 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -5,10 +5,7 @@ use zksync_config::{ ContractsConfig, EthConfig, GasAdjusterConfig, }; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{ - clients::{MockSettlementLayer, L2}, - BaseFees, BoundEthInterface, -}; +use zksync_eth_client::{clients::MockSettlementLayer, BaseFees, BoundEthInterface}; use zksync_l1_contract_interface::i_executor::methods::{ExecuteBatches, ProveBatches}; use zksync_node_fee_model::l1_gas_price::{GasAdjuster, GasAdjusterClient}; use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_artifacts}; @@ -20,7 +17,7 @@ use zksync_types::{ }; use crate::{ - abstract_l1_interface::{L1BlockNumbers, OperatorType, RealL1Interface}, + abstract_l1_interface::{L1BlockNumbers, OperatorType}, aggregated_operations::AggregatedOperation, tests::{default_l1_batch_metadata, l1_batch_with_metadata}, Aggregator, EthTxAggregator, EthTxManager, diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs index 4bb2bdcfabd9..d6989d8db72b 100644 --- a/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs +++ b/core/node/node_framework/src/implementations/layers/eth_sender/manager.rs @@ -11,7 +11,6 @@ use crate::{ BoundEthInterfaceResource, }, gas_adjuster::GasAdjusterResource, - l1_tx_params::TxParamsResource, pools::{MasterPool, PoolResource, ReplicaPool}, }, service::StopReceiver, From c7849fa8059b5a22fd7a8afdbed9db5eb6cbf7e9 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 15:57:49 +0200 Subject: [PATCH 40/43] fix Signed-off-by: tomg10 --- .../zk_inception/src/commands/ecosystem/args/create.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs index 4063f4ccdcd2..24cf4e3b4a10 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs @@ -65,9 +65,9 @@ impl EcosystemCreateArgs { } }); - let l1_network = self - .l1_network - .unwrap_or_else(|| PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask()); + let l1_network = self.l1_network.unwrap_or_else(|| { + PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask() + }); // Make the only chain as a default one self.chain.set_as_default = Some(true); From 78f32f6473325735903987f0b42fd2693b4e3c4b Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 16:32:01 +0200 Subject: [PATCH 41/43] lint fixes Signed-off-by: tomg10 --- core/node/eth_sender/src/abstract_l1_interface.rs | 3 +-- core/node/eth_sender/src/eth_tx_manager.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/node/eth_sender/src/abstract_l1_interface.rs b/core/node/eth_sender/src/abstract_l1_interface.rs index bac95c725773..312f483fd29e 100644 --- a/core/node/eth_sender/src/abstract_l1_interface.rs +++ b/core/node/eth_sender/src/abstract_l1_interface.rs @@ -249,8 +249,7 @@ impl AbstractL1Interface for RealL1Interface { .query_client(operator_type) .block_number() .await? - .as_u64() - .into(); + .as_u64(); let finalized = (latest_block_number.saturating_sub(confirmations) as u32).into(); (finalized, finalized) diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index dc54683c19ac..862aba3fac3e 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -426,7 +426,7 @@ impl EthTxManager { fn operator_type(&self, tx: &EthTx) -> OperatorType { if tx.is_gateway { OperatorType::Gateway - } else if tx.from_addr == None { + } else if tx.from_addr.is_none() { OperatorType::NonBlob } else { OperatorType::Blob From 4fd3c08d4e1d17f1a3e1b815571d92e43fa2885b Mon Sep 17 00:00:00 2001 From: tomg10 Date: Mon, 12 Aug 2024 16:39:53 +0200 Subject: [PATCH 42/43] fmt Signed-off-by: tomg10 --- .../zk_inception/src/commands/ecosystem/args/create.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs index 24cf4e3b4a10..4063f4ccdcd2 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/ecosystem/args/create.rs @@ -65,9 +65,9 @@ impl EcosystemCreateArgs { } }); - let l1_network = self.l1_network.unwrap_or_else(|| { - PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask() - }); + let l1_network = self + .l1_network + .unwrap_or_else(|| PromptSelect::new(MSG_L1_NETWORK_PROMPT, L1Network::iter()).ask()); // Make the only chain as a default one self.chain.set_as_default = Some(true); From be87c01cd0187fcc9f9ed389eeaf31cbdd9f6264 Mon Sep 17 00:00:00 2001 From: tomg10 Date: Tue, 13 Aug 2024 14:57:55 +0200 Subject: [PATCH 43/43] fix Signed-off-by: tomg10 --- core/node/eth_sender/src/eth_fees_oracle.rs | 14 +++++++------- core/node/eth_sender/src/eth_tx_manager.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/node/eth_sender/src/eth_fees_oracle.rs b/core/node/eth_sender/src/eth_fees_oracle.rs index c875da404fdb..271a33d49c32 100644 --- a/core/node/eth_sender/src/eth_fees_oracle.rs +++ b/core/node/eth_sender/src/eth_fees_oracle.rs @@ -30,7 +30,7 @@ pub(crate) trait EthFeesOracle: 'static + Sync + Send + fmt::Debug { #[derive(Debug)] pub(crate) struct GasAdjusterFeesOracle { - pub l1_gas_adjuster: Arc, + pub gas_adjuster: Arc, pub max_acceptable_priority_fee_in_gwei: u64, } @@ -39,9 +39,9 @@ impl GasAdjusterFeesOracle { &self, previous_sent_tx: &Option, ) -> Result { - let base_fee_per_gas = self.l1_gas_adjuster.get_blob_tx_base_fee(); - let priority_fee_per_gas = self.l1_gas_adjuster.get_blob_tx_priority_fee(); - let blob_base_fee_per_gas = Some(self.l1_gas_adjuster.get_blob_tx_blob_base_fee()); + let base_fee_per_gas = self.gas_adjuster.get_blob_tx_base_fee(); + let priority_fee_per_gas = self.gas_adjuster.get_blob_tx_priority_fee(); + let blob_base_fee_per_gas = Some(self.gas_adjuster.get_blob_tx_blob_base_fee()); if let Some(previous_sent_tx) = previous_sent_tx { // for blob transactions on re-sending need to double all gas prices @@ -71,7 +71,7 @@ impl GasAdjusterFeesOracle { previous_sent_tx: &Option, time_in_mempool: u32, ) -> Result { - let mut base_fee_per_gas = self.l1_gas_adjuster.get_base_fee(time_in_mempool); + let mut base_fee_per_gas = self.gas_adjuster.get_base_fee(time_in_mempool); if let Some(previous_sent_tx) = previous_sent_tx { self.verify_base_fee_not_too_low_on_resend( previous_sent_tx.id, @@ -80,7 +80,7 @@ impl GasAdjusterFeesOracle { )?; } - let mut priority_fee_per_gas = self.l1_gas_adjuster.get_priority_fee(); + let mut priority_fee_per_gas = self.gas_adjuster.get_priority_fee(); if let Some(previous_sent_tx) = previous_sent_tx { // Increase `priority_fee_per_gas` by at least 20% to prevent "replacement transaction under-priced" error. @@ -119,7 +119,7 @@ impl GasAdjusterFeesOracle { previous_base_fee: u64, base_fee_to_use: u64, ) -> Result<(), EthSenderError> { - let next_block_minimal_base_fee = self.l1_gas_adjuster.get_next_block_minimal_base_fee(); + let next_block_minimal_base_fee = self.gas_adjuster.get_next_block_minimal_base_fee(); if base_fee_to_use < min(next_block_minimal_base_fee, previous_base_fee) { // If the base fee is lower than the previous used one // or is lower than the minimal possible value for the next block, sending is skipped. diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index 862aba3fac3e..a97aed88a0a5 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -46,7 +46,7 @@ impl EthTxManager { let ethereum_gateway_blobs = ethereum_gateway_blobs.map(|eth| eth.for_component("eth_tx_manager")); let fees_oracle = GasAdjusterFeesOracle { - l1_gas_adjuster: gas_adjuster, + gas_adjuster, max_acceptable_priority_fee_in_gwei: config.max_acceptable_priority_fee_in_gwei, }; Self {