From bb5f129deb75f9dad029da55ec8e2c0defefbe6e Mon Sep 17 00:00:00 2001 From: Artem Fomiuk <88630083+Artemka374@users.noreply.github.com> Date: Tue, 7 May 2024 22:39:05 +0300 Subject: [PATCH 1/9] feat: Update provers current version (#1872) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ Update current version of provers ## Why ❔ ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- core/lib/basic_types/src/protocol_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/basic_types/src/protocol_version.rs b/core/lib/basic_types/src/protocol_version.rs index 805953e9d02..5ddd79e021f 100644 --- a/core/lib/basic_types/src/protocol_version.rs +++ b/core/lib/basic_types/src/protocol_version.rs @@ -57,7 +57,7 @@ impl ProtocolVersionId { } pub fn current_prover_version() -> Self { - Self::Version23 + Self::Version24 } pub fn next() -> Self { From 3dc0344ee24eb7fd2a903f17033860117ae3561a Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Wed, 8 May 2024 10:57:19 +0300 Subject: [PATCH 2/9] refactor(eth-client): Remove dependency on `web3` (#1857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ - Removes the dependency on `web3` crate by vendoring its relevant part (types and tokenization traits) into `zksync_basic_types`. - Refactors `zksync_eth_client` to use `jsonrpsee` instead of `web3` + `jsonrpc-core`. ## Why ❔ `web3` and `jsonrpc-core` are both unmaintained or barely maintained. Using two RPC libraries for L1 / L2 clients is clearly suboptimal. ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Tests for the changes have been added / updated. - [x] Documentation comments have been added / updated. - [x] Code has been formatted via `zk fmt` and `zk lint`. - [x] Spellcheck has been run via `zk spellcheck`. - [x] Linkcheck has been run via `zk linkcheck`. --- Cargo.lock | 114 +-- Cargo.toml | 2 +- core/bin/block_reverter/src/main.rs | 54 +- core/bin/external_node/src/tests.rs | 22 +- core/lib/basic_types/Cargo.toml | 5 +- core/lib/basic_types/src/lib.rs | 9 +- core/lib/basic_types/src/protocol_version.rs | 18 +- core/lib/basic_types/src/web3/contract.rs | 186 ++++ core/lib/basic_types/src/web3/mod.rs | 962 ++++++++++++++++++ core/lib/basic_types/src/web3/tests.rs | 85 ++ core/lib/config/src/configs/chain.rs | 11 +- core/lib/crypto/src/hasher/keccak.rs | 2 +- core/lib/crypto_primitives/Cargo.toml | 1 - .../crypto_primitives/src/ecdsa_signature.rs | 39 +- .../src/eip712_signature/member_types.rs | 3 +- .../src/eip712_signature/tests.rs | 3 +- .../src/eip712_signature/typed_structure.rs | 3 +- .../src/packed_eth_signature.rs | 3 +- core/lib/dal/src/blocks_web3_dal.rs | 4 +- core/lib/dal/src/consensus/tests.rs | 2 +- core/lib/dal/src/models/storage_event.rs | 4 +- .../lib/dal/src/models/storage_transaction.rs | 8 +- core/lib/dal/src/models/tests.rs | 6 +- core/lib/eth_client/Cargo.toml | 6 +- core/lib/eth_client/src/clients/http/decl.rs | 75 ++ core/lib/eth_client/src/clients/http/mod.rs | 1 + core/lib/eth_client/src/clients/http/query.rs | 156 +-- .../eth_client/src/clients/http/signing.rs | 22 +- core/lib/eth_client/src/clients/mock.rs | 76 +- core/lib/eth_client/src/lib.rs | 33 +- core/lib/eth_client/src/types.rs | 353 ++----- core/lib/eth_signer/Cargo.toml | 10 +- core/lib/eth_signer/src/json_rpc_signer.rs | 2 +- core/lib/eth_signer/src/pk_signer.rs | 2 +- core/lib/eth_signer/src/raw_ethereum_tx.rs | 22 +- .../src/i_executor/methods/execute_batches.rs | 6 +- .../src/i_executor/methods/prove_batches.rs | 6 +- .../structures/commit_batch_info.rs | 20 +- .../structures/stored_batch_info.rs | 14 +- core/lib/l1_contract_interface/src/lib.rs | 2 +- .../src/multicall3/mod.rs | 13 +- .../src/tracers/prestate_tracer/mod.rs | 4 +- core/lib/multivm/src/tracers/validator/mod.rs | 2 +- .../vm_1_3_2/oracles/tracer/validation.rs | 4 +- .../src/versions/vm_1_3_2/test_utils.rs | 2 +- .../types/internals/transaction_data.rs | 6 +- .../src/versions/vm_1_4_1/utils/l2_blocks.rs | 3 +- .../types/internals/transaction_data.rs | 6 +- .../src/versions/vm_1_4_2/utils/l2_blocks.rs | 3 +- .../types/internals/transaction_data.rs | 6 +- .../vm_boojum_integration/utils/l2_blocks.rs | 3 +- .../versions/vm_latest/tests/code_oracle.rs | 2 +- .../src/versions/vm_latest/tests/sekp256r1.rs | 2 +- .../types/internals/transaction_data.rs | 6 +- .../src/versions/vm_latest/utils/l2_blocks.rs | 3 +- .../src/versions/vm_m5/oracles/tracer.rs | 2 +- .../multivm/src/versions/vm_m5/test_utils.rs | 2 +- .../vm_m6/oracles/tracer/validation.rs | 4 +- .../multivm/src/versions/vm_m6/test_utils.rs | 2 +- .../types/internals/transaction_data.rs | 6 +- .../vm_refunds_enhancement/utils/l2_blocks.rs | 3 +- .../types/internals/transaction_data.rs | 6 +- .../vm_virtual_blocks/utils/l2_blocks.rs | 3 +- core/lib/object_store/src/objects.rs | 3 +- core/lib/snapshots_applier/Cargo.toml | 1 + core/lib/snapshots_applier/src/lib.rs | 1 - core/lib/snapshots_applier/src/tests/utils.rs | 3 +- core/lib/types/src/api/mod.rs | 5 +- core/lib/types/src/block.rs | 2 +- core/lib/types/src/commitment/mod.rs | 2 +- .../types/src/contract_verification_api.rs | 2 +- core/lib/types/src/debug_flat_call.rs | 2 +- core/lib/types/src/event/mod.rs | 4 +- core/lib/types/src/l1/mod.rs | 3 +- core/lib/types/src/l2/mod.rs | 10 +- core/lib/types/src/lib.rs | 2 +- core/lib/types/src/protocol_upgrade.rs | 4 +- core/lib/types/src/snapshots.rs | 2 +- core/lib/types/src/storage/mod.rs | 2 +- core/lib/types/src/transaction_request.rs | 50 +- core/lib/types/src/tx/execute.rs | 2 +- core/lib/types/src/utils.rs | 4 +- core/lib/utils/src/misc.rs | 2 +- core/lib/web3_decl/src/types.rs | 10 +- .../src/api_server/tx_sender/proxy.rs | 2 +- .../web3/backend_jsonrpsee/namespaces/eth.rs | 4 +- .../web3/backend_jsonrpsee/namespaces/zks.rs | 3 +- .../src/api_server/web3/metrics.rs | 2 +- .../src/api_server/web3/namespaces/eth.rs | 9 +- .../src/api_server/web3/namespaces/zks.rs | 3 +- .../src/consistency_checker/mod.rs | 39 +- .../src/consistency_checker/tests/mod.rs | 15 +- core/lib/zksync_core/src/utils/mod.rs | 55 +- core/node/block_reverter/Cargo.toml | 2 +- core/node/block_reverter/src/lib.rs | 145 +-- core/node/eth_sender/src/eth_tx_aggregator.rs | 23 +- core/node/eth_sender/src/eth_tx_manager.rs | 12 +- core/node/eth_sender/src/tests.rs | 4 +- core/node/eth_watch/src/client.rs | 28 +- .../event_processors/governance_upgrades.rs | 4 +- .../eth_watch/src/event_processors/mod.rs | 2 +- .../src/event_processors/priority_ops.rs | 2 +- core/node/eth_watch/src/lib.rs | 2 +- core/node/eth_watch/src/tests.rs | 6 +- core/node/genesis/src/lib.rs | 2 +- .../src/request_processor.rs | 2 +- .../src/account/tx_command_executor.rs | 2 +- core/tests/loadnext/src/executor.rs | 2 +- core/tests/loadnext/src/rng.rs | 2 +- core/tests/loadnext/src/sdk/ethereum/mod.rs | 50 +- core/tests/loadnext/src/sdk/mod.rs | 2 +- .../loadnext/src/sdk/operations/transfer.rs | 2 +- .../loadnext/src/sdk/operations/withdraw.rs | 4 +- core/tests/loadnext/src/sdk/utils.rs | 2 +- core/tests/loadnext/src/sdk/wallet.rs | 5 +- prover/Cargo.lock | 221 +--- prover/witness_generator/src/main.rs | 6 +- 117 files changed, 1966 insertions(+), 1259 deletions(-) create mode 100644 core/lib/basic_types/src/web3/contract.rs create mode 100644 core/lib/basic_types/src/web3/mod.rs create mode 100644 core/lib/basic_types/src/web3/tests.rs create mode 100644 core/lib/eth_client/src/clients/http/decl.rs diff --git a/Cargo.lock b/Cargo.lock index d31d7c8524c..3b89168b2ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1703,19 +1703,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2 1.0.69", - "quote 1.0.33", - "rustc_version", - "syn 1.0.109", -] - [[package]] name = "derive_more" version = "1.0.0-beta.6" @@ -2659,30 +2646,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.3.3" @@ -3132,7 +3095,7 @@ dependencies = [ "tokio-util", "tracing", "url", - "webpki-roots 0.26.0", + "webpki-roots", ] [[package]] @@ -5170,7 +5133,6 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -5181,15 +5143,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.11", - "rustls-pemfile 1.0.3", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.24.1", "tokio-util", "tower-service", "url", @@ -5197,7 +5156,6 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.2", "winreg", ] @@ -7528,60 +7486,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web3" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5388522c899d1e1c96a4c307e3797e0f697ba7c77dd8e0e625ecba9dd0342937" -dependencies = [ - "arrayvec 0.7.4", - "base64 0.21.5", - "bytes", - "derive_more 0.99.17", - "ethabi", - "ethereum-types", - "futures 0.3.28", - "futures-timer", - "headers", - "hex", - "idna", - "jsonrpc-core", - "log", - "once_cell", - "parking_lot", - "pin-project", - "reqwest", - "rlp", - "secp256k1", - "serde", - "serde_json", - "soketto", - "tiny-keccak 2.0.2", - "tokio", - "tokio-stream", - "tokio-util", - "url", - "web3-async-native-tls", -] - -[[package]] -name = "web3-async-native-tls" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" -dependencies = [ - "native-tls", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - [[package]] name = "webpki-roots" version = "0.26.0" @@ -8118,12 +8022,15 @@ dependencies = [ "anyhow", "bincode", "chrono", + "ethabi", + "hex", "num_enum 0.7.2", "serde", "serde_json", "strum", + "thiserror", + "tiny-keccak 2.0.2", "url", - "web3", ] [[package]] @@ -8140,7 +8047,7 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_dal", - "zksync_eth_signer", + "zksync_eth_client", "zksync_merkle_tree", "zksync_object_store", "zksync_state", @@ -8507,7 +8414,6 @@ dependencies = [ "serde", "serde_json", "thiserror", - "web3", "zksync_basic_types", "zksync_utils", ] @@ -8579,10 +8485,9 @@ version = "0.1.0" dependencies = [ "async-trait", "hex", - "jsonrpc-core", + "jsonrpsee", "pretty_assertions", "rlp", - "serde", "serde_json", "static_assertions", "thiserror", @@ -8634,9 +8539,7 @@ dependencies = [ "jsonrpc-core", "reqwest", "rlp", - "secp256k1", "serde", - "serde_derive", "serde_json", "thiserror", "tokio", @@ -9083,6 +8986,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", + "futures 0.3.28", "serde", "test-casing", "thiserror", @@ -9165,7 +9069,7 @@ dependencies = [ "bincode", "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "chrono", - "derive_more 1.0.0-beta.6", + "derive_more", "hex", "itertools 0.10.5", "num", diff --git a/Cargo.toml b/Cargo.toml index 115e18d0a4a..2d04037ea58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,7 +137,6 @@ secp256k1 = { version = "0.27.0", features = ["recovery", "global-context"] } semver = "1" sentry = "0.31" serde = "1" -serde_derive = "1.0.90" serde_json = "1" serde_with = "1" serde_yaml = "0.9" @@ -153,6 +152,7 @@ test-log = "0.2.15" thiserror = "1" thread_local = "1.1" tikv-jemallocator = "0.5" +tiny-keccak = "2" tokio = "1" tower = "0.4.13" tower-http = "0.4.1" diff --git a/core/bin/block_reverter/src/main.rs b/core/bin/block_reverter/src/main.rs index e24c1f72655..5bd15def73a 100644 --- a/core/bin/block_reverter/src/main.rs +++ b/core/bin/block_reverter/src/main.rs @@ -3,7 +3,13 @@ use std::env; use anyhow::Context as _; use clap::{Parser, Subcommand}; use tokio::io::{self, AsyncReadExt}; -use zksync_block_reverter::{BlockReverter, BlockReverterEthConfig, NodeRole}; +use zksync_block_reverter::{ + eth_client::{ + clients::{PKSigningClient, QueryClient}, + EthInterface, + }, + BlockReverter, BlockReverterEthConfig, NodeRole, +}; use zksync_config::{ configs::{chain::NetworkConfig, ObservabilityConfig}, ContractsConfig, DBConfig, EthConfig, PostgresConfig, @@ -11,7 +17,7 @@ use zksync_config::{ use zksync_dal::{ConnectionPool, Core}; use zksync_env_config::{object_store::SnapshotsObjectStoreConfig, FromEnv}; use zksync_object_store::ObjectStoreFactory; -use zksync_types::{Address, L1BatchNumber, U256}; +use zksync_types::{Address, L1BatchNumber}; #[derive(Debug, Parser)] #[command(author = "Matter Labs", version, about = "Block revert utility", long_about = None)] @@ -94,12 +100,10 @@ async fn main() -> anyhow::Result<()> { let eth_sender = EthConfig::from_env().context("EthConfig::from_env()")?; let db_config = DBConfig::from_env().context("DBConfig::from_env()")?; - let default_priority_fee_per_gas = U256::from( - eth_sender - .gas_adjuster - .context("gas_adjuster")? - .default_priority_fee_per_gas, - ); + let default_priority_fee_per_gas = eth_sender + .gas_adjuster + .context("gas_adjuster")? + .default_priority_fee_per_gas; let contracts = ContractsConfig::from_env().context("ContractsConfig::from_env()")?; let network = NetworkConfig::from_env().context("NetworkConfig::from_env()")?; let postgres_config = PostgresConfig::from_env().context("PostgresConfig::from_env()")?; @@ -109,7 +113,7 @@ async fn main() -> anyhow::Result<()> { .map_err(|err| { anyhow::anyhow!("failed parsing `CONTRACTS_ERA_CHAIN_ID` env variable: {err}") })?; - let config = BlockReverterEthConfig::new(eth_sender, &contracts, &network, era_chain_id)?; + let config = BlockReverterEthConfig::new(ð_sender, &contracts, &network, era_chain_id)?; let connection_pool = ConnectionPool::::builder( postgres_config.master_url()?, @@ -125,8 +129,11 @@ async fn main() -> anyhow::Result<()> { json, operator_address, } => { + let eth_client = + QueryClient::new(eth_sender.web3_url.clone()).context("Ethereum client")?; + let suggested_values = block_reverter - .suggested_values(&config, operator_address) + .suggested_values(ð_client, &config, operator_address) .await?; if json { println!("{}", serde_json::to_string(&suggested_values)?); @@ -139,13 +146,34 @@ async fn main() -> anyhow::Result<()> { priority_fee_per_gas, nonce, } => { - let priority_fee_per_gas = - priority_fee_per_gas.map_or(default_priority_fee_per_gas, U256::from); + let eth_client = + QueryClient::new(eth_sender.web3_url.clone()).context("Ethereum client")?; + #[allow(deprecated)] + let reverter_private_key = eth_sender + .sender + .context("eth_sender_config")? + .private_key() + .context("eth_sender_config.private_key")? + .context("eth_sender_config.private_key is not set")?; + + let priority_fee_per_gas = priority_fee_per_gas.unwrap_or(default_priority_fee_per_gas); + let l1_chain_id = eth_client + .fetch_chain_id() + .await + .context("cannot fetch Ethereum chain ID")?; + let eth_client = PKSigningClient::new_raw( + reverter_private_key, + contracts.diamond_proxy_addr, + priority_fee_per_gas, + l1_chain_id, + Box::new(eth_client), + ); + block_reverter .send_ethereum_revert_transaction( + ð_client, &config, L1BatchNumber(l1_batch_number), - priority_fee_per_gas, nonce, ) .await?; diff --git a/core/bin/external_node/src/tests.rs b/core/bin/external_node/src/tests.rs index c31ec1c62b5..d1ab1ab00b6 100644 --- a/core/bin/external_node/src/tests.rs +++ b/core/bin/external_node/src/tests.rs @@ -163,12 +163,24 @@ async fn external_node_basics(components_str: &'static str) { }); let l2_client = BoxedL2Client::new(l2_client); - let eth_client = MockEthereum::default().with_call_handler(move |call| { + let eth_client = MockEthereum::default().with_call_handler(move |call, _| { tracing::info!("L1 call: {call:?}"); - if call.contract_address() == diamond_proxy_addr { - match call.function_name() { - "getPubdataPricingMode" => return ethabi::Token::Uint(0.into()), // "rollup" mode encoding - "getProtocolVersion" => { + if call.to == Some(diamond_proxy_addr) { + let call_signature = &call.data.as_ref().unwrap().0[..4]; + let contract = zksync_contracts::hyperchain_contract(); + let pricing_mode_sig = contract + .function("getPubdataPricingMode") + .unwrap() + .short_signature(); + let protocol_version_sig = contract + .function("getProtocolVersion") + .unwrap() + .short_signature(); + match call_signature { + sig if sig == pricing_mode_sig => { + return ethabi::Token::Uint(0.into()); // "rollup" mode encoding + } + sig if sig == protocol_version_sig => { return ethabi::Token::Uint((ProtocolVersionId::latest() as u16).into()) } _ => { /* unknown call; panic below */ } diff --git a/core/lib/basic_types/Cargo.toml b/core/lib/basic_types/Cargo.toml index d4ecd72f060..918aa41cad0 100644 --- a/core/lib/basic_types/Cargo.toml +++ b/core/lib/basic_types/Cargo.toml @@ -10,7 +10,10 @@ keywords.workspace = true categories.workspace = true [dependencies] -web3 = { workspace = true, features = ["http-rustls-tls", "test", "signing"] } +ethabi.workspace = true +hex.workspace = true +tiny-keccak.workspace = true +thiserror.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true chrono.workspace = true diff --git a/core/lib/basic_types/src/lib.rs b/core/lib/basic_types/src/lib.rs index 36d3f8e6d1e..d30418bfc33 100644 --- a/core/lib/basic_types/src/lib.rs +++ b/core/lib/basic_types/src/lib.rs @@ -13,11 +13,11 @@ use std::{ str::FromStr, }; -use serde::{de, Deserialize, Deserializer, Serialize}; -pub use web3::{ - self, ethabi, - types::{Address, Bytes, Log, TransactionRequest, H128, H160, H2048, H256, U128, U256, U64}, +pub use ethabi::{ + self, + ethereum_types::{Address, Bloom as H2048, H128, H160, H256, H512, H520, H64, U128, U256, U64}, }; +use serde::{de, Deserialize, Deserializer, Serialize}; #[macro_use] mod macros; @@ -27,6 +27,7 @@ pub mod protocol_version; pub mod prover_dal; pub mod url; pub mod vm_version; +pub mod web3; /// Account place in the global state tree is uniquely identified by its address. /// Binary this type is represented by 160 bit big-endian representation of account address. diff --git a/core/lib/basic_types/src/protocol_version.rs b/core/lib/basic_types/src/protocol_version.rs index 5ddd79e021f..b5d15e6cbc7 100644 --- a/core/lib/basic_types/src/protocol_version.rs +++ b/core/lib/basic_types/src/protocol_version.rs @@ -2,9 +2,13 @@ use std::convert::{TryFrom, TryInto}; use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; -use web3::contract::{tokens::Detokenize, Error}; -use crate::{ethabi::Token, vm_version::VmVersion, H256, U256}; +use crate::{ + ethabi::Token, + vm_version::VmVersion, + web3::contract::{Detokenize, Error}, + H256, U256, +}; #[repr(u16)] #[derive( @@ -178,12 +182,18 @@ pub struct VerifierParams { impl Detokenize for VerifierParams { fn from_tokens(tokens: Vec) -> Result { if tokens.len() != 1 { - return Err(Error::Abi(crate::ethabi::Error::InvalidData)); + return Err(Error::InvalidOutputType(format!( + "expected single token, got {tokens:?}" + ))); } let tokens = match tokens[0].clone() { Token::Tuple(tokens) => tokens, - _ => return Err(Error::Abi(crate::ethabi::Error::InvalidData)), + other => { + return Err(Error::InvalidOutputType(format!( + "expected a tuple, got {other:?}" + ))) + } }; let vks_vec: Vec = tokens diff --git a/core/lib/basic_types/src/web3/contract.rs b/core/lib/basic_types/src/web3/contract.rs new file mode 100644 index 00000000000..1f24034c974 --- /dev/null +++ b/core/lib/basic_types/src/web3/contract.rs @@ -0,0 +1,186 @@ +//! Serialization logic allowing to convert between [`ethabi::Token`]s and domain types, such as `H256`, +//! `U256` and `Address`. +//! +//! The majority of the code is copied from the `web3` crate 0.19.0, https://github.com/tomusdrw/rust-web3, +//! licensed under the MIT open-source license. + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("invalid output type: {0}")] + InvalidOutputType(String), + #[error("{0}")] + Other(String), +} + +use crate::{H160, H256, U256}; + +pub trait Detokenize: Sized { + fn from_tokens(tokens: Vec) -> Result; +} + +impl Detokenize for T { + fn from_tokens(mut tokens: Vec) -> Result { + if tokens.len() != 1 { + return Err(Error::InvalidOutputType(format!( + "expected array with 1 token, got {tokens:?}" + ))); + } + Self::from_token(tokens.pop().unwrap()) + } +} + +pub trait Tokenize { + fn into_tokens(self) -> Vec; +} + +impl Tokenize for T { + fn into_tokens(self) -> Vec { + vec![self.into_token()] + } +} + +impl Tokenize for () { + fn into_tokens(self) -> Vec { + vec![] + } +} + +macro_rules! impl_tokenize_for_tuple { + ($($idx:tt : $ty:ident),+) => { + impl<$($ty,)+> Tokenize for ($($ty,)+) + where + $($ty : Tokenizable,)+ + { + fn into_tokens(self) -> Vec { + vec![$(self.$idx.into_token(),)+] + } + } + }; +} + +impl_tokenize_for_tuple!(0: A); +impl_tokenize_for_tuple!(0: A, 1: B); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C, 3: D); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G); +impl_tokenize_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H); + +pub trait Tokenizable: Sized { + fn from_token(token: ethabi::Token) -> Result; + fn into_token(self) -> ethabi::Token; +} + +impl Tokenizable for bool { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::Bool(flag) => Ok(flag), + _ => Err(Error::InvalidOutputType(format!( + "expected Boolean, got {token:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::Bool(self) + } +} + +impl Tokenizable for H160 { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::Address(address) => Ok(address), + _ => Err(Error::InvalidOutputType(format!( + "expected address, got {token:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::Address(self) + } +} + +impl Tokenizable for U256 { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::Uint(value) => Ok(value), + _ => Err(Error::InvalidOutputType(format!( + "expected uint256, got {token:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::Uint(self) + } +} + +impl Tokenizable for H256 { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::FixedBytes(value) => { + value.as_slice().try_into().map(H256).map_err(|_| { + Error::InvalidOutputType(format!("expected bytes32, got {value:?}")) + }) + } + _ => Err(Error::InvalidOutputType(format!( + "expected bytes32, got {token:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::FixedBytes(self.as_bytes().to_vec()) + } +} + +impl Tokenizable for Vec { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::Bytes(bytes) => Ok(bytes), + _ => Err(Error::InvalidOutputType(format!( + "expected bytes, got {token:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::Bytes(self) + } +} + +impl Tokenizable for ethabi::Token { + fn from_token(token: ethabi::Token) -> Result { + Ok(token) + } + + fn into_token(self) -> ethabi::Token { + self + } +} + +impl Tokenizable for Vec { + fn from_token(token: ethabi::Token) -> Result { + match token { + ethabi::Token::FixedArray(tokens) | ethabi::Token::Array(tokens) => { + tokens.into_iter().map(Tokenizable::from_token).collect() + } + other => Err(Error::InvalidOutputType(format!( + "Expected `Array`, got {other:?}" + ))), + } + } + + fn into_token(self) -> ethabi::Token { + ethabi::Token::Array(self.into_iter().map(Tokenizable::into_token).collect()) + } +} + +/// Marker trait for `Tokenizable` types that are can tokenized to and from a +/// `Token::Array` and `Token:FixedArray`. +pub trait TokenizableItem: Tokenizable {} + +impl TokenizableItem for ethabi::Token {} +impl TokenizableItem for Vec {} diff --git a/core/lib/basic_types/src/web3/mod.rs b/core/lib/basic_types/src/web3/mod.rs new file mode 100644 index 00000000000..be785040d2d --- /dev/null +++ b/core/lib/basic_types/src/web3/mod.rs @@ -0,0 +1,962 @@ +//! Selected Web3 types copied from the `web3` crate. +//! +//! The majority of the code is copied verbatim from the `web3` crate 0.19.0, https://github.com/tomusdrw/rust-web3, +//! licensed under the MIT open-source license. + +use std::fmt; + +use ethabi::ethereum_types::{Address, H64}; +use serde::{ + de::{Error, Unexpected, Visitor}, + ser::SerializeStruct, + Deserialize, Deserializer, Serialize, Serializer, +}; +use serde_json::Value; + +use crate::{H160, H2048, H256, U256, U64}; + +pub mod contract; +#[cfg(test)] +mod tests; + +pub type Index = U64; + +// `Signature`, `keccak256`: from `web3::signing` + +/// A struct that represents the components of a secp256k1 signature. +pub struct Signature { + /// V component in Electrum format with chain-id replay protection. + pub v: u64, + /// R component of the signature. + pub r: H256, + /// S component of the signature. + pub s: H256, +} + +/// Compute the Keccak-256 hash of input bytes. +pub fn keccak256(bytes: &[u8]) -> [u8; 32] { + use tiny_keccak::{Hasher, Keccak}; + + let mut output = [0u8; 32]; + let mut hasher = Keccak::v256(); + hasher.update(bytes); + hasher.finalize(&mut output); + output +} + +// `Bytes`: from `web3::types::bytes` + +/// Raw bytes wrapper +#[derive(Clone, Default, PartialEq, Eq, Hash)] +pub struct Bytes(pub Vec); + +impl>> From for Bytes { + fn from(data: T) -> Self { + Bytes(data.into()) + } +} + +impl Serialize for Bytes { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut serialized = "0x".to_owned(); + serialized.push_str(&hex::encode(&self.0)); + serializer.serialize_str(serialized.as_ref()) + } +} + +impl<'a> Deserialize<'a> for Bytes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + deserializer.deserialize_identifier(BytesVisitor) + } +} + +impl fmt::Debug for Bytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let serialized = format!("0x{}", hex::encode(&self.0)); + f.debug_tuple("Bytes").field(&serialized).finish() + } +} + +struct BytesVisitor; + +impl<'a> Visitor<'a> for BytesVisitor { + type Value = Bytes; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a 0x-prefixed hex-encoded vector of bytes") + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + if let Some(value) = value.strip_prefix("0x") { + let bytes = + hex::decode(value).map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?; + Ok(Bytes(bytes)) + } else { + Err(Error::invalid_value(Unexpected::Str(value), &"0x prefix")) + } + } + + fn visit_string(self, value: String) -> Result + where + E: Error, + { + self.visit_str(value.as_ref()) + } +} + +// `Log`: from `web3::types::log` + +/// Filter +#[derive(Default, Debug, PartialEq, Clone, Serialize)] +pub struct Filter { + /// From Block + #[serde(rename = "fromBlock", skip_serializing_if = "Option::is_none")] + from_block: Option, + /// To Block + #[serde(rename = "toBlock", skip_serializing_if = "Option::is_none")] + to_block: Option, + /// Block Hash + #[serde(rename = "blockHash", skip_serializing_if = "Option::is_none")] + block_hash: Option, + /// Address + #[serde(skip_serializing_if = "Option::is_none")] + address: Option>, + /// Topics + #[serde(skip_serializing_if = "Option::is_none")] + topics: Option>>>, + /// Limit + #[serde(skip_serializing_if = "Option::is_none")] + limit: Option, +} + +#[derive(Default, Debug, PartialEq, Clone)] +struct ValueOrArray(Vec); + +impl Serialize for ValueOrArray +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self.0.len() { + 0 => serializer.serialize_none(), + 1 => Serialize::serialize(&self.0[0], serializer), + _ => Serialize::serialize(&self.0, serializer), + } + } +} + +// Filter Builder +#[derive(Default, Clone)] +pub struct FilterBuilder { + filter: Filter, +} + +impl FilterBuilder { + /// Sets `from_block`. The fields `from_block` and `block_hash` are + /// mutually exclusive. Setting `from_block` will clear a previously set + /// `block_hash`. + pub fn from_block(mut self, block: BlockNumber) -> Self { + self.filter.block_hash = None; + self.filter.from_block = Some(block); + self + } + + /// Sets `to_block`. The fields `to_block` and `block_hash` are mutually + /// exclusive. Setting `to_block` will clear a previously set `block_hash`. + pub fn to_block(mut self, block: BlockNumber) -> Self { + self.filter.block_hash = None; + self.filter.to_block = Some(block); + self + } + + /// Sets `block_hash`. The field `block_hash` and the pair `from_block` and + /// `to_block` are mutually exclusive. Setting `block_hash` will clear a + /// previously set `from_block` and `to_block`. + pub fn block_hash(mut self, hash: H256) -> Self { + self.filter.from_block = None; + self.filter.to_block = None; + self.filter.block_hash = Some(hash); + self + } + + /// Single address + pub fn address(mut self, address: Vec) -> Self { + self.filter.address = Some(ValueOrArray(address)); + self + } + + /// Topics + pub fn topics( + mut self, + topic1: Option>, + topic2: Option>, + topic3: Option>, + topic4: Option>, + ) -> Self { + let mut topics = vec![topic1, topic2, topic3, topic4] + .into_iter() + .rev() + .skip_while(Option::is_none) + .map(|option| option.map(ValueOrArray)) + .collect::>(); + topics.reverse(); + + self.filter.topics = Some(topics); + self + } + + /// Sets the topics according to the given `ethabi` topic filter + pub fn topic_filter(self, topic_filter: ethabi::TopicFilter) -> Self { + self.topics( + topic_to_option(topic_filter.topic0), + topic_to_option(topic_filter.topic1), + topic_to_option(topic_filter.topic2), + topic_to_option(topic_filter.topic3), + ) + } + + /// Limit the result + pub fn limit(mut self, limit: usize) -> Self { + self.filter.limit = Some(limit); + self + } + + /// Returns filter + pub fn build(&self) -> Filter { + self.filter.clone() + } +} + +/// Converts a `Topic` to an equivalent `Option>`, suitable for `FilterBuilder::topics` +fn topic_to_option(topic: ethabi::Topic) -> Option> { + match topic { + ethabi::Topic::Any => None, + ethabi::Topic::OneOf(v) => Some(v), + ethabi::Topic::This(t) => Some(vec![t]), + } +} + +/// A log produced by a transaction. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Log { + /// H160 + pub address: H160, + /// Topics + pub topics: Vec, + /// Data + pub data: Bytes, + /// Block Hash + #[serde(rename = "blockHash")] + pub block_hash: Option, + /// Block Number + #[serde(rename = "blockNumber")] + pub block_number: Option, + /// Transaction Hash + #[serde(rename = "transactionHash")] + pub transaction_hash: Option, + /// Transaction Index + #[serde(rename = "transactionIndex")] + pub transaction_index: Option, + /// Log Index in Block + #[serde(rename = "logIndex")] + pub log_index: Option, + /// Log Index in Transaction + #[serde(rename = "transactionLogIndex")] + pub transaction_log_index: Option, + /// Log Type + #[serde(rename = "logType")] + pub log_type: Option, + /// Removed + pub removed: Option, +} + +impl Log { + /// Returns true if the log has been removed. + pub fn is_removed(&self) -> bool { + if let Some(val_removed) = self.removed { + return val_removed; + } + if let Some(val_log_type) = &self.log_type { + if val_log_type == "removed" { + return true; + } + } + false + } +} + +// `BlockHeader`, `BlockId`, `BlockNumber`: from `web3::types::block` + +/// The block header type returned from RPC calls. +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct BlockHeader { + /// Hash of the block + pub hash: Option, + /// Hash of the parent + #[serde(rename = "parentHash")] + pub parent_hash: H256, + /// Hash of the uncles + #[serde(rename = "sha3Uncles")] + #[serde(default)] + pub uncles_hash: H256, + /// Miner / author's address. + #[serde(rename = "miner", default, deserialize_with = "null_to_default")] + pub author: H160, + /// State root hash + #[serde(rename = "stateRoot")] + pub state_root: H256, + /// Transactions root hash + #[serde(rename = "transactionsRoot")] + pub transactions_root: H256, + /// Transactions receipts root hash + #[serde(rename = "receiptsRoot")] + pub receipts_root: H256, + /// Block number. None if pending. + pub number: Option, + /// Gas Used + #[serde(rename = "gasUsed")] + pub gas_used: U256, + /// Gas Limit + #[serde(rename = "gasLimit", default)] + pub gas_limit: U256, + /// Base fee per unit of gas (if past London) + #[serde(rename = "baseFeePerGas", skip_serializing_if = "Option::is_none")] + pub base_fee_per_gas: Option, + /// Extra data + #[serde(rename = "extraData")] + pub extra_data: Bytes, + /// Logs bloom + #[serde(rename = "logsBloom")] + pub logs_bloom: H2048, + /// Timestamp + pub timestamp: U256, + /// Difficulty + #[serde(default)] + pub difficulty: U256, + /// Mix Hash + #[serde(rename = "mixHash")] + pub mix_hash: Option, + /// Nonce + pub nonce: Option, +} + +/// The block type returned from RPC calls. +#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] +pub struct Block { + /// Hash of the block + pub hash: Option, + /// Hash of the parent + #[serde(rename = "parentHash")] + pub parent_hash: H256, + /// Hash of the uncles + #[serde(rename = "sha3Uncles", default)] + pub uncles_hash: H256, + /// Author's address. + #[serde(rename = "miner", default, deserialize_with = "null_to_default")] + pub author: H160, + /// State root hash + #[serde(rename = "stateRoot")] + pub state_root: H256, + /// Transactions root hash + #[serde(rename = "transactionsRoot")] + pub transactions_root: H256, + /// Transactions receipts root hash + #[serde(rename = "receiptsRoot")] + pub receipts_root: H256, + /// Block number. None if pending. + pub number: Option, + /// Gas Used + #[serde(rename = "gasUsed")] + pub gas_used: U256, + /// Gas Limit + #[serde(rename = "gasLimit", default)] + pub gas_limit: U256, + /// Base fee per unit of gas (if past London) + #[serde(rename = "baseFeePerGas", skip_serializing_if = "Option::is_none")] + pub base_fee_per_gas: Option, + /// Extra data + #[serde(rename = "extraData")] + pub extra_data: Bytes, + /// Logs bloom + #[serde(rename = "logsBloom")] + pub logs_bloom: Option, + /// Timestamp + pub timestamp: U256, + /// Difficulty + #[serde(default)] + pub difficulty: U256, + /// Total difficulty + #[serde(rename = "totalDifficulty")] + pub total_difficulty: Option, + /// Seal fields + #[serde(default, rename = "sealFields")] + pub seal_fields: Vec, + /// Uncles' hashes + #[serde(default)] + pub uncles: Vec, + /// Transactions + pub transactions: Vec, + /// Size in bytes + pub size: Option, + /// Mix Hash + #[serde(rename = "mixHash")] + pub mix_hash: Option, + /// Nonce + pub nonce: Option, + /// Excess blob gas + #[serde(rename = "excessBlobGas")] + pub excess_blob_gas: Option, +} + +fn null_to_default<'de, D, T>(deserializer: D) -> Result +where + T: Default + Deserialize<'de>, + D: Deserializer<'de>, +{ + let option = Option::deserialize(deserializer)?; + Ok(option.unwrap_or_default()) +} + +/// Block Identifier +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum BlockId { + /// By Hash + Hash(H256), + /// By Number + Number(BlockNumber), +} + +impl Serialize for BlockId { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + BlockId::Hash(x) => { + let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?; + s.serialize_field("blockHash", &format!("{:?}", x))?; + s.end() + } + BlockId::Number(ref num) => num.serialize(serializer), + } + } +} + +impl From for BlockId { + fn from(num: U64) -> Self { + BlockNumber::Number(num).into() + } +} + +impl From for BlockId { + fn from(num: BlockNumber) -> Self { + BlockId::Number(num) + } +} + +impl From for BlockId { + fn from(hash: H256) -> Self { + BlockId::Hash(hash) + } +} + +/// Block Number +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum BlockNumber { + /// Finalized block + Finalized, + /// Safe block + Safe, + /// Latest block + Latest, + /// Earliest block (genesis) + Earliest, + /// Pending block (not yet part of the blockchain) + Pending, + /// Block by number from canon chain + Number(U64), +} + +impl> From for BlockNumber { + fn from(num: T) -> Self { + BlockNumber::Number(num.into()) + } +} + +impl Serialize for BlockNumber { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + BlockNumber::Number(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), + BlockNumber::Latest => serializer.serialize_str("latest"), + BlockNumber::Earliest => serializer.serialize_str("earliest"), + BlockNumber::Pending => serializer.serialize_str("pending"), + BlockNumber::Finalized => serializer.serialize_str("finalized"), + BlockNumber::Safe => serializer.serialize_str("safe"), + } + } +} + +impl<'a> Deserialize<'a> for BlockNumber { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + let value = String::deserialize(deserializer)?; + match value.as_str() { + "latest" => Ok(BlockNumber::Latest), + "earliest" => Ok(BlockNumber::Earliest), + "pending" => Ok(BlockNumber::Pending), + "finalized" => Ok(BlockNumber::Finalized), + "safe" => Ok(BlockNumber::Safe), + _ if value.starts_with("0x") => U64::from_str_radix(&value[2..], 16) + .map(BlockNumber::Number) + .map_err(|e| D::Error::custom(format!("invalid block number: {}", e))), + _ => Err(D::Error::custom( + "invalid block number: missing 0x prefix".to_string(), + )), + } + } +} + +// `AccessList`, `AccessListItem`, `TransactionReceipt`, `SignedTransaction`: from `web3::types::transaction` + +/// Access list +pub type AccessList = Vec; + +/// Access list item +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccessListItem { + /// Accessed address + pub address: Address, + /// Accessed storage keys + pub storage_keys: Vec, +} + +/// Description of a Transaction, pending or in the chain. +#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] +pub struct Transaction { + /// Hash + pub hash: H256, + /// Nonce + pub nonce: U256, + /// Block hash. None when pending. + #[serde(rename = "blockHash")] + pub block_hash: Option, + /// Block number. None when pending. + #[serde(rename = "blockNumber")] + pub block_number: Option, + /// Transaction Index. None when pending. + #[serde(rename = "transactionIndex")] + pub transaction_index: Option, + /// Sender + #[serde(default, skip_serializing_if = "Option::is_none")] + pub from: Option
, + /// Recipient (None when contract creation) + pub to: Option
, + /// Transferred value + pub value: U256, + /// Gas Price + #[serde(rename = "gasPrice")] + pub gas_price: Option, + /// Gas amount + pub gas: U256, + /// Input data + pub input: Bytes, + /// ECDSA recovery id + #[serde(default, skip_serializing_if = "Option::is_none")] + pub v: Option, + /// ECDSA signature r, 32 bytes + #[serde(default, skip_serializing_if = "Option::is_none")] + pub r: Option, + /// ECDSA signature s, 32 bytes + #[serde(default, skip_serializing_if = "Option::is_none")] + pub s: Option, + /// Raw transaction data + #[serde(default, skip_serializing_if = "Option::is_none")] + pub raw: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Access list + #[serde( + rename = "accessList", + default, + skip_serializing_if = "Option::is_none" + )] + pub access_list: Option, + /// Max fee per gas + #[serde(rename = "maxFeePerGas", skip_serializing_if = "Option::is_none")] + pub max_fee_per_gas: Option, + /// miner bribe + #[serde( + rename = "maxPriorityFeePerGas", + skip_serializing_if = "Option::is_none" + )] + pub max_priority_fee_per_gas: Option, +} + +/// "Receipt" of an executed transaction: details of its execution. +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +pub struct TransactionReceipt { + /// Transaction hash. + #[serde(rename = "transactionHash")] + pub transaction_hash: H256, + /// Index within the block. + #[serde(rename = "transactionIndex")] + pub transaction_index: Index, + /// Hash of the block this transaction was included within. + #[serde(rename = "blockHash")] + pub block_hash: Option, + /// Number of the block this transaction was included within. + #[serde(rename = "blockNumber")] + pub block_number: Option, + /// Sender + /// Note: default address if the client did not return this value + /// (maintains backwards compatibility for <= 0.7.0 when this field was missing) + #[serde(default)] + pub from: Address, + /// Recipient (None when contract creation) + /// Note: Also `None` if the client did not return this value + /// (maintains backwards compatibility for <= 0.7.0 when this field was missing) + #[serde(default)] + pub to: Option
, + /// Cumulative gas used within the block after this was executed. + #[serde(rename = "cumulativeGasUsed")] + pub cumulative_gas_used: U256, + /// Gas used by this transaction alone. + /// + /// Gas used is `None` if the the client is running in light client mode. + #[serde(rename = "gasUsed")] + pub gas_used: Option, + /// Contract address created, or `None` if not a deployment. + #[serde(rename = "contractAddress")] + pub contract_address: Option
, + /// Logs generated within this transaction. + pub logs: Vec, + /// Status: either 1 (success) or 0 (failure). + pub status: Option, + /// State root. + pub root: Option, + /// Logs bloom + #[serde(rename = "logsBloom")] + pub logs_bloom: H2048, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Effective gas price + #[serde(rename = "effectiveGasPrice")] + pub effective_gas_price: Option, +} + +/// Data for offline signed transaction +#[derive(Clone, Debug, PartialEq)] +pub struct SignedTransaction { + /// The given message hash + pub message_hash: H256, + /// V value with chain replay protection. + pub v: u64, + /// R value. + pub r: H256, + /// S value. + pub s: H256, + /// The raw signed transaction ready to be sent with `send_raw_transaction` + pub raw_transaction: Bytes, + /// The transaction hash for the RLP encoded transaction. + pub transaction_hash: H256, +} + +/// Transaction Identifier +#[derive(Clone, Debug, PartialEq)] +pub enum TransactionId { + /// By hash + Hash(H256), + /// By block and index + Block(BlockId, Index), +} + +impl From for TransactionId { + fn from(hash: H256) -> Self { + TransactionId::Hash(hash) + } +} + +// `CallRequest`, `TransactionCondition`: from `web3::types::transaction_request` + +/// Call contract request (eth_call / eth_estimateGas) +/// +/// When using this for `eth_estimateGas`, all the fields +/// are optional. However, for usage in `eth_call` the +/// `to` field must be provided. +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct CallRequest { + /// Sender address (None for arbitrary address) + #[serde(skip_serializing_if = "Option::is_none")] + pub from: Option
, + /// To address (None allowed for eth_estimateGas) + #[serde(skip_serializing_if = "Option::is_none")] + pub to: Option
, + /// Supplied gas (None for sensible default) + #[serde(skip_serializing_if = "Option::is_none")] + pub gas: Option, + /// Gas price (None for sensible default) + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "gasPrice")] + pub gas_price: Option, + /// Transferred value (None for no transfer) + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, + /// Data (None for empty data) + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Access list + #[serde( + rename = "accessList", + default, + skip_serializing_if = "Option::is_none" + )] + pub access_list: Option, + /// Max fee per gas + #[serde(rename = "maxFeePerGas", skip_serializing_if = "Option::is_none")] + pub max_fee_per_gas: Option, + /// miner bribe + #[serde( + rename = "maxPriorityFeePerGas", + skip_serializing_if = "Option::is_none" + )] + pub max_priority_fee_per_gas: Option, +} + +/// Represents condition on minimum block number or block timestamp. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub enum TransactionCondition { + /// Valid at this minimum block number. + #[serde(rename = "block")] + Block(u64), + /// Valid at given Unix time. + #[serde(rename = "time")] + Timestamp(u64), +} + +// `FeeHistory`: from `web3::types::fee_history` + +/// 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>>, +} + +// `SyncInfo`, `SyncState`: from `web3::types::sync_state` + +/// Information about current blockchain syncing operations. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SyncInfo { + /// The block at which import began. + pub starting_block: U256, + /// The highest currently synced block. + pub current_block: U256, + /// The estimated highest block. + pub highest_block: U256, +} + +/// The current state of blockchain syncing operations. +#[derive(Debug, Clone, PartialEq)] +pub enum SyncState { + /// Blockchain is syncing. + Syncing(SyncInfo), + /// Blockchain is not syncing. + NotSyncing, +} + +// The `eth_syncing` method returns either `false` or an instance of the sync info object. +// This doesn't play particularly well with the features exposed by `serde_derive`, +// so we use the custom impls below to ensure proper behavior. +impl<'de> Deserialize<'de> for SyncState { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Sync info from subscription has a different key format + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[serde(rename_all = "PascalCase")] + struct SubscriptionSyncInfo { + /// The block at which import began. + pub starting_block: U256, + /// The highest currently synced block. + pub current_block: U256, + /// The estimated highest block. + pub highest_block: U256, + } + + impl From for SyncInfo { + fn from(s: SubscriptionSyncInfo) -> Self { + Self { + starting_block: s.starting_block, + current_block: s.current_block, + highest_block: s.highest_block, + } + } + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + struct SubscriptionSyncState { + pub syncing: bool, + pub status: Option, + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum SyncStateVariants { + Rpc(SyncInfo), + Subscription(SubscriptionSyncState), + Boolean(bool), + } + + let v: SyncStateVariants = Deserialize::deserialize(deserializer)?; + match v { + SyncStateVariants::Rpc(info) => Ok(SyncState::Syncing(info)), + SyncStateVariants::Subscription(state) => match state.status { + None if !state.syncing => Ok(SyncState::NotSyncing), + Some(ref info) if state.syncing => Ok(SyncState::Syncing(info.clone().into())), + _ => Err(D::Error::custom( + "expected object or `syncing = false`, got `syncing = true`", + )), + }, + SyncStateVariants::Boolean(boolean) => { + if !boolean { + Ok(SyncState::NotSyncing) + } else { + Err(D::Error::custom("expected object or `false`, got `true`")) + } + } + } + } +} + +impl Serialize for SyncState { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + SyncState::Syncing(info) => info.serialize(serializer), + SyncState::NotSyncing => false.serialize(serializer), + } + } +} + +// `TraceFilter`: from `web3::types::trace_filtering` + +/// Trace filter +#[derive(Debug, Default, Clone, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct TraceFilter { + /// From block + #[serde(rename = "fromBlock", skip_serializing_if = "Option::is_none")] + from_block: Option, + /// To block + #[serde(rename = "toBlock", skip_serializing_if = "Option::is_none")] + to_block: Option, + /// From address + #[serde(rename = "fromAddress", skip_serializing_if = "Option::is_none")] + from_address: Option>, + /// To address + #[serde(rename = "toAddress", skip_serializing_if = "Option::is_none")] + to_address: Option>, + /// Output offset + #[serde(skip_serializing_if = "Option::is_none")] + after: Option, + /// Output amount + #[serde(skip_serializing_if = "Option::is_none")] + count: Option, +} + +// `Work`: from `web3::types::work` + +/// Miner's work package +#[derive(Debug, PartialEq, Eq)] +pub struct Work { + /// The proof-of-work hash. + pub pow_hash: H256, + /// The seed hash. + pub seed_hash: H256, + /// The target. + pub target: H256, + /// The block number: this isn't always stored. + pub number: Option, +} + +impl<'a> Deserialize<'a> for Work { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + let v: Value = Deserialize::deserialize(deserializer)?; + + let (pow_hash, seed_hash, target, number) = + serde_json::from_value::<(H256, H256, H256, u64)>(v.clone()) + .map(|(pow_hash, seed_hash, target, number)| { + (pow_hash, seed_hash, target, Some(number)) + }) + .or_else(|_| { + serde_json::from_value::<(H256, H256, H256)>(v) + .map(|(pow_hash, seed_hash, target)| (pow_hash, seed_hash, target, None)) + }) + .map_err(|e| D::Error::custom(format!("Cannot deserialize Work: {:?}", e)))?; + + Ok(Work { + pow_hash, + seed_hash, + target, + number, + }) + } +} + +impl Serialize for Work { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + match self.number.as_ref() { + Some(num) => ( + &self.pow_hash, + &self.seed_hash, + &self.target, + U256::from(*num), + ) + .serialize(s), + None => (&self.pow_hash, &self.seed_hash, &self.target).serialize(s), + } + } +} diff --git a/core/lib/basic_types/src/web3/tests.rs b/core/lib/basic_types/src/web3/tests.rs new file mode 100644 index 00000000000..e7c0a0d048a --- /dev/null +++ b/core/lib/basic_types/src/web3/tests.rs @@ -0,0 +1,85 @@ +use super::*; + +#[test] +fn block_can_be_deserialized() { + let post_dencun = r#" + { + "baseFeePerGas": "0x3e344c311", + "blobGasUsed": "0xc0000", + "difficulty": "0x0", + "excessBlobGas": "0x4b40000", + "extraData": "0xd883010d0d846765746888676f312e32302e34856c696e7578", + "gasLimit": "0x1c9c380", + "gasUsed": "0x96070e", + "hash": "0x2c77691707319e5b8a5afde5b75c77ec0ccb1f556c1ccd9e0e49ef5795bc9015", + "logsBloom": "0x08a212844c2050e028d95b42b718a550c7215100101028408e90520820c81c1171400212a0200483f89c89010a0604934650804fc0a283a06d011041a22c000296e0880394850081700ac41a156812a59ea5de0518a43bcb0000a865c242c42348f570a9a3704350c484424d0400ab04000805e0840094680028a218c0099dc2ca42b01c63224045510375050860308894480901e8a6d0e818035158805218400e493001c9a8060a205c1112611442040804041fc00088cca49e262b068000349cf611ebc61c1b00220282150c16096c1370921412420815008398200041721d12d2988ea090d0429208010564809845080808707a1d3052f343020e88091221", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0xcae6acf2f1e34499c234db81aff35299979046ab0e544276005899ce5f320858", + "nonce": "0x0000000000000000", + "number": "0x51fca7", + "parentBeaconBlockRoot": "0x08750d6ce3bf47639efc14c43f44fc1c018d593f1b48aacd222668422ed289ce", + "parentHash": "0x2f3978cb0dec7ecbb01fff2be87b101cf61e9bfb31d64c15a19aca7c4f74c87e", + "receiptsRoot": "0xdad010222b2ce0862e928402b2d10d9651d78d9276c8ad30bc9c0793aba9dd18", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xa862", + "stateRoot": "0xf77a819b26fef9fe5c7cd9511b0fff950725e878cb311914de162be068fb8c70", + "timestamp": "0x65ddadfc", + "totalDifficulty": "0x3c656d23029ab0", + "transactions": ["0x8660a77cc4f13681e039b8f980579c53f522ba13aad64481a5bdfe5f62b54bbb", "0xab5820f72a6374db701a5e27668f14dac867ade71806bb754b561a63a9441df4"], + "transactionsRoot": "0xd9f4b814ee427db492c4fcc249df665b616db61bd423413ad7ffd9b464aced1e", + "uncles": [], + "withdrawals": [{ + "address": "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", + "amount": "0x24e0", + "index": "0x2457a70", + "validatorIndex": "0x3df" + }, { + "address": "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", + "amount": "0x24e0", + "index": "0x2457a71", + "validatorIndex": "0x3e1" + }], + "withdrawalsRoot": "0x576ea3c5cc0bf9d73f64e9786e7b44595a62a76a54989acc8ae84b2015fde929" + }"#; + let block: Block = serde_json::from_str(post_dencun).unwrap(); + assert_eq!(block.excess_blob_gas, Some(U64::from(0x4b40000))); + + let pre_dencun = r#" + { + "baseFeePerGas": "0x910fe39fd", + "difficulty": "0x0", + "extraData": "0x546974616e2028746974616e6275696c6465722e78797a29", + "gasLimit": "0x1c9c380", + "gasUsed": "0x10d5e31", + "hash": "0x40a92d343f724efbc2c85b710a433391b9102813560704ec7db89572a3b23451", + "logsBloom": "0x15a15083ea8148119f3845a4a7f01c291a1393153ec36e21ecdc60cffea60c55c16397c190e48eb7efa27f96500959541a91c251a8e0aeca5ed0942a4dec8a118b6a25bdd9248c6b8b53556ed62c0be8daec00f984ec196f5faa4f52cae5ceb76ade34648e73ac6371bed5ecd1491fc7083a2d75ea88e7e0f7448d56969cb8069fc09a768d1a93f1833f81c1050e36e465220cf99f9502bbc4e0b5475d52b8e1ea819ecb7bacb8baeb16d8f59b9904cc171b970d0834c8fecd6291df1514dae1ff474e939c5af95773a013f6926d1dd5915591d28e18201daf707923f417a9ead1796959c3cfe6facf0c85a7a620aac8a44616eb484db2d78039fb606de4549d", + "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "mixHash": "0x041736203c26f01d68a6a3b5728205cc27cb1674fdad8cc85dd722933483b446", + "nonce": "0x0000000000000000", + "number": "0x126c531", + "parentHash": "0x57535175149b25b4258e6de43e7484f6b6f144dcddbb0add5c2f25e700c57508", + "receiptsRoot": "0x8cc94702aca57e058aaa5da92e7e776f76ac67191a638c5664844deb59616c8f", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x3bfca", + "stateRoot": "0xbeb859bb91bc80792f6640ff469837927dc5a7ad5393484b2e1b536f3815af2f", + "timestamp": "0x65ddae8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": ["0x61b183ea82664e6afb05d3fa692f71561381e5c9280e80062770ff88d4c3c8be", "0x3dd322f75e4315dd265c22a8ae3e51bd32253f43664d1dc4d2afb68746da7e70"], + "transactionsRoot": "0xba2b8ff471608f8877abc6d06f7f599e3c942671b11598b0595fc13185681458", + "uncles": [], + "withdrawals": [{ + "address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f", + "amount": "0x1168dd0", + "index": "0x22d6606", + "validatorIndex": "0x5c797" + }, { + "address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f", + "amount": "0x117bae7", + "index": "0x22d6607", + "validatorIndex": "0x5c798" + }], + "withdrawalsRoot": "0xf3386eae1beb91726fe62e2aba4b975ed4f3be2222c739bf2b4d72dd20324a8b" + }"#; + let block: Block = serde_json::from_str(pre_dencun).unwrap(); + assert!(block.excess_blob_gas.is_none()); +} diff --git a/core/lib/config/src/configs/chain.rs b/core/lib/config/src/configs/chain.rs index 934f7e4103d..79d5c5fe880 100644 --- a/core/lib/config/src/configs/chain.rs +++ b/core/lib/config/src/configs/chain.rs @@ -2,11 +2,9 @@ use std::{str::FromStr, time::Duration}; use serde::{Deserialize, Serialize}; use zksync_basic_types::{ + ethabi, network::Network, - web3::{ - contract::{tokens::Detokenize, Error as Web3ContractError}, - ethabi, Error as Web3ApiError, - }, + web3::contract::{Detokenize, Error as Web3ContractError}, Address, L2ChainId, H256, U256, }; @@ -67,9 +65,8 @@ pub enum L1BatchCommitDataGeneratorMode { impl Detokenize for L1BatchCommitDataGeneratorMode { fn from_tokens(tokens: Vec) -> Result { fn error(tokens: &[ethabi::Token]) -> Web3ContractError { - Web3ContractError::Api(Web3ApiError::Decoder(format!( - "L1BatchCommitDataGeneratorMode::from_tokens: {tokens:?}" - ))) + let message = format!("L1BatchCommitDataGeneratorMode::from_tokens: {tokens:?}"); + Web3ContractError::InvalidOutputType(message) } match tokens.as_slice() { diff --git a/core/lib/crypto/src/hasher/keccak.rs b/core/lib/crypto/src/hasher/keccak.rs index d3baab873f9..91b18dba3a6 100644 --- a/core/lib/crypto/src/hasher/keccak.rs +++ b/core/lib/crypto/src/hasher/keccak.rs @@ -1,4 +1,4 @@ -use zksync_basic_types::{web3::signing::keccak256, H256}; +use zksync_basic_types::{web3::keccak256, H256}; use crate::hasher::Hasher; diff --git a/core/lib/crypto_primitives/Cargo.toml b/core/lib/crypto_primitives/Cargo.toml index 2d151036513..1664c4c95bb 100644 --- a/core/lib/crypto_primitives/Cargo.toml +++ b/core/lib/crypto_primitives/Cargo.toml @@ -11,7 +11,6 @@ categories.workspace = true [dependencies] -web3.workspace = true secp256k1 = { workspace = true, features = ["global-context"] } zksync_utils.workspace = true zksync_basic_types.workspace = true diff --git a/core/lib/crypto_primitives/src/ecdsa_signature.rs b/core/lib/crypto_primitives/src/ecdsa_signature.rs index 1d4f63eb50e..026e42307dc 100644 --- a/core/lib/crypto_primitives/src/ecdsa_signature.rs +++ b/core/lib/crypto_primitives/src/ecdsa_signature.rs @@ -31,9 +31,9 @@ use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, Message as SecpMessage, PublicKey, SecretKey, SECP256K1, }; -use web3::{ - signing::keccak256, - types::{Address, H256, H512, H520}, +use zksync_basic_types::{ + web3::{self, keccak256}, + Address, H256, H512, H520, }; type Message = H256; @@ -104,6 +104,39 @@ impl K256PrivateKey { result.as_bytes_mut().copy_from_slice(&hash[12..]); result } + + pub fn sign_web3(&self, message: &H256, chain_id: Option) -> web3::Signature { + let message = secp256k1::Message::from_slice(message.as_bytes()).unwrap(); + let (recovery_id, signature) = SECP256K1 + .sign_ecdsa_recoverable(&message, &self.0) + .serialize_compact(); + + let standard_v = recovery_id.to_i32() as u64; + let v = if let Some(chain_id) = chain_id { + // When signing with a chain ID, add chain replay protection. + standard_v + 35 + chain_id * 2 + } else { + // Otherwise, convert to 'Electrum' notation. + standard_v + 27 + }; + let r = H256::from_slice(&signature[..32]); + let s = H256::from_slice(&signature[32..]); + + web3::Signature { r, s, v } + } + + pub fn sign_web3_message(&self, message: &H256) -> web3::Signature { + let message = secp256k1::Message::from_slice(message.as_bytes()).unwrap(); + let (recovery_id, signature) = SECP256K1 + .sign_ecdsa_recoverable(&message, &self.0) + .serialize_compact(); + + let v = recovery_id.to_i32() as u64; + let r = H256::from_slice(&signature[..32]); + let s = H256::from_slice(&signature[32..]); + + web3::Signature { v, r, s } + } } /// Convert public key into the address diff --git a/core/lib/crypto_primitives/src/eip712_signature/member_types.rs b/core/lib/crypto_primitives/src/eip712_signature/member_types.rs index 65ad0140d0c..158753fc01e 100644 --- a/core/lib/crypto_primitives/src/eip712_signature/member_types.rs +++ b/core/lib/crypto_primitives/src/eip712_signature/member_types.rs @@ -1,5 +1,4 @@ -use web3::signing::keccak256; -use zksync_basic_types::{Address, H256, U256}; +use zksync_basic_types::{web3::keccak256, Address, H256, U256}; use crate::eip712_signature::typed_structure::{EncodedStructureMember, StructMember}; diff --git a/core/lib/crypto_primitives/src/eip712_signature/tests.rs b/core/lib/crypto_primitives/src/eip712_signature/tests.rs index 39221ac50e8..4ec9122ff4b 100644 --- a/core/lib/crypto_primitives/src/eip712_signature/tests.rs +++ b/core/lib/crypto_primitives/src/eip712_signature/tests.rs @@ -1,8 +1,7 @@ use std::str::FromStr; use serde::Serialize; -use web3::signing::keccak256; -use zksync_basic_types::{Address, H256, U256}; +use zksync_basic_types::{web3::keccak256, Address, H256, U256}; use crate::{ ecdsa_signature::K256PrivateKey, diff --git a/core/lib/crypto_primitives/src/eip712_signature/typed_structure.rs b/core/lib/crypto_primitives/src/eip712_signature/typed_structure.rs index 45ece03596c..8b738364897 100644 --- a/core/lib/crypto_primitives/src/eip712_signature/typed_structure.rs +++ b/core/lib/crypto_primitives/src/eip712_signature/typed_structure.rs @@ -1,7 +1,6 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; -use web3::signing::keccak256; -use zksync_basic_types::{L2ChainId, H256, U256}; +use zksync_basic_types::{web3::keccak256, L2ChainId, H256, U256}; use crate::eip712_signature::struct_builder::{EncodeBuilder, StructBuilder, TypeBuilder}; diff --git a/core/lib/crypto_primitives/src/packed_eth_signature.rs b/core/lib/crypto_primitives/src/packed_eth_signature.rs index 524204fab1b..7e5efc07bb9 100644 --- a/core/lib/crypto_primitives/src/packed_eth_signature.rs +++ b/core/lib/crypto_primitives/src/packed_eth_signature.rs @@ -1,7 +1,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use thiserror::Error; -use web3::signing::keccak256; -use zksync_basic_types::{Address, H256}; +use zksync_basic_types::{web3::keccak256, Address, H256}; use zksync_utils::ZeroPrefixHexSerde; use crate::{ diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 1d8061e8583..81a28879571 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -7,8 +7,8 @@ use zksync_types::{ api, l2_to_l1_log::L2ToL1Log, vm_trace::Call, - web3::types::{BlockHeader, U64}, - Bytes, L1BatchNumber, L2BlockNumber, ProtocolVersionId, H160, H2048, H256, U256, + web3::{BlockHeader, Bytes}, + L1BatchNumber, L2BlockNumber, ProtocolVersionId, H160, H2048, H256, U256, U64, }; use zksync_utils::bigdecimal_to_u256; diff --git a/core/lib/dal/src/consensus/tests.rs b/core/lib/dal/src/consensus/tests.rs index 99570a1c191..694634f11a8 100644 --- a/core/lib/dal/src/consensus/tests.rs +++ b/core/lib/dal/src/consensus/tests.rs @@ -4,7 +4,7 @@ use zksync_protobuf::{ repr::{decode, encode}, ProtoRepr, }; -use zksync_types::{Bytes, Execute, ExecuteTransactionCommon, Transaction}; +use zksync_types::{web3::Bytes, Execute, ExecuteTransactionCommon, Transaction}; use crate::tests::{mock_l1_execute, mock_l2_transaction, mock_protocol_upgrade_transaction}; diff --git a/core/lib/dal/src/models/storage_event.rs b/core/lib/dal/src/models/storage_event.rs index 7de9dae73c0..98e53ae374e 100644 --- a/core/lib/dal/src/models/storage_event.rs +++ b/core/lib/dal/src/models/storage_event.rs @@ -1,7 +1,7 @@ use zksync_types::{ api::{L2ToL1Log, Log}, - web3::types::{Bytes, Index, U256, U64}, - Address, H256, + web3::{Bytes, Index}, + Address, H256, U256, U64, }; #[derive(sqlx::FromRow, Debug, Clone)] diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 4c1d0297cd7..ed9c9b981db 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -10,11 +10,11 @@ use zksync_types::{ protocol_upgrade::ProtocolUpgradeTxCommonData, transaction_request::PaymasterParams, vm_trace::{Call, LegacyCall, LegacyMixedCall}, - web3::types::U64, - Address, Bytes, Execute, ExecuteTransactionCommon, L1TxCommonData, L2ChainId, L2TxCommonData, - Nonce, PackedEthSignature, PriorityOpId, ProtocolVersionId, Transaction, EIP_1559_TX_TYPE, + web3::Bytes, + Address, Execute, ExecuteTransactionCommon, L1TxCommonData, L2ChainId, L2TxCommonData, Nonce, + PackedEthSignature, PriorityOpId, ProtocolVersionId, Transaction, EIP_1559_TX_TYPE, EIP_2930_TX_TYPE, EIP_712_TX_TYPE, H160, H256, PRIORITY_OPERATION_L2_TX_TYPE, - PROTOCOL_UPGRADE_TX_TYPE, U256, + PROTOCOL_UPGRADE_TX_TYPE, U256, U64, }; use zksync_utils::{bigdecimal_to_u256, h256_to_account_address}; diff --git a/core/lib/dal/src/models/tests.rs b/core/lib/dal/src/models/tests.rs index 43ee8eabb73..6ed3d084431 100644 --- a/core/lib/dal/src/models/tests.rs +++ b/core/lib/dal/src/models/tests.rs @@ -3,9 +3,9 @@ use zksync_types::{ fee::Fee, l1::{OpProcessingType, PriorityQueueType}, l2::TransactionType, - Address, Bytes, Execute, ExecuteTransactionCommon, Transaction, EIP_1559_TX_TYPE, - EIP_2930_TX_TYPE, EIP_712_TX_TYPE, H160, H256, PRIORITY_OPERATION_L2_TX_TYPE, - PROTOCOL_UPGRADE_TX_TYPE, U256, + web3::Bytes, + Address, Execute, ExecuteTransactionCommon, Transaction, EIP_1559_TX_TYPE, EIP_2930_TX_TYPE, + EIP_712_TX_TYPE, H160, H256, PRIORITY_OPERATION_L2_TX_TYPE, PROTOCOL_UPGRADE_TX_TYPE, U256, }; use zksync_utils::bigdecimal_to_u256; diff --git a/core/lib/eth_client/Cargo.toml b/core/lib/eth_client/Cargo.toml index 24462a12fab..24041e77f83 100644 --- a/core/lib/eth_client/Cargo.toml +++ b/core/lib/eth_client/Cargo.toml @@ -16,10 +16,12 @@ zksync_eth_signer.workspace = true zksync_config.workspace = true zksync_contracts.workspace = true -jsonrpc-core.workspace = true -serde.workspace = true thiserror.workspace = true async-trait.workspace = true +jsonrpsee = { workspace = true, features = [ + "client", + "macros", +] } tracing.workspace = true rlp.workspace = true diff --git a/core/lib/eth_client/src/clients/http/decl.rs b/core/lib/eth_client/src/clients/http/decl.rs new file mode 100644 index 00000000000..1dbda9d2264 --- /dev/null +++ b/core/lib/eth_client/src/clients/http/decl.rs @@ -0,0 +1,75 @@ +use jsonrpsee::proc_macros::rpc; +use zksync_types::{web3, Address, H256, U256, U64}; + +/// Subset of the L1 `eth` namespace used by the L1 client. +#[rpc(client, namespace = "eth")] +pub(super) trait L1EthNamespace { + #[method(name = "chainId")] + async fn chain_id(&self) -> RpcResult; + + #[method(name = "blockNumber")] + async fn get_block_number(&self) -> RpcResult; + + // **Important.** Must be called with `full_transactions = false` only. + #[method(name = "getBlockByNumber")] + async fn get_block_by_number( + &self, + block_number: web3::BlockNumber, + full_transactions: bool, + ) -> RpcResult>>; + + // **Important.** Must be called with `full_transactions = false` only. + #[method(name = "getBlockByHash")] + async fn get_block_by_hash( + &self, + hash: H256, + full_transactions: bool, + ) -> RpcResult>>; + + #[method(name = "getTransactionCount")] + async fn get_transaction_count( + &self, + address: Address, + block: Option, + ) -> RpcResult; + + #[method(name = "gasPrice")] + async fn gas_price(&self) -> RpcResult; + + #[method(name = "call")] + async fn call( + &self, + req: web3::CallRequest, + block: Option, + ) -> RpcResult; + + #[method(name = "getBalance")] + async fn get_balance( + &self, + address: Address, + block: Option, + ) -> RpcResult; + + #[method(name = "getLogs")] + async fn get_logs(&self, filter: web3::Filter) -> RpcResult>; + + #[method(name = "sendRawTransaction")] + async fn send_raw_transaction(&self, tx_bytes: web3::Bytes) -> RpcResult; + + #[method(name = "feeHistory")] + async fn fee_history( + &self, + block_count: U64, + newest_block: web3::BlockNumber, + reward_percentiles: Option>, + ) -> RpcResult; + + #[method(name = "getTransactionByHash")] + async fn get_transaction_by_hash(&self, hash: H256) -> RpcResult>; + + #[method(name = "getTransactionReceipt")] + async fn get_transaction_receipt( + &self, + hash: H256, + ) -> RpcResult>; +} diff --git a/core/lib/eth_client/src/clients/http/mod.rs b/core/lib/eth_client/src/clients/http/mod.rs index c39e8d425c1..bfdf2129a5e 100644 --- a/core/lib/eth_client/src/clients/http/mod.rs +++ b/core/lib/eth_client/src/clients/http/mod.rs @@ -9,6 +9,7 @@ pub use self::{ signing::{PKSigningClient, SigningClient}, }; +mod decl; mod query; mod signing; diff --git a/core/lib/eth_client/src/clients/http/query.rs b/core/lib/eth_client/src/clients/http/query.rs index b36647bfcbf..89b793d463f 100644 --- a/core/lib/eth_client/src/clients/http/query.rs +++ b/core/lib/eth_client/src/clients/http/query.rs @@ -1,34 +1,20 @@ use std::fmt; use async_trait::async_trait; -use zksync_types::{ - url::SensitiveUrl, - web3::{ - self, - contract::Contract, - ethabi, helpers, - helpers::CallFuture, - transports::Http, - types::{ - Address, BlockId, BlockNumber, Bytes, Filter, Log, Transaction, TransactionId, - TransactionReceipt, H256, U256, U64, - }, - Transport, Web3, - }, - L1ChainId, -}; +use jsonrpsee::{core::ClientError, http_client::HttpClient}; +use zksync_types::{url::SensitiveUrl, web3, Address, L1ChainId, H256, U256, U64}; +use super::{decl::L1EthNamespaceClient, Method, COUNTERS, LATENCIES}; use crate::{ - clients::http::{Method, COUNTERS, LATENCIES}, - types::{Error, ExecutedTxStatus, FailureInfo, FeeHistory, RawTokens}, - Block, ContractCall, EthInterface, RawTransactionBytes, + types::{Error, ExecutedTxStatus, FailureInfo}, + EthInterface, RawTransactionBytes, }; /// An "anonymous" Ethereum client that can invoke read-only methods that aren't /// tied to a particular account. #[derive(Clone)] pub struct QueryClient { - web3: Web3, + web3: HttpClient, url: SensitiveUrl, component: &'static str, } @@ -46,9 +32,8 @@ impl fmt::Debug for QueryClient { impl QueryClient { /// Creates a new HTTP client. pub fn new(url: SensitiveUrl) -> Result { - let transport = Http::new(url.expose_str())?; Ok(Self { - web3: Web3::new(transport), + web3: ::builder().build(url.expose_str())?, url, component: "", }) @@ -69,24 +54,24 @@ impl EthInterface for QueryClient { async fn fetch_chain_id(&self) -> Result { COUNTERS.call[&(Method::ChainId, self.component)].inc(); let latency = LATENCIES.direct[&Method::ChainId].start(); - let raw_chain_id = self.web3.eth().chain_id().await?; + let raw_chain_id = self.web3.chain_id().await?; latency.observe(); - let chain_id = - u64::try_from(raw_chain_id).map_err(|err| ethabi::Error::Other(err.into()))?; + let chain_id = u64::try_from(raw_chain_id).map_err(|err| { + Error::EthereumGateway(ClientError::Custom(format!("invalid chainId: {err}"))) + })?; Ok(L1ChainId(chain_id)) } async fn nonce_at_for_account( &self, account: Address, - block: BlockNumber, + block: web3::BlockNumber, ) -> Result { COUNTERS.call[&(Method::NonceAtForAccount, self.component)].inc(); let latency = LATENCIES.direct[&Method::NonceAtForAccount].start(); let nonce = self .web3 - .eth() - .transaction_count(account, Some(block)) + .get_transaction_count(account, Some(block)) .await?; latency.observe(); Ok(nonce) @@ -95,7 +80,7 @@ impl EthInterface for QueryClient { async fn block_number(&self) -> Result { COUNTERS.call[&(Method::BlockNumber, self.component)].inc(); let latency = LATENCIES.direct[&Method::BlockNumber].start(); - let block_number = self.web3.eth().block_number().await?; + let block_number = self.web3.get_block_number().await?; latency.observe(); Ok(block_number) } @@ -103,14 +88,14 @@ impl EthInterface for QueryClient { async fn get_gas_price(&self) -> Result { COUNTERS.call[&(Method::GetGasPrice, self.component)].inc(); let latency = LATENCIES.direct[&Method::GetGasPrice].start(); - let network_gas_price = self.web3.eth().gas_price().await?; + let network_gas_price = self.web3.gas_price().await?; latency.observe(); Ok(network_gas_price) } async fn send_raw_tx(&self, tx: RawTransactionBytes) -> Result { let latency = LATENCIES.direct[&Method::SendRawTx].start(); - let tx = self.web3.eth().send_raw_transaction(Bytes(tx.0)).await?; + let tx = self.web3.send_raw_transaction(web3::Bytes(tx.0)).await?; latency.observe(); Ok(tx) } @@ -134,18 +119,15 @@ impl EthInterface for QueryClient { let chunk_end = (chunk_start + MAX_REQUEST_CHUNK).min(upto_block); let chunk_size = chunk_end - chunk_start; - let block_count = helpers::serialize(&U256::from(chunk_size)); - let newest_block = helpers::serialize(&web3::types::BlockNumber::from(chunk_end)); - let reward_percentiles = helpers::serialize(&Option::<()>::None); - - let fee_history: FeeHistory = CallFuture::new(self.web3.transport().execute( - "eth_feeHistory", - vec![block_count, newest_block, reward_percentiles], - )) - .await?; - if let Some(base_fees) = fee_history.base_fee_per_gas { - history.extend(base_fees); - } + let fee_history = self + .web3 + .fee_history( + U64::from(chunk_size), + web3::BlockNumber::from(chunk_end), + None, + ) + .await?; + history.extend(fee_history.base_fee_per_gas); } latency.observe(); @@ -158,8 +140,7 @@ impl EthInterface for QueryClient { let block = self .web3 - .eth() - .block(BlockId::Number(BlockNumber::Pending)) + .get_block_by_number(web3::BlockNumber::Pending, false) .await?; let block = if let Some(block) = block { block @@ -167,8 +148,7 @@ impl EthInterface for QueryClient { // Fallback for local reth. Because of artificial nature of producing blocks in local reth setup // there may be no pending block self.web3 - .eth() - .block(BlockId::Number(BlockNumber::Latest)) + .get_block_by_number(web3::BlockNumber::Latest, false) .await? .expect("Latest block always exists") }; @@ -202,15 +182,15 @@ impl EthInterface for QueryClient { async fn failure_reason(&self, tx_hash: H256) -> Result, Error> { let latency = LATENCIES.direct[&Method::FailureReason].start(); - let transaction = self.web3.eth().transaction(tx_hash.into()).await?; - let receipt = self.web3.eth().transaction_receipt(tx_hash).await?; + let transaction = self.web3.get_transaction_by_hash(tx_hash).await?; + let receipt = self.web3.get_transaction_receipt(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::types::CallRequest { + let call_request = web3::CallRequest { from: transaction.from, to: transaction.to, gas: Some(transaction.gas), @@ -223,18 +203,18 @@ impl EthInterface for QueryClient { access_list: None, }; - let call_error = self + let err = self .web3 - .eth() .call(call_request, receipt.block_number.map(Into::into)) .await .err(); - let failure_info = match call_error { - Some(web3::Error::Rpc(rpc_error)) => { - let revert_code = rpc_error.code.code(); - let message_len = "execution reverted: ".len().min(rpc_error.message.len()); - let revert_reason = rpc_error.message[message_len..].to_string(); + let failure_info = match err { + Some(ClientError::Call(call_err)) => { + 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, @@ -254,39 +234,27 @@ impl EthInterface for QueryClient { } } - async fn get_tx(&self, hash: H256) -> Result, Error> { + async fn get_tx(&self, hash: H256) -> Result, Error> { COUNTERS.call[&(Method::GetTx, self.component)].inc(); - let tx = self - .web3 - .eth() - .transaction(TransactionId::Hash(hash)) - .await?; + let tx = self.web3.get_transaction_by_hash(hash).await?; Ok(tx) } async fn call_contract_function( &self, - call: ContractCall, - ) -> Result, Error> { + request: web3::CallRequest, + block: Option, + ) -> Result { let latency = LATENCIES.direct[&Method::CallContractFunction].start(); - let contract = Contract::new(self.web3.eth(), call.contract_address, call.contract_abi); - let RawTokens(res) = contract - .query( - &call.inner.name, - call.inner.params, - call.inner.from, - call.inner.options, - call.inner.block, - ) - .await?; + let output_bytes = self.web3.call(request, block).await?; latency.observe(); - Ok(res) + Ok(output_bytes) } - async fn tx_receipt(&self, tx_hash: H256) -> Result, Error> { + async fn tx_receipt(&self, tx_hash: H256) -> Result, Error> { COUNTERS.call[&(Method::TxReceipt, self.component)].inc(); let latency = LATENCIES.direct[&Method::TxReceipt].start(); - let receipt = self.web3.eth().transaction_receipt(tx_hash).await?; + let receipt = self.web3.get_transaction_receipt(tx_hash).await?; latency.observe(); Ok(receipt) } @@ -294,43 +262,25 @@ impl EthInterface for QueryClient { async fn eth_balance(&self, address: Address) -> Result { COUNTERS.call[&(Method::EthBalance, self.component)].inc(); let latency = LATENCIES.direct[&Method::EthBalance].start(); - let balance = self.web3.eth().balance(address, None).await?; + let balance = self.web3.get_balance(address, None).await?; latency.observe(); Ok(balance) } - async fn logs(&self, filter: Filter) -> Result, Error> { + async fn logs(&self, filter: web3::Filter) -> Result, Error> { COUNTERS.call[&(Method::Logs, self.component)].inc(); let latency = LATENCIES.direct[&Method::Logs].start(); - let logs = self.web3.eth().logs(filter).await?; + let logs = self.web3.get_logs(filter).await?; latency.observe(); Ok(logs) } - async fn block(&self, block_id: BlockId) -> Result>, Error> { + async fn block(&self, block_id: web3::BlockId) -> Result>, Error> { COUNTERS.call[&(Method::Block, self.component)].inc(); let latency = LATENCIES.direct[&Method::Block].start(); - // Copy of `web3::block` implementation. It's required to deserialize response as `crate::types::Block` - // that has EIP-4844 fields. - let block = { - let include_txs = helpers::serialize(&false); - - let result = match block_id { - BlockId::Hash(hash) => { - let hash = helpers::serialize(&hash); - self.web3 - .transport() - .execute("eth_getBlockByHash", vec![hash, include_txs]) - } - BlockId::Number(num) => { - let num = helpers::serialize(&num); - self.web3 - .transport() - .execute("eth_getBlockByNumber", vec![num, include_txs]) - } - }; - - CallFuture::new(result).await? + let block = match block_id { + web3::BlockId::Hash(hash) => self.web3.get_block_by_hash(hash, false).await?, + web3::BlockId::Number(num) => self.web3.get_block_by_number(num, false).await?, }; latency.observe(); Ok(block) diff --git a/core/lib/eth_client/src/clients/http/signing.rs b/core/lib/eth_client/src/clients/http/signing.rs index 2d93fed5acd..dca1a0bad12 100644 --- a/core/lib/eth_client/src/clients/http/signing.rs +++ b/core/lib/eth_client/src/clients/http/signing.rs @@ -4,13 +4,7 @@ use async_trait::async_trait; use zksync_contracts::hyperchain_contract; use zksync_eth_signer::{raw_ethereum_tx::TransactionParameters, EthereumSigner, PrivateKeySigner}; use zksync_types::{ - web3::{ - self, - contract::tokens::Detokenize, - ethabi, - types::{Address, H160, U256}, - }, - K256PrivateKey, L1ChainId, EIP_4844_TX_TYPE, + ethabi, web3, Address, K256PrivateKey, L1ChainId, EIP_4844_TX_TYPE, H160, U256, }; use super::{Method, LATENCIES}; @@ -181,7 +175,7 @@ impl BoundEthInterface for SigningClient { }; let mut signed_tx = self.inner.eth_signer.sign_transaction(tx).await?; - let hash = web3::signing::keccak256(&signed_tx).into(); + let hash = web3::keccak256(&signed_tx).into(); latency.observe(); if let Some(sidecar) = options.blob_tx_sidecar { @@ -201,14 +195,16 @@ impl BoundEthInterface for SigningClient { &self, token_address: Address, address: Address, - erc20_abi: ethabi::Contract, + erc20_abi: ðabi::Contract, ) -> Result { let latency = LATENCIES.direct[&Method::Allowance].start(); - let args = CallFunctionArgs::new("allowance", (self.inner.sender_account, address)) - .for_contract(token_address, erc20_abi); - let res = self.as_ref().call_contract_function(args).await?; + let allowance: U256 = + CallFunctionArgs::new("allowance", (self.inner.sender_account, address)) + .for_contract(token_address, erc20_abi) + .call(self.as_ref()) + .await?; latency.observe(); - Ok(U256::from_tokens(res)?) + Ok(allowance) } } diff --git a/core/lib/eth_client/src/clients/mock.rs b/core/lib/eth_client/src/clients/mock.rs index 6f5c96c8832..60d14bc29f0 100644 --- a/core/lib/eth_client/src/clients/mock.rs +++ b/core/lib/eth_client/src/clients/mock.rs @@ -5,20 +5,16 @@ use std::{ }; use async_trait::async_trait; -use jsonrpc_core::types::error::Error as RpcError; +use jsonrpsee::{core::ClientError, types::ErrorObject}; use zksync_types::{ - web3::{ - contract::tokens::Tokenize, - ethabi, - types::{BlockId, BlockNumber, Filter, Log, Transaction, TransactionReceipt, U64}, - Error as Web3Error, - }, - Address, L1ChainId, H160, H256, U256, + ethabi, + web3::{self, contract::Tokenize, BlockId}, + Address, L1ChainId, H160, H256, U256, U64, }; use crate::{ types::{Error, ExecutedTxStatus, FailureInfo, SignedCallResult}, - Block, BoundEthInterface, ContractCall, EthInterface, Options, RawTransactionBytes, + BoundEthInterface, EthInterface, Options, RawTransactionBytes, }; #[derive(Debug, Clone)] @@ -55,7 +51,7 @@ impl From> for MockTx { } } -impl From for Transaction { +impl From for web3::Transaction { fn from(tx: MockTx) -> Self { Self { to: Some(tx.recipient), @@ -106,11 +102,11 @@ impl MockEthereumInner { let status = ExecutedTxStatus { tx_hash, success, - receipt: TransactionReceipt { + receipt: web3::TransactionReceipt { gas_used: Some(21000u32.into()), block_number: Some(block_number.into()), transaction_hash: tx_hash, - ..TransactionReceipt::default() + ..web3::TransactionReceipt::default() }, }; self.tx_statuses.insert(tx_hash, status); @@ -124,14 +120,15 @@ pub struct MockExecutedTxHandle<'a> { } impl MockExecutedTxHandle<'_> { - pub fn with_logs(&mut self, logs: Vec) -> &mut Self { + pub fn with_logs(&mut self, logs: Vec) -> &mut Self { let status = self.inner.tx_statuses.get_mut(&self.tx_hash).unwrap(); status.receipt.logs = logs; self } } -type CallHandler = dyn Fn(&ContractCall) -> Result + Send + Sync; +type CallHandler = + dyn Fn(&web3::CallRequest, BlockId) -> Result + Send + Sync; /// Mock Ethereum client is capable of recording all the incoming requests for the further analysis. #[derive(Clone)] @@ -173,8 +170,8 @@ impl Default for MockEthereum { excess_blob_gas_history: vec![], non_ordering_confirmations: false, inner: Arc::default(), - call_handler: Arc::new(|call| { - panic!("Unexpected eth_call: {call:?}"); + call_handler: Arc::new(|call, block_id| { + panic!("Unexpected eth_call: {call:?}, {block_id:?}"); }), } } @@ -278,17 +275,17 @@ impl MockEthereum { pub fn with_call_handler(self, call_handler: F) -> Self where - F: 'static + Send + Sync + Fn(&ContractCall) -> ethabi::Token, + F: 'static + Send + Sync + Fn(&web3::CallRequest, BlockId) -> ethabi::Token, { Self { - call_handler: Arc::new(move |call| Ok(call_handler(call))), + call_handler: Arc::new(move |call, block_id| Ok(call_handler(call, block_id))), ..self } } pub fn with_fallible_call_handler(self, call_handler: F) -> Self where - F: 'static + Send + Sync + Fn(&ContractCall) -> Result, + F: 'static + Send + Sync + Fn(&web3::CallRequest, BlockId) -> Result, { Self { call_handler: Arc::new(call_handler), @@ -325,11 +322,12 @@ impl EthInterface for MockEthereum { let mut inner = self.inner.write().unwrap(); if mock_tx.nonce < inner.current_nonce { - return Err(Error::EthereumGateway(Web3Error::Rpc(RpcError { - message: "transaction with the same nonce already processed".to_string(), - code: 101.into(), - data: None, - }))); + let err = ErrorObject::owned( + 101, + "transaction with the same nonce already processed", + None::<()>, + ); + return Err(Error::EthereumGateway(ClientError::Call(err))); } if mock_tx.nonce == inner.pending_nonce { @@ -342,7 +340,7 @@ impl EthInterface for MockEthereum { async fn nonce_at_for_account( &self, account: Address, - block: BlockNumber, + block: web3::BlockNumber, ) -> Result { if account != Self::SENDER_ACCOUNT { unimplemented!("Getting nonce for custom account is not supported"); @@ -350,13 +348,13 @@ impl EthInterface for MockEthereum { let inner = self.inner.read().unwrap(); Ok(match block { - BlockNumber::Number(block_number) => { + web3::BlockNumber::Number(block_number) => { let mut nonce_range = inner.nonces.range(..=block_number.as_u64()); let (_, &nonce) = nonce_range.next_back().unwrap_or((&0, &0)); nonce.into() } - BlockNumber::Pending => inner.pending_nonce.into(), - BlockNumber::Latest => inner.current_nonce.into(), + web3::BlockNumber::Pending => inner.pending_nonce.into(), + web3::BlockNumber::Latest => inner.current_nonce.into(), _ => unimplemented!( "`nonce_at_for_account()` called with unsupported block number: {block:?}" ), @@ -393,12 +391,14 @@ impl EthInterface for MockEthereum { async fn call_contract_function( &self, - call: ContractCall, - ) -> Result, Error> { - (self.call_handler)(&call).map(|token| vec![token]) + request: web3::CallRequest, + block: Option, + ) -> Result { + (self.call_handler)(&request, block.unwrap_or(web3::BlockNumber::Pending.into())) + .map(|token| web3::Bytes(ethabi::encode(&[token]))) } - async fn get_tx(&self, hash: H256) -> Result, Error> { + async fn get_tx(&self, hash: H256) -> Result, Error> { let txs = &self.inner.read().unwrap().sent_txs; let Some(tx) = txs.get(&hash) else { return Ok(None); @@ -406,7 +406,7 @@ impl EthInterface for MockEthereum { Ok(Some(tx.clone().into())) } - async fn tx_receipt(&self, _tx_hash: H256) -> Result, Error> { + async fn tx_receipt(&self, _tx_hash: H256) -> Result, Error> { unimplemented!("Not needed right now") } @@ -414,13 +414,13 @@ impl EthInterface for MockEthereum { unimplemented!("Not needed right now") } - async fn logs(&self, _filter: Filter) -> Result, Error> { + async fn logs(&self, _filter: web3::Filter) -> Result, Error> { unimplemented!("Not needed right now") } - async fn block(&self, block_id: BlockId) -> Result>, Error> { + async fn block(&self, block_id: web3::BlockId) -> Result>, Error> { match block_id { - BlockId::Number(BlockNumber::Number(number)) => { + web3::BlockId::Number(web3::BlockNumber::Number(number)) => { let excess_blob_gas = self .excess_blob_gas_history .get(number.as_usize()) @@ -430,7 +430,7 @@ impl EthInterface for MockEthereum { .get(number.as_usize()) .map(|base_fee| (*base_fee).into()); - Ok(Some(Block { + Ok(Some(web3::Block { number: Some(number), excess_blob_gas, base_fee_per_gas, @@ -487,7 +487,7 @@ impl BoundEthInterface for MockEthereum { &self, _token_address: Address, _contract_address: Address, - _erc20_abi: ethabi::Contract, + _erc20_abi: ðabi::Contract, ) -> Result { unimplemented!("Not needed right now") } diff --git a/core/lib/eth_client/src/lib.rs b/core/lib/eth_client/src/lib.rs index 0f44174f044..ef023592d14 100644 --- a/core/lib/eth_client/src/lib.rs +++ b/core/lib/eth_client/src/lib.rs @@ -1,21 +1,20 @@ use std::fmt; use async_trait::async_trait; +pub use jsonrpsee::core::ClientError; use zksync_types::{ eth_sender::EthTxBlobSidecar, + ethabi, web3, web3::{ - ethabi, - types::{ - AccessList, Address, BlockId, BlockNumber, Filter, Log, Transaction, - TransactionCondition, TransactionReceipt, H160, H256, U256, U64, - }, + AccessList, Block, BlockId, BlockNumber, Filter, Log, Transaction, TransactionCondition, + TransactionReceipt, }, - L1ChainId, + Address, L1ChainId, H160, H256, U256, U64, }; pub use crate::types::{ - encode_blob_tx_with_sidecar, Block, CallFunctionArgs, ContractCall, Error, ExecutedTxStatus, - FailureInfo, RawTransactionBytes, SignedCallResult, + encode_blob_tx_with_sidecar, CallFunctionArgs, ContractCall, ContractError, Error, + ExecutedTxStatus, FailureInfo, RawTransactionBytes, SignedCallResult, }; pub mod clients; @@ -137,8 +136,11 @@ pub trait EthInterface: 'static + Sync + Send + fmt::Debug { async fn eth_balance(&self, address: Address) -> Result; /// Invokes a function on a contract specified by `contract_address` / `contract_abi` using `eth_call`. - async fn call_contract_function(&self, call: ContractCall) - -> Result, Error>; + async fn call_contract_function( + &self, + request: web3::CallRequest, + block: Option, + ) -> Result; /// Returns the logs for the specified filter. async fn logs(&self, filter: Filter) -> Result, Error>; @@ -198,7 +200,7 @@ pub trait BoundEthInterface: AsRef + 'static + Sync + Send + f &self, token_address: Address, address: Address, - erc20_abi: ethabi::Contract, + erc20_abi: ðabi::Contract, ) -> Result; /// Signs the transaction and sends it to the Ethereum network. @@ -250,15 +252,6 @@ impl dyn BoundEthInterface { self.as_ref().eth_balance(self.sender_account()).await } - /// Invokes a function on a contract specified by `Self::contract()` / `Self::contract_addr()`. - pub async fn call_main_contract_function( - &self, - args: CallFunctionArgs, - ) -> Result, Error> { - let args = args.for_contract(self.contract_addr(), self.contract().clone()); - self.as_ref().call_contract_function(args).await - } - /// Encodes a function using the `Self::contract()` ABI. /// /// `params` are tokenized parameters of the function. Most of the time, you can use diff --git a/core/lib/eth_client/src/types.rs b/core/lib/eth_client/src/types.rs index 1f04f23430d..c30a8540def 100644 --- a/core/lib/eth_client/src/types.rs +++ b/core/lib/eth_client/src/types.rs @@ -1,43 +1,23 @@ use rlp::RlpStream; -use serde::{Deserialize, Deserializer, Serialize}; use zksync_types::{ eth_sender::EthTxBlobSidecar, - ethabi::ethereum_types::H64, + ethabi, web3, web3::{ - contract::{ - tokens::{Detokenize, Tokenize}, - Error as ContractError, Options, - }, - ethabi, - types::{Address, BlockId, BlockNumber, TransactionReceipt, H256, U256}, + contract::{Detokenize, Tokenize}, + BlockId, Bytes, TransactionReceipt, }, - Bytes, EIP_4844_TX_TYPE, H160, H2048, U64, + Address, EIP_4844_TX_TYPE, H256, U256, }; -/// Wrapper for `Vec` that doesn't wrap them in an additional array in `Tokenize` implementation. -#[derive(Debug)] -pub(crate) struct RawTokens(pub Vec); - -impl Tokenize for RawTokens { - fn into_tokens(self) -> Vec { - self.0 - } -} - -impl Detokenize for RawTokens { - fn from_tokens(tokens: Vec) -> Result { - Ok(Self(tokens)) - } -} +use crate::EthInterface; /// Arguments for calling a function in an unspecified Ethereum smart contract. #[derive(Debug)] pub struct CallFunctionArgs { pub(crate) name: String, pub(crate) from: Option
, - pub(crate) options: Options, pub(crate) block: Option, - pub(crate) params: RawTokens, + pub(crate) params: Vec, } impl CallFunctionArgs { @@ -45,9 +25,8 @@ impl CallFunctionArgs { Self { name: name.to_owned(), from: None, - options: Options::default(), block: None, - params: RawTokens(params.into_tokens()), + params: params.into_tokens(), } } @@ -64,8 +43,8 @@ impl CallFunctionArgs { pub fn for_contract( self, contract_address: Address, - contract_abi: ethabi::Contract, - ) -> ContractCall { + contract_abi: ðabi::Contract, + ) -> ContractCall<'_> { ContractCall { contract_address, contract_abi, @@ -77,13 +56,13 @@ impl CallFunctionArgs { /// Information sufficient for calling a function in a specific Ethereum smart contract. Instantiated /// using [`CallFunctionArgs::for_contract()`]. #[derive(Debug)] -pub struct ContractCall { +pub struct ContractCall<'a> { pub(crate) contract_address: Address, - pub(crate) contract_abi: ethabi::Contract, + pub(crate) contract_abi: &'a ethabi::Contract, pub(crate) inner: CallFunctionArgs, } -impl ContractCall { +impl ContractCall<'_> { pub fn contract_address(&self) -> Address { self.contract_address } @@ -93,25 +72,100 @@ impl ContractCall { } pub fn args(&self) -> &[ethabi::Token] { - &self.inner.params.0 + &self.inner.params + } + + pub async fn call(&self, client: &dyn EthInterface) -> Result { + let func = self + .contract_abi + .function(&self.inner.name) + .map_err(ContractError::Function)?; + let encoded_input = + func.encode_input(&self.inner.params) + .map_err(|source| ContractError::EncodeInput { + signature: func.signature(), + input: self.inner.params.clone(), + source, + })?; + + let request = web3::CallRequest { + from: self.inner.from, + to: Some(self.contract_address), + data: Some(Bytes(encoded_input)), + // Other options are never set + gas: None, + gas_price: None, + value: None, + transaction_type: None, + access_list: None, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + }; + + let encoded_output = client + .call_contract_function(request, self.inner.block) + .await?; + let output_tokens = func.decode_output(&encoded_output.0).map_err(|source| { + ContractError::DecodeOutput { + signature: func.signature(), + output: encoded_output, + source, + } + })?; + Ok(Res::from_tokens(output_tokens.clone()).map_err(|source| { + ContractError::DetokenizeOutput { + signature: func.signature(), + output: output_tokens, + source, + } + })?) } } +/// Contract-related subset of Ethereum client errors. +#[derive(Debug, thiserror::Error)] +pub enum ContractError { + /// Failed resolving a function specified for the contract call in the contract ABI. + #[error("failed resolving contract function: {0}")] + Function(#[source] ethabi::Error), + /// Failed encoding input for the contract call. + #[error("failed encoding input {input:?} for call to `{signature}`: {source}")] + EncodeInput { + signature: String, + input: Vec, + #[source] + source: ethabi::Error, + }, + /// Failed decoding contract call output from bytes into tokens. + #[error("failed decoding output {output:?} for call to `{signature}`: {source}")] + DecodeOutput { + signature: String, + output: Bytes, + #[source] + source: ethabi::Error, + }, + /// Failed decoding contract call output from tokens into a final response value. + #[error("failed decoding output {output:?} for call to `{signature}`: {source}")] + DetokenizeOutput { + signature: String, + output: Vec, + #[source] + source: web3::contract::Error, + }, +} + /// Common error type exposed by the crate, #[derive(Debug, thiserror::Error)] pub enum Error { /// Problem on the Ethereum client side (e.g. bad RPC call, network issues). #[error("Request to ethereum gateway failed: {0}")] - EthereumGateway(#[from] zksync_types::web3::Error), + EthereumGateway(#[from] jsonrpsee::core::ClientError), /// Problem with a contract call. #[error("Call to contract failed: {0}")] - Contract(#[from] zksync_types::web3::contract::Error), + Contract(#[from] ContractError), /// Problem with transaction signer. #[error("Transaction signing failed: {0}")] Signer(#[from] zksync_eth_signer::error::SignerError), - /// Problem with transaction decoding. - #[error("Decoding revert reason failed: {0}")] - Decode(#[from] ethabi::Error), /// Incorrect fee provided for a transaction. #[error("Max fee {0} less than priority fee {1}")] WrongFeeProvided(U256, U256), @@ -260,130 +314,17 @@ pub struct FailureInfo { pub gas_limit: U256, } -/// The fee history type returned from RPC calls. -/// We don't use `FeeHistory` from `web3` crate because it's not compatible -/// with node implementations that skip empty `base_fee_per_gas`. -#[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. - pub base_fee_per_gas: Option>, - /// A vector of block gas used ratios. These are calculated as the ratio of gas used and gas limit. - pub gas_used_ratio: Option>, - /// 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>>, -} - -/// The block type returned from RPC calls. -/// This is generic over a `TX` type. -/// We can't use `Block` from `web3` crate because it doesn't support `excessBlobGas`. -#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] -pub struct Block { - /// Hash of the block - pub hash: Option, - /// Hash of the parent - #[serde(rename = "parentHash")] - pub parent_hash: H256, - /// Hash of the uncles - #[serde(rename = "sha3Uncles")] - #[cfg_attr(feature = "allow-missing-fields", serde(default))] - pub uncles_hash: H256, - /// Author's address. - #[serde(rename = "miner", default, deserialize_with = "null_to_default")] - pub author: H160, - /// State root hash - #[serde(rename = "stateRoot")] - pub state_root: H256, - /// Transactions root hash - #[serde(rename = "transactionsRoot")] - pub transactions_root: H256, - /// Transactions receipts root hash - #[serde(rename = "receiptsRoot")] - pub receipts_root: H256, - /// Block number. None if pending. - pub number: Option, - /// Gas Used - #[serde(rename = "gasUsed")] - pub gas_used: U256, - /// Gas Limit - #[serde(rename = "gasLimit")] - #[cfg_attr(feature = "allow-missing-fields", serde(default))] - pub gas_limit: U256, - /// Base fee per unit of gas (if past London) - #[serde(rename = "baseFeePerGas", skip_serializing_if = "Option::is_none")] - pub base_fee_per_gas: Option, - /// Extra data - #[serde(rename = "extraData")] - pub extra_data: Bytes, - /// Logs bloom - #[serde(rename = "logsBloom")] - pub logs_bloom: Option, - /// Timestamp - pub timestamp: U256, - /// Difficulty - #[cfg_attr(feature = "allow-missing-fields", serde(default))] - pub difficulty: U256, - /// Total difficulty - #[serde(rename = "totalDifficulty")] - pub total_difficulty: Option, - /// Seal fields - #[serde(default, rename = "sealFields")] - pub seal_fields: Vec, - /// Uncles' hashes - #[cfg_attr(feature = "allow-missing-fields", serde(default))] - pub uncles: Vec, - /// Transactions - pub transactions: Vec, - /// Size in bytes - pub size: Option, - /// Mix Hash - #[serde(rename = "mixHash")] - pub mix_hash: Option, - /// Nonce - pub nonce: Option, - /// Excess blob gas - #[serde(rename = "excessBlobGas")] - pub excess_blob_gas: Option, -} - -fn null_to_default<'de, D, T>(deserializer: D) -> Result -where - T: Default + Deserialize<'de>, - D: Deserializer<'de>, -{ - let option = Option::deserialize(deserializer)?; - Ok(option.unwrap_or_default()) -} - #[cfg(test)] mod tests { - use std::str::FromStr; - - use pretty_assertions::assert_eq; use zksync_eth_signer::{EthereumSigner, PrivateKeySigner, TransactionParameters}; use zksync_types::{ eth_sender::{EthTxBlobSidecarV1, SidecarBlobV1}, web3::{self}, - K256PrivateKey, EIP_4844_TX_TYPE, H160, H256, U256, U64, + K256PrivateKey, EIP_4844_TX_TYPE, H256, U256, U64, }; use super::*; - #[test] - fn raw_tokens_are_compatible_with_actual_call() { - let vk_contract = zksync_contracts::verifier_contract(); - let args = CallFunctionArgs::new("verificationKeyHash", ()); - let func = vk_contract.function(&args.name).unwrap(); - func.encode_input(&args.params.into_tokens()).unwrap(); - - let output_tokens = vec![ethabi::Token::FixedBytes(vec![1; 32])]; - let RawTokens(output_tokens) = RawTokens::from_tokens(output_tokens).unwrap(); - let hash = H256::from_tokens(output_tokens).unwrap(); - assert_eq!(hash, H256::repeat_byte(1)); - } - #[tokio::test] // Tests the encoding of the `EIP_4844_TX_TYPE` transaction to // network format defined by the `EIP`. That is, a signed transaction @@ -422,7 +363,11 @@ mod tests { nonce: 0.into(), max_priority_fee_per_gas: U256::from(1), gas_price: Some(U256::from(4)), - to: Some(H160::from_str("0x0000000000000000000000000000000000000001").unwrap()), + to: Some( + "0x0000000000000000000000000000000000000001" + .parse() + .unwrap(), + ), gas: 0x3.into(), value: Default::default(), data: Default::default(), @@ -441,7 +386,7 @@ mod tests { .await .unwrap(); - let hash = web3::signing::keccak256(&raw_tx).into(); + let hash = web3::keccak256(&raw_tx).into(); // Transaction generated with https://github.com/inphi/blob-utils with // the above parameters. let expected_str = include_str!("testdata/4844_tx_1.txt"); @@ -477,9 +422,9 @@ mod tests { // network format defined by the `EIP`. That is, a signed transaction // itself and the sidecar containing the blobs. async fn test_generating_signed_raw_transaction_with_4844_sidecar_two_blobs() { - let private_key = - H256::from_str("27593fea79697e947890ecbecce7901b0008345e5d7259710d0dd5e500d040be") - .unwrap(); + let private_key = "27593fea79697e947890ecbecce7901b0008345e5d7259710d0dd5e500d040be" + .parse() + .unwrap(); let private_key = K256PrivateKey::from_bytes(private_key).unwrap(); let commitment_1 = hex::decode( @@ -530,7 +475,11 @@ mod tests { nonce: 0.into(), max_priority_fee_per_gas: U256::from(1), gas_price: Some(U256::from(4)), - to: Some(H160::from_str("0x0000000000000000000000000000000000000001").unwrap()), + to: Some( + "0x0000000000000000000000000000000000000001" + .parse() + .unwrap(), + ), gas: 0x3.into(), value: Default::default(), data: Default::default(), @@ -546,7 +495,7 @@ mod tests { .await .unwrap(); - let hash = web3::signing::keccak256(&raw_tx).into(); + let hash = web3::keccak256(&raw_tx).into(); // Transaction generated with https://github.com/inphi/blob-utils with // the above parameters. let expected_str = include_str!("testdata/4844_tx_2.txt"); @@ -584,88 +533,4 @@ mod tests { let expected_str = expected_str.to_owned(); pretty_assertions::assert_eq!(raw_tx_str, expected_str); } - - #[test] - fn block_can_be_deserialized() { - let post_dencun = r#" - { - "baseFeePerGas": "0x3e344c311", - "blobGasUsed": "0xc0000", - "difficulty": "0x0", - "excessBlobGas": "0x4b40000", - "extraData": "0xd883010d0d846765746888676f312e32302e34856c696e7578", - "gasLimit": "0x1c9c380", - "gasUsed": "0x96070e", - "hash": "0x2c77691707319e5b8a5afde5b75c77ec0ccb1f556c1ccd9e0e49ef5795bc9015", - "logsBloom": "0x08a212844c2050e028d95b42b718a550c7215100101028408e90520820c81c1171400212a0200483f89c89010a0604934650804fc0a283a06d011041a22c000296e0880394850081700ac41a156812a59ea5de0518a43bcb0000a865c242c42348f570a9a3704350c484424d0400ab04000805e0840094680028a218c0099dc2ca42b01c63224045510375050860308894480901e8a6d0e818035158805218400e493001c9a8060a205c1112611442040804041fc00088cca49e262b068000349cf611ebc61c1b00220282150c16096c1370921412420815008398200041721d12d2988ea090d0429208010564809845080808707a1d3052f343020e88091221", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0xcae6acf2f1e34499c234db81aff35299979046ab0e544276005899ce5f320858", - "nonce": "0x0000000000000000", - "number": "0x51fca7", - "parentBeaconBlockRoot": "0x08750d6ce3bf47639efc14c43f44fc1c018d593f1b48aacd222668422ed289ce", - "parentHash": "0x2f3978cb0dec7ecbb01fff2be87b101cf61e9bfb31d64c15a19aca7c4f74c87e", - "receiptsRoot": "0xdad010222b2ce0862e928402b2d10d9651d78d9276c8ad30bc9c0793aba9dd18", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0xa862", - "stateRoot": "0xf77a819b26fef9fe5c7cd9511b0fff950725e878cb311914de162be068fb8c70", - "timestamp": "0x65ddadfc", - "totalDifficulty": "0x3c656d23029ab0", - "transactions": ["0x8660a77cc4f13681e039b8f980579c53f522ba13aad64481a5bdfe5f62b54bbb", "0xab5820f72a6374db701a5e27668f14dac867ade71806bb754b561a63a9441df4"], - "transactionsRoot": "0xd9f4b814ee427db492c4fcc249df665b616db61bd423413ad7ffd9b464aced1e", - "uncles": [], - "withdrawals": [{ - "address": "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", - "amount": "0x24e0", - "index": "0x2457a70", - "validatorIndex": "0x3df" - }, { - "address": "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", - "amount": "0x24e0", - "index": "0x2457a71", - "validatorIndex": "0x3e1" - }], - "withdrawalsRoot": "0x576ea3c5cc0bf9d73f64e9786e7b44595a62a76a54989acc8ae84b2015fde929" - }"#; - let block: Block = serde_json::from_str(post_dencun).unwrap(); - assert_eq!(block.excess_blob_gas, Some(U64::from(0x4b40000))); - - let pre_dencun = r#" - { - "baseFeePerGas": "0x910fe39fd", - "difficulty": "0x0", - "extraData": "0x546974616e2028746974616e6275696c6465722e78797a29", - "gasLimit": "0x1c9c380", - "gasUsed": "0x10d5e31", - "hash": "0x40a92d343f724efbc2c85b710a433391b9102813560704ec7db89572a3b23451", - "logsBloom": "0x15a15083ea8148119f3845a4a7f01c291a1393153ec36e21ecdc60cffea60c55c16397c190e48eb7efa27f96500959541a91c251a8e0aeca5ed0942a4dec8a118b6a25bdd9248c6b8b53556ed62c0be8daec00f984ec196f5faa4f52cae5ceb76ade34648e73ac6371bed5ecd1491fc7083a2d75ea88e7e0f7448d56969cb8069fc09a768d1a93f1833f81c1050e36e465220cf99f9502bbc4e0b5475d52b8e1ea819ecb7bacb8baeb16d8f59b9904cc171b970d0834c8fecd6291df1514dae1ff474e939c5af95773a013f6926d1dd5915591d28e18201daf707923f417a9ead1796959c3cfe6facf0c85a7a620aac8a44616eb484db2d78039fb606de4549d", - "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", - "mixHash": "0x041736203c26f01d68a6a3b5728205cc27cb1674fdad8cc85dd722933483b446", - "nonce": "0x0000000000000000", - "number": "0x126c531", - "parentHash": "0x57535175149b25b4258e6de43e7484f6b6f144dcddbb0add5c2f25e700c57508", - "receiptsRoot": "0x8cc94702aca57e058aaa5da92e7e776f76ac67191a638c5664844deb59616c8f", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x3bfca", - "stateRoot": "0xbeb859bb91bc80792f6640ff469837927dc5a7ad5393484b2e1b536f3815af2f", - "timestamp": "0x65ddae8b", - "totalDifficulty": "0xc70d815d562d3cfa955", - "transactions": ["0x61b183ea82664e6afb05d3fa692f71561381e5c9280e80062770ff88d4c3c8be", "0x3dd322f75e4315dd265c22a8ae3e51bd32253f43664d1dc4d2afb68746da7e70"], - "transactionsRoot": "0xba2b8ff471608f8877abc6d06f7f599e3c942671b11598b0595fc13185681458", - "uncles": [], - "withdrawals": [{ - "address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f", - "amount": "0x1168dd0", - "index": "0x22d6606", - "validatorIndex": "0x5c797" - }, { - "address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f", - "amount": "0x117bae7", - "index": "0x22d6607", - "validatorIndex": "0x5c798" - }], - "withdrawalsRoot": "0xf3386eae1beb91726fe62e2aba4b975ed4f3be2222c739bf2b4d72dd20324a8b" - }"#; - let block: Block = serde_json::from_str(pre_dencun).unwrap(); - assert!(block.excess_blob_gas.is_none()); - } } diff --git a/core/lib/eth_signer/Cargo.toml b/core/lib/eth_signer/Cargo.toml index 4365c7881ee..a2a69d5d31c 100644 --- a/core/lib/eth_signer/Cargo.toml +++ b/core/lib/eth_signer/Cargo.toml @@ -10,19 +10,13 @@ keywords.workspace = true categories.workspace = true [dependencies] -zksync_types = { path = "../types" } - -serde.workspace = true -serde_derive.workspace = true +zksync_types.workspace = true +serde = { workspace = true, features = ["derive"] } serde_json.workspace = true hex.workspace = true -secp256k1.workspace = true - rlp.workspace = true - reqwest = { workspace = true, features = ["json", "blocking"] } thiserror.workspace = true - jsonrpc-core.workspace = true async-trait.workspace = true diff --git a/core/lib/eth_signer/src/json_rpc_signer.rs b/core/lib/eth_signer/src/json_rpc_signer.rs index 505865e5a53..edb7f43b0de 100644 --- a/core/lib/eth_signer/src/json_rpc_signer.rs +++ b/core/lib/eth_signer/src/json_rpc_signer.rs @@ -1,4 +1,4 @@ -use jsonrpc_core::types::response::Output; +use jsonrpc_core::types::response::Output; // FIXME: remove this dependency use serde_json::Value; use zksync_types::{Address, EIP712TypedStructure, Eip712Domain, PackedEthSignature, H256}; diff --git a/core/lib/eth_signer/src/pk_signer.rs b/core/lib/eth_signer/src/pk_signer.rs index dbc8c524c86..47b0e110991 100644 --- a/core/lib/eth_signer/src/pk_signer.rs +++ b/core/lib/eth_signer/src/pk_signer.rs @@ -63,7 +63,7 @@ impl EthereumSigner for PrivateKeySigner { blob_versioned_hashes: raw_tx.blob_versioned_hashes, }; - let signed = tx.sign(self.private_key.expose_secret(), raw_tx.chain_id); + let signed = tx.sign(&self.private_key, raw_tx.chain_id); Ok(signed.raw_transaction.0) } } diff --git a/core/lib/eth_signer/src/raw_ethereum_tx.rs b/core/lib/eth_signer/src/raw_ethereum_tx.rs index 74328be0618..9479b5bd9d7 100644 --- a/core/lib/eth_signer/src/raw_ethereum_tx.rs +++ b/core/lib/eth_signer/src/raw_ethereum_tx.rs @@ -12,11 +12,8 @@ use rlp::RlpStream; use zksync_types::{ ethabi::Address, - web3::{ - signing::{self, Signature}, - types::{AccessList, SignedTransaction}, - }, - H256, U256, U64, + web3::{keccak256, AccessList, Signature, SignedTransaction}, + K256PrivateKey, H256, U256, U64, }; const LEGACY_TX_ID: u64 = 0; @@ -244,29 +241,26 @@ impl Transaction { } /// Sign and return a raw signed transaction. - pub fn sign(self, sign: impl signing::Key, chain_id: u64) -> SignedTransaction { + pub fn sign(self, private_key: &K256PrivateKey, chain_id: u64) -> SignedTransaction { let adjust_v_value = matches!( self.transaction_type.map(|t| t.as_u64()), Some(LEGACY_TX_ID) | None ); let encoded = self.encode(chain_id, None); - - let hash = signing::keccak256(encoded.as_ref()); + let message_hash = H256(keccak256(encoded.as_ref())); let signature = if adjust_v_value { - sign.sign(&hash, Some(chain_id)) - .expect("hash is non-zero 32-bytes; qed") + private_key.sign_web3(&message_hash, Some(chain_id)) } else { - sign.sign_message(&hash) - .expect("hash is non-zero 32-bytes; qed") + private_key.sign_web3_message(&message_hash) }; let signed = self.encode(chain_id, Some(&signature)); - let transaction_hash = signing::keccak256(signed.as_ref()).into(); + let transaction_hash = keccak256(signed.as_ref()).into(); SignedTransaction { - message_hash: hash.into(), + message_hash, v: signature.v, r: signature.r, s: signature.s, diff --git a/core/lib/l1_contract_interface/src/i_executor/methods/execute_batches.rs b/core/lib/l1_contract_interface/src/i_executor/methods/execute_batches.rs index 9b759270a2a..9da78ea08e6 100644 --- a/core/lib/l1_contract_interface/src/i_executor/methods/execute_batches.rs +++ b/core/lib/l1_contract_interface/src/i_executor/methods/execute_batches.rs @@ -1,8 +1,6 @@ -use zksync_types::{ - commitment::L1BatchWithMetadata, ethabi::Token, web3::contract::tokens::Tokenizable, -}; +use zksync_types::{commitment::L1BatchWithMetadata, ethabi::Token}; -use crate::{i_executor::structures::StoredBatchInfo, Tokenize}; +use crate::{i_executor::structures::StoredBatchInfo, Tokenizable, Tokenize}; /// Input required to encode `executeBatches` call. #[derive(Debug, Clone)] diff --git a/core/lib/l1_contract_interface/src/i_executor/methods/prove_batches.rs b/core/lib/l1_contract_interface/src/i_executor/methods/prove_batches.rs index 20daf12f48c..35f95201402 100644 --- a/core/lib/l1_contract_interface/src/i_executor/methods/prove_batches.rs +++ b/core/lib/l1_contract_interface/src/i_executor/methods/prove_batches.rs @@ -1,10 +1,8 @@ use crypto_codegen::serialize_proof; use zksync_prover_interface::outputs::L1BatchProofForL1; -use zksync_types::{ - commitment::L1BatchWithMetadata, ethabi::Token, web3::contract::tokens::Tokenizable, U256, -}; +use zksync_types::{commitment::L1BatchWithMetadata, ethabi::Token, U256}; -use crate::{i_executor::structures::StoredBatchInfo, Tokenize}; +use crate::{i_executor::structures::StoredBatchInfo, Tokenizable, Tokenize}; /// Input required to encode `proveBatches` call. #[derive(Debug, Clone)] 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 50f4e6cb2bd..e40d4e61c66 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 @@ -2,7 +2,7 @@ use zksync_types::{ commitment::{pre_boojum_serialize_commitments, serialize_commitments, L1BatchWithMetadata}, ethabi::Token, pubdata_da::PubdataDA, - web3::{contract::Error as Web3ContractError, error::Error as Web3ApiError}, + web3::contract::Error as ContractError, ProtocolVersionId, U256, }; @@ -163,16 +163,11 @@ impl<'a> CommitBatchInfoRollup<'a> { } impl<'a> Tokenizable for CommitBatchInfoRollup<'a> { - fn from_token(_token: Token) -> Result - where - Self: Sized, - { + fn from_token(_token: Token) -> Result { // Currently there is no need to decode this struct. // We still want to implement `Tokenizable` trait for it, so that *once* it's needed // the implementation is provided here and not in some other inconsistent way. - Err(Web3ContractError::Api(Web3ApiError::Decoder( - "Not implemented".to_string(), - ))) + Err(ContractError::Other("Not implemented".into())) } fn into_token(self) -> Token { @@ -367,16 +362,11 @@ impl<'a> CommitBatchInfoValidium<'a> { } impl<'a> Tokenizable for CommitBatchInfoValidium<'a> { - fn from_token(_token: Token) -> Result - where - Self: Sized, - { + fn from_token(_token: Token) -> Result { // Currently there is no need to decode this struct. // We still want to implement `Tokenizable` trait for it, so that *once* it's needed // the implementation is provided here and not in some other inconsistent way. - Err(Web3ContractError::Api(Web3ApiError::Decoder( - "Not implemented".to_string(), - ))) + Err(ContractError::Other("Not implemented".into())) } fn into_token(self) -> Token { diff --git a/core/lib/l1_contract_interface/src/i_executor/structures/stored_batch_info.rs b/core/lib/l1_contract_interface/src/i_executor/structures/stored_batch_info.rs index 10fccc0198d..929b860beff 100644 --- a/core/lib/l1_contract_interface/src/i_executor/structures/stored_batch_info.rs +++ b/core/lib/l1_contract_interface/src/i_executor/structures/stored_batch_info.rs @@ -1,8 +1,5 @@ use zksync_types::{ - commitment::L1BatchWithMetadata, - ethabi::Token, - web3::{contract::Error as Web3ContractError, error::Error as Web3ApiError}, - U256, + commitment::L1BatchWithMetadata, ethabi::Token, web3::contract::Error as ContractError, U256, }; use crate::Tokenizable; @@ -12,16 +9,11 @@ use crate::Tokenizable; pub struct StoredBatchInfo<'a>(pub &'a L1BatchWithMetadata); impl<'a> Tokenizable for StoredBatchInfo<'a> { - fn from_token(_token: Token) -> Result - where - Self: Sized, - { + fn from_token(_token: Token) -> Result { // Currently there is no need to decode this struct. // We still want to implement `Tokenizable` trait for it, so that *once* it's needed // the implementation is provided here and not in some other inconsistent way. - Err(Web3ContractError::Api(Web3ApiError::Decoder( - "Not implemented".to_string(), - ))) + Err(ContractError::Other("Not implemented".into())) } fn into_token(self) -> Token { diff --git a/core/lib/l1_contract_interface/src/lib.rs b/core/lib/l1_contract_interface/src/lib.rs index c50bd8118ec..fc96347bf70 100644 --- a/core/lib/l1_contract_interface/src/lib.rs +++ b/core/lib/l1_contract_interface/src/lib.rs @@ -8,7 +8,7 @@ //! while `Tokenize` trait represents items that are encoded via array of `Token`s //! (for example, transaction input). -pub use zksync_types::web3::contract::tokens::{Detokenize, Tokenizable, Tokenize}; +pub use zksync_types::web3::contract::{Detokenize, Tokenizable, Tokenize}; /// Rust interface for (subset of) `IExector.sol`. pub mod i_executor; diff --git a/core/lib/l1_contract_interface/src/multicall3/mod.rs b/core/lib/l1_contract_interface/src/multicall3/mod.rs index a47d034d586..7d922668f94 100644 --- a/core/lib/l1_contract_interface/src/multicall3/mod.rs +++ b/core/lib/l1_contract_interface/src/multicall3/mod.rs @@ -2,7 +2,7 @@ use std::mem; use zksync_types::{ ethabi::Token, - web3::contract::{tokens::Tokenizable, Error}, + web3::contract::{Error as ContractError, Tokenizable}, Address, }; @@ -21,7 +21,7 @@ impl Tokenizable for Multicall3Call { self.calldata.into_token(), ]) } - fn from_token(token: Token) -> Result { + fn from_token(token: Token) -> Result { let Token::Tuple(mut result_token) = token else { return Err(error(&[token], "Multicall3Call")); }; @@ -46,7 +46,7 @@ pub struct Multicall3Result { } impl Tokenizable for Multicall3Result { - fn from_token(token: Token) -> Result { + fn from_token(token: Token) -> Result { let Token::Tuple(mut result_token) = token else { return Err(error(&[token], "Multicall3Result")); }; @@ -68,8 +68,7 @@ impl Tokenizable for Multicall3Result { } } -fn error(token: &[Token], result_struct_name: &str) -> Error { - Error::InvalidOutputType(format!( - "Expected `{result_struct_name}` token, got token: {token:?}" - )) +fn error(token: &[Token], result_struct_name: &str) -> ContractError { + let message = format!("expected `{result_struct_name}` token, got token: {token:?}"); + ContractError::InvalidOutputType(message) } diff --git a/core/lib/multivm/src/tracers/prestate_tracer/mod.rs b/core/lib/multivm/src/tracers/prestate_tracer/mod.rs index ca95f16a9a6..81e2acfd4be 100644 --- a/core/lib/multivm/src/tracers/prestate_tracer/mod.rs +++ b/core/lib/multivm/src/tracers/prestate_tracer/mod.rs @@ -3,8 +3,8 @@ use std::{collections::HashMap, fmt, sync::Arc}; use once_cell::sync::OnceCell; use zksync_state::{StoragePtr, WriteStorage}; use zksync_types::{ - get_code_key, get_nonce_key, web3::signing::keccak256, AccountTreeId, Address, StorageKey, - StorageValue, H160, H256, L2_BASE_TOKEN_ADDRESS, U256, + get_code_key, get_nonce_key, web3::keccak256, AccountTreeId, Address, StorageKey, StorageValue, + H160, H256, L2_BASE_TOKEN_ADDRESS, U256, }; use zksync_utils::{address_to_h256, h256_to_u256}; diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index 03489316f0d..b56d92015a3 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -7,7 +7,7 @@ use zksync_system_constants::{ L2_BASE_TOKEN_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, SYSTEM_CONTEXT_ADDRESS, }; use zksync_types::{ - vm_trace::ViolatedValidationRule, web3::signing::keccak256, AccountTreeId, Address, StorageKey, + vm_trace::ViolatedValidationRule, web3::keccak256, AccountTreeId, Address, StorageKey, VmVersion, H256, U256, }; use zksync_utils::{be_bytes_to_safe_address, u256_to_account_address, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_1_3_2/oracles/tracer/validation.rs b/core/lib/multivm/src/versions/vm_1_3_2/oracles/tracer/validation.rs index 63d6b2183d9..1681bf63a2b 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/oracles/tracer/validation.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/oracles/tracer/validation.rs @@ -12,9 +12,7 @@ use zksync_system_constants::{ KECCAK256_PRECOMPILE_ADDRESS, L2_BASE_TOKEN_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, SYSTEM_CONTEXT_ADDRESS, }; -use zksync_types::{ - get_code_key, web3::signing::keccak256, AccountTreeId, Address, StorageKey, H256, U256, -}; +use zksync_types::{get_code_key, web3::keccak256, AccountTreeId, Address, StorageKey, H256, U256}; use zksync_utils::{ be_bytes_to_safe_address, h256_to_account_address, u256_to_account_address, u256_to_h256, }; diff --git a/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs b/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs index 2e902586ef7..375a8bdb7ad 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs @@ -14,7 +14,7 @@ use zksync_contracts::deployer_contract; use zksync_state::WriteStorage; use zksync_types::{ ethabi::{Address, Token}, - web3::signing::keccak256, + web3::keccak256, Execute, Nonce, StorageKey, StorageValue, CONTRACT_DEPLOYER_ADDRESS, H256, U256, }; use zksync_utils::{ diff --git a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs index 82d4a076699..3ec35ebb247 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -240,7 +240,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_1_4_1/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_1_4_1/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs index 54cb59aeb52..6ad20f16b4f 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -240,7 +240,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_1_4_2/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_1_4_2/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs index 81d967029f6..ddaca7d158a 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -254,7 +254,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_boojum_integration/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs b/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs index a8507cb92ca..feb60f93a23 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs @@ -1,6 +1,6 @@ use ethabi::Token; use zk_evm_1_5_0::aux_structures::Timestamp; -use zksync_types::{get_known_code_key, web3::signing::keccak256, Address, Execute, U256}; +use zksync_types::{get_known_code_key, web3::keccak256, Address, Execute, U256}; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256, u256_to_h256}; use crate::{ diff --git a/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs b/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs index e70234da780..18917456888 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs @@ -1,6 +1,6 @@ use zk_evm_1_5_0::zkevm_opcode_defs::p256; use zksync_system_constants::P256VERIFY_PRECOMPILE_ADDRESS; -use zksync_types::{web3::signing::keccak256, Execute, H256, U256}; +use zksync_types::{web3::keccak256, Execute, H256, U256}; use zksync_utils::h256_to_u256; use crate::{ diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs index a59d248bde3..aa4df7793d1 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -234,7 +234,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_latest/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_latest/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_m5/oracles/tracer.rs b/core/lib/multivm/src/versions/vm_m5/oracles/tracer.rs index fd00b2da782..7094fb6f068 100644 --- a/core/lib/multivm/src/versions/vm_m5/oracles/tracer.rs +++ b/core/lib/multivm/src/versions/vm_m5/oracles/tracer.rs @@ -16,7 +16,7 @@ use zk_evm_1_3_1::{ }, }; use zksync_types::{ - get_code_key, web3::signing::keccak256, AccountTreeId, Address, StorageKey, + get_code_key, web3::keccak256, AccountTreeId, Address, StorageKey, ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS, CONTRACT_DEPLOYER_ADDRESS, H256, KECCAK256_PRECOMPILE_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, SYSTEM_CONTEXT_ADDRESS, U256, diff --git a/core/lib/multivm/src/versions/vm_m5/test_utils.rs b/core/lib/multivm/src/versions/vm_m5/test_utils.rs index 80e4404b104..e91b365d534 100644 --- a/core/lib/multivm/src/versions/vm_m5/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_m5/test_utils.rs @@ -15,7 +15,7 @@ use zk_evm_1_3_1::{ use zksync_contracts::deployer_contract; use zksync_types::{ ethabi::{Address, Token}, - web3::signing::keccak256, + web3::keccak256, Execute, Nonce, StorageKey, StorageValue, CONTRACT_DEPLOYER_ADDRESS, H256, U256, }; use zksync_utils::{ diff --git a/core/lib/multivm/src/versions/vm_m6/oracles/tracer/validation.rs b/core/lib/multivm/src/versions/vm_m6/oracles/tracer/validation.rs index 084c25310ec..f046ba5befe 100644 --- a/core/lib/multivm/src/versions/vm_m6/oracles/tracer/validation.rs +++ b/core/lib/multivm/src/versions/vm_m6/oracles/tracer/validation.rs @@ -11,9 +11,7 @@ use zksync_system_constants::{ KECCAK256_PRECOMPILE_ADDRESS, L2_BASE_TOKEN_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, SYSTEM_CONTEXT_ADDRESS, }; -use zksync_types::{ - get_code_key, web3::signing::keccak256, AccountTreeId, Address, StorageKey, H256, U256, -}; +use zksync_types::{get_code_key, web3::keccak256, AccountTreeId, Address, StorageKey, H256, U256}; use zksync_utils::{ be_bytes_to_safe_address, h256_to_account_address, u256_to_account_address, u256_to_h256, }; diff --git a/core/lib/multivm/src/versions/vm_m6/test_utils.rs b/core/lib/multivm/src/versions/vm_m6/test_utils.rs index 348ebab94a2..bd724dca5ca 100644 --- a/core/lib/multivm/src/versions/vm_m6/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_m6/test_utils.rs @@ -13,7 +13,7 @@ use zk_evm_1_3_1::{aux_structures::Timestamp, vm_state::VmLocalState}; use zksync_contracts::deployer_contract; use zksync_types::{ ethabi::{Address, Token}, - web3::signing::keccak256, + web3::keccak256, Execute, Nonce, StorageKey, StorageValue, CONTRACT_DEPLOYER_ADDRESS, H256, U256, }; use zksync_utils::{ diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs index 1493cf7e59d..a356eb74e66 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -254,7 +254,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs index 6fee52542fc..67f4050c5a0 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs @@ -6,8 +6,8 @@ use zksync_types::{ l1::is_l1_tx_type, l2::{L2Tx, TransactionType}, transaction_request::{PaymasterParams, TransactionRequest}, - Bytes, Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, - U256, + web3::Bytes, + Execute, ExecuteTransactionCommon, L2ChainId, L2TxCommonData, Nonce, Transaction, H256, U256, }; use zksync_utils::{address_to_h256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; @@ -254,7 +254,7 @@ impl TransactionData { } fn canonical_l1_tx_hash(&self) -> Result { - use zksync_types::web3::signing::keccak256; + use zksync_types::web3::keccak256; if !is_l1_tx_type(self.tx_type) { return Err(TxHashCalculationError::CannotCalculateL1HashForL2Tx); diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/utils/l2_blocks.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/utils/l2_blocks.rs index d0f89fcb365..ec30a86013b 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/utils/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/utils/l2_blocks.rs @@ -5,8 +5,7 @@ use zksync_system_constants::{ SYSTEM_CONTEXT_STORED_L2_BLOCK_HASHES, }; use zksync_types::{ - block::unpack_block_info, web3::signing::keccak256, AccountTreeId, L2BlockNumber, StorageKey, - H256, U256, + block::unpack_block_info, web3::keccak256, AccountTreeId, L2BlockNumber, StorageKey, H256, U256, }; use zksync_utils::{h256_to_u256, u256_to_h256}; diff --git a/core/lib/object_store/src/objects.rs b/core/lib/object_store/src/objects.rs index 0fee5af8fb9..c11b2626323 100644 --- a/core/lib/object_store/src/objects.rs +++ b/core/lib/object_store/src/objects.rs @@ -178,7 +178,8 @@ impl dyn ObjectStore + '_ { mod tests { use zksync_types::{ snapshots::{SnapshotFactoryDependency, SnapshotStorageLog}, - AccountTreeId, Bytes, StorageKey, H160, H256, + web3::Bytes, + AccountTreeId, StorageKey, H160, H256, }; use super::*; diff --git a/core/lib/snapshots_applier/Cargo.toml b/core/lib/snapshots_applier/Cargo.toml index 35ad3e9f30c..a293b7714b9 100644 --- a/core/lib/snapshots_applier/Cargo.toml +++ b/core/lib/snapshots_applier/Cargo.toml @@ -22,6 +22,7 @@ vise.workspace = true anyhow.workspace = true async-trait.workspace = true +futures.workspace = true tokio = { workspace = true, features = ["time"] } tracing.workspace = true thiserror.workspace = true diff --git a/core/lib/snapshots_applier/src/lib.rs b/core/lib/snapshots_applier/src/lib.rs index 9f0c79c0c14..fcfd0909c3e 100644 --- a/core/lib/snapshots_applier/src/lib.rs +++ b/core/lib/snapshots_applier/src/lib.rs @@ -16,7 +16,6 @@ use zksync_types::{ SnapshotStorageLogsChunk, SnapshotStorageLogsStorageKey, SnapshotVersion, }, tokens::TokenInfo, - web3::futures, L1BatchNumber, L2BlockNumber, H256, }; use zksync_utils::bytecode::hash_bytecode; diff --git a/core/lib/snapshots_applier/src/tests/utils.rs b/core/lib/snapshots_applier/src/tests/utils.rs index d7191408636..4629d8c0a2f 100644 --- a/core/lib/snapshots_applier/src/tests/utils.rs +++ b/core/lib/snapshots_applier/src/tests/utils.rs @@ -13,7 +13,8 @@ use zksync_types::{ SnapshotStorageLogsChunkMetadata, SnapshotStorageLogsStorageKey, SnapshotVersion, }, tokens::{TokenInfo, TokenMetadata}, - AccountTreeId, Address, Bytes, L1BatchNumber, L2BlockNumber, ProtocolVersionId, StorageKey, + web3::Bytes, + AccountTreeId, Address, L1BatchNumber, L2BlockNumber, ProtocolVersionId, StorageKey, StorageValue, H160, H256, }; use zksync_web3_decl::error::EnrichedClientResult; diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index 0c2bd2006fd..6bebb238880 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -2,8 +2,8 @@ use chrono::{DateTime, Utc}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use strum::Display; use zksync_basic_types::{ - web3::types::{Bytes, H160, H256, H64, U256, U64}, - L1BatchNumber, + web3::{AccessList, Bytes, Index}, + L1BatchNumber, H160, H2048, H256, H64, U256, U64, }; use zksync_contracts::BaseSystemContractsHashes; @@ -13,7 +13,6 @@ pub use crate::transaction_request::{ use crate::{ protocol_version::L1VerifierConfig, vm_trace::{Call, CallType}, - web3::types::{AccessList, Index, H2048}, Address, L2BlockNumber, ProtocolVersionId, }; diff --git a/core/lib/types/src/block.rs b/core/lib/types/src/block.rs index 3cf09f9645f..e1e98671bd8 100644 --- a/core/lib/types/src/block.rs +++ b/core/lib/types/src/block.rs @@ -10,7 +10,7 @@ use crate::{ fee_model::BatchFeeInput, l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, priority_op_onchain_data::PriorityOpOnchainData, - web3::signing::keccak256, + web3::keccak256, AccountTreeId, L1BatchNumber, L2BlockNumber, ProtocolVersionId, Transaction, }; diff --git a/core/lib/types/src/commitment/mod.rs b/core/lib/types/src/commitment/mod.rs index ecb60fa1e17..31baa78ee1f 100644 --- a/core/lib/types/src/commitment/mod.rs +++ b/core/lib/types/src/commitment/mod.rs @@ -24,7 +24,7 @@ use crate::{ l2_to_l1_logs_tree_size, parse_system_logs_for_blob_hashes, L2ToL1Log, SystemL2ToL1Log, UserL2ToL1Log, }, - web3::signing::keccak256, + web3::keccak256, writes::{ compress_state_diffs, InitialStorageWrite, RepeatedStorageWrite, StateDiffRecord, PADDED_ENCODED_STORAGE_DIFF_LEN_BYTES, diff --git a/core/lib/types/src/contract_verification_api.rs b/core/lib/types/src/contract_verification_api.rs index 5be7a18be0e..033bb9dc9f3 100644 --- a/core/lib/types/src/contract_verification_api.rs +++ b/core/lib/types/src/contract_verification_api.rs @@ -7,7 +7,7 @@ use serde::{ }; pub use crate::Execute as ExecuteData; -use crate::{Address, Bytes}; +use crate::{web3::Bytes, Address}; #[derive(Debug, Clone, Serialize)] #[serde(tag = "codeFormat", content = "sourceCode")] diff --git a/core/lib/types/src/debug_flat_call.rs b/core/lib/types/src/debug_flat_call.rs index c0ac0661806..1b4bfdd21ce 100644 --- a/core/lib/types/src/debug_flat_call.rs +++ b/core/lib/types/src/debug_flat_call.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use zksync_basic_types::web3::types::{Bytes, U256}; +use zksync_basic_types::{web3::Bytes, U256}; use crate::{ api::{DebugCall, DebugCallType, ResultDebugCall}, diff --git a/core/lib/types/src/event/mod.rs b/core/lib/types/src/event/mod.rs index eb05011201f..055b41d77c7 100644 --- a/core/lib/types/src/event/mod.rs +++ b/core/lib/types/src/event/mod.rs @@ -14,9 +14,9 @@ use crate::{ ethabi, l2_to_l1_log::L2ToL1Log, tokens::{TokenInfo, TokenMetadata}, - web3::types::Index, + web3::{Bytes, Index}, zk_evm_types::{LogQuery, Timestamp}, - Address, Bytes, L1BatchNumber, CONTRACT_DEPLOYER_ADDRESS, H256, KNOWN_CODES_STORAGE_ADDRESS, + Address, L1BatchNumber, CONTRACT_DEPLOYER_ADDRESS, H256, KNOWN_CODES_STORAGE_ADDRESS, L1_MESSENGER_ADDRESS, U256, U64, }; diff --git a/core/lib/types/src/l1/mod.rs b/core/lib/types/src/l1/mod.rs index b4b28058140..e94be684f9d 100644 --- a/core/lib/types/src/l1/mod.rs +++ b/core/lib/types/src/l1/mod.rs @@ -5,7 +5,8 @@ use std::convert::TryFrom; use serde::{Deserialize, Serialize}; use zksync_basic_types::{ ethabi::{decode, ParamType, Token}, - Address, L1BlockNumber, Log, PriorityOpId, H160, H256, U256, + web3::Log, + Address, L1BlockNumber, PriorityOpId, H160, H256, U256, }; use zksync_utils::u256_to_account_address; diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index ccf3285b592..bf232f0eb15 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -14,11 +14,11 @@ use crate::{ helpers::unix_timestamp_ms, transaction_request::PaymasterParams, tx::Execute, - web3::types::U64, - Address, Bytes, EIP712TypedStructure, Eip712Domain, ExecuteTransactionCommon, InputData, - L2ChainId, Nonce, PackedEthSignature, StructBuilder, Transaction, EIP_1559_TX_TYPE, - EIP_2930_TX_TYPE, EIP_712_TX_TYPE, H256, LEGACY_TX_TYPE, PRIORITY_OPERATION_L2_TX_TYPE, - PROTOCOL_UPGRADE_TX_TYPE, U256, + web3::Bytes, + Address, EIP712TypedStructure, Eip712Domain, ExecuteTransactionCommon, InputData, L2ChainId, + Nonce, PackedEthSignature, StructBuilder, Transaction, EIP_1559_TX_TYPE, EIP_2930_TX_TYPE, + EIP_712_TX_TYPE, H256, LEGACY_TX_TYPE, PRIORITY_OPERATION_L2_TX_TYPE, PROTOCOL_UPGRADE_TX_TYPE, + U256, U64, }; pub mod error; diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 5f3e5cbe555..25f4173831b 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -81,7 +81,7 @@ pub struct Transaction { pub common_data: ExecuteTransactionCommon, pub execute: Execute, pub received_timestamp_ms: u64, - pub raw_bytes: Option, + pub raw_bytes: Option, } impl std::fmt::Debug for Transaction { diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 21103ad0eeb..677f22e7fe4 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -8,8 +8,8 @@ use zksync_utils::u256_to_account_address; use crate::{ ethabi::{decode, encode, ParamType, Token}, helpers::unix_timestamp_ms, - web3::signing::keccak256, - Address, Execute, ExecuteTransactionCommon, Log, Transaction, TransactionType, H256, + web3::{keccak256, Log}, + Address, Execute, ExecuteTransactionCommon, Transaction, TransactionType, H256, PROTOCOL_UPGRADE_TX_TYPE, U256, }; diff --git a/core/lib/types/src/snapshots.rs b/core/lib/types/src/snapshots.rs index f0096a7bf12..6e4f734a33c 100644 --- a/core/lib/types/src/snapshots.rs +++ b/core/lib/types/src/snapshots.rs @@ -7,7 +7,7 @@ use zksync_basic_types::{AccountTreeId, L1BatchNumber, L2BlockNumber, H256}; use zksync_protobuf::{required, ProtoFmt}; use zksync_utils::u256_to_h256; -use crate::{utils, Bytes, ProtocolVersionId, StorageKey, StorageValue, U256}; +use crate::{utils, web3::Bytes, ProtocolVersionId, StorageKey, StorageValue, U256}; /// Information about all snapshots persisted by the node. #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/core/lib/types/src/storage/mod.rs b/core/lib/types/src/storage/mod.rs index 9d558d013fa..6614ccd600d 100644 --- a/core/lib/types/src/storage/mod.rs +++ b/core/lib/types/src/storage/mod.rs @@ -2,7 +2,7 @@ use core::fmt::Debug; use blake2::{Blake2s256, Digest}; use serde::{Deserialize, Serialize}; -use zksync_basic_types::{web3::signing::keccak256, L2ChainId}; +use zksync_basic_types::{web3::keccak256, L2ChainId}; use crate::{AccountTreeId, Address, H160, H256, U256}; diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 066fd1c109b..72551d762d1 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -15,8 +15,8 @@ use crate::{ fee::Fee, l1::L1Tx, l2::{L2Tx, TransactionType}, - web3::{signing::keccak256, types::AccessList}, - Address, Bytes, EIP712TypedStructure, Eip712Domain, L1TxCommonData, L2ChainId, Nonce, + web3::{keccak256, AccessList, Bytes}, + Address, EIP712TypedStructure, Eip712Domain, L1TxCommonData, L2ChainId, Nonce, PackedEthSignature, StructBuilder, LEGACY_TX_TYPE, U256, U64, }; @@ -956,52 +956,6 @@ mod tests { use zksync_crypto_primitives::K256PrivateKey; use super::*; - use crate::web3::{ - api::Namespace, - transports::test::TestTransport, - types::{TransactionParameters, H256, U256}, - }; - - #[tokio::test] - async fn decode_real_tx() { - let accounts = crate::web3::api::Accounts::new(TestTransport::default()); - - let private_key_bytes: H256 = - "4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318" - .parse() - .unwrap(); - let private_key = K256PrivateKey::from_bytes(private_key_bytes).unwrap(); - let address = private_key.address(); - - let tx = TransactionParameters { - nonce: Some(U256::from(1u32)), - to: Some(Address::random()), - gas: Default::default(), - gas_price: Some(U256::from(2u32)), - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - value: Default::default(), - data: Bytes(vec![1, 2, 3]), - chain_id: Some(270), - transaction_type: None, - access_list: None, - }; - let signed_tx = accounts - .sign_transaction(tx.clone(), private_key.expose_secret()) - .await - .unwrap(); - let (tx2, _) = TransactionRequest::from_bytes( - signed_tx.raw_transaction.0.as_slice(), - L2ChainId::from(270), - ) - .unwrap(); - assert_eq!(tx.gas, tx2.gas); - assert_eq!(tx.gas_price.unwrap(), tx2.gas_price); - assert_eq!(tx.nonce.unwrap(), tx2.nonce); - assert_eq!(tx.data, tx2.input); - assert_eq!(tx.value, tx2.value); - assert_eq!(address, tx2.from.unwrap()); - } #[test] fn decode_rlp() { diff --git a/core/lib/types/src/tx/execute.rs b/core/lib/types/src/tx/execute.rs index baafe374675..e54f469b135 100644 --- a/core/lib/types/src/tx/execute.rs +++ b/core/lib/types/src/tx/execute.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use zksync_utils::ZeroPrefixHexSerde; -use crate::{web3::ethabi, Address, EIP712TypedStructure, StructBuilder, H256, U256}; +use crate::{ethabi, Address, EIP712TypedStructure, StructBuilder, H256, U256}; /// `Execute` transaction executes a previously deployed smart contract in the L2 rollup. #[derive(Clone, Default, Serialize, Deserialize, PartialEq)] diff --git a/core/lib/types/src/utils.rs b/core/lib/types/src/utils.rs index df9a88fde00..2bbbc34e8f7 100644 --- a/core/lib/types/src/utils.rs +++ b/core/lib/types/src/utils.rs @@ -5,8 +5,8 @@ use zksync_basic_types::{Address, H256}; use zksync_utils::{address_to_h256, u256_to_h256}; use crate::{ - system_contracts::DEPLOYMENT_NONCE_INCREMENT, web3::signing::keccak256, AccountTreeId, - StorageKey, L2_BASE_TOKEN_ADDRESS, U256, + system_contracts::DEPLOYMENT_NONCE_INCREMENT, web3::keccak256, AccountTreeId, StorageKey, + L2_BASE_TOKEN_ADDRESS, U256, }; /// Displays a Unix timestamp (seconds since epoch) in human-readable form. Useful for logging. diff --git a/core/lib/utils/src/misc.rs b/core/lib/utils/src/misc.rs index 94f7a9adc09..52bd7657c4e 100644 --- a/core/lib/utils/src/misc.rs +++ b/core/lib/utils/src/misc.rs @@ -1,4 +1,4 @@ -use zksync_basic_types::{web3::signing::keccak256, H256, U256}; +use zksync_basic_types::{web3::keccak256, H256, U256}; pub const fn ceil_div(a: u64, b: u64) -> u64 { if a == 0 { diff --git a/core/lib/web3_decl/src/types.rs b/core/lib/web3_decl/src/types.rs index cdbfac66d28..ec6bbed4688 100644 --- a/core/lib/web3_decl/src/types.rs +++ b/core/lib/web3_decl/src/types.rs @@ -15,14 +15,10 @@ use rlp::Rlp; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; pub use zksync_types::{ api::{Block, BlockNumber, Log, TransactionReceipt, TransactionRequest}, + ethabi, vm_trace::{ContractSourceDebugInfo, VmDebugTrace, VmExecutionStep}, - web3::{ - ethabi, - types::{ - Address, BlockHeader, Bytes, CallRequest, FeeHistory, Index, SyncState, TraceFilter, - Transaction, Work, H160, H256, H64, U256, U64, - }, - }, + web3::{BlockHeader, Bytes, CallRequest, FeeHistory, Index, SyncState, TraceFilter, Work}, + Address, Transaction, H160, H256, H64, U256, U64, }; /// Token in the zkSync network diff --git a/core/lib/zksync_core/src/api_server/tx_sender/proxy.rs b/core/lib/zksync_core/src/api_server/tx_sender/proxy.rs index eeb42994017..9155cbfac77 100644 --- a/core/lib/zksync_core/src/api_server/tx_sender/proxy.rs +++ b/core/lib/zksync_core/src/api_server/tx_sender/proxy.rs @@ -122,7 +122,7 @@ impl TxProxy { async fn submit_tx_impl(&self, tx: &L2Tx) -> EnrichedClientResult { let input_data = tx.common_data.input_data().expect("raw tx is absent"); - let raw_tx = zksync_types::Bytes(input_data.to_vec()); + let raw_tx = zksync_types::web3::Bytes(input_data.to_vec()); let tx_hash = tx.hash(); tracing::info!("Proxying tx {tx_hash:?}"); self.client diff --git a/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/eth.rs b/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/eth.rs index cf3c93698fc..03abcef7799 100644 --- a/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/eth.rs @@ -4,8 +4,8 @@ use zksync_types::{ TransactionReceipt, TransactionVariant, }, transaction_request::CallRequest, - web3::types::{FeeHistory, Index, SyncState}, - Address, Bytes, H256, U256, U64, + web3::{Bytes, FeeHistory, Index, SyncState}, + Address, H256, U256, U64, }; use zksync_web3_decl::{ jsonrpsee::core::{async_trait, RpcResult}, diff --git a/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/zks.rs b/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/zks.rs index dd07564538b..a119422c97f 100644 --- a/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/zks.rs +++ b/core/lib/zksync_core/src/api_server/web3/backend_jsonrpsee/namespaces/zks.rs @@ -9,7 +9,8 @@ use zksync_types::{ fee::Fee, fee_model::{FeeParams, PubdataIndependentBatchFeeModelInput}, transaction_request::CallRequest, - Address, Bytes, L1BatchNumber, L2BlockNumber, StorageLogQueryType, H256, U256, U64, + web3::Bytes, + Address, L1BatchNumber, L2BlockNumber, StorageLogQueryType, H256, U256, U64, }; use zksync_web3_decl::{ jsonrpsee::core::{async_trait, RpcResult}, diff --git a/core/lib/zksync_core/src/api_server/web3/metrics.rs b/core/lib/zksync_core/src/api_server/web3/metrics.rs index bc397397a65..f2ec4a683c9 100644 --- a/core/lib/zksync_core/src/api_server/web3/metrics.rs +++ b/core/lib/zksync_core/src/api_server/web3/metrics.rs @@ -524,7 +524,7 @@ mod tests { assert_matches!(rpc_params, ObservedRpcParams::Owned { .. }); assert_eq!(rpc_params.to_string(), r#" with params ["0x1"]"#); - let raw_params = [zksync_types::Bytes(vec![0xff; 512])]; + let raw_params = [zksync_types::web3::Bytes(vec![0xff; 512])]; let raw_params = serde_json::value::to_raw_value(&raw_params).unwrap(); assert_eq!(raw_params.get().len(), 1_030); // 1024 'f' chars + '0x' + '[]' + '""' let rpc_params = ObservedRpcParams::new(Some(&Cow::Borrowed(&raw_params))); diff --git a/core/lib/zksync_core/src/api_server/web3/namespaces/eth.rs b/core/lib/zksync_core/src/api_server/web3/namespaces/eth.rs index 41d61ff26c8..45e938cf216 100644 --- a/core/lib/zksync_core/src/api_server/web3/namespaces/eth.rs +++ b/core/lib/zksync_core/src/api_server/web3/namespaces/eth.rs @@ -9,11 +9,8 @@ use zksync_types::{ l2::{L2Tx, TransactionType}, transaction_request::CallRequest, utils::decompose_full_nonce, - web3::{ - self, - types::{FeeHistory, SyncInfo, SyncState}, - }, - AccountTreeId, Bytes, L2BlockNumber, StorageKey, H256, L2_BASE_TOKEN_ADDRESS, U256, + web3::{self, Bytes, FeeHistory, SyncInfo, SyncState}, + AccountTreeId, L2BlockNumber, StorageKey, H256, L2_BASE_TOKEN_ADDRESS, U256, }; use zksync_utils::u256_to_h256; use zksync_web3_decl::{ @@ -653,7 +650,7 @@ 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::types::BlockNumber::Number(oldest_block.into()), + oldest_block: web3::BlockNumber::Number(oldest_block.into()), base_fee_per_gas, gas_used_ratio, reward, diff --git a/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs b/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs index 032536bfd06..339961f7dd6 100644 --- a/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs +++ b/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs @@ -18,7 +18,8 @@ use zksync_types::{ tokens::ETHEREUM_ADDRESS, transaction_request::CallRequest, utils::storage_key_for_standard_token_balance, - AccountTreeId, Bytes, L1BatchNumber, L2BlockNumber, ProtocolVersionId, StorageKey, Transaction, + web3::Bytes, + AccountTreeId, L1BatchNumber, L2BlockNumber, ProtocolVersionId, StorageKey, Transaction, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, U64, }; use zksync_utils::{address_to_h256, h256_to_u256}; diff --git a/core/lib/zksync_core/src/consistency_checker/mod.rs b/core/lib/zksync_core/src/consistency_checker/mod.rs index 64bf5e98f25..9b94a9c5ef6 100644 --- a/core/lib/zksync_core/src/consistency_checker/mod.rs +++ b/core/lib/zksync_core/src/consistency_checker/mod.rs @@ -5,17 +5,14 @@ use serde::Serialize; use tokio::sync::watch; use zksync_contracts::PRE_BOOJUM_COMMIT_FUNCTION; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{CallFunctionArgs, Error as L1ClientError, EthInterface}; +use zksync_eth_client::{CallFunctionArgs, ClientError, Error as L1ClientError, EthInterface}; use zksync_eth_sender::l1_batch_commit_data_generator::L1BatchCommitDataGenerator; use zksync_health_check::{Health, HealthStatus, HealthUpdater, ReactiveHealthCheck}; use zksync_l1_contract_interface::i_executor::commit::kzg::ZK_SYNC_BYTES_PER_BLOB; use zksync_shared_metrics::{CheckerComponent, EN_METRICS}; use zksync_types::{ - commitment::L1BatchWithMetadata, - ethabi::Token, - pubdata_da::PubdataDA, - web3::{self, contract::Error as Web3ContractError, ethabi}, - Address, L1BatchNumber, ProtocolVersionId, H256, U256, + commitment::L1BatchWithMetadata, ethabi, ethabi::Token, pubdata_da::PubdataDA, Address, + L1BatchNumber, ProtocolVersionId, H256, U256, }; use crate::utils::wait_for_l1_batch_with_metadata; @@ -40,7 +37,7 @@ impl CheckError { matches!( self, Self::Web3(L1ClientError::EthereumGateway( - web3::Error::Unreachable | web3::Error::Transport(_) | web3::Error::Io(_) + ClientError::Transport(_) | ClientError::RequestTimeout )) ) } @@ -257,13 +254,13 @@ impl LocalL1BatchCommitData { pub fn detect_da( protocol_version: ProtocolVersionId, reference: &Token, -) -> Result { +) -> Result { /// These are used by the L1 Contracts to indicate what DA layer is used for pubdata const PUBDATA_SOURCE_CALLDATA: u8 = 0; const PUBDATA_SOURCE_BLOBS: u8 = 1; - fn parse_error(message: impl Into>) -> Web3ContractError { - Web3ContractError::Abi(ethabi::Error::Other(message.into())) + fn parse_error(message: impl Into>) -> ethabi::Error { + ethabi::Error::Other(message.into()) } if protocol_version.is_pre_1_4_2() { @@ -513,22 +510,12 @@ impl ConsistencyChecker { }; tracing::debug!("Performing sanity checks for diamond proxy contract {address:?}"); - let call = CallFunctionArgs::new("getProtocolVersion", ()) - .for_contract(address, self.contract.clone()); - let response = self.l1_client.call_contract_function(call).await?; - // Response should be a single token with the contract name. - match response.as_slice() { - [ethabi::Token::Uint(version)] => { - tracing::info!("Checked diamond proxy {address:?} (protocol version: {version})"); - Ok(()) - } - _ => { - let err = anyhow::anyhow!( - "unexpected `getProtocolVersion` response from contract {address:?}: {response:?}" - ); - Err(CheckError::Internal(err)) - } - } + let version: U256 = CallFunctionArgs::new("getProtocolVersion", ()) + .for_contract(address, &self.contract) + .call(self.l1_client.as_ref()) + .await?; + tracing::info!("Checked diamond proxy {address:?} (protocol version: {version})"); + Ok(()) } pub async fn run(mut self, mut stop_receiver: watch::Receiver) -> anyhow::Result<()> { diff --git a/core/lib/zksync_core/src/consistency_checker/tests/mod.rs b/core/lib/zksync_core/src/consistency_checker/tests/mod.rs index d222eadaea6..061bc3e7ea5 100644 --- a/core/lib/zksync_core/src/consistency_checker/tests/mod.rs +++ b/core/lib/zksync_core/src/consistency_checker/tests/mod.rs @@ -17,7 +17,7 @@ use zksync_node_test_utils::{ DeploymentMode, }; use zksync_types::{ - aggregated_operations::AggregatedActionType, commitment::L1BatchWithMetadata, Log, + aggregated_operations::AggregatedActionType, commitment::L1BatchWithMetadata, web3::Log, ProtocolVersion, ProtocolVersionId, H256, }; @@ -107,10 +107,15 @@ pub(crate) fn create_mock_checker( } fn create_mock_ethereum() -> MockEthereum { - MockEthereum::default().with_call_handler(|call| { - assert_eq!(call.contract_address(), DIAMOND_PROXY_ADDR); - assert_eq!(call.function_name(), "getProtocolVersion"); - assert_eq!(call.args(), []); + MockEthereum::default().with_call_handler(|call, _block_id| { + assert_eq!(call.to, Some(DIAMOND_PROXY_ADDR)); + let contract = zksync_contracts::hyperchain_contract(); + let expected_input = contract + .function("getProtocolVersion") + .unwrap() + .encode_input(&[]) + .unwrap(); + assert_eq!(call.data, Some(expected_input.into())); ethabi::Token::Uint((ProtocolVersionId::latest() as u16).into()) }) } diff --git a/core/lib/zksync_core/src/utils/mod.rs b/core/lib/zksync_core/src/utils/mod.rs index a8b03c02b47..2235792fce7 100644 --- a/core/lib/zksync_core/src/utils/mod.rs +++ b/core/lib/zksync_core/src/utils/mod.rs @@ -11,12 +11,8 @@ use async_trait::async_trait; use tokio::sync::watch; use zksync_config::configs::chain::L1BatchCommitDataGeneratorMode; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_eth_client::{CallFunctionArgs, Error as EthClientError, EthInterface}; -use zksync_l1_contract_interface::Detokenize; -use zksync_types::{ - ethabi::{self, Address}, - L1BatchNumber, ProtocolVersionId, -}; +use zksync_eth_client::{CallFunctionArgs, ContractError, Error as EthClientError, EthInterface}; +use zksync_types::{Address, L1BatchNumber, ProtocolVersionId}; /// Fallible and async predicate for binary search. #[async_trait] @@ -166,12 +162,14 @@ pub(crate) async fn pending_protocol_version( async fn get_pubdata_pricing_mode( diamond_proxy_address: Address, eth_client: &dyn EthInterface, -) -> Result, EthClientError> { - let args = CallFunctionArgs::new("getPubdataPricingMode", ()).for_contract( - diamond_proxy_address, - zksync_contracts::hyperchain_contract(), - ); - eth_client.call_contract_function(args).await +) -> Result { + CallFunctionArgs::new("getPubdataPricingMode", ()) + .for_contract( + diamond_proxy_address, + &zksync_contracts::hyperchain_contract(), + ) + .call(eth_client) + .await } pub async fn ensure_l1_batch_commit_data_generation_mode( @@ -181,14 +179,7 @@ pub async fn ensure_l1_batch_commit_data_generation_mode( ) -> anyhow::Result<()> { match get_pubdata_pricing_mode(diamond_proxy_address, eth_client).await { // Getters contract support getPubdataPricingMode method - Ok(l1_contract_pubdata_pricing_mode) => { - let l1_contract_batch_commitment_mode = - L1BatchCommitDataGeneratorMode::from_tokens(l1_contract_pubdata_pricing_mode) - .context( - "Unable to parse L1BatchCommitDataGeneratorMode received from L1 contract", - )?; - - // contracts mode == server mode + Ok(l1_contract_batch_commitment_mode) => { anyhow::ensure!( l1_contract_batch_commitment_mode == selected_l1_batch_commit_data_generator_mode, "The selected L1BatchCommitDataGeneratorMode ({:?}) does not match the commitment mode used on L1 contract ({:?})", @@ -201,7 +192,7 @@ pub async fn ensure_l1_batch_commit_data_generation_mode( // Getters contract does not support getPubdataPricingMode method. // This case is accepted for backwards compatibility with older contracts, but emits a // warning in case the wrong contract address was passed by the caller. - Err(EthClientError::Contract(_)) => { + Err(EthClientError::Contract(ContractError::Function(_))) => { tracing::warn!("Getters contract does not support getPubdataPricingMode method"); Ok(()) } @@ -213,9 +204,9 @@ pub async fn ensure_l1_batch_commit_data_generation_mode( mod tests { use std::{mem, sync::Mutex}; - use zksync_eth_client::clients::MockEthereum; + use zksync_eth_client::{clients::MockEthereum, ClientError}; use zksync_node_genesis::{insert_genesis_batch, GenesisParams}; - use zksync_types::U256; + use zksync_types::{ethabi, U256}; use super::*; @@ -266,7 +257,7 @@ mod tests { fn mock_ethereum(token: ethabi::Token, err: Option) -> MockEthereum { let err_mutex = Mutex::new(err); - MockEthereum::default().with_fallible_call_handler(move |_call| { + MockEthereum::default().with_fallible_call_handler(move |_, _| { let err = mem::take(&mut *err_mutex.lock().unwrap()); if let Some(err) = err { Err(err) @@ -277,13 +268,14 @@ mod tests { } fn mock_ethereum_with_legacy_contract() -> MockEthereum { - let err = - EthClientError::Contract(zksync_types::web3::contract::Error::InterfaceUnsupported); + let abi_err = ethabi::Error::InvalidName("getPubdataPricingMode".into()); + let err = EthClientError::Contract(ContractError::Function(abi_err)); mock_ethereum(ethabi::Token::Uint(U256::zero()), Some(err)) } - fn mock_ethereum_with_tx_error() -> MockEthereum { - let err = EthClientError::EthereumGateway(zksync_types::web3::Error::Unreachable); + fn mock_ethereum_with_transport_error() -> MockEthereum { + let err = + EthClientError::EthereumGateway(ClientError::Transport(anyhow::anyhow!("unreachable"))); mock_ethereum(ethabi::Token::Uint(U256::zero()), Some(err)) } @@ -365,14 +357,13 @@ mod tests { let err = ensure_l1_batch_commit_data_generation_mode( L1BatchCommitDataGeneratorMode::Rollup, addr, - &mock_ethereum_with_tx_error(), + &mock_ethereum_with_transport_error(), ) .await .unwrap_err(); assert!( - err.chain() - .any(|cause| cause.is::()), + err.chain().any(|cause| cause.is::()), "{err:?}" ); } @@ -391,7 +382,7 @@ mod tests { .to_string(); assert!( - err.contains("Unable to parse L1BatchCommitDataGeneratorMode"), + err.contains("L1BatchCommitDataGeneratorMode::from_tokens"), "{err}", ); } diff --git a/core/node/block_reverter/Cargo.toml b/core/node/block_reverter/Cargo.toml index 586b6c78cd5..178e3da6c58 100644 --- a/core/node/block_reverter/Cargo.toml +++ b/core/node/block_reverter/Cargo.toml @@ -16,7 +16,7 @@ zksync_config.workspace = true zksync_contracts.workspace = true zksync_object_store.workspace = true zksync_storage.workspace = true -zksync_eth_signer.workspace = true +zksync_eth_client.workspace = true zksync_state.workspace = true zksync_merkle_tree.workspace = true diff --git a/core/node/block_reverter/src/lib.rs b/core/node/block_reverter/src/lib.rs index a75c1c8e415..1a9e71c38c1 100644 --- a/core/node/block_reverter/src/lib.rs +++ b/core/node/block_reverter/src/lib.rs @@ -6,7 +6,9 @@ use tokio::fs; use zksync_config::{configs::chain::NetworkConfig, ContractsConfig, EthConfig}; use zksync_contracts::hyperchain_contract; use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_eth_signer::{EthereumSigner, PrivateKeySigner, TransactionParameters}; +// Public re-export to simplify the API use. +pub use zksync_eth_client as eth_client; +use zksync_eth_client::{BoundEthInterface, CallFunctionArgs, EthInterface, Options}; use zksync_merkle_tree::domain::ZkSyncTree; use zksync_object_store::{ObjectStore, ObjectStoreError}; use zksync_state::RocksdbStorage; @@ -18,14 +20,8 @@ use zksync_types::{ SnapshotFactoryDependencies, SnapshotMetadata, SnapshotStorageLogsChunk, SnapshotStorageLogsStorageKey, }, - url::SensitiveUrl, - web3::{ - contract::{Contract, Options}, - transports::Http, - types::{BlockId, BlockNumber}, - Web3, - }, - Address, K256PrivateKey, L1BatchNumber, L2ChainId, H160, H256, U256, + web3::BlockNumber, + Address, L1BatchNumber, L2ChainId, H160, H256, U256, }; #[cfg(test)] @@ -33,8 +29,6 @@ mod tests; #[derive(Debug)] pub struct BlockReverterEthConfig { - eth_client_url: SensitiveUrl, - reverter_private_key: Option, diamond_proxy_addr: H160, validator_timelock_addr: H160, default_priority_fee_per_gas: u64, @@ -44,26 +38,17 @@ pub struct BlockReverterEthConfig { impl BlockReverterEthConfig { pub fn new( - eth_config: EthConfig, + eth_config: &EthConfig, contract: &ContractsConfig, network_config: &NetworkConfig, era_chain_id: L2ChainId, ) -> anyhow::Result { - #[allow(deprecated)] - // `BlockReverter` doesn't support non env configs yet - let reverter_private_key = eth_config - .sender - .context("eth_sender_config")? - .private_key() - .context("eth_sender_config.private_key")?; - Ok(Self { - eth_client_url: eth_config.web3_url, - reverter_private_key, diamond_proxy_addr: contract.diamond_proxy_addr, validator_timelock_addr: contract.validator_timelock_addr, default_priority_fee_per_gas: eth_config .gas_adjuster + .as_ref() .context("gas adjuster")? .default_priority_fee_per_gas, hyperchain_id: network_config.zksync_network_id, @@ -452,32 +437,17 @@ impl BlockReverter { /// Sends a revert transaction to L1. pub async fn send_ethereum_revert_transaction( &self, + eth_client: &dyn BoundEthInterface, eth_config: &BlockReverterEthConfig, last_l1_batch_to_keep: L1BatchNumber, - priority_fee_per_gas: U256, nonce: u64, ) -> anyhow::Result<()> { tracing::info!( "Sending Ethereum revert transaction for L1 batch #{last_l1_batch_to_keep} with config {eth_config:?}, \ - priority fee: {priority_fee_per_gas}, nonce: {nonce}" + nonce: {nonce}" ); - let transport = - Http::new(eth_config.eth_client_url.expose_str()).context("cannot create L1 client")?; - let web3 = Web3::new(transport); let contract = hyperchain_contract(); - let signer = PrivateKeySigner::new( - eth_config - .reverter_private_key - .clone() - .context("private key is required to send revert transaction")?, - ); - let chain_id = web3 - .eth() - .chain_id() - .await - .context("failed getting L1 chain ID")? - .as_u64(); // It is expected that for all new chains `revertBatchesSharedBridge` can be used. // For Era, we are using `revertBatches` function for backwards compatibility in case the migration @@ -501,56 +471,27 @@ impl BlockReverter { .context("failed encoding `revertBatchesSharedBridge` input")? }; - let base_fee = web3 - .eth() - .block(BlockId::Number(BlockNumber::Pending)) - .await - .context("failed getting pending L1 block")? - .map(|block| { - block - .base_fee_per_gas - .context("no base_fee_per_gas in pending block") - }) - .transpose()?; - let base_fee = if let Some(base_fee) = base_fee { - base_fee - } else { - // Pending block doesn't exist, use the latest one. - web3.eth() - .block(BlockId::Number(BlockNumber::Latest)) - .await - .context("failed geting latest L1 block")? - .context("no latest L1 block")? - .base_fee_per_gas - .context("no base_fee_per_gas in latest block")? - }; - - let tx = TransactionParameters { - to: eth_config.validator_timelock_addr.into(), - data, - chain_id, - nonce: nonce.into(), - max_priority_fee_per_gas: priority_fee_per_gas, - max_fee_per_gas: base_fee + priority_fee_per_gas, - gas: 5_000_000.into(), + let options = Options { + nonce: Some(nonce.into()), + gas: Some(5_000_000.into()), ..Default::default() }; - let signed_tx = signer - .sign_transaction(tx) + let signed_tx = eth_client + .sign_prepared_tx_for_addr(data, eth_config.validator_timelock_addr, options) .await .context("cannot sign revert transaction")?; - let hash = web3 - .eth() - .send_raw_transaction(signed_tx.into()) + let hash = eth_client + .as_ref() + .send_raw_tx(signed_tx.raw_tx) .await .context("failed sending revert transaction")?; tracing::info!("Sent revert transaction to L1 with hash {hash:?}"); loop { - let maybe_receipt = web3 - .eth() - .transaction_receipt(hash) + let maybe_receipt = eth_client + .as_ref() + .tx_receipt(hash) .await .context("failed getting receipt for revert transaction")?; if let Some(receipt) = maybe_receipt { @@ -568,9 +509,10 @@ impl BlockReverter { } } - #[tracing::instrument(skip(contract), err, fields(contract.address = ?contract.address()))] + #[tracing::instrument(err)] async fn get_l1_batch_number_from_contract( - contract: &Contract, + eth_client: &dyn EthInterface, + contract_address: Address, op: AggregatedActionType, ) -> anyhow::Result { let function_name = match op { @@ -578,14 +520,12 @@ impl BlockReverter { AggregatedActionType::PublishProofOnchain => "getTotalBatchesVerified", AggregatedActionType::Execute => "getTotalBatchesExecuted", }; - let block_number: U256 = contract - .query(function_name, (), None, Options::default(), None) + let block_number: U256 = CallFunctionArgs::new(function_name, ()) + .for_contract(contract_address, &hyperchain_contract()) + .call(eth_client) .await .with_context(|| { - format!( - "failed calling `{function_name}` for contract {:?}", - contract.address() - ) + format!("failed calling `{function_name}` for contract {contract_address:?}") })?; Ok(L1BatchNumber(block_number.as_u32())) } @@ -593,28 +533,32 @@ impl BlockReverter { /// Returns suggested values for a reversion. pub async fn suggested_values( &self, + eth_client: &dyn EthInterface, eth_config: &BlockReverterEthConfig, reverter_address: Address, ) -> anyhow::Result { tracing::info!("Computing suggested revert values for config {eth_config:?}"); - let transport = - Http::new(eth_config.eth_client_url.expose_str()).context("cannot create L1 client")?; - let web3 = Web3::new(transport); let contract_address = eth_config.diamond_proxy_addr; - let contract = Contract::new(web3.eth(), contract_address, hyperchain_contract()); - let last_committed_l1_batch_number = - Self::get_l1_batch_number_from_contract(&contract, AggregatedActionType::Commit) - .await?; + let last_committed_l1_batch_number = Self::get_l1_batch_number_from_contract( + eth_client, + contract_address, + AggregatedActionType::Commit, + ) + .await?; let last_verified_l1_batch_number = Self::get_l1_batch_number_from_contract( - &contract, + eth_client, + contract_address, AggregatedActionType::PublishProofOnchain, ) .await?; - let last_executed_l1_batch_number = - Self::get_l1_batch_number_from_contract(&contract, AggregatedActionType::Execute) - .await?; + let last_executed_l1_batch_number = Self::get_l1_batch_number_from_contract( + eth_client, + contract_address, + AggregatedActionType::Execute, + ) + .await?; tracing::info!( "Last L1 batch numbers on contract: committed {last_committed_l1_batch_number}, \ @@ -622,9 +566,8 @@ impl BlockReverter { ); let priority_fee = eth_config.default_priority_fee_per_gas; - let nonce = web3 - .eth() - .transaction_count(reverter_address, Some(BlockNumber::Pending)) + let nonce = eth_client + .nonce_at_for_account(reverter_address, BlockNumber::Pending) .await .with_context(|| format!("failed getting transaction count for {reverter_address:?}"))? .as_u64(); diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 95d9b395b5a..59e40d7f26d 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -8,7 +8,7 @@ use zksync_eth_client::{BoundEthInterface, CallFunctionArgs}; use zksync_l1_contract_interface::{ i_executor::commit::kzg::{KzgInfo, ZK_SYNC_BYTES_PER_BLOB}, multicall3::{Multicall3Call, Multicall3Result}, - Detokenize, Tokenizable, Tokenize, + Tokenizable, Tokenize, }; use zksync_shared_metrics::BlockL1Stage; use zksync_types::{ @@ -19,7 +19,7 @@ use zksync_types::{ l2_to_l1_log::UserL2ToL1Log, protocol_version::{L1VerifierConfig, VerifierParams}, pubdata_da::PubdataDA, - web3::{contract::Error as Web3ContractError, types::BlockNumber}, + web3::{contract::Error as Web3ContractError, BlockNumber}, Address, L2ChainId, ProtocolVersionId, H256, U256, }; @@ -141,13 +141,10 @@ impl EthTxAggregator { let calldata = self.generate_calldata_for_multicall(); let args = CallFunctionArgs::new(&self.functions.aggregate3.name, calldata).for_contract( self.l1_multicall3_address, - self.functions.multicall_contract.clone(), + &self.functions.multicall_contract, ); - let aggregate3_result = (*self.eth_client) - .as_ref() - .call_contract_function(args) - .await?; - self.parse_multicall_data(Token::from_tokens(aggregate3_result)?) + let aggregate3_result: Token = args.call((*self.eth_client).as_ref()).await?; + self.parse_multicall_data(aggregate3_result) } // Multicall's aggregate function accepts 1 argument - arrays of different contract calls. @@ -336,13 +333,11 @@ impl EthTxAggregator { verifier_address: Address, ) -> Result { let get_vk_hash = &self.functions.verification_key_hash; - let args = CallFunctionArgs::new(&get_vk_hash.name, ()) - .for_contract(verifier_address, self.functions.verifier_contract.clone()); - let vk_hash = (*self.eth_client) - .as_ref() - .call_contract_function(args) + let vk_hash: H256 = CallFunctionArgs::new(&get_vk_hash.name, ()) + .for_contract(verifier_address, &self.functions.verifier_contract) + .call((*self.eth_client).as_ref()) .await?; - Ok(H256::from_tokens(vk_hash)?) + Ok(vk_hash) } #[tracing::instrument(skip(self, storage))] diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index d9b401d3341..5570d3bd6fa 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -5,18 +5,15 @@ 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, Error, EthInterface, ExecutedTxStatus, Options, - RawTransactionBytes, SignedCallResult, + encode_blob_tx_with_sidecar, BoundEthInterface, ClientError, Error, EthInterface, + ExecutedTxStatus, Options, RawTransactionBytes, SignedCallResult, }; use zksync_node_fee_model::l1_gas_price::L1TxParamsProvider; use zksync_shared_metrics::BlockL1Stage; use zksync_types::{ aggregated_operations::AggregatedActionType, eth_sender::{EthTx, EthTxBlobSidecar}, - web3::{ - error::Error as Web3Error, - types::{BlockId, BlockNumber}, - }, + web3::{BlockId, BlockNumber}, Address, L1BlockNumber, Nonce, EIP_1559_TX_TYPE, EIP_4844_TX_TYPE, H256, U256, }; use zksync_utils::time::seconds_since_epoch; @@ -225,7 +222,8 @@ impl EthTxManager { previous_base_fee, next_block_minimal_base_fee ); - return Err(ETHSenderError::from(Error::from(Web3Error::Internal))); + let err = ClientError::Custom("base_fee_per_gas is too low".into()); + return Err(ETHSenderError::from(Error::EthereumGateway(err))); } // Increase `priority_fee_per_gas` by at least 20% to prevent "replacement transaction under-priced" error. diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index f21789378a4..e576c0072b2 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -101,8 +101,8 @@ impl EthSenderTester { .collect(), ) .with_non_ordering_confirmation(non_ordering_confirmations) - .with_call_handler(move |call| { - assert_eq!(call.contract_address(), contracts_config.l1_multicall3_addr); + .with_call_handler(move |call, _| { + assert_eq!(call.to, Some(contracts_config.l1_multicall3_addr)); mock_multicall_response() }); gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); diff --git a/core/node/eth_watch/src/client.rs b/core/node/eth_watch/src/client.rs index 71948060987..f617b1f1826 100644 --- a/core/node/eth_watch/src/client.rs +++ b/core/node/eth_watch/src/client.rs @@ -2,14 +2,10 @@ use std::fmt; use zksync_contracts::verifier_contract; pub(super) use zksync_eth_client::Error as EthClientError; -use zksync_eth_client::{CallFunctionArgs, EthInterface}; +use zksync_eth_client::{CallFunctionArgs, ClientError, EthInterface}; use zksync_types::{ ethabi::Contract, - web3::{ - self, - contract::tokens::Detokenize, - types::{BlockId, BlockNumber, FilterBuilder, Log}, - }, + web3::{BlockId, BlockNumber, FilterBuilder, Log}, Address, H256, }; @@ -101,10 +97,10 @@ impl EthHttpQueryClient { impl EthClient for EthHttpQueryClient { async fn scheduler_vk_hash(&self, verifier_address: Address) -> Result { // New verifier returns the hash of the verification key. - let args = CallFunctionArgs::new("verificationKeyHash", ()) - .for_contract(verifier_address, self.verifier_contract_abi.clone()); - let vk_hash_tokens = self.client.call_contract_function(args).await?; - Ok(H256::from_tokens(vk_hash_tokens)?) + CallFunctionArgs::new("verificationKeyHash", ()) + .for_contract(verifier_address, &self.verifier_contract_abi) + .call(self.client.as_ref()) + .await } async fn get_events( @@ -120,8 +116,8 @@ impl EthClient for EthHttpQueryClient { if let Err(EthClientError::EthereumGateway(err)) = &result { tracing::warn!("Provider returned error message: {:?}", err); let err_message = err.to_string(); - let err_code = if let web3::Error::Rpc(err) = err { - Some(err.code.code()) + let err_code = if let ClientError::Call(err) = err { + Some(err.code()) } else { None }; @@ -192,11 +188,11 @@ impl EthClient for EthHttpQueryClient { .block(BlockId::Number(BlockNumber::Finalized)) .await? .ok_or_else(|| { - web3::Error::InvalidResponse("Finalized block must be present on L1".into()) + ClientError::Custom("Finalized block must be present on L1".into()) })?; - let block_number = block.number.ok_or_else(|| { - web3::Error::InvalidResponse("Finalized block must contain number".into()) - })?; + let block_number = block + .number + .ok_or_else(|| ClientError::Custom("Finalized block must contain number".into()))?; Ok(block_number.as_u64()) } } diff --git a/core/node/eth_watch/src/event_processors/governance_upgrades.rs b/core/node/eth_watch/src/event_processors/governance_upgrades.rs index 32f91cecaa9..b2e06cf6c89 100644 --- a/core/node/eth_watch/src/event_processors/governance_upgrades.rs +++ b/core/node/eth_watch/src/event_processors/governance_upgrades.rs @@ -1,8 +1,8 @@ use anyhow::Context as _; use zksync_dal::{Connection, Core, CoreDal, DalError}; use zksync_types::{ - ethabi::Contract, protocol_upgrade::GovernanceOperation, web3::types::Log, Address, - ProtocolUpgrade, ProtocolVersionId, H256, + ethabi::Contract, protocol_upgrade::GovernanceOperation, web3::Log, Address, ProtocolUpgrade, + ProtocolVersionId, H256, }; use crate::{ diff --git a/core/node/eth_watch/src/event_processors/mod.rs b/core/node/eth_watch/src/event_processors/mod.rs index f67436ddf53..2a3a6344bdb 100644 --- a/core/node/eth_watch/src/event_processors/mod.rs +++ b/core/node/eth_watch/src/event_processors/mod.rs @@ -1,7 +1,7 @@ use std::fmt; use zksync_dal::{Connection, Core}; -use zksync_types::{web3::types::Log, H256}; +use zksync_types::{web3::Log, H256}; pub(crate) use self::{ governance_upgrades::GovernanceUpgradesEventProcessor, priority_ops::PriorityOpsEventProcessor, diff --git a/core/node/eth_watch/src/event_processors/priority_ops.rs b/core/node/eth_watch/src/event_processors/priority_ops.rs index 25e959033a4..2783637fdb9 100644 --- a/core/node/eth_watch/src/event_processors/priority_ops.rs +++ b/core/node/eth_watch/src/event_processors/priority_ops.rs @@ -4,7 +4,7 @@ use anyhow::Context; use zksync_contracts::hyperchain_contract; use zksync_dal::{Connection, Core, CoreDal, DalError}; use zksync_shared_metrics::{TxStage, APP_METRICS}; -use zksync_types::{l1::L1Tx, web3::types::Log, PriorityOpId, H256}; +use zksync_types::{l1::L1Tx, web3::Log, PriorityOpId, H256}; use crate::{ client::EthClient, diff --git a/core/node/eth_watch/src/lib.rs b/core/node/eth_watch/src/lib.rs index 588ae94d9fc..a8042bb2a92 100644 --- a/core/node/eth_watch/src/lib.rs +++ b/core/node/eth_watch/src/lib.rs @@ -9,7 +9,7 @@ use tokio::sync::watch; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_system_constants::PRIORITY_EXPIRATION; use zksync_types::{ - ethabi::Contract, web3::types::BlockNumber as Web3BlockNumber, Address, PriorityOpId, + ethabi::Contract, web3::BlockNumber as Web3BlockNumber, Address, PriorityOpId, ProtocolVersionId, }; diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index c9ce406ed60..a3dfda07bf1 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -7,9 +7,9 @@ use zksync_types::{ ethabi::{encode, Hash, Token}, l1::{L1Tx, OpProcessingType, PriorityQueueType}, protocol_upgrade::{ProtocolUpgradeTx, ProtocolUpgradeTxCommonData}, - web3::types::{Address, BlockNumber, Log}, - Execute, L1TxCommonData, PriorityOpId, ProtocolUpgrade, ProtocolVersion, ProtocolVersionId, - Transaction, H256, U256, + web3::{BlockNumber, Log}, + Address, Execute, L1TxCommonData, PriorityOpId, ProtocolUpgrade, ProtocolVersion, + ProtocolVersionId, Transaction, H256, U256, }; use crate::{ diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 8037880cd18..fc95141adee 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -19,7 +19,7 @@ use zksync_types::{ protocol_upgrade::decode_set_chain_id_event, protocol_version::{L1VerifierConfig, VerifierParams}, system_contracts::get_system_smart_contracts, - web3::types::{BlockNumber, FilterBuilder}, + web3::{BlockNumber, FilterBuilder}, AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersion, ProtocolVersionId, StorageKey, H256, }; diff --git a/core/node/proof_data_handler/src/request_processor.rs b/core/node/proof_data_handler/src/request_processor.rs index 210ada7aac0..8b3d0de745d 100644 --- a/core/node/proof_data_handler/src/request_processor.rs +++ b/core/node/proof_data_handler/src/request_processor.rs @@ -14,7 +14,7 @@ use zksync_prover_interface::api::{ SubmitProofRequest, SubmitProofResponse, }; use zksync_types::{ - basic_fri_types::Eip4844Blobs, commitment::serialize_commitments, web3::signing::keccak256, + basic_fri_types::Eip4844Blobs, commitment::serialize_commitments, web3::keccak256, L1BatchNumber, H256, }; diff --git a/core/tests/loadnext/src/account/tx_command_executor.rs b/core/tests/loadnext/src/account/tx_command_executor.rs index b4065227380..2a916564fd6 100644 --- a/core/tests/loadnext/src/account/tx_command_executor.rs +++ b/core/tests/loadnext/src/account/tx_command_executor.rs @@ -17,11 +17,11 @@ use crate::{ report::ReportLabel, sdk::{ error::ClientError, + ethabi, ethereum::PriorityOpHolder, utils::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, - web3::ethabi, EthNamespaceClient, }, utils::format_gwei, diff --git a/core/tests/loadnext/src/executor.rs b/core/tests/loadnext/src/executor.rs index c813c97c019..fe262acc138 100644 --- a/core/tests/loadnext/src/executor.rs +++ b/core/tests/loadnext/src/executor.rs @@ -22,7 +22,7 @@ use crate::{ utils::{ get_approval_based_paymaster_input, get_approval_based_paymaster_input_for_estimation, }, - web3::types::TransactionReceipt, + web3::TransactionReceipt, EthNamespaceClient, EthereumProvider, ZksNamespaceClient, }, utils::format_eth, diff --git a/core/tests/loadnext/src/rng.rs b/core/tests/loadnext/src/rng.rs index 4bb7844a1c4..ed483e95bd5 100644 --- a/core/tests/loadnext/src/rng.rs +++ b/core/tests/loadnext/src/rng.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; use rand::{rngs::SmallRng, seq::SliceRandom, thread_rng, RngCore, SeedableRng}; -use crate::{all::AllWeighted, sdk::web3::signing::keccak256}; +use crate::{all::AllWeighted, sdk::web3::keccak256}; // SmallRng seed type is [u8; 32]. const SEED_SIZE: usize = 32; diff --git a/core/tests/loadnext/src/sdk/ethereum/mod.rs b/core/tests/loadnext/src/sdk/ethereum/mod.rs index 5ec65b96c89..d4dabdeb519 100644 --- a/core/tests/loadnext/src/sdk/ethereum/mod.rs +++ b/core/tests/loadnext/src/sdk/ethereum/mod.rs @@ -10,23 +10,20 @@ use zksync_eth_client::{ use zksync_eth_signer::EthereumSigner; use zksync_types::{ api::BridgeAddresses, + ethabi, l1::L1Tx, network::Network, url::SensitiveUrl, - web3::{ - contract::tokens::{Detokenize, Tokenize}, - ethabi, - types::{TransactionReceipt, H160, H256, U256}, - }, - Address, L1ChainId, L1TxCommonData, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, + web3::{contract::Tokenize, TransactionReceipt}, + Address, L1ChainId, L1TxCommonData, H160, H256, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, }; use zksync_web3_decl::namespaces::{EthNamespaceClient, ZksNamespaceClient}; use crate::sdk::{ error::ClientError, + ethabi::Bytes, operations::SyncTransactionHandle, utils::{is_token_eth, load_contract}, - web3::ethabi::Bytes, }; const IERC20_INTERFACE: &str = include_str!("../abi/IERC20.json"); @@ -150,14 +147,14 @@ impl EthereumProvider { address: Address, token_address: Address, ) -> Result { - let args = CallFunctionArgs::new("balanceOf", address) - .for_contract(token_address, self.erc20_abi.clone()); - let res = self - .query_client() - .call_contract_function(args) + CallFunctionArgs::new("balanceOf", address) + .for_contract(token_address, &self.erc20_abi) + .call(self.query_client()) .await - .map_err(|err| ClientError::NetworkError(err.to_string()))?; - U256::from_tokens(res).map_err(|err| ClientError::MalformedResponse(err.to_string())) + .map_err(|err| match err { + Error::EthereumGateway(err) => ClientError::NetworkError(err.to_string()), + _ => ClientError::MalformedResponse(err.to_string()), + }) } /// Returns the pending nonce for the Ethereum account. @@ -185,14 +182,14 @@ impl EthereumProvider { ) -> Result { // TODO(EVM-571): This should be moved to the shared bridge, which does not have `l2_token_address` on L1. Use L2 contracts instead. let bridge = bridge.unwrap_or(self.default_bridges.l1_erc20_default_bridge.unwrap()); - let args = CallFunctionArgs::new("l2TokenAddress", l1_token_address) - .for_contract(bridge, self.l1_erc20_bridge_abi.clone()); - let res = self - .query_client() - .call_contract_function(args) + CallFunctionArgs::new("l2TokenAddress", l1_token_address) + .for_contract(bridge, &self.l1_erc20_bridge_abi) + .call(self.query_client()) .await - .map_err(|err| ClientError::NetworkError(err.to_string()))?; - Address::from_tokens(res).map_err(|err| ClientError::MalformedResponse(err.to_string())) + .map_err(|err| match err { + Error::EthereumGateway(err) => ClientError::NetworkError(err.to_string()), + _ => ClientError::MalformedResponse(err.to_string()), + }) } /// Checks whether ERC20 of a certain token deposit with limit is approved for account. @@ -206,7 +203,7 @@ impl EthereumProvider { let bridge = bridge.unwrap_or(self.default_bridges.l1_erc20_default_bridge.unwrap()); let current_allowance = self .client() - .allowance_on_account(token_address, bridge, self.erc20_abi.clone()) + .allowance_on_account(token_address, bridge, &self.erc20_abi) .await .map_err(|err| ClientError::NetworkError(err.to_string()))?; @@ -365,10 +362,11 @@ impl EthereumProvider { }; let args = CallFunctionArgs::new( "l2TransactionBaseCost", - (gas_price, gas_limit, gas_per_pubdata_byte), + (gas_price, gas_limit, U256::from(gas_per_pubdata_byte)), ); - let res = self.client().call_main_contract_function(args).await?; - Ok(U256::from_tokens(res)?) + args.for_contract(self.eth_client.contract_addr(), self.eth_client.contract()) + .call(self.query_client()) + .await } #[allow(clippy::too_many_arguments)] @@ -405,7 +403,7 @@ impl EthereumProvider { l2_value, calldata, gas_limit, - L1_TO_L2_GAS_PER_PUBDATA, + U256::from(L1_TO_L2_GAS_PER_PUBDATA), factory_deps, refund_recipient, ) diff --git a/core/tests/loadnext/src/sdk/mod.rs b/core/tests/loadnext/src/sdk/mod.rs index 90ce41b83fc..b2abf133b5c 100644 --- a/core/tests/loadnext/src/sdk/mod.rs +++ b/core/tests/loadnext/src/sdk/mod.rs @@ -1,4 +1,4 @@ -pub use zksync_types::{self, network::Network, web3}; +pub use zksync_types::{self, ethabi, network::Network, web3}; pub use zksync_web3_decl::{ jsonrpsee::http_client::*, namespaces::{EthNamespaceClient, NetNamespaceClient, Web3NamespaceClient, ZksNamespaceClient}, diff --git a/core/tests/loadnext/src/sdk/operations/transfer.rs b/core/tests/loadnext/src/sdk/operations/transfer.rs index 70de489886b..8fe35fae92e 100644 --- a/core/tests/loadnext/src/sdk/operations/transfer.rs +++ b/core/tests/loadnext/src/sdk/operations/transfer.rs @@ -6,7 +6,7 @@ use crate::sdk::{ ethereum::ierc20_contract, operations::SyncTransactionHandle, wallet::Wallet, - web3::contract::tokens::Tokenize, + web3::contract::Tokenize, zksync_types::{transaction_request::PaymasterParams, Execute, L2TxCommonData}, EthNamespaceClient, ZksNamespaceClient, }; diff --git a/core/tests/loadnext/src/sdk/operations/withdraw.rs b/core/tests/loadnext/src/sdk/operations/withdraw.rs index e970693f506..89a8f40713a 100644 --- a/core/tests/loadnext/src/sdk/operations/withdraw.rs +++ b/core/tests/loadnext/src/sdk/operations/withdraw.rs @@ -1,7 +1,7 @@ use zksync_eth_signer::EthereumSigner; use zksync_types::{ - fee::Fee, l2::L2Tx, tokens::ETHEREUM_ADDRESS, transaction_request::PaymasterParams, - web3::ethabi, Address, Nonce, L2_BASE_TOKEN_ADDRESS, U256, + ethabi, fee::Fee, l2::L2Tx, tokens::ETHEREUM_ADDRESS, transaction_request::PaymasterParams, + Address, Nonce, L2_BASE_TOKEN_ADDRESS, U256, }; use crate::sdk::{ diff --git a/core/tests/loadnext/src/sdk/utils.rs b/core/tests/loadnext/src/sdk/utils.rs index 6fa846ec461..dfd41b7e834 100644 --- a/core/tests/loadnext/src/sdk/utils.rs +++ b/core/tests/loadnext/src/sdk/utils.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use zksync_types::{transaction_request::PaymasterParams, Address, U256}; -use crate::sdk::web3::ethabi::{Contract, Token}; +use crate::sdk::ethabi::{Contract, Token}; const IPAYMASTER_FLOW_INTERFACE: &str = include_str!("./abi/IPaymasterFlow.json"); diff --git a/core/tests/loadnext/src/sdk/wallet.rs b/core/tests/loadnext/src/sdk/wallet.rs index 62dbddbe8aa..9dc7eff3c79 100644 --- a/core/tests/loadnext/src/sdk/wallet.rs +++ b/core/tests/loadnext/src/sdk/wallet.rs @@ -4,7 +4,8 @@ use zksync_types::{ l2::L2Tx, tokens::ETHEREUM_ADDRESS, transaction_request::CallRequest, - Address, Bytes, Eip712Domain, U256, + web3::Bytes, + Address, Eip712Domain, U256, }; use zksync_web3_decl::{ jsonrpsee::http_client::{HttpClient, HttpClientBuilder}, @@ -16,7 +17,7 @@ use crate::sdk::{ ethereum::{ierc20_contract, EthereumProvider}, operations::*, signer::Signer, - web3::contract::tokens::Tokenizable, + web3::contract::Tokenizable, }; #[derive(Debug)] diff --git a/prover/Cargo.lock b/prover/Cargo.lock index eab8da6b6f2..c06f6f74048 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -1563,19 +1563,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2 1.0.78", - "quote 1.0.35", - "rustc_version", - "syn 1.0.109", -] - [[package]] name = "derive_more" version = "1.0.0-beta.6" @@ -2208,12 +2195,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - [[package]] name = "futures-util" version = "0.3.30" @@ -2418,30 +2399,6 @@ dependencies = [ "hashbrown 0.14.3", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.3.3" @@ -2612,20 +2569,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - [[package]] name = "hyper-timeout" version = "0.4.1" @@ -2680,16 +2623,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.5.0" @@ -2855,21 +2788,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonrpc-core" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" -dependencies = [ - "futures 0.3.30", - "futures-executor", - "futures-util", - "log", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "jsonwebtoken" version = "8.3.0" @@ -4660,7 +4578,6 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -4671,7 +4588,6 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", "rustls-pemfile", "serde", "serde_json", @@ -4680,7 +4596,6 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls", "tokio-util", "tower-service", "url", @@ -4688,7 +4603,6 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", "winreg", ] @@ -4911,18 +4825,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.7", - "rustls-webpki", - "sct", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -4932,16 +4834,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - [[package]] name = "rustversion" version = "1.0.14" @@ -4990,16 +4882,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - [[package]] name = "seahash" version = "4.1.0" @@ -5287,19 +5169,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha1" version = "0.10.6" @@ -5517,21 +5386,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.1", - "bytes", - "futures 0.3.30", - "httparse", - "log", - "rand 0.8.5", - "sha-1", -] - [[package]] name = "spin" version = "0.5.2" @@ -6193,16 +6047,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.14" @@ -6222,7 +6066,6 @@ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -6602,7 +6445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] @@ -6856,60 +6699,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web3" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5388522c899d1e1c96a4c307e3797e0f697ba7c77dd8e0e625ecba9dd0342937" -dependencies = [ - "arrayvec 0.7.4", - "base64 0.21.7", - "bytes", - "derive_more 0.99.17", - "ethabi", - "ethereum-types", - "futures 0.3.30", - "futures-timer", - "headers", - "hex", - "idna 0.4.0", - "jsonrpc-core", - "log", - "once_cell", - "parking_lot", - "pin-project", - "reqwest", - "rlp", - "secp256k1", - "serde", - "serde_json", - "soketto", - "tiny-keccak 2.0.2", - "tokio", - "tokio-stream", - "tokio-util", - "url", - "web3-async-native-tls", -] - -[[package]] -name = "web3-async-native-tls" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" -dependencies = [ - "native-tls", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "which" version = "4.4.2" @@ -7512,12 +7301,15 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "ethabi", + "hex", "num_enum 0.7.2", "serde", "serde_json", "strum", + "thiserror", + "tiny-keccak 2.0.2", "url", - "web3", ] [[package]] @@ -7658,7 +7450,6 @@ dependencies = [ "serde", "serde_json", "thiserror", - "web3", "zksync_basic_types", "zksync_utils", ] @@ -8002,7 +7793,7 @@ dependencies = [ "anyhow", "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "chrono", - "derive_more 1.0.0-beta.6", + "derive_more", "hex", "itertools 0.10.5", "num", diff --git a/prover/witness_generator/src/main.rs b/prover/witness_generator/src/main.rs index f234a80b481..2c6cd6583dc 100644 --- a/prover/witness_generator/src/main.rs +++ b/prover/witness_generator/src/main.rs @@ -3,7 +3,7 @@ use std::time::{Duration, Instant}; use anyhow::{anyhow, Context as _}; -use futures::{channel::mpsc, executor::block_on, SinkExt}; +use futures::{channel::mpsc, executor::block_on, SinkExt, StreamExt}; use prometheus_exporter::PrometheusExporterConfig; use prover_dal::{ConnectionPool, Prover, ProverDal}; use structopt::StructOpt; @@ -15,9 +15,7 @@ use zksync_config::{ use zksync_env_config::{object_store::ProverObjectStoreConfig, FromEnv}; use zksync_object_store::ObjectStoreFactory; use zksync_queued_job_processor::JobProcessor; -use zksync_types::{ - basic_fri_types::AggregationRound, web3::futures::StreamExt, ProtocolVersionId, -}; +use zksync_types::{basic_fri_types::AggregationRound, ProtocolVersionId}; use zksync_utils::wait_for_tasks::ManagedTasks; use zksync_vk_setup_data_server_fri::commitment_utils::get_cached_commitments; From 4df5b7f176491c0e3e6a47cea08a2eccb8001e67 Mon Sep 17 00:00:00 2001 From: zksync-era-bot <147085853+zksync-era-bot@users.noreply.github.com> Date: Wed, 8 May 2024 11:28:33 +0300 Subject: [PATCH 3/9] chore(main): release core 24.1.0 (#1836) :robot: I have created a release *beep* *boop* --- ## [24.1.0](https://github.com/matter-labs/zksync-era/compare/core-v24.0.0...core-v24.1.0) (2024-05-08) ### Features * add `sendRawTransactionWithDetailedOutput` API ([#1806](https://github.com/matter-labs/zksync-era/issues/1806)) ([6a30a31](https://github.com/matter-labs/zksync-era/commit/6a30a3161972461cb707ec5549aed6e837933a27)) * add getGasPerPubdataByte endpoint ([#1778](https://github.com/matter-labs/zksync-era/issues/1778)) ([d62dd08](https://github.com/matter-labs/zksync-era/commit/d62dd0801faae5442dc72e93a2c746769351cee0)) * **config:** Wrap sensitive urls ([#1828](https://github.com/matter-labs/zksync-era/issues/1828)) ([c8ee740](https://github.com/matter-labs/zksync-era/commit/c8ee740a4cc7dc9196d4223397e0bfc9fd8198cf)) * **db:** Implement weak references to RocksDB ([e0d4daa](https://github.com/matter-labs/zksync-era/commit/e0d4daa990c2563d2bd9a048d7350a545f136f00)) * **en:** Add pruning health checks and rework pruning config ([#1790](https://github.com/matter-labs/zksync-era/issues/1790)) ([e0d4daa](https://github.com/matter-labs/zksync-era/commit/e0d4daa990c2563d2bd9a048d7350a545f136f00)) * Extract proof_data_handler into separate crate ([#1677](https://github.com/matter-labs/zksync-era/issues/1677)) ([f4facee](https://github.com/matter-labs/zksync-era/commit/f4faceef1cb2f155dad37a61be3823a96b96c2ab)) * Extract several crates from zksync_core ([#1859](https://github.com/matter-labs/zksync-era/issues/1859)) ([7dcf796](https://github.com/matter-labs/zksync-era/commit/7dcf79606e0f37b468c82b6bdcb374149bc30f34)) * **node:** Extract genesis into separate crate ([#1797](https://github.com/matter-labs/zksync-era/issues/1797)) ([a8c4599](https://github.com/matter-labs/zksync-era/commit/a8c459951cea4692a7d7c9bdf3dc8323d2ad86ba)) * **Prover CLI:** `status batch` command ([#1638](https://github.com/matter-labs/zksync-era/issues/1638)) ([3fd6d65](https://github.com/matter-labs/zksync-era/commit/3fd6d653cad1e783f7a52eead13b322d4c6639a9)) * prover components versioning ([#1660](https://github.com/matter-labs/zksync-era/issues/1660)) ([29a4ffc](https://github.com/matter-labs/zksync-era/commit/29a4ffc6b9420590f32a9e1d1585ebffb95eeb6c)) * Update provers current version ([#1872](https://github.com/matter-labs/zksync-era/issues/1872)) ([bb5f129](https://github.com/matter-labs/zksync-era/commit/bb5f129deb75f9dad029da55ec8e2c0defefbe6e)) ### Bug Fixes * **basic_types:** bincode deserialization for `L2ChainId` ([#1835](https://github.com/matter-labs/zksync-era/issues/1835)) ([fde85f4](https://github.com/matter-labs/zksync-era/commit/fde85f4e182b38322d766fdd697a70f13d10ffac)) * **contract-verifier:** YUL system-mode verification ([#1863](https://github.com/matter-labs/zksync-era/issues/1863)) ([5aa7d41](https://github.com/matter-labs/zksync-era/commit/5aa7d415d4b03efd0d9c52d36cf1a1818e23efcf)) * **loadtest:** Do not initiate transactions with 0 amount ([#1847](https://github.com/matter-labs/zksync-era/issues/1847)) ([1bbe108](https://github.com/matter-labs/zksync-era/commit/1bbe108ae4f864f9d257a09d38e4baf22ea0b2c0)) ### Performance Improvements * **db:** Fine-tune state keeper cache performance / RAM usage ([#1804](https://github.com/matter-labs/zksync-era/issues/1804)) ([82bf40e](https://github.com/matter-labs/zksync-era/commit/82bf40e414e11b40c4ba4bad20f5d421a62d2e2f)) * **state-keeper:** Improve `FilterWrittenSlots` l1 batch seal stage ([#1854](https://github.com/matter-labs/zksync-era/issues/1854)) ([4cf235f](https://github.com/matter-labs/zksync-era/commit/4cf235f807932ac53fec1403005dcd7ffc0fb539)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: perekopskiy --- .github/release-please/manifest.json | 2 +- .../workflows/release-please-cargo-lock.yml | 25 ++++++++++++++-- Cargo.lock | 2 +- core/CHANGELOG.md | 30 +++++++++++++++++++ core/bin/external_node/Cargo.toml | 2 +- 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/.github/release-please/manifest.json b/.github/release-please/manifest.json index e8576716ada..26b89c3bd39 100644 --- a/.github/release-please/manifest.json +++ b/.github/release-please/manifest.json @@ -1,4 +1,4 @@ { - "core": "24.0.0", + "core": "24.1.0", "prover": "14.0.0" } diff --git a/.github/workflows/release-please-cargo-lock.yml b/.github/workflows/release-please-cargo-lock.yml index db51f59c068..bf0e8e05102 100644 --- a/.github/workflows/release-please-cargo-lock.yml +++ b/.github/workflows/release-please-cargo-lock.yml @@ -6,30 +6,49 @@ on: name: release-please-update-cargo-lock jobs: update_cargo_lock: - runs-on: [matterlabs-default-infra-runners] + runs-on: [matterlabs-ci-runner] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: submodules: "recursive" + persist-credentials: false + + - name: Check last commit + id: condition + run: | + COMMIT=$(git log -1 --pretty=%B) + if [[ "$COMMIT" == "Update Cargo.lock" ]]; then + echo "Cargo.lock is already updated" + echo "::set-output name=skip_steps::true" + else + echo "Cargo.lock should be updated" + echo "::set-output name=skip_steps::false" + fi - name: Setup environment + if: steps.condition.outputs.skip_steps != 'true' run: | echo ZKSYNC_HOME=$(pwd) >> $GITHUB_ENV echo $(pwd)/bin >> $GITHUB_PATH echo IN_DOCKER=1 >> .env + - name: Start services - run: | - docker compose up -d zk + if: steps.condition.outputs.skip_steps != 'true' + run: docker compose up -d zk + - name: Cargo check + if: steps.condition.outputs.skip_steps != 'true' run: ci_run cargo check - name: Push changes + if: steps.condition.outputs.skip_steps != 'true' env: GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} run: | git config --global user.email "zksync-era-bot@users.noreply.github.com" git config --global user.name "zksync-era-bot" + git remote set-url origin 'https://${{ secrets.RELEASE_TOKEN }}@github.com/matter-labs/zksync-era.git' git add ./Cargo.lock git commit -m "Update Cargo.lock" git push diff --git a/Cargo.lock b/Cargo.lock index 3b89168b2ce..b6054250761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8566,7 +8566,7 @@ dependencies = [ [[package]] name = "zksync_external_node" -version = "24.0.0" +version = "24.1.0" dependencies = [ "anyhow", "assert_matches", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index ffaef69bf64..8c510b25176 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## [24.1.0](https://github.com/matter-labs/zksync-era/compare/core-v24.0.0...core-v24.1.0) (2024-05-08) + + +### Features + +* add `sendRawTransactionWithDetailedOutput` API ([#1806](https://github.com/matter-labs/zksync-era/issues/1806)) ([6a30a31](https://github.com/matter-labs/zksync-era/commit/6a30a3161972461cb707ec5549aed6e837933a27)) +* add getGasPerPubdataByte endpoint ([#1778](https://github.com/matter-labs/zksync-era/issues/1778)) ([d62dd08](https://github.com/matter-labs/zksync-era/commit/d62dd0801faae5442dc72e93a2c746769351cee0)) +* **config:** Wrap sensitive urls ([#1828](https://github.com/matter-labs/zksync-era/issues/1828)) ([c8ee740](https://github.com/matter-labs/zksync-era/commit/c8ee740a4cc7dc9196d4223397e0bfc9fd8198cf)) +* **db:** Implement weak references to RocksDB ([e0d4daa](https://github.com/matter-labs/zksync-era/commit/e0d4daa990c2563d2bd9a048d7350a545f136f00)) +* **en:** Add pruning health checks and rework pruning config ([#1790](https://github.com/matter-labs/zksync-era/issues/1790)) ([e0d4daa](https://github.com/matter-labs/zksync-era/commit/e0d4daa990c2563d2bd9a048d7350a545f136f00)) +* Extract proof_data_handler into separate crate ([#1677](https://github.com/matter-labs/zksync-era/issues/1677)) ([f4facee](https://github.com/matter-labs/zksync-era/commit/f4faceef1cb2f155dad37a61be3823a96b96c2ab)) +* Extract several crates from zksync_core ([#1859](https://github.com/matter-labs/zksync-era/issues/1859)) ([7dcf796](https://github.com/matter-labs/zksync-era/commit/7dcf79606e0f37b468c82b6bdcb374149bc30f34)) +* **node:** Extract genesis into separate crate ([#1797](https://github.com/matter-labs/zksync-era/issues/1797)) ([a8c4599](https://github.com/matter-labs/zksync-era/commit/a8c459951cea4692a7d7c9bdf3dc8323d2ad86ba)) +* **Prover CLI:** `status batch` command ([#1638](https://github.com/matter-labs/zksync-era/issues/1638)) ([3fd6d65](https://github.com/matter-labs/zksync-era/commit/3fd6d653cad1e783f7a52eead13b322d4c6639a9)) +* prover components versioning ([#1660](https://github.com/matter-labs/zksync-era/issues/1660)) ([29a4ffc](https://github.com/matter-labs/zksync-era/commit/29a4ffc6b9420590f32a9e1d1585ebffb95eeb6c)) +* Update provers current version ([#1872](https://github.com/matter-labs/zksync-era/issues/1872)) ([bb5f129](https://github.com/matter-labs/zksync-era/commit/bb5f129deb75f9dad029da55ec8e2c0defefbe6e)) + + +### Bug Fixes + +* **basic_types:** bincode deserialization for `L2ChainId` ([#1835](https://github.com/matter-labs/zksync-era/issues/1835)) ([fde85f4](https://github.com/matter-labs/zksync-era/commit/fde85f4e182b38322d766fdd697a70f13d10ffac)) +* **contract-verifier:** YUL system-mode verification ([#1863](https://github.com/matter-labs/zksync-era/issues/1863)) ([5aa7d41](https://github.com/matter-labs/zksync-era/commit/5aa7d415d4b03efd0d9c52d36cf1a1818e23efcf)) +* **loadtest:** Do not initiate transactions with 0 amount ([#1847](https://github.com/matter-labs/zksync-era/issues/1847)) ([1bbe108](https://github.com/matter-labs/zksync-era/commit/1bbe108ae4f864f9d257a09d38e4baf22ea0b2c0)) + + +### Performance Improvements + +* **db:** Fine-tune state keeper cache performance / RAM usage ([#1804](https://github.com/matter-labs/zksync-era/issues/1804)) ([82bf40e](https://github.com/matter-labs/zksync-era/commit/82bf40e414e11b40c4ba4bad20f5d421a62d2e2f)) +* **state-keeper:** Improve `FilterWrittenSlots` l1 batch seal stage ([#1854](https://github.com/matter-labs/zksync-era/issues/1854)) ([4cf235f](https://github.com/matter-labs/zksync-era/commit/4cf235f807932ac53fec1403005dcd7ffc0fb539)) + ## [24.0.0](https://github.com/matter-labs/zksync-era/compare/core-v23.1.0...core-v24.0.0) (2024-04-30) diff --git a/core/bin/external_node/Cargo.toml b/core/bin/external_node/Cargo.toml index 137c8a9abab..b496dfd72c7 100644 --- a/core/bin/external_node/Cargo.toml +++ b/core/bin/external_node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zksync_external_node" -version = "24.0.0" # x-release-please-version +version = "24.1.0" # x-release-please-version edition.workspace = true authors.workspace = true homepage.workspace = true From f2100a1d487e8595bf17b5075fb7b0023c33737e Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Wed, 8 May 2024 11:31:48 +0300 Subject: [PATCH 4/9] refactor(en): Remove chain IDs and unused field from remote EN config (#1869) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ - Removes `max_pubdata_per_batch` from the remote EN config. - Moves L1 and L2 chain IDs from the remote config to the required one. Adds a managed task asynchronously validating these IDs. ## Why ❔ - `max_pubdata_per_batch` is unused. - L1 and L2 chain IDs are required to start a node anyway. Async validation means that the EN can now start w/o connecting to L1 / L2 nodes (well, other than to fetch contract addresses etc., but those will be dealt with separately). ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Tests for the changes have been added / updated. - [x] Documentation comments have been added / updated. - [x] Code has been formatted via `zk fmt` and `zk lint`. - [x] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- core/bin/external_node/src/config/mod.rs | 95 +----- core/bin/external_node/src/helpers.rs | 285 +++++++++++++++++- core/bin/external_node/src/main.rs | 28 +- core/bin/external_node/src/metrics.rs | 4 +- core/bin/external_node/src/tests.rs | 5 +- .../src/api_server/tx_sender/mod.rs | 2 - 6 files changed, 321 insertions(+), 98 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 138b7a12776..d5bed56ec8f 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1,7 +1,6 @@ use std::{ - env, fmt, + env, num::{NonZeroU32, NonZeroU64, NonZeroUsize}, - str::FromStr, time::Duration, }; @@ -25,17 +24,14 @@ use zksync_core::{ }; #[cfg(test)] use zksync_dal::{ConnectionPool, Core}; -use zksync_eth_client::EthInterface; use zksync_protobuf_config::proto; use zksync_snapshots_applier::SnapshotsApplierConfig; -use zksync_types::{ - api::BridgeAddresses, fee_model::FeeParams, url::SensitiveUrl, ETHEREUM_ADDRESS, -}; +use zksync_types::{api::BridgeAddresses, url::SensitiveUrl, ETHEREUM_ADDRESS}; use zksync_web3_decl::{ client::BoxedL2Client, error::ClientRpcContext, jsonrpsee::{core::ClientError, types::error::ErrorCode}, - namespaces::{EnNamespaceClient, EthNamespaceClient, ZksNamespaceClient}, + namespaces::{EnNamespaceClient, ZksNamespaceClient}, }; pub(crate) mod observability; @@ -61,10 +57,7 @@ pub(crate) struct RemoteENConfig { pub l1_weth_bridge_addr: Option
, pub l2_weth_bridge_addr: Option
, pub l2_testnet_paymaster_addr: Option
, - pub l2_chain_id: L2ChainId, - pub l1_chain_id: L1ChainId, pub base_token_addr: Address, - pub max_pubdata_per_batch: u64, pub l1_batch_commit_data_generator_mode: L1BatchCommitDataGeneratorMode, pub dummy_verifier: bool, } @@ -105,24 +98,6 @@ impl RemoteENConfig { } response => response.context("Failed to fetch base token address")?, }; - let l2_chain_id = client.chain_id().rpc_context("chain_id").await?; - let l2_chain_id = L2ChainId::try_from(l2_chain_id.as_u64()) - .map_err(|err| anyhow::anyhow!("invalid chain ID supplied by main node: {err}"))?; - let l1_chain_id = client.l1_chain_id().rpc_context("l1_chain_id").await?; - let l1_chain_id = L1ChainId(l1_chain_id.as_u64()); - - let fee_params = client - .get_fee_params() - .rpc_context("get_fee_params") - .await?; - let max_pubdata_per_batch = match fee_params { - FeeParams::V1(_) => { - const MAX_V1_PUBDATA_PER_BATCH: u64 = 100_000; - - MAX_V1_PUBDATA_PER_BATCH - } - FeeParams::V2(params) => params.config.max_pubdata_per_batch, - }; // These two config variables should always have the same value. // TODO(EVM-578): double check and potentially forbid both of them being `None`. @@ -157,10 +132,7 @@ impl RemoteENConfig { l2_shared_bridge_addr: l2_erc20_shared_bridge, l1_weth_bridge_addr: bridges.l1_weth_bridge, l2_weth_bridge_addr: bridges.l2_weth_bridge, - l2_chain_id, - l1_chain_id, base_token_addr, - max_pubdata_per_batch, l1_batch_commit_data_generator_mode: genesis .as_ref() .map(|a| a.l1_batch_commit_data_generator_mode) @@ -183,13 +155,10 @@ impl RemoteENConfig { l2_erc20_bridge_addr: Some(Address::repeat_byte(3)), l2_weth_bridge_addr: None, l2_testnet_paymaster_addr: None, - l2_chain_id: L2ChainId::default(), - l1_chain_id: L1ChainId(9), base_token_addr: Address::repeat_byte(4), l1_shared_bridge_proxy_addr: Some(Address::repeat_byte(5)), l1_weth_bridge_addr: None, l2_shared_bridge_addr: Some(Address::repeat_byte(6)), - max_pubdata_per_batch: 1 << 17, l1_batch_commit_data_generator_mode: L1BatchCommitDataGeneratorMode::Rollup, dummy_verifier: true, } @@ -639,6 +608,13 @@ impl OptionalENConfig { /// This part of the external node config is required for its operation. #[derive(Debug, Deserialize, Clone, PartialEq)] pub(crate) struct RequiredENConfig { + /// L1 chain ID (e.g., 9 for Ethereum mainnet). This ID will be checked against the `eth_client_url` RPC provider on initialization + /// to ensure that there's no mismatch between the expected and actual L1 network. + pub l1_chain_id: L1ChainId, + /// 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, + /// Port on which the HTTP RPC server is listening. pub http_port: u16, /// Port on which the WebSocket RPC server is listening. @@ -665,6 +641,8 @@ impl RequiredENConfig { #[cfg(test)] fn mock(temp_dir: &tempfile::TempDir) -> Self { Self { + l1_chain_id: L1ChainId(9), + l2_chain_id: L2ChainId::default(), http_port: 0, ws_port: 0, healthcheck_port: 0, @@ -822,7 +800,6 @@ impl ExternalNodeConfig { required: RequiredENConfig, optional: OptionalENConfig, main_node_client: &BoxedL2Client, - eth_client: &dyn EthInterface, ) -> anyhow::Result { let experimental = envy::prefixed("EN_EXPERIMENTAL_") .from_env::() @@ -838,36 +815,6 @@ impl ExternalNodeConfig { let remote = RemoteENConfig::fetch(main_node_client) .await .context("Unable to fetch required config values from the main node")?; - // We can query them from main node, but it's better to set them explicitly - // as well to avoid connecting to wrong environment variables unintentionally. - let eth_chain_id = eth_client - .fetch_chain_id() - .await - .context("Unable to check L1 chain ID through the configured L1 client")?; - - let l2_chain_id: L2ChainId = env_var("EN_L2_CHAIN_ID")?; - anyhow::ensure!( - l2_chain_id == remote.l2_chain_id, - "Configured L2 chain id doesn't match the one from main node. - Make sure your configuration is correct and you are corrected to the right main node. - Main node L2 chain id: {:?}. Local config value: {l2_chain_id:?}", - remote.l2_chain_id, - ); - - let l1_chain_id: L1ChainId = env_var("EN_L1_CHAIN_ID")?; - anyhow::ensure!( - l1_chain_id == remote.l1_chain_id, - "Configured L1 chain id doesn't match the one from main node. - Make sure your configuration is correct and you are corrected to the right main node. - Main node L1 chain id: {}. Local config value: {l1_chain_id}", - remote.l1_chain_id, - ); - anyhow::ensure!( - l1_chain_id == eth_chain_id, - "Configured L1 chain id doesn't match the one from eth node. - Make sure your configuration is correct and you are corrected to the right eth node. - Eth node chain id: {eth_chain_id}. Local config value: {l1_chain_id}" - ); let postgres = PostgresConfig::from_env()?; Ok(Self { @@ -899,22 +846,11 @@ impl ExternalNodeConfig { } } -fn env_var(name: &str) -> anyhow::Result -where - T: FromStr, - T::Err: fmt::Display, -{ - env::var(name) - .with_context(|| format!("`{name}` env variable is not set"))? - .parse() - .map_err(|err| anyhow::anyhow!("unable to parse `{name}` env variable: {err}")) -} - impl From for InternalApiConfig { fn from(config: ExternalNodeConfig) -> Self { Self { - l1_chain_id: config.remote.l1_chain_id, - l2_chain_id: config.remote.l2_chain_id, + l1_chain_id: config.required.l1_chain_id, + l2_chain_id: config.required.l2_chain_id, max_tx_size: config.optional.max_tx_size, estimate_gas_scale_factor: config.optional.estimate_gas_scale_factor, estimate_gas_acceptable_overestimation: config @@ -958,8 +894,7 @@ impl From for TxSenderConfig { // and they will be enforced by the main node anyway. max_allowed_l2_tx_gas_limit: u64::MAX, validation_computational_gas_limit: u32::MAX, - chain_id: config.remote.l2_chain_id, - max_pubdata_per_batch: config.remote.max_pubdata_per_batch, + chain_id: config.required.l2_chain_id, // Does not matter for EN. whitelisted_tokens_for_aa: Default::default(), } diff --git a/core/bin/external_node/src/helpers.rs b/core/bin/external_node/src/helpers.rs index 2bc580c43fe..d7112816475 100644 --- a/core/bin/external_node/src/helpers.rs +++ b/core/bin/external_node/src/helpers.rs @@ -1,7 +1,17 @@ //! Miscellaneous helpers for the EN. +use std::time::Duration; + +use futures::FutureExt; +use tokio::sync::watch; +use zksync_basic_types::{L1ChainId, L2ChainId}; +use zksync_eth_client::EthInterface; use zksync_health_check::{async_trait, CheckHealth, Health, HealthStatus}; -use zksync_web3_decl::{client::BoxedL2Client, namespaces::EthNamespaceClient}; +use zksync_web3_decl::{ + client::BoxedL2Client, + error::ClientRpcContext, + namespaces::{EthNamespaceClient, ZksNamespaceClient}, +}; /// Main node health check. #[derive(Debug)] @@ -30,3 +40,276 @@ impl CheckHealth for MainNodeHealthCheck { HealthStatus::Ready.into() } } + +/// Ethereum client health check. +#[derive(Debug)] +pub(crate) struct EthClientHealthCheck(Box); + +impl From> for EthClientHealthCheck { + fn from(client: Box) -> Self { + Self(client.for_component("ethereum_health_check")) + } +} + +#[async_trait] +impl CheckHealth for EthClientHealthCheck { + fn name(&self) -> &'static str { + "ethereum_http_rpc" + } + + async fn check_health(&self) -> Health { + if let Err(err) = self.0.block_number().await { + tracing::warn!("Health-check call to Ethereum HTTP RPC failed: {err}"); + let details = serde_json::json!({ + "error": err.to_string(), + }); + // Unlike main node client, losing connection to L1 is not fatal for the node + return Health::from(HealthStatus::Affected).with_details(details); + } + HealthStatus::Ready.into() + } +} + +/// Task that validates chain IDs using main node and Ethereum clients. +#[derive(Debug)] +pub(crate) struct ValidateChainIdsTask { + l1_chain_id: L1ChainId, + l2_chain_id: L2ChainId, + eth_client: Box, + main_node_client: BoxedL2Client, +} + +impl ValidateChainIdsTask { + const BACKOFF_INTERVAL: Duration = Duration::from_secs(5); + + pub fn new( + l1_chain_id: L1ChainId, + l2_chain_id: L2ChainId, + eth_client: Box, + main_node_client: BoxedL2Client, + ) -> Self { + Self { + l1_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"), + } + } + + async fn check_eth_client( + eth_client: Box, + expected: L1ChainId, + ) -> anyhow::Result<()> { + loop { + match eth_client.fetch_chain_id().await { + Ok(chain_id) => { + anyhow::ensure!( + expected == chain_id, + "Configured L1 chain ID doesn't match the one from Ethereum node. \ + Make sure your configuration is correct and you are corrected to the right Ethereum node. \ + Eth node chain ID: {chain_id}. Local config value: {expected}" + ); + tracing::info!( + "Checked that L1 chain ID {chain_id} is returned by Ethereum client" + ); + return Ok(()); + } + Err(err) => { + tracing::warn!("Error getting L1 chain ID from Ethereum client: {err}"); + tokio::time::sleep(Self::BACKOFF_INTERVAL).await; + } + } + } + } + + async fn check_l1_chain_using_main_node( + main_node_client: BoxedL2Client, + expected: L1ChainId, + ) -> anyhow::Result<()> { + loop { + match main_node_client + .l1_chain_id() + .rpc_context("l1_chain_id") + .await + { + Ok(chain_id) => { + let chain_id = L1ChainId(chain_id.as_u64()); + anyhow::ensure!( + expected == chain_id, + "Configured L1 chain ID doesn't match the one from main node. \ + Make sure your configuration is correct and you are corrected to the right main node. \ + Main node L1 chain ID: {chain_id}. Local config value: {expected}" + ); + tracing::info!( + "Checked that L1 chain ID {chain_id} is returned by main node client" + ); + return Ok(()); + } + Err(err) if err.is_transient() => { + tracing::warn!( + "Transient error getting L1 chain ID from main node client, will retry in {:?}: {err}", + Self::BACKOFF_INTERVAL + ); + tokio::time::sleep(Self::BACKOFF_INTERVAL).await; + } + Err(err) => { + tracing::error!("Error getting L1 chain ID from main node client: {err}"); + return Err(err.into()); + } + } + } + } + + async fn check_l2_chain_using_main_node( + main_node_client: BoxedL2Client, + expected: L2ChainId, + ) -> anyhow::Result<()> { + loop { + match main_node_client.chain_id().rpc_context("chain_id").await { + Ok(chain_id) => { + let chain_id = L2ChainId::try_from(chain_id.as_u64()).map_err(|err| { + anyhow::anyhow!("invalid chain ID supplied by main node: {err}") + })?; + anyhow::ensure!( + expected == chain_id, + "Configured L2 chain ID doesn't match the one from main node. \ + Make sure your configuration is correct and you are corrected to the right main node. \ + Main node L2 chain ID: {chain_id:?}. Local config value: {expected:?}" + ); + tracing::info!( + "Checked that L2 chain ID {chain_id:?} is returned by main node client" + ); + return Ok(()); + } + Err(err) if err.is_transient() => { + tracing::warn!( + "Transient error getting L2 chain ID from main node client, will retry in {:?}: {err}", + Self::BACKOFF_INTERVAL + ); + tokio::time::sleep(Self::BACKOFF_INTERVAL).await; + } + Err(err) => { + tracing::error!("Error getting L2 chain ID from main node client: {err}"); + return Err(err.into()); + } + } + } + } + + 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 main_node_l1_check = + Self::check_l1_chain_using_main_node(self.main_node_client.clone(), self.l1_chain_id) + .fuse(); + let main_node_l2_check = + Self::check_l2_chain_using_main_node(self.main_node_client, self.l2_chain_id).fuse(); + loop { + tokio::select! { + Err(err) = eth_client_check => return Err(err), + Err(err) = main_node_l1_check => return Err(err), + Err(err) = main_node_l2_check => return Err(err), + _ = stop_receiver.changed() => return Ok(()), + } + } + } +} + +#[cfg(test)] +mod tests { + use zksync_eth_client::clients::MockEthereum; + use zksync_types::U64; + use zksync_web3_decl::client::MockL2Client; + + use super::*; + + #[tokio::test] + async fn validating_chain_ids_errors() { + let main_node_client = MockL2Client::new(|method, _| match method { + "eth_chainId" => Ok(serde_json::json!(U64::from(270))), + "zks_L1ChainId" => Ok(serde_json::json!(U64::from(3))), + _ => panic!("unexpected L2 call: {method}"), + }); + + let validation_task = ValidateChainIdsTask::new( + L1ChainId(3), // << mismatch with the Ethereum client + L2ChainId::default(), + Box::::default(), + BoxedL2Client::new(main_node_client.clone()), + ); + let (_stop_sender, stop_receiver) = watch::channel(false); + let err = validation_task + .run(stop_receiver.clone()) + .await + .unwrap_err() + .to_string(); + assert!( + err.contains("L1 chain ID") && err.contains("Ethereum node"), + "{err}" + ); + + let validation_task = ValidateChainIdsTask::new( + L1ChainId(9), // << mismatch with the main node client + L2ChainId::from(270), + Box::::default(), + BoxedL2Client::new(main_node_client.clone()), + ); + let err = validation_task + .run(stop_receiver.clone()) + .await + .unwrap_err() + .to_string(); + assert!( + err.contains("L1 chain ID") && err.contains("main node"), + "{err}" + ); + + let main_node_client = MockL2Client::new(|method, _| match method { + "eth_chainId" => Ok(serde_json::json!(U64::from(270))), + "zks_L1ChainId" => Ok(serde_json::json!(U64::from(9))), + _ => panic!("unexpected L2 call: {method}"), + }); + + let validation_task = ValidateChainIdsTask::new( + L1ChainId(9), + L2ChainId::from(271), // << mismatch with the main node client + Box::::default(), + BoxedL2Client::new(main_node_client.clone()), + ); + let err = validation_task + .run(stop_receiver) + .await + .unwrap_err() + .to_string(); + assert!( + err.contains("L2 chain ID") && err.contains("main node"), + "{err}" + ); + } + + #[tokio::test] + async fn validating_chain_ids_success() { + let main_node_client = MockL2Client::new(|method, _| match method { + "eth_chainId" => Ok(serde_json::json!(U64::from(270))), + "zks_L1ChainId" => Ok(serde_json::json!(U64::from(9))), + _ => panic!("unexpected L2 call: {method}"), + }); + + let validation_task = ValidateChainIdsTask::new( + L1ChainId(9), + L2ChainId::default(), + Box::::default(), + BoxedL2Client::new(main_node_client.clone()), + ); + let (stop_sender, stop_receiver) = watch::channel(false); + let task = tokio::spawn(validation_task.run(stop_receiver)); + + // Wait a little and ensure that the task hasn't terminated. + tokio::time::sleep(Duration::from_millis(50)).await; + assert!(!task.is_finished()); + + stop_sender.send_replace(true); + task.await.unwrap().unwrap(); + } +} diff --git a/core/bin/external_node/src/main.rs b/core/bin/external_node/src/main.rs index 721a117378a..dc938094038 100644 --- a/core/bin/external_node/src/main.rs +++ b/core/bin/external_node/src/main.rs @@ -66,7 +66,7 @@ use crate::{ observability::observability_config_from_env, ExternalNodeConfig, OptionalENConfig, RequiredENConfig, }, - helpers::MainNodeHealthCheck, + helpers::{EthClientHealthCheck, MainNodeHealthCheck, ValidateChainIdsTask}, init::ensure_storage_initialized, metrics::RUST_METRICS, }; @@ -253,7 +253,7 @@ async fn run_core( main_node_client.clone(), output_handler, stop_receiver.clone(), - config.remote.l2_chain_id, + config.required.l2_chain_id, task_handles, ) .await?; @@ -830,14 +830,9 @@ async fn main() -> anyhow::Result<()> { let eth_client_url = &required_config.eth_client_url; let eth_client = Box::new(QueryClient::new(eth_client_url.clone())?); - let mut config = ExternalNodeConfig::new( - required_config, - optional_config, - &main_node_client, - eth_client.as_ref(), - ) - .await - .context("Failed to load external node config")?; + let mut config = ExternalNodeConfig::new(required_config, optional_config, &main_node_client) + .await + .context("Failed to load external node config")?; if !opt.enable_consensus { config.consensus = None; } @@ -911,6 +906,7 @@ async fn run_node( app_health.insert_custom_component(Arc::new(MainNodeHealthCheck::from( main_node_client.clone(), )))?; + app_health.insert_custom_component(Arc::new(EthClientHealthCheck::from(eth_client.clone())))?; app_health.insert_custom_component(Arc::new(ConnectionPoolHealthCheck::new( connection_pool.clone(), )))?; @@ -935,6 +931,14 @@ async fn run_node( Ok(()) }); + let validate_chain_ids_task = ValidateChainIdsTask::new( + config.required.l1_chain_id, + config.required.l2_chain_id, + eth_client.clone(), + main_node_client.clone(), + ); + let validate_chain_ids_task = tokio::spawn(validate_chain_ids_task.run(stop_receiver.clone())); + let version_sync_task_pool = connection_pool.clone(); let version_sync_task_main_node_client = main_node_client.clone(); let mut stop_receiver_for_version_sync = stop_receiver.clone(); @@ -948,14 +952,14 @@ async fn run_node( stop_receiver_for_version_sync.changed().await.ok(); Ok(()) }); - let mut task_handles = vec![metrics_task, version_sync_task]; + let mut task_handles = vec![metrics_task, validate_chain_ids_task, version_sync_task]; // Make sure that the node storage is initialized either via genesis or snapshot recovery. ensure_storage_initialized( connection_pool.clone(), main_node_client.clone(), &app_health, - config.remote.l2_chain_id, + config.required.l2_chain_id, config.optional.snapshots_recovery_enabled, ) .await?; diff --git a/core/bin/external_node/src/metrics.rs b/core/bin/external_node/src/metrics.rs index a95b5af700c..08397f824f5 100644 --- a/core/bin/external_node/src/metrics.rs +++ b/core/bin/external_node/src/metrics.rs @@ -32,8 +32,8 @@ impl ExternalNodeMetrics { pub(crate) fn observe_config(&self, config: &ExternalNodeConfig) { let info = ExternalNodeInfo { server_version: SERVER_VERSION, - l1_chain_id: config.remote.l1_chain_id.0, - l2_chain_id: config.remote.l2_chain_id.as_u64(), + l1_chain_id: config.required.l1_chain_id.0, + l2_chain_id: config.required.l2_chain_id.as_u64(), postgres_pool_size: config.postgres.max_connections, }; tracing::info!("Setting general node information: {info:?}"); diff --git a/core/bin/external_node/src/tests.rs b/core/bin/external_node/src/tests.rs index d1ab1ab00b6..a89621b116c 100644 --- a/core/bin/external_node/src/tests.rs +++ b/core/bin/external_node/src/tests.rs @@ -5,7 +5,7 @@ use test_casing::test_casing; use zksync_basic_types::protocol_version::ProtocolVersionId; use zksync_eth_client::clients::MockEthereum; use zksync_node_genesis::{insert_genesis_batch, GenesisParams}; -use zksync_types::{api, ethabi, fee_model::FeeParams, L1BatchNumber, L2BlockNumber, H256}; +use zksync_types::{api, ethabi, fee_model::FeeParams, L1BatchNumber, L2BlockNumber, H256, U64}; use zksync_web3_decl::client::{BoxedL2Client, MockL2Client}; use super::*; @@ -134,6 +134,9 @@ async fn external_node_basics(components_str: &'static str) { let l2_client = MockL2Client::new(move |method, params| { tracing::info!("Called L2 client: {method}({params:?})"); match method { + "eth_chainId" => Ok(serde_json::json!(U64::from(270))), + "zks_L1ChainId" => Ok(serde_json::json!(U64::from(9))), + "zks_L1BatchNumber" => Ok(serde_json::json!("0x0")), "zks_getL1BatchDetails" => { let (number,): (L1BatchNumber,) = serde_json::from_value(params)?; diff --git a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs index cc9e70c555e..1a03c91bcaa 100644 --- a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs +++ b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs @@ -239,7 +239,6 @@ pub struct TxSenderConfig { pub vm_execution_cache_misses_limit: Option, pub validation_computational_gas_limit: u32, pub chain_id: L2ChainId, - pub max_pubdata_per_batch: u64, pub whitelisted_tokens_for_aa: Vec
, } @@ -259,7 +258,6 @@ impl TxSenderConfig { validation_computational_gas_limit: state_keeper_config .validation_computational_gas_limit, chain_id, - max_pubdata_per_batch: state_keeper_config.max_pubdata_per_batch, whitelisted_tokens_for_aa: web3_json_config.whitelisted_tokens_for_aa.clone(), } } From 6de925c64ecc3c23bf16346ab56b171387b3fbba Mon Sep 17 00:00:00 2001 From: perekopskiy <53865202+perekopskiy@users.noreply.github.com> Date: Wed, 8 May 2024 12:35:48 +0300 Subject: [PATCH 5/9] ci: Fix IMAGE_TAG_SUFFIX in create_manifest (#1878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ Fix IMAGE_TAG_SUFFIX in create_manifest ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- .github/workflows/build-core-template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-core-template.yml b/.github/workflows/build-core-template.yml index 8172a49b5d8..27bb29e6816 100644 --- a/.github/workflows/build-core-template.yml +++ b/.github/workflows/build-core-template.yml @@ -169,7 +169,7 @@ jobs: - name: snapshots-creator platform: linux/amd64 env: - IMAGE_TAG_SUFFIX: ${{ inputs.image_tag_suffix }}${{ (inputs.en_alpha_release && matrix.components == 'external-node') && '-alpha' || '' }} + IMAGE_TAG_SUFFIX: ${{ inputs.image_tag_suffix }}${{ (inputs.en_alpha_release && matrix.component.name == 'external-node') && '-alpha' || '' }} steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 From 07de1c2612b0bbe42f72bdfc5b9e20dfd2c29a31 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 8 May 2024 14:05:42 +0400 Subject: [PATCH 6/9] refactor: Remove BWIP (#1875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ Fully removes the BWIP component. This PR assumes that all instances of BWIP are already scaled down, which was confirmed by @EmilLuta ## Why ❔ The component was deprioritizing for time being, and it's easier to recreate it once we needed than to maintain. ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- .github/workflows/ci-core-reusable.yml | 4 +- Cargo.lock | 1 - core/bin/zksync_server/src/main.rs | 2 +- ...4710daa723e2d9a23317c347f6081465c3643.json | 52 ---- ...095596297be0d728a0aa2d9b180fb72de222b.json | 22 -- ...b04ba5868d1897553df85aac15b169ebb0732.json | 28 --- ...3260b49ce42daaf9dbe8075daf0a8e0ad9914.json | 12 - ...f396f9d193615d70184d4327378a7fc8a5665.json | 30 --- ...578179e6269c6ff36877cedee264067ccdafc.json | 65 ----- .../dal/doc/BasicWitnessInputProducerDal.md | 25 -- ...asic_witness_input_producer_table.down.sql | 18 ++ ..._basic_witness_input_producer_table.up.sql | 5 + .../src/basic_witness_input_producer_dal.rs | 234 ------------------ core/lib/dal/src/lib.rs | 10 +- core/lib/object_store/src/objects.rs | 12 - core/lib/state/src/lib.rs | 2 - core/lib/state/src/storage_view.rs | 10 +- core/lib/state/src/witness.rs | 56 ----- core/lib/types/src/storage/mod.rs | 1 - core/lib/zksync_core/Cargo.toml | 1 - .../basic_witness_input_producer/metrics.rs | 18 -- .../src/basic_witness_input_producer/mod.rs | 197 --------------- core/lib/zksync_core/src/lib.rs | 52 ---- .../src/metadata_calculator/tests.rs | 5 - .../src/metadata_calculator/updater.rs | 5 - core/node/shared_metrics/src/lib.rs | 2 - 26 files changed, 28 insertions(+), 841 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-083991abb3f1c2183d1bd1fb2ad4710daa723e2d9a23317c347f6081465c3643.json delete mode 100644 core/lib/dal/.sqlx/query-280cf015e40353e2833c0a70b77095596297be0d728a0aa2d9b180fb72de222b.json delete mode 100644 core/lib/dal/.sqlx/query-32792c6aee69cb8c8b928a209a3b04ba5868d1897553df85aac15b169ebb0732.json delete mode 100644 core/lib/dal/.sqlx/query-6bd3094be764e6378fe52b5bb533260b49ce42daaf9dbe8075daf0a8e0ad9914.json delete mode 100644 core/lib/dal/.sqlx/query-73c4bf1e35d49faaab9f7828e80f396f9d193615d70184d4327378a7fc8a5665.json delete mode 100644 core/lib/dal/.sqlx/query-99dd6f04e82585d81ac23bc4871578179e6269c6ff36877cedee264067ccdafc.json delete mode 100644 core/lib/dal/doc/BasicWitnessInputProducerDal.md create mode 100644 core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.down.sql create mode 100644 core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.up.sql delete mode 100644 core/lib/dal/src/basic_witness_input_producer_dal.rs delete mode 100644 core/lib/state/src/witness.rs delete mode 100644 core/lib/zksync_core/src/basic_witness_input_producer/metrics.rs delete mode 100644 core/lib/zksync_core/src/basic_witness_input_producer/mod.rs diff --git a/.github/workflows/ci-core-reusable.yml b/.github/workflows/ci-core-reusable.yml index 02181726428..b581803569a 100644 --- a/.github/workflows/ci-core-reusable.yml +++ b/.github/workflows/ci-core-reusable.yml @@ -134,7 +134,7 @@ jobs: base_token: ["Eth", "Custom"] deployment_mode: ["Rollup", "Validium"] env: - SERVER_COMPONENTS: "api,tree,eth,state_keeper,housekeeper,basic_witness_input_producer,commitment_generator${{ matrix.consensus && ',consensus' || '' }}" + SERVER_COMPONENTS: "api,tree,eth,state_keeper,housekeeper,commitment_generator${{ matrix.consensus && ',consensus' || '' }}" runs-on: [matterlabs-ci-runner] steps: @@ -282,7 +282,7 @@ jobs: runs-on: [matterlabs-ci-runner] env: - SERVER_COMPONENTS: "api,tree,eth,state_keeper,housekeeper,basic_witness_input_producer,commitment_generator${{ matrix.consensus && ',consensus' || '' }}" + SERVER_COMPONENTS: "api,tree,eth,state_keeper,housekeeper,commitment_generator${{ matrix.consensus && ',consensus' || '' }}" EXT_NODE_FLAGS: "${{ matrix.consensus && '-- --enable-consensus' || '' }}" steps: diff --git a/Cargo.lock b/Cargo.lock index b6054250761..d35270db078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8378,7 +8378,6 @@ dependencies = [ "zksync_protobuf_build", "zksync_protobuf_config", "zksync_prover_interface", - "zksync_queued_job_processor", "zksync_shared_metrics", "zksync_state", "zksync_storage", diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index a2a3eba027b..d9a3246a078 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -45,7 +45,7 @@ struct Cli { /// Comma-separated list of components to launch. #[arg( long, - default_value = "api,tree,eth,state_keeper,housekeeper,basic_witness_input_producer,commitment_generator" + default_value = "api,tree,eth,state_keeper,housekeeper,commitment_generator" )] components: ComponentsToRun, /// Path to the yaml config. If set, it will be used instead of env vars. diff --git a/core/lib/dal/.sqlx/query-083991abb3f1c2183d1bd1fb2ad4710daa723e2d9a23317c347f6081465c3643.json b/core/lib/dal/.sqlx/query-083991abb3f1c2183d1bd1fb2ad4710daa723e2d9a23317c347f6081465c3643.json deleted file mode 100644 index e2c3a710556..00000000000 --- a/core/lib/dal/.sqlx/query-083991abb3f1c2183d1bd1fb2ad4710daa723e2d9a23317c347f6081465c3643.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE basic_witness_input_producer_jobs\n SET\n status = $1,\n updated_at = NOW(),\n time_taken = $3,\n error = $4\n WHERE\n l1_batch_number = $2\n AND status != $5\n RETURNING\n basic_witness_input_producer_jobs.attempts\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "attempts", - "type_info": "Int2" - } - ], - "parameters": { - "Left": [ - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - }, - "Int8", - "Time", - "Text", - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - } - ] - }, - "nullable": [ - false - ] - }, - "hash": "083991abb3f1c2183d1bd1fb2ad4710daa723e2d9a23317c347f6081465c3643" -} diff --git a/core/lib/dal/.sqlx/query-280cf015e40353e2833c0a70b77095596297be0d728a0aa2d9b180fb72de222b.json b/core/lib/dal/.sqlx/query-280cf015e40353e2833c0a70b77095596297be0d728a0aa2d9b180fb72de222b.json deleted file mode 100644 index 5b49941ed18..00000000000 --- a/core/lib/dal/.sqlx/query-280cf015e40353e2833c0a70b77095596297be0d728a0aa2d9b180fb72de222b.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n attempts\n FROM\n basic_witness_input_producer_jobs\n WHERE\n l1_batch_number = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "attempts", - "type_info": "Int2" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false - ] - }, - "hash": "280cf015e40353e2833c0a70b77095596297be0d728a0aa2d9b180fb72de222b" -} diff --git a/core/lib/dal/.sqlx/query-32792c6aee69cb8c8b928a209a3b04ba5868d1897553df85aac15b169ebb0732.json b/core/lib/dal/.sqlx/query-32792c6aee69cb8c8b928a209a3b04ba5868d1897553df85aac15b169ebb0732.json deleted file mode 100644 index 32b36d7fed9..00000000000 --- a/core/lib/dal/.sqlx/query-32792c6aee69cb8c8b928a209a3b04ba5868d1897553df85aac15b169ebb0732.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n basic_witness_input_producer_jobs (l1_batch_number, status, created_at, updated_at)\n VALUES\n ($1, $2, NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - } - ] - }, - "nullable": [] - }, - "hash": "32792c6aee69cb8c8b928a209a3b04ba5868d1897553df85aac15b169ebb0732" -} diff --git a/core/lib/dal/.sqlx/query-6bd3094be764e6378fe52b5bb533260b49ce42daaf9dbe8075daf0a8e0ad9914.json b/core/lib/dal/.sqlx/query-6bd3094be764e6378fe52b5bb533260b49ce42daaf9dbe8075daf0a8e0ad9914.json deleted file mode 100644 index c90296e322c..00000000000 --- a/core/lib/dal/.sqlx/query-6bd3094be764e6378fe52b5bb533260b49ce42daaf9dbe8075daf0a8e0ad9914.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n DELETE FROM basic_witness_input_producer_jobs\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [] - }, - "nullable": [] - }, - "hash": "6bd3094be764e6378fe52b5bb533260b49ce42daaf9dbe8075daf0a8e0ad9914" -} diff --git a/core/lib/dal/.sqlx/query-73c4bf1e35d49faaab9f7828e80f396f9d193615d70184d4327378a7fc8a5665.json b/core/lib/dal/.sqlx/query-73c4bf1e35d49faaab9f7828e80f396f9d193615d70184d4327378a7fc8a5665.json deleted file mode 100644 index aa38e1c4035..00000000000 --- a/core/lib/dal/.sqlx/query-73c4bf1e35d49faaab9f7828e80f396f9d193615d70184d4327378a7fc8a5665.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE basic_witness_input_producer_jobs\n SET\n status = $1,\n updated_at = NOW(),\n time_taken = $3,\n input_blob_url = $4\n WHERE\n l1_batch_number = $2\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - }, - "Int8", - "Time", - "Text" - ] - }, - "nullable": [] - }, - "hash": "73c4bf1e35d49faaab9f7828e80f396f9d193615d70184d4327378a7fc8a5665" -} diff --git a/core/lib/dal/.sqlx/query-99dd6f04e82585d81ac23bc4871578179e6269c6ff36877cedee264067ccdafc.json b/core/lib/dal/.sqlx/query-99dd6f04e82585d81ac23bc4871578179e6269c6ff36877cedee264067ccdafc.json deleted file mode 100644 index b8c14c53462..00000000000 --- a/core/lib/dal/.sqlx/query-99dd6f04e82585d81ac23bc4871578179e6269c6ff36877cedee264067ccdafc.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE basic_witness_input_producer_jobs\n SET\n status = $1,\n attempts = attempts + 1,\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = (\n SELECT\n l1_batch_number\n FROM\n basic_witness_input_producer_jobs\n WHERE\n status = $2\n OR (\n status = $1\n AND processing_started_at < NOW() - $4::INTERVAL\n )\n OR (\n status = $3\n AND attempts < $5\n )\n ORDER BY\n l1_batch_number ASC\n LIMIT\n 1\n FOR UPDATE\n SKIP LOCKED\n )\n RETURNING\n basic_witness_input_producer_jobs.l1_batch_number\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "l1_batch_number", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - }, - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - }, - { - "Custom": { - "name": "basic_witness_input_producer_job_status", - "kind": { - "Enum": [ - "Queued", - "ManuallySkipped", - "InProgress", - "Successful", - "Failed" - ] - } - } - }, - "Interval", - "Int2" - ] - }, - "nullable": [ - false - ] - }, - "hash": "99dd6f04e82585d81ac23bc4871578179e6269c6ff36877cedee264067ccdafc" -} diff --git a/core/lib/dal/doc/BasicWitnessInputProducerDal.md b/core/lib/dal/doc/BasicWitnessInputProducerDal.md deleted file mode 100644 index b2e0dfbbc6a..00000000000 --- a/core/lib/dal/doc/BasicWitnessInputProducerDal.md +++ /dev/null @@ -1,25 +0,0 @@ -# BasicWitnessInputProducerDal - -## Table Name - -basic_witness_input_producer_jobs - -## `status` Diagram - -```mermaid ---- -title: Status Diagram ---- -stateDiagram-v2 - [*] --> Queued : create_basic_witness_input_producer_job - Queued --> InProgress : get_next_basic_witness_input_producer_job - Failed --> InProgress : get_next_basic_witness_input_producer_job - - InProgress --> Successful : mark_job_as_successful - InProgress --> Failed : mark_job_as_failed - Successful --> [*] - - [*] --> ManuallySkipped : mark_proof_generation_job_as_skipped - ManuallySkipped --> [*] - -``` diff --git a/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.down.sql b/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.down.sql new file mode 100644 index 00000000000..f6fca69aafd --- /dev/null +++ b/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.down.sql @@ -0,0 +1,18 @@ +CREATE TYPE basic_witness_input_producer_job_status AS ENUM ('Queued', 'ManuallySkipped', 'InProgress', 'Successful', 'Failed'); + +CREATE TABLE IF NOT EXISTS basic_witness_input_producer_jobs +( + l1_batch_number BIGINT NOT NULL PRIMARY KEY, + attempts SMALLINT NOT NULL DEFAULT 0, + status basic_witness_input_producer_job_status, + picked_by TEXT, + input_blob_url TEXT, + error TEXT, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, + processing_started_at TIMESTAMP, + time_taken TIME +); + +CREATE INDEX IF NOT EXISTS idx_basic_witness_input_producer_jobs_status_processing_attempts + ON basic_witness_input_producer_jobs (status, processing_started_at, attempts); diff --git a/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.up.sql b/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.up.sql new file mode 100644 index 00000000000..20f6671c758 --- /dev/null +++ b/core/lib/dal/migrations/20240508065104_drop_basic_witness_input_producer_table.up.sql @@ -0,0 +1,5 @@ +DROP INDEX IF EXISTS idx_basic_witness_input_producer_jobs_status_processing_attempts; + +DROP TABLE IF EXISTS basic_witness_input_producer_jobs; + +DROP TYPE IF EXISTS basic_witness_input_producer_job_status; diff --git a/core/lib/dal/src/basic_witness_input_producer_dal.rs b/core/lib/dal/src/basic_witness_input_producer_dal.rs deleted file mode 100644 index 2a30226a761..00000000000 --- a/core/lib/dal/src/basic_witness_input_producer_dal.rs +++ /dev/null @@ -1,234 +0,0 @@ -#![doc = include_str!("../doc/BasicWitnessInputProducerDal.md")] - -use std::time::{Duration, Instant}; - -use sqlx::postgres::types::PgInterval; -use zksync_db_connection::{ - connection::Connection, - error::DalResult, - instrument::InstrumentExt, - utils::{duration_to_naive_time, pg_interval_from_duration}, -}; -use zksync_types::L1BatchNumber; - -use crate::Core; - -#[derive(Debug)] -pub struct BasicWitnessInputProducerDal<'a, 'c> { - pub(crate) storage: &'a mut Connection<'c, Core>, -} - -/// The amount of attempts to process a job before giving up. -pub const JOB_MAX_ATTEMPT: i16 = 10; - -/// Time to wait for job to be processed -const JOB_PROCESSING_TIMEOUT: PgInterval = pg_interval_from_duration(Duration::from_secs(10 * 60)); - -/// Status of a job that the producer will work on. - -#[derive(Debug, sqlx::Type)] -#[sqlx(type_name = "basic_witness_input_producer_job_status")] -pub enum BasicWitnessInputProducerJobStatus { - /// When the job is queued. Metadata calculator creates the job and marks it as queued. - Queued, - /// The job is not going to be processed. This state is designed for manual operations on DB. - /// It is expected to be used if some jobs should be skipped like: - /// - testing purposes (want to check a specific L1 Batch, I can mark everything before it skipped) - /// - trim down costs on some environments (if I've done breaking changes, - /// makes no sense to wait for everything to be processed, I can just skip them and save resources) - ManuallySkipped, - /// Currently being processed by one of the jobs. Transitory state, will transition to either - /// [`BasicWitnessInputProducerStatus::Successful`] or [`BasicWitnessInputProducerStatus::Failed`]. - InProgress, - /// The final (happy case) state we expect all jobs to end up. After the run is complete, - /// the job uploaded it's inputs, it lands in successful. - Successful, - /// The job failed for reasons. It will be marked as such and the error persisted in DB. - /// If it failed less than MAX_ATTEMPTs, the job will be retried, - /// otherwise it will stay in this state as final state. - Failed, -} - -impl BasicWitnessInputProducerDal<'_, '_> { - pub async fn create_basic_witness_input_producer_job( - &mut self, - l1_batch_number: L1BatchNumber, - ) -> DalResult<()> { - sqlx::query!( - r#" - INSERT INTO - basic_witness_input_producer_jobs (l1_batch_number, status, created_at, updated_at) - VALUES - ($1, $2, NOW(), NOW()) - ON CONFLICT (l1_batch_number) DO NOTHING - "#, - i64::from(l1_batch_number.0), - BasicWitnessInputProducerJobStatus::Queued as BasicWitnessInputProducerJobStatus, - ) - .instrument("create_basic_witness_input_producer_job") - .with_arg("l1_batch_number", &l1_batch_number) - .report_latency() - .execute(self.storage) - .await?; - - Ok(()) - } - - pub async fn get_next_basic_witness_input_producer_job( - &mut self, - ) -> DalResult> { - let l1_batch_number = sqlx::query!( - r#" - UPDATE basic_witness_input_producer_jobs - SET - status = $1, - attempts = attempts + 1, - updated_at = NOW(), - processing_started_at = NOW() - WHERE - l1_batch_number = ( - SELECT - l1_batch_number - FROM - basic_witness_input_producer_jobs - WHERE - status = $2 - OR ( - status = $1 - AND processing_started_at < NOW() - $4::INTERVAL - ) - OR ( - status = $3 - AND attempts < $5 - ) - ORDER BY - l1_batch_number ASC - LIMIT - 1 - FOR UPDATE - SKIP LOCKED - ) - RETURNING - basic_witness_input_producer_jobs.l1_batch_number - "#, - BasicWitnessInputProducerJobStatus::InProgress as BasicWitnessInputProducerJobStatus, - BasicWitnessInputProducerJobStatus::Queued as BasicWitnessInputProducerJobStatus, - BasicWitnessInputProducerJobStatus::Failed as BasicWitnessInputProducerJobStatus, - &JOB_PROCESSING_TIMEOUT, - JOB_MAX_ATTEMPT, - ) - .instrument("get_next_basic_witness_input_producer_job") - .report_latency() - .fetch_optional(self.storage) - .await? - .map(|job| L1BatchNumber(job.l1_batch_number as u32)); - - Ok(l1_batch_number) - } - - pub async fn get_basic_witness_input_producer_job_attempts( - &mut self, - l1_batch_number: L1BatchNumber, - ) -> DalResult> { - let attempts = sqlx::query!( - r#" - SELECT - attempts - FROM - basic_witness_input_producer_jobs - WHERE - l1_batch_number = $1 - "#, - i64::from(l1_batch_number.0), - ) - .instrument("get_basic_witness_input_producer_job_attempts") - .with_arg("l1_batch_number", &l1_batch_number) - .fetch_optional(self.storage) - .await? - .map(|job| job.attempts as u32); - - Ok(attempts) - } - - pub async fn mark_job_as_successful( - &mut self, - l1_batch_number: L1BatchNumber, - started_at: Instant, - object_path: &str, - ) -> DalResult<()> { - sqlx::query!( - r#" - UPDATE basic_witness_input_producer_jobs - SET - status = $1, - updated_at = NOW(), - time_taken = $3, - input_blob_url = $4 - WHERE - l1_batch_number = $2 - "#, - BasicWitnessInputProducerJobStatus::Successful as BasicWitnessInputProducerJobStatus, - i64::from(l1_batch_number.0), - duration_to_naive_time(started_at.elapsed()), - object_path, - ) - .instrument("mark_job_as_successful") - .with_arg("l1_batch_number", &l1_batch_number) - .report_latency() - .execute(self.storage) - .await?; - - Ok(()) - } - - pub async fn mark_job_as_failed( - &mut self, - l1_batch_number: L1BatchNumber, - started_at: Instant, - error: String, - ) -> DalResult> { - let attempts = sqlx::query!( - r#" - UPDATE basic_witness_input_producer_jobs - SET - status = $1, - updated_at = NOW(), - time_taken = $3, - error = $4 - WHERE - l1_batch_number = $2 - AND status != $5 - RETURNING - basic_witness_input_producer_jobs.attempts - "#, - BasicWitnessInputProducerJobStatus::Failed as BasicWitnessInputProducerJobStatus, - i64::from(l1_batch_number.0), - duration_to_naive_time(started_at.elapsed()), - error, - BasicWitnessInputProducerJobStatus::Successful as BasicWitnessInputProducerJobStatus, - ) - .instrument("mark_job_as_failed") - .with_arg("l1_batch_number", &l1_batch_number) - .report_latency() - .fetch_optional(self.storage) - .await? - .map(|job| job.attempts as u32); - - Ok(attempts) - } -} - -/// These functions should only be used for tests. -impl BasicWitnessInputProducerDal<'_, '_> { - pub async fn delete_all_jobs(&mut self) -> DalResult<()> { - sqlx::query!( - r#" - DELETE FROM basic_witness_input_producer_jobs - "# - ) - .instrument("delete_all_bwip_jobs") - .execute(self.storage) - .await?; - Ok(()) - } -} diff --git a/core/lib/dal/src/lib.rs b/core/lib/dal/src/lib.rs index 8289bbcdcc7..5a95f9688ff 100644 --- a/core/lib/dal/src/lib.rs +++ b/core/lib/dal/src/lib.rs @@ -12,8 +12,7 @@ pub use zksync_db_connection::{ }; use crate::{ - basic_witness_input_producer_dal::BasicWitnessInputProducerDal, blocks_dal::BlocksDal, - blocks_web3_dal::BlocksWeb3Dal, consensus_dal::ConsensusDal, + blocks_dal::BlocksDal, blocks_web3_dal::BlocksWeb3Dal, consensus_dal::ConsensusDal, contract_verification_dal::ContractVerificationDal, eth_sender_dal::EthSenderDal, events_dal::EventsDal, events_web3_dal::EventsWeb3Dal, factory_deps_dal::FactoryDepsDal, proof_generation_dal::ProofGenerationDal, protocol_versions_dal::ProtocolVersionsDal, @@ -26,7 +25,6 @@ use crate::{ transactions_web3_dal::TransactionsWeb3Dal, }; -pub mod basic_witness_input_producer_dal; pub mod blocks_dal; pub mod blocks_web3_dal; pub mod consensus; @@ -73,8 +71,6 @@ where fn transactions_web3_dal(&mut self) -> TransactionsWeb3Dal<'_, 'a>; - fn basic_witness_input_producer_dal(&mut self) -> BasicWitnessInputProducerDal<'_, 'a>; - fn blocks_dal(&mut self) -> BlocksDal<'_, 'a>; fn blocks_web3_dal(&mut self) -> BlocksWeb3Dal<'_, 'a>; @@ -137,10 +133,6 @@ impl<'a> CoreDal<'a> for Connection<'a, Core> { TransactionsWeb3Dal { storage: self } } - fn basic_witness_input_producer_dal(&mut self) -> BasicWitnessInputProducerDal<'_, 'a> { - BasicWitnessInputProducerDal { storage: self } - } - fn blocks_dal(&mut self) -> BlocksDal<'_, 'a> { BlocksDal { storage: self } } diff --git a/core/lib/object_store/src/objects.rs b/core/lib/object_store/src/objects.rs index c11b2626323..90b19fc52d3 100644 --- a/core/lib/object_store/src/objects.rs +++ b/core/lib/object_store/src/objects.rs @@ -10,7 +10,6 @@ use zksync_types::{ snapshots::{ SnapshotFactoryDependencies, SnapshotStorageLogsChunk, SnapshotStorageLogsStorageKey, }, - storage::witness_block_state::WitnessBlockState, L1BatchNumber, }; @@ -118,17 +117,6 @@ impl StoredObject for SnapshotStorageLogsChunk { } } -impl StoredObject for WitnessBlockState { - const BUCKET: Bucket = Bucket::WitnessInput; - type Key<'a> = L1BatchNumber; - - fn encode_key(key: Self::Key<'_>) -> String { - format!("witness_block_state_for_l1_batch_{key}.bin") - } - - serialize_using_bincode!(); -} - impl dyn ObjectStore + '_ { /// Fetches the value for the given key if it exists. /// diff --git a/core/lib/state/src/lib.rs b/core/lib/state/src/lib.rs index 0621e2b33a3..cd16f65f41b 100644 --- a/core/lib/state/src/lib.rs +++ b/core/lib/state/src/lib.rs @@ -27,7 +27,6 @@ mod storage_factory; mod storage_view; #[cfg(test)] mod test_utils; -mod witness; pub use self::{ cache::sequential_cache::SequentialCache, @@ -42,7 +41,6 @@ pub use self::{ shadow_storage::ShadowStorage, storage_factory::{BatchDiff, PgOrRocksdbStorage, ReadStorageFactory, RocksdbWithMemory}, storage_view::{StorageView, StorageViewMetrics}, - witness::WitnessStorage, }; /// Functionality to read from the VM storage. diff --git a/core/lib/state/src/storage_view.rs b/core/lib/state/src/storage_view.rs index 3a38ad12199..7756f6007ee 100644 --- a/core/lib/state/src/storage_view.rs +++ b/core/lib/state/src/storage_view.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, Instant}, }; -use zksync_types::{witness_block_state::WitnessBlockState, StorageKey, StorageValue, H256}; +use zksync_types::{StorageKey, StorageValue, H256}; use crate::{ReadStorage, WriteStorage}; @@ -53,14 +53,6 @@ pub struct StorageView { } impl StorageView { - /// Returns the block's start state using StorageView's in-memory cache for the run - pub fn witness_block_state(&self) -> WitnessBlockState { - WitnessBlockState { - read_storage_key: self.read_storage_keys.clone(), - is_write_initial: self.initial_writes_cache.clone(), - } - } - /// Returns the modified storage keys pub fn modified_storage_keys(&self) -> &HashMap { &self.modified_storage_keys diff --git a/core/lib/state/src/witness.rs b/core/lib/state/src/witness.rs deleted file mode 100644 index 50e2d9b5407..00000000000 --- a/core/lib/state/src/witness.rs +++ /dev/null @@ -1,56 +0,0 @@ -use vise::{Counter, Metrics}; -use zksync_types::{witness_block_state::WitnessBlockState, StorageKey, StorageValue, H256}; - -use crate::ReadStorage; - -#[derive(Debug, Metrics)] -#[metrics(prefix = "witness_storage")] -struct WitnessStorageMetrics { - /// Number of unexpected calls when calling `get_enumeration_index` on a witness storage. - get_enumeration_index_unexpected_call: Counter, -} - -#[vise::register] -static METRICS: vise::Global = vise::Global::new(); - -/// [`ReadStorage`] implementation backed by binary serialized [`WitnessHashBlockState`]. -/// Note that `load_factory_deps` is not used. -/// FactoryDeps data is used straight inside witness generator, loaded with the blob. -#[derive(Debug)] -pub struct WitnessStorage<'a> { - block_state: WitnessBlockState, - metrics: &'a WitnessStorageMetrics, -} - -impl WitnessStorage<'_> { - /// Creates a new storage with the provided witness's block state. - pub fn new(block_state: WitnessBlockState) -> Self { - Self { - block_state, - metrics: &METRICS, - } - } -} - -impl ReadStorage for WitnessStorage<'_> { - fn read_value(&mut self, key: &StorageKey) -> StorageValue { - *self - .block_state - .read_storage_key - .get(key) - .unwrap_or(&H256::default()) - } - - fn is_write_initial(&mut self, key: &StorageKey) -> bool { - *self.block_state.is_write_initial.get(key).unwrap_or(&false) - } - - fn load_factory_dep(&mut self, _hash: H256) -> Option> { - None - } - - fn get_enumeration_index(&mut self, _key: &StorageKey) -> Option { - self.metrics.get_enumeration_index_unexpected_call.inc(); - None - } -} diff --git a/core/lib/types/src/storage/mod.rs b/core/lib/types/src/storage/mod.rs index 6614ccd600d..510ec5b19d1 100644 --- a/core/lib/types/src/storage/mod.rs +++ b/core/lib/types/src/storage/mod.rs @@ -7,7 +7,6 @@ use zksync_basic_types::{web3::keccak256, L2ChainId}; use crate::{AccountTreeId, Address, H160, H256, U256}; pub mod log; -pub mod witness_block_state; pub mod writes; pub use log::*; diff --git a/core/lib/zksync_core/Cargo.toml b/core/lib/zksync_core/Cargo.toml index a8349f3acd9..756d32ab74a 100644 --- a/core/lib/zksync_core/Cargo.toml +++ b/core/lib/zksync_core/Cargo.toml @@ -28,7 +28,6 @@ zksync_eth_client.workspace = true zksync_eth_signer.workspace = true zksync_l1_contract_interface.workspace = true zksync_mempool.workspace = true -zksync_queued_job_processor.workspace = true zksync_circuit_breaker.workspace = true zksync_storage.workspace = true zksync_merkle_tree.workspace = true diff --git a/core/lib/zksync_core/src/basic_witness_input_producer/metrics.rs b/core/lib/zksync_core/src/basic_witness_input_producer/metrics.rs deleted file mode 100644 index ffe05162951..00000000000 --- a/core/lib/zksync_core/src/basic_witness_input_producer/metrics.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! BasicWitnessInputProducer metrics. - -use std::time::Duration; - -use vise::{Buckets, Gauge, Histogram, Metrics, Unit}; - -#[derive(Debug, Metrics)] -#[metrics(prefix = "basic_witness_input_producer")] -pub(crate) struct BasicWitnessInputProducerMetrics { - #[metrics(buckets = Buckets::LATENCIES, unit = Unit::Seconds)] - pub process_batch_time: Histogram, - #[metrics(buckets = Buckets::LATENCIES, unit = Unit::Seconds)] - pub upload_input_time: Histogram, - pub block_number_processed: Gauge, -} - -#[vise::register] -pub(super) static METRICS: vise::Global = vise::Global::new(); diff --git a/core/lib/zksync_core/src/basic_witness_input_producer/mod.rs b/core/lib/zksync_core/src/basic_witness_input_producer/mod.rs deleted file mode 100644 index 34d54e3d449..00000000000 --- a/core/lib/zksync_core/src/basic_witness_input_producer/mod.rs +++ /dev/null @@ -1,197 +0,0 @@ -use std::{sync::Arc, time::Instant}; - -use anyhow::Context; -use async_trait::async_trait; -use multivm::interface::{L2BlockEnv, VmInterface}; -use tokio::{runtime::Handle, task::JoinHandle}; -use vm_utils::{create_vm, execute_tx}; -use zksync_dal::{ - basic_witness_input_producer_dal::JOB_MAX_ATTEMPT, ConnectionPool, Core, CoreDal, -}; -use zksync_object_store::{ObjectStore, ObjectStoreFactory}; -use zksync_queued_job_processor::JobProcessor; -use zksync_types::{witness_block_state::WitnessBlockState, L1BatchNumber, L2ChainId}; - -use self::metrics::METRICS; - -mod metrics; -/// Component that extracts all data (from DB) necessary to run a Basic Witness Generator. -/// Does this by rerunning an entire L1Batch and extracting information from both the VM run and DB. -/// This component will upload Witness Inputs to the object store. -/// This allows Witness Generator workflow (that needs only Basic Witness Generator Inputs) -/// to be run only using the object store information, having no other external dependency. -#[derive(Debug)] -pub struct BasicWitnessInputProducer { - connection_pool: ConnectionPool, - l2_chain_id: L2ChainId, - object_store: Arc, -} - -impl BasicWitnessInputProducer { - pub async fn new( - connection_pool: ConnectionPool, - store_factory: &ObjectStoreFactory, - l2_chain_id: L2ChainId, - ) -> anyhow::Result { - Ok(BasicWitnessInputProducer { - connection_pool, - object_store: store_factory.create_store().await, - l2_chain_id, - }) - } - - fn process_job_impl( - rt_handle: Handle, - l1_batch_number: L1BatchNumber, - started_at: Instant, - connection_pool: ConnectionPool, - l2_chain_id: L2ChainId, - ) -> anyhow::Result { - let mut connection = rt_handle - .block_on(connection_pool.connection()) - .context("failed to get connection for BasicWitnessInputProducer")?; - - let l2_blocks_execution_data = rt_handle.block_on( - connection - .transactions_dal() - .get_l2_blocks_to_execute_for_l1_batch(l1_batch_number), - )?; - - let (mut vm, storage_view) = - create_vm(rt_handle.clone(), l1_batch_number, connection, l2_chain_id) - .context("failed to create vm for BasicWitnessInputProducer")?; - - tracing::info!("Started execution of l1_batch: {l1_batch_number:?}"); - - let next_l2_blocks_data = l2_blocks_execution_data - .iter() - .skip(1) - .map(Some) - .chain([None]); - let l2_blocks_data = l2_blocks_execution_data.iter().zip(next_l2_blocks_data); - - for (l2_block_data, next_l2_block_data) in l2_blocks_data { - tracing::debug!( - "Started execution of L2 block: {:?}, executing {:?} transactions", - l2_block_data.number, - l2_block_data.txs.len(), - ); - for tx in &l2_block_data.txs { - tracing::trace!("Started execution of tx: {tx:?}"); - execute_tx(tx, &mut vm) - .context("failed to execute transaction in BasicWitnessInputProducer")?; - tracing::trace!("Finished execution of tx: {tx:?}"); - } - if let Some(next_l2_block_data) = next_l2_block_data { - vm.start_new_l2_block(L2BlockEnv::from_l2_block_data(next_l2_block_data)); - } - - tracing::debug!("Finished execution of L2 block: {:?}", l2_block_data.number); - } - vm.finish_batch(); - tracing::info!("Finished execution of l1_batch: {l1_batch_number:?}"); - - METRICS.process_batch_time.observe(started_at.elapsed()); - tracing::info!( - "BasicWitnessInputProducer took {:?} for L1BatchNumber {}", - started_at.elapsed(), - l1_batch_number.0 - ); - - let witness_block_state = (*storage_view).borrow().witness_block_state(); - Ok(witness_block_state) - } -} - -#[async_trait] -impl JobProcessor for BasicWitnessInputProducer { - type Job = L1BatchNumber; - type JobId = L1BatchNumber; - type JobArtifacts = WitnessBlockState; - const SERVICE_NAME: &'static str = "basic_witness_input_producer"; - - async fn get_next_job(&self) -> anyhow::Result> { - let mut connection = self.connection_pool.connection().await?; - let l1_batch_to_process = connection - .basic_witness_input_producer_dal() - .get_next_basic_witness_input_producer_job() - .await?; - Ok(l1_batch_to_process.map(|number| (number, number))) - } - - async fn save_failure(&self, job_id: Self::JobId, started_at: Instant, error: String) { - let attempts = self - .connection_pool - .connection() - .await - .unwrap() - .basic_witness_input_producer_dal() - .mark_job_as_failed(job_id, started_at, error) - .await - .expect("errored whilst marking job as failed"); - if let Some(tries) = attempts { - tracing::warn!("Failed to process job: {job_id:?}, after {tries} tries."); - } else { - tracing::warn!("L1 Batch {job_id:?} was processed successfully by another worker."); - } - } - - async fn process_job( - &self, - _job_id: &Self::JobId, - job: Self::Job, - started_at: Instant, - ) -> JoinHandle> { - let l2_chain_id = self.l2_chain_id; - let connection_pool = self.connection_pool.clone(); - tokio::task::spawn_blocking(move || { - let rt_handle = Handle::current(); - Self::process_job_impl( - rt_handle, - job, - started_at, - connection_pool.clone(), - l2_chain_id, - ) - }) - } - - async fn save_result( - &self, - job_id: Self::JobId, - started_at: Instant, - artifacts: Self::JobArtifacts, - ) -> anyhow::Result<()> { - let upload_started_at = Instant::now(); - let object_path = self - .object_store - .put(job_id, &artifacts) - .await - .context("failed to upload artifacts for BasicWitnessInputProducer")?; - METRICS - .upload_input_time - .observe(upload_started_at.elapsed()); - let mut connection = self.connection_pool.connection().await?; - let mut transaction = connection.start_transaction().await?; - transaction - .basic_witness_input_producer_dal() - .mark_job_as_successful(job_id, started_at, &object_path) - .await?; - transaction.commit().await?; - METRICS.block_number_processed.set(job_id.0 as i64); - Ok(()) - } - - fn max_attempts(&self) -> u32 { - JOB_MAX_ATTEMPT as u32 - } - - async fn get_job_attempts(&self, job_id: &L1BatchNumber) -> anyhow::Result { - let mut connection = self.connection_pool.connection().await?; - Ok(connection - .basic_witness_input_producer_dal() - .get_basic_witness_input_producer_job_attempts(*job_id) - .await - .map(|attempts| attempts.unwrap_or(0))?) - } -} diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs index cc8976d6b22..b8513c6963f 100644 --- a/core/lib/zksync_core/src/lib.rs +++ b/core/lib/zksync_core/src/lib.rs @@ -76,7 +76,6 @@ use zksync_node_fee_model::{ }; use zksync_node_genesis::{ensure_genesis_state, GenesisParams}; use zksync_object_store::{ObjectStore, ObjectStoreFactory}; -use zksync_queued_job_processor::JobProcessor; use zksync_shared_metrics::{InitStage, APP_METRICS}; use zksync_state::{PostgresStorageCaches, RocksdbStorageOptions}; use zksync_types::{ethabi::Contract, fee_model::FeeModelConfig, Address, L2ChainId}; @@ -90,7 +89,6 @@ use crate::{ tx_sender::{ApiContracts, TxSender, TxSenderBuilder, TxSenderConfig}, web3::{self, mempool_cache::MempoolCache, state::InternalApiConfig, Namespace}, }, - basic_witness_input_producer::BasicWitnessInputProducer, metadata_calculator::{MetadataCalculator, MetadataCalculatorConfig}, state_keeper::{ create_state_keeper, AsyncRocksdbCache, MempoolFetcher, MempoolGuard, OutputHandler, @@ -100,7 +98,6 @@ use crate::{ }; pub mod api_server; -pub mod basic_witness_input_producer; pub mod consensus; pub mod consistency_checker; pub mod metadata_calculator; @@ -176,9 +173,6 @@ pub enum Component { EthTxManager, /// State keeper. StateKeeper, - /// Produces input for basic witness generator and uploads it as bin encoded file (blob) to GCS. - /// The blob is later used as input for Basic Witness Generators. - BasicWitnessInputProducer, /// Component for housekeeping task such as cleaning blobs from GCS, reporting metrics etc. Housekeeper, /// Component for exposing APIs to prover for providing proof generation data and accepting proofs. @@ -209,9 +203,6 @@ impl FromStr for Components { "tree_api" => Ok(Components(vec![Component::TreeApi])), "state_keeper" => Ok(Components(vec![Component::StateKeeper])), "housekeeper" => Ok(Components(vec![Component::Housekeeper])), - "basic_witness_input_producer" => { - Ok(Components(vec![Component::BasicWitnessInputProducer])) - } "eth" => Ok(Components(vec![ Component::EthWatcher, Component::EthTxAggregator, @@ -766,23 +757,6 @@ pub async fn initialize_components( .await .context("add_trees_to_task_futures()")?; - if components.contains(&Component::BasicWitnessInputProducer) { - let singleton_connection_pool = - ConnectionPool::::singleton(postgres_config.master_url()?) - .build() - .await - .context("failed to build singleton connection_pool")?; - add_basic_witness_input_producer_to_task_futures( - &mut task_futures, - &singleton_connection_pool, - &store_factory, - l2_chain_id, - stop_receiver.clone(), - ) - .await - .context("add_basic_witness_input_producer_to_task_futures()")?; - } - if components.contains(&Component::Housekeeper) { add_house_keeper_to_task_futures(configs, &mut task_futures, stop_receiver.clone()) .await @@ -1061,32 +1035,6 @@ async fn run_tree( Ok(()) } -async fn add_basic_witness_input_producer_to_task_futures( - task_futures: &mut Vec>>, - connection_pool: &ConnectionPool, - store_factory: &ObjectStoreFactory, - l2_chain_id: L2ChainId, - stop_receiver: watch::Receiver, -) -> anyhow::Result<()> { - // Witness Generator won't be spawned with `ZKSYNC_LOCAL_SETUP` running. - // BasicWitnessInputProducer shouldn't be producing input for it locally either. - if std::env::var("ZKSYNC_LOCAL_SETUP") == Ok("true".to_owned()) { - return Ok(()); - } - let started_at = Instant::now(); - tracing::info!("initializing BasicWitnessInputProducer"); - let producer = - BasicWitnessInputProducer::new(connection_pool.clone(), store_factory, l2_chain_id).await?; - task_futures.push(tokio::spawn(producer.run(stop_receiver, None))); - tracing::info!( - "Initialized BasicWitnessInputProducer in {:?}", - started_at.elapsed() - ); - let elapsed = started_at.elapsed(); - APP_METRICS.init_latency[&InitStage::BasicWitnessInputProducer].set(elapsed); - Ok(()) -} - async fn add_house_keeper_to_task_futures( configs: &GeneralConfig, task_futures: &mut Vec>>, diff --git a/core/lib/zksync_core/src/metadata_calculator/tests.rs b/core/lib/zksync_core/src/metadata_calculator/tests.rs index 9958a3542f1..00522f27896 100644 --- a/core/lib/zksync_core/src/metadata_calculator/tests.rs +++ b/core/lib/zksync_core/src/metadata_calculator/tests.rs @@ -484,11 +484,6 @@ pub(crate) async fn reset_db_state(pool: &ConnectionPool, num_batches: usi .delete_initial_writes(L1BatchNumber(0)) .await .unwrap(); - storage - .basic_witness_input_producer_dal() - .delete_all_jobs() - .await - .unwrap(); let logs = gen_storage_logs(0..100, num_batches); extend_db_state(&mut storage, logs).await; diff --git a/core/lib/zksync_core/src/metadata_calculator/updater.rs b/core/lib/zksync_core/src/metadata_calculator/updater.rs index 1b853557558..b4f7d90117a 100644 --- a/core/lib/zksync_core/src/metadata_calculator/updater.rs +++ b/core/lib/zksync_core/src/metadata_calculator/updater.rs @@ -142,11 +142,6 @@ impl TreeUpdater { // right away without having to implement dedicated code. if let Some(object_key) = &object_key { - storage - .basic_witness_input_producer_dal() - .create_basic_witness_input_producer_job(l1_batch_number) - .await - .context("failed to create basic_witness_input_producer job")?; storage .proof_generation_dal() .insert_proof_generation_details(l1_batch_number, object_key) diff --git a/core/node/shared_metrics/src/lib.rs b/core/node/shared_metrics/src/lib.rs index 75f9c520565..7673b3c0bba 100644 --- a/core/node/shared_metrics/src/lib.rs +++ b/core/node/shared_metrics/src/lib.rs @@ -27,7 +27,6 @@ pub enum InitStage { EthTxAggregator, EthTxManager, Tree, - BasicWitnessInputProducer, Consensus, } @@ -42,7 +41,6 @@ impl fmt::Display for InitStage { Self::EthTxAggregator => formatter.write_str("eth_tx_aggregator"), Self::EthTxManager => formatter.write_str("eth_tx_manager"), Self::Tree => formatter.write_str("tree"), - Self::BasicWitnessInputProducer => formatter.write_str("basic_witness_input_producer"), Self::Consensus => formatter.write_str("consensus"), } } From cead2fbbf42f0109966154b88ac6cb52f019b614 Mon Sep 17 00:00:00 2001 From: perekopskiy <53865202+perekopskiy@users.noreply.github.com> Date: Wed, 8 May 2024 13:16:12 +0300 Subject: [PATCH 7/9] ci: workflow_dispatch for release stable EN (#1881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ ## Why ❔ ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- .github/workflows/release-stable-en.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-stable-en.yml b/.github/workflows/release-stable-en.yml index 526c5a15b64..253f89755eb 100644 --- a/.github/workflows/release-stable-en.yml +++ b/.github/workflows/release-stable-en.yml @@ -1,7 +1,7 @@ -name: Workflow to push stable EN image +name: Release stable EN image on: - workflow_call: + workflow_dispatch: inputs: tag_name: description: "Tag of an image" From e7078bde293379c7c3552bd15be368791705e331 Mon Sep 17 00:00:00 2001 From: Bence Haromi <56651250+benceharomi@users.noreply.github.com> Date: Wed, 8 May 2024 11:21:36 +0100 Subject: [PATCH 8/9] fix: local-node rich account funding (#1879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ Fixes gas estimation for local-node rich account funding. ## Why ❔ ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [x] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. Co-authored-by: mm --- .../local-setup-preparation/src/index.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/infrastructure/local-setup-preparation/src/index.ts b/infrastructure/local-setup-preparation/src/index.ts index c2179bd407a..805d13aadcd 100644 --- a/infrastructure/local-setup-preparation/src/index.ts +++ b/infrastructure/local-setup-preparation/src/index.ts @@ -25,12 +25,14 @@ async function depositWithRichAccounts() { const gasPrice = await ethProvider.getGasPrice(); const contract = new ethers.Contract(process.env.CONTRACTS_BRIDGEHUB_PROXY_ADDR, utils.BRIDGEHUB_ABI, ethProvider); - const expectedCost = await contract.l2TransactionBaseCost( - chainId, - gasPrice, - DEPOSIT_L2_GAS_LIMIT, - utils.DEFAULT_GAS_PER_PUBDATA_LIMIT - ); + const expectedCost = + (await contract.l2TransactionBaseCost( + chainId, + gasPrice, + DEPOSIT_L2_GAS_LIMIT, + utils.DEFAULT_GAS_PER_PUBDATA_LIMIT + )) * 1.5; + // We multiply the expected cost with 1.5 (in case gas price changes a little between calls - especially when we send 10 in a row). for (const wallet of wallets) { if (!(await isOperator(chainId, wallet.address))) { From a704bce6513e25e8ddd1d23f0065ee64061a89eb Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Wed, 8 May 2024 12:35:55 +0200 Subject: [PATCH 9/9] ci: Fix docker build for zk-enviroment image (#1880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ ## Why ❔ ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Tests for the changes have been added / updated. - [x] Documentation comments have been added / updated. - [x] Code has been formatted via `zk fmt` and `zk lint`. - [ ] Spellcheck has been run via `zk spellcheck`. - [ ] Linkcheck has been run via `zk linkcheck`. --- docker/zk-environment/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/zk-environment/Dockerfile b/docker/zk-environment/Dockerfile index 0c714db68e4..022120c1b0f 100644 --- a/docker/zk-environment/Dockerfile +++ b/docker/zk-environment/Dockerfile @@ -83,7 +83,7 @@ ENV NODE_MAJOR=18 RUN mkdir -p /etc/apt/keyrings && \ wget -c -O - https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ - apt-get update && apt-get install nodejs npm -y && \ + apt-get update && apt-get install nodejs -y && \ npm install -g yarn && npm install -g cspell && npm install -g markdown-link-check # Install Rust and required cargo packages