diff --git a/Cargo.lock b/Cargo.lock index 16152c6bf698..25bd17479b5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1767,28 +1767,16 @@ dependencies = [ "typenum", ] -[[package]] -name = "bitvec" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" -dependencies = [ - "funty 1.1.0", - "radium 0.6.2", - "tap", - "wyz 0.2.0", -] - [[package]] name = "bitvec" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "funty 2.0.0", - "radium 0.7.0", + "funty", + "radium", "tap", - "wyz 0.5.1", + "wyz", ] [[package]] @@ -1958,7 +1946,7 @@ dependencies = [ "crossbeam", "crypto-bigint 0.5.5", "derivative", - "ethereum-types 0.14.1", + "ethereum-types", "firestorm", "itertools 0.10.5", "lazy_static", @@ -3579,28 +3567,13 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ethabi" -version = "16.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c98847055d934070b90e806e12d3936b787d0a115068981c1d8dfd5dfef5a5" -dependencies = [ - "ethereum-types 0.12.1", - "hex", - "serde", - "serde_json", - "sha3 0.9.1", - "thiserror", - "uint", -] - [[package]] name = "ethabi" version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" dependencies = [ - "ethereum-types 0.14.1", + "ethereum-types", "hex", "once_cell", "regex", @@ -3611,19 +3584,6 @@ dependencies = [ "uint", ] -[[package]] -name = "ethbloom" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" -dependencies = [ - "crunchy", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde 0.3.2", - "tiny-keccak 2.0.2", -] - [[package]] name = "ethbloom" version = "0.13.0" @@ -3631,37 +3591,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", - "fixed-hash 0.8.0", + "fixed-hash", "impl-rlp", - "impl-serde 0.4.0", + "impl-serde", "tiny-keccak 2.0.2", ] -[[package]] -name = "ethereum-types" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" -dependencies = [ - "ethbloom 0.11.1", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde 0.3.2", - "primitive-types 0.10.1", - "uint", -] - [[package]] name = "ethereum-types" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ - "ethbloom 0.13.0", - "fixed-hash 0.8.0", + "ethbloom", + "fixed-hash", "impl-rlp", - "impl-serde 0.4.0", - "primitive-types 0.12.2", + "impl-serde", + "primitive-types", "uint", ] @@ -3773,18 +3719,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c5f6c2c942da57e2aaaa84b8a521489486f14e75e7fa91dab70aba913975f98" -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - [[package]] name = "fixed-hash" version = "0.8.0" @@ -3887,7 +3821,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" dependencies = [ "cfg-if", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-info", ] @@ -3898,7 +3832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" dependencies = [ "cfg-if", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-info", "serde", ] @@ -3948,12 +3882,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "funty" version = "2.0.0" @@ -4881,22 +4809,13 @@ dependencies = [ "version_check", ] -[[package]] -name = "impl-codec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" -dependencies = [ - "parity-scale-codec 2.3.1", -] - [[package]] name = "impl-codec" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ - "parity-scale-codec 3.6.12", + "parity-scale-codec", ] [[package]] @@ -4908,15 +4827,6 @@ dependencies = [ "rlp", ] -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", -] - [[package]] name = "impl-serde" version = "0.4.0" @@ -5451,14 +5361,6 @@ dependencies = [ "log", ] -[[package]] -name = "kzgpad-rs" -version = "0.1.0" -source = "git+https://github.com/Layr-Labs/kzgpad-rs.git?tag=v0.1.0#b5f8c8d3d6482407dc118cb1f51597a017a1cc89" -dependencies = [ - "rand 0.8.5", -] - [[package]] name = "lalrpop" version = "0.20.2" @@ -6559,20 +6461,6 @@ dependencies = [ "sha2 0.10.8", ] -[[package]] -name = "parity-scale-codec" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" -dependencies = [ - "arrayvec 0.7.6", - "bitvec 0.20.4", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive 2.3.1", - "serde", -] - [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -6580,25 +6468,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec 0.7.6", - "bitvec 1.0.1", + "bitvec", "byte-slice-cast", "impl-trait-for-tuples", - "parity-scale-codec-derive 3.6.12", + "parity-scale-codec-derive", "serde", ] -[[package]] -name = "parity-scale-codec-derive" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 1.0.109", -] - [[package]] name = "parity-scale-codec-derive" version = "3.6.12" @@ -6999,29 +6875,16 @@ dependencies = [ "elliptic-curve 0.13.8", ] -[[package]] -name = "primitive-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" -dependencies = [ - "fixed-hash 0.7.0", - "impl-codec 0.5.1", - "impl-rlp", - "impl-serde 0.3.2", - "uint", -] - [[package]] name = "primitive-types" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ - "fixed-hash 0.8.0", - "impl-codec 0.6.0", + "fixed-hash", + "impl-codec", "impl-rlp", - "impl-serde 0.4.0", + "impl-serde", "scale-info", "uint", ] @@ -7403,12 +7266,6 @@ dependencies = [ "proc-macro2 1.0.89", ] -[[package]] -name = "radium" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" - [[package]] name = "radium" version = "0.7.0" @@ -7788,7 +7645,7 @@ version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bytecheck", "bytes", "hashbrown 0.12.3", @@ -7870,8 +7727,8 @@ dependencies = [ "fastrlp", "num-bigint 0.4.6", "num-traits", - "parity-scale-codec 3.6.12", - "primitive-types 0.12.2", + "parity-scale-codec", + "primitive-types", "proptest", "rand 0.8.5", "rlp", @@ -8173,7 +8030,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" dependencies = [ - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-info", "serde", ] @@ -8185,8 +8042,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7caaf753f8ed1ab4752c6afb20174f03598c664724e0e32628e161c21000ff76" dependencies = [ "derive_more 0.99.18", - "parity-scale-codec 3.6.12", - "primitive-types 0.12.2", + "parity-scale-codec", + "primitive-types", "scale-bits", "scale-decode-derive", "scale-info", @@ -8213,8 +8070,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d70cb4b29360105483fac1ed567ff95d65224a14dd275b6303ed0a654c78de5" dependencies = [ "derive_more 0.99.18", - "parity-scale-codec 3.6.12", - "primitive-types 0.12.2", + "parity-scale-codec", + "primitive-types", "scale-bits", "scale-encode-derive", "scale-info", @@ -8240,10 +8097,10 @@ version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa7ffc1c0ef49b0452c6e2986abf2b07743320641ffd5fc63d552458e3b779b" dependencies = [ - "bitvec 1.0.1", + "bitvec", "cfg-if", "derive_more 1.0.0", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-info-derive", "serde", ] @@ -8284,7 +8141,7 @@ dependencies = [ "derive_more 0.99.18", "either", "frame-metadata 15.1.0", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-bits", "scale-decode", "scale-encode", @@ -8444,7 +8301,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap 4.5.20", - "ethabi 18.0.0", + "ethabi", "glob", "hex", "serde", @@ -9582,11 +9439,11 @@ dependencies = [ "frame-metadata 16.0.0", "futures 0.3.31", "hex", - "impl-serde 0.4.0", + "impl-serde", "instant", "jsonrpsee 0.21.0", - "parity-scale-codec 3.6.12", - "primitive-types 0.12.2", + "parity-scale-codec", + "primitive-types", "scale-bits", "scale-decode", "scale-encode", @@ -9614,7 +9471,7 @@ dependencies = [ "heck 0.4.1", "hex", "jsonrpsee 0.21.0", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "proc-macro2 1.0.89", "quote 1.0.37", "scale-info", @@ -9649,7 +9506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "365251668613323064803427af8c7c7bc366cd8b28e33639640757669dafebd5" dependencies = [ "darling 0.20.10", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "proc-macro-error", "quote 1.0.37", "scale-typegen", @@ -9664,7 +9521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c02aca8d39a1f6c55fff3a8fd81557d30a610fedc1cef03f889a81bc0f8f0b52" dependencies = [ "frame-metadata 16.0.0", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "scale-info", "sp-core-hashing", "thiserror", @@ -9679,7 +9536,7 @@ dependencies = [ "bip39", "hex", "hmac 0.12.1", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "pbkdf2", "regex", "schnorrkel", @@ -11332,12 +11189,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "wyz" version = "0.5.1" @@ -11615,7 +11466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e0154bd4ae8202c96c52b29dd44f944bfd08c1c233fef843744463964de957" dependencies = [ "bitflags 1.3.2", - "ethereum-types 0.14.1", + "ethereum-types", "lazy_static", "sha2 0.10.8", ] @@ -11628,7 +11479,7 @@ checksum = "e0769f7b27d8fb06e715da3290c575cac5d04d10a557faef180e847afce50ac4" dependencies = [ "bitflags 2.6.0", "blake2 0.10.6", - "ethereum-types 0.14.1", + "ethereum-types", "k256 0.11.6", "lazy_static", "sha2_ce", @@ -11643,7 +11494,7 @@ checksum = "6be7bd5f0e0b61211f544147289640b4712715589d7f2fe5229d92a7a3ac64c0" dependencies = [ "bitflags 2.6.0", "blake2 0.10.6", - "ethereum-types 0.14.1", + "ethereum-types", "k256 0.13.4", "lazy_static", "sha2 0.10.8", @@ -11658,7 +11509,7 @@ checksum = "b83f3b279248af4ca86dec20a54127f02110b45570f3f6c1d13df49ba75c28a5" dependencies = [ "bitflags 2.6.0", "blake2 0.10.6", - "ethereum-types 0.14.1", + "ethereum-types", "k256 0.13.4", "lazy_static", "p256", @@ -11697,7 +11548,7 @@ dependencies = [ "anyhow", "bincode", "chrono", - "ethabi 18.0.0", + "ethabi", "hex", "num_enum 0.7.3", "secrecy", @@ -12065,7 +11916,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "ethabi 18.0.0", + "ethabi", "hex", "regex", "semver 1.0.23", @@ -12091,7 +11942,7 @@ name = "zksync_contracts" version = "0.1.0" dependencies = [ "envy", - "ethabi 18.0.0", + "ethabi", "hex", "once_cell", "serde", @@ -12167,15 +12018,14 @@ dependencies = [ "blake2b_simd", "bytes", "celestia-types", - "ethabi 16.0.0", + "ethabi", "flate2", "futures 0.3.31", "hex", "http 1.1.0", "jsonrpsee 0.23.2", - "kzgpad-rs", "num-bigint 0.4.6", - "parity-scale-codec 3.6.12", + "parity-scale-codec", "pbjson-types", "prost 0.12.6", "rand 0.8.5", @@ -12668,7 +12518,7 @@ dependencies = [ "circuit_sequencer_api 0.141.2", "circuit_sequencer_api 0.142.2", "circuit_sequencer_api 0.150.7", - "ethabi 18.0.0", + "ethabi", "hex", "itertools 0.10.5", "once_cell", @@ -13232,7 +13082,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b310ab8a21681270e73f177ddf7974cabb7a96f0624ab8b008fd6ee1f9b4f687" dependencies = [ - "ethereum-types 0.14.1", + "ethereum-types", "franklin-crypto", "handlebars", "hex", @@ -13378,7 +13228,7 @@ dependencies = [ name = "zksync_test_account" version = "0.1.0" dependencies = [ - "ethabi 18.0.0", + "ethabi", "hex", "rand 0.8.5", "zksync_contracts", @@ -13479,7 +13329,7 @@ version = "0.2.1" source = "git+https://github.com/matter-labs/vm2.git?rev=457d8a7eea9093af9440662e33e598c13ba41633#457d8a7eea9093af9440662e33e598c13ba41633" dependencies = [ "enum_dispatch", - "primitive-types 0.12.2", + "primitive-types", "zk_evm_abstractions 0.150.7", "zkevm_opcode_defs 0.150.7", "zksync_vm2_interface", @@ -13490,7 +13340,7 @@ name = "zksync_vm2_interface" version = "0.2.1" source = "git+https://github.com/matter-labs/vm2.git?rev=457d8a7eea9093af9440662e33e598c13ba41633#457d8a7eea9093af9440662e33e598c13ba41633" dependencies = [ - "primitive-types 0.12.2", + "primitive-types", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e491c64605bc..6d651176ab6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -219,6 +219,11 @@ pbjson-types = "0.6.0" # Eigen tokio-stream = "0.1.16" +alloy = { version = "0.3", features = ["full"] } +rust-kzg-bn254 = {git = "https://github.com/lambdaclass/rust-kzg-bn254", branch = "bump-ark"} +ark-bn254 = "0.5.0-alpha.0" +num-bigint = "0.4.6" +serial_test = "3.1.1" # Here and below: # We *always* pin the latest version of protocol to disallow accidental changes in the execution logic. diff --git a/core/lib/config/src/configs/da_client/eigen.rs b/core/lib/config/src/configs/da_client/eigen.rs index f94675871463..0084cfe05186 100644 --- a/core/lib/config/src/configs/da_client/eigen.rs +++ b/core/lib/config/src/configs/da_client/eigen.rs @@ -1,30 +1,8 @@ use serde::Deserialize; use zksync_basic_types::secrets::PrivateKey; - -pub const EIGEN_MEMSTORE_CLIENT_NAME: &str = "MemStore"; -pub const EIGEN_DISPERSER_CLIENT_NAME: &str = "Disperser"; - -#[derive(Clone, Debug, PartialEq, Deserialize)] -pub enum EigenConfig { - MemStore(MemStoreConfig), - Disperser(DisperserConfig), -} - -/// Configuration for the EigenDA in-memory client. -#[derive(Clone, Debug, PartialEq, Deserialize, Default)] -pub struct MemStoreConfig { - pub max_blob_size_bytes: u64, - /// Blob expiration time in seconds - pub blob_expiration: u64, - /// Latency in milliseconds for get operations - pub get_latency: u64, - /// Latency in milliseconds for put operations - pub put_latency: u64, -} - /// Configuration for the EigenDA remote disperser client. #[derive(Clone, Debug, PartialEq, Deserialize, Default)] -pub struct DisperserConfig { +pub struct EigenConfig { /// URL of the Disperser RPC server pub disperser_rpc: String, /// Block height needed to reach in order to consider the blob finalized diff --git a/core/lib/env_config/src/da_client.rs b/core/lib/env_config/src/da_client.rs index 7dc5ece5db59..7e711c5ff588 100644 --- a/core/lib/env_config/src/da_client.rs +++ b/core/lib/env_config/src/da_client.rs @@ -1,21 +1,17 @@ use std::env; -use zksync_config::{ - configs::{ - da_client::{ - avail::{ - AvailClientConfig, AvailSecrets, AVAIL_FULL_CLIENT_NAME, - AVAIL_GAS_RELAY_CLIENT_NAME, - }, - celestia::CelestiaSecrets, - eigen::{EigenSecrets, EIGEN_DISPERSER_CLIENT_NAME, EIGEN_MEMSTORE_CLIENT_NAME}, - DAClientConfig, AVAIL_CLIENT_CONFIG_NAME, CELESTIA_CLIENT_CONFIG_NAME, - EIGEN_CLIENT_CONFIG_NAME, OBJECT_STORE_CLIENT_CONFIG_NAME, +use zksync_config::configs::{ + da_client::{ + avail::{ + AvailClientConfig, AvailSecrets, AVAIL_FULL_CLIENT_NAME, AVAIL_GAS_RELAY_CLIENT_NAME, }, - secrets::DataAvailabilitySecrets, - AvailConfig, + celestia::CelestiaSecrets, + eigen::EigenSecrets, + DAClientConfig, AVAIL_CLIENT_CONFIG_NAME, CELESTIA_CLIENT_CONFIG_NAME, + EIGEN_CLIENT_CONFIG_NAME, OBJECT_STORE_CLIENT_CONFIG_NAME, }, - EigenConfig, + secrets::DataAvailabilitySecrets, + AvailConfig, }; use crate::{envy_load, FromEnv}; @@ -38,17 +34,7 @@ impl FromEnv for DAClientConfig { }, }), CELESTIA_CLIENT_CONFIG_NAME => Self::Celestia(envy_load("da_celestia_config", "DA_")?), - EIGEN_CLIENT_CONFIG_NAME => match env::var("DA_EIGEN_CLIENT_TYPE")?.as_str() { - EIGEN_DISPERSER_CLIENT_NAME => Self::Eigen(EigenConfig::Disperser(envy_load( - "da_eigen_config_disperser", - "DA_", - )?)), - EIGEN_MEMSTORE_CLIENT_NAME => Self::Eigen(EigenConfig::MemStore(envy_load( - "da_eigen_config_memstore", - "DA_", - )?)), - _ => anyhow::bail!("Unknown Eigen DA client type"), - }, + EIGEN_CLIENT_CONFIG_NAME => Self::Eigen(envy_load("da_eigen_config", "DA_")?), OBJECT_STORE_CLIENT_CONFIG_NAME => { Self::ObjectStore(envy_load("da_object_store", "DA_")?) } @@ -108,7 +94,6 @@ mod tests { configs::{ da_client::{ avail::{AvailClientConfig, AvailDefaultConfig}, - eigen::{DisperserConfig, MemStoreConfig}, DAClientConfig::{self, ObjectStore}, }, object_store::ObjectStoreMode::GCS, @@ -259,32 +244,7 @@ mod tests { } #[test] - fn from_env_eigen_client_memstore() { - let mut lock = MUTEX.lock(); - let config = r#" - DA_CLIENT="Eigen" - DA_EIGEN_CLIENT_TYPE="MemStore" - DA_MAX_BLOB_SIZE_BYTES=10 - DA_BLOB_EXPIRATION=20 - DA_GET_LATENCY=30 - DA_PUT_LATENCY=40 - "#; - lock.set_env(config); - - let actual = DAClientConfig::from_env().unwrap(); - assert_eq!( - actual, - DAClientConfig::Eigen(EigenConfig::MemStore(MemStoreConfig { - max_blob_size_bytes: 10, - blob_expiration: 20, - get_latency: 30, - put_latency: 40, - })) - ); - } - - #[test] - fn from_env_eigen_client_remote() { + fn from_env_eigen_client() { let mut lock = MUTEX.lock(); let config = r#" DA_CLIENT="Eigen" @@ -306,7 +266,7 @@ mod tests { let actual = DAClientConfig::from_env().unwrap(); assert_eq!( actual, - DAClientConfig::Eigen(EigenConfig::Disperser(DisperserConfig { + DAClientConfig::Eigen(EigenConfig { disperser_rpc: "http://localhost:8080".to_string(), eth_confirmation_depth: 0, eigenda_eth_rpc: "http://localhost:8545".to_string(), @@ -318,7 +278,7 @@ mod tests { authenticated: false, verify_cert: false, path_to_points: "resources".to_string(), - })) + }) ); } diff --git a/core/lib/protobuf_config/src/da_client.rs b/core/lib/protobuf_config/src/da_client.rs index 1ae882198cd3..02fb386d3762 100644 --- a/core/lib/protobuf_config/src/da_client.rs +++ b/core/lib/protobuf_config/src/da_client.rs @@ -4,7 +4,7 @@ use zksync_config::configs::{ da_client::{ avail::{AvailClientConfig, AvailConfig, AvailDefaultConfig, AvailGasRelayConfig}, celestia::CelestiaConfig, - eigen::{DisperserConfig, EigenConfig, MemStoreConfig}, + eigen::EigenConfig, DAClientConfig::{Avail, Celestia, Eigen, ObjectStore}, }, }; @@ -52,53 +52,31 @@ impl ProtoRepr for proto::DataAvailabilityClient { chain_id: required(&conf.chain_id).context("chain_id")?.clone(), timeout_ms: *required(&conf.timeout_ms).context("timeout_ms")?, }), - proto::data_availability_client::Config::Eigen(conf) => { - let config = required(&conf.config).context("config")?; - let eigen_config = match config { - proto::eigen_config::Config::MemStore(conf) => { - EigenConfig::MemStore(MemStoreConfig { - max_blob_size_bytes: *required(&conf.max_blob_size_bytes) - .context("max_blob_size_bytes")?, - blob_expiration: *required(&conf.blob_expiration) - .context("blob_expiration")?, - get_latency: *required(&conf.get_latency).context("get_latency")?, - put_latency: *required(&conf.put_latency).context("put_latency")?, - }) - } - proto::eigen_config::Config::Disperser(conf) => { - EigenConfig::Disperser(DisperserConfig { - disperser_rpc: required(&conf.disperser_rpc) - .context("disperser_rpc")? - .clone(), - eth_confirmation_depth: *required(&conf.eth_confirmation_depth) - .context("eth_confirmation_depth")?, - eigenda_eth_rpc: required(&conf.eigenda_eth_rpc) - .context("eigenda_eth_rpc")? - .clone(), - eigenda_svc_manager_address: required( - &conf.eigenda_svc_manager_address, - ) - .context("eigenda_svc_manager_address")? - .clone(), - blob_size_limit: *required(&conf.blob_size_limit) - .context("blob_size_limit")?, - status_query_timeout: *required(&conf.status_query_timeout) - .context("status_query_timeout")?, - status_query_interval: *required(&conf.status_query_interval) - .context("status_query_interval")?, - wait_for_finalization: *required(&conf.wait_for_finalization) - .context("wait_for_finalization")?, - authenticated: *required(&conf.authenticated) - .context("authenticated")?, - verify_cert: *required(&conf.verify_cert).context("verify_cert")?, - path_to_points: required(&conf.path_to_points) - .context("path_to_points")? - .clone(), - }) - } - }; - Eigen(eigen_config) - } + proto::data_availability_client::Config::Eigen(conf) => Eigen(EigenConfig { + disperser_rpc: required(&conf.disperser_rpc) + .context("disperser_rpc")? + .clone(), + eth_confirmation_depth: *required(&conf.eth_confirmation_depth) + .context("eth_confirmation_depth")?, + eigenda_eth_rpc: required(&conf.eigenda_eth_rpc) + .context("eigenda_eth_rpc")? + .clone(), + eigenda_svc_manager_address: required(&conf.eigenda_svc_manager_address) + .context("eigenda_svc_manager_address")? + .clone(), + blob_size_limit: *required(&conf.blob_size_limit).context("blob_size_limit")?, + status_query_timeout: *required(&conf.status_query_timeout) + .context("status_query_timeout")?, + status_query_interval: *required(&conf.status_query_interval) + .context("status_query_interval")?, + wait_for_finalization: *required(&conf.wait_for_finalization) + .context("wait_for_finalization")?, + authenticated: *required(&conf.authenticated).context("authenticated")?, + verify_cert: *required(&conf.verify_cert).context("verify_cert")?, + path_to_points: required(&conf.path_to_points) + .context("path_to_points")? + .clone(), + }), proto::data_availability_client::Config::ObjectStore(conf) => { ObjectStore(object_store_proto::ObjectStore::read(conf)?) } @@ -135,41 +113,19 @@ impl ProtoRepr for proto::DataAvailabilityClient { timeout_ms: Some(config.timeout_ms), }) } - Eigen(config) => match config { - EigenConfig::MemStore(config) => { - proto::data_availability_client::Config::Eigen(proto::EigenConfig { - config: Some(proto::eigen_config::Config::MemStore( - proto::MemStoreConfig { - max_blob_size_bytes: Some(config.max_blob_size_bytes), - blob_expiration: Some(config.blob_expiration), - get_latency: Some(config.get_latency), - put_latency: Some(config.put_latency), - }, - )), - }) - } - EigenConfig::Disperser(config) => { - proto::data_availability_client::Config::Eigen(proto::EigenConfig { - config: Some(proto::eigen_config::Config::Disperser( - proto::DisperserConfig { - disperser_rpc: Some(config.disperser_rpc.clone()), - eth_confirmation_depth: Some(config.eth_confirmation_depth), - eigenda_eth_rpc: Some(config.eigenda_eth_rpc.clone()), - eigenda_svc_manager_address: Some( - config.eigenda_svc_manager_address.clone(), - ), - blob_size_limit: Some(config.blob_size_limit), - status_query_timeout: Some(config.status_query_timeout), - status_query_interval: Some(config.status_query_interval), - wait_for_finalization: Some(config.wait_for_finalization), - authenticated: Some(config.authenticated), - verify_cert: Some(config.verify_cert), - path_to_points: Some(config.path_to_points.clone()), - }, - )), - }) - } - }, + Eigen(config) => proto::data_availability_client::Config::Eigen(proto::EigenConfig { + disperser_rpc: Some(config.disperser_rpc.clone()), + eth_confirmation_depth: Some(config.eth_confirmation_depth), + eigenda_eth_rpc: Some(config.eigenda_eth_rpc.clone()), + eigenda_svc_manager_address: Some(config.eigenda_svc_manager_address.clone()), + blob_size_limit: Some(config.blob_size_limit), + status_query_timeout: Some(config.status_query_timeout), + status_query_interval: Some(config.status_query_interval), + wait_for_finalization: Some(config.wait_for_finalization), + authenticated: Some(config.authenticated), + verify_cert: Some(config.verify_cert), + path_to_points: Some(config.path_to_points.clone()), + }), ObjectStore(config) => proto::data_availability_client::Config::ObjectStore( object_store_proto::ObjectStore::build(config), ), diff --git a/core/lib/protobuf_config/src/proto/config/da_client.proto b/core/lib/protobuf_config/src/proto/config/da_client.proto index 2f50224df0d1..1b7ed54d06c6 100644 --- a/core/lib/protobuf_config/src/proto/config/da_client.proto +++ b/core/lib/protobuf_config/src/proto/config/da_client.proto @@ -36,14 +36,7 @@ message CelestiaConfig { optional uint64 timeout_ms = 4; } -message MemStoreConfig { - optional uint64 max_blob_size_bytes = 3; - optional uint64 blob_expiration = 4; - optional uint64 get_latency = 5; - optional uint64 put_latency = 6; -} - -message DisperserConfig { +message EigenConfig { optional string disperser_rpc = 3; optional int32 eth_confirmation_depth = 4; optional string eigenda_eth_rpc = 5; diff --git a/core/node/da_clients/Cargo.toml b/core/node/da_clients/Cargo.toml index 7283277d148a..7e9158d52f92 100644 --- a/core/node/da_clients/Cargo.toml +++ b/core/node/da_clients/Cargo.toml @@ -56,13 +56,12 @@ pbjson-types.workspace = true # Eigen dependencies tokio-stream.workspace = true rlp.workspace = true -kzgpad-rs = { git = "https://github.com/Layr-Labs/kzgpad-rs.git", tag = "v0.1.0" } rand.workspace = true sha3.workspace = true tiny-keccak.workspace = true -alloy = { version = "0.3", features = ["full"] } -ethabi = "16.0.0" -rust-kzg-bn254 = {git = "https://github.com/lambdaclass/rust-kzg-bn254", branch = "bump-ark"} -ark-bn254 = "0.5.0-alpha.0" -num-bigint = "0.4.6" -serial_test = "3.1.1" +alloy.workspace = true +ethabi.workspace = true +rust-kzg-bn254.workspace = true +ark-bn254.workspace = true +num-bigint.workspace = true +serial_test.workspace = true diff --git a/core/node/da_clients/src/eigen/client.rs b/core/node/da_clients/src/eigen/client.rs index 44ca7355ad47..7a463cd17f86 100644 --- a/core/node/da_clients/src/eigen/client.rs +++ b/core/node/da_clients/src/eigen/client.rs @@ -10,7 +10,7 @@ use zksync_da_client::{ DataAvailabilityClient, }; -use super::{blob_info::BlobInfo, memstore::MemStore, sdk::RawEigenClient, Disperser}; +use super::{blob_info::BlobInfo, sdk::RawEigenClient}; use crate::utils::to_non_retriable_da_error; /// EigenClient is a client for the Eigen DA service. @@ -19,7 +19,7 @@ use crate::utils::to_non_retriable_da_error; /// - Memstore: Stores blobs in memory, used for testing purposes. #[derive(Debug, Clone)] pub struct EigenClient { - client: Disperser, + client: Arc, } impl EigenClient { @@ -27,14 +27,10 @@ impl EigenClient { let private_key = SecretKey::from_str(secrets.private_key.0.expose_secret().as_str()) .map_err(|e| anyhow::anyhow!("Failed to parse private key: {}", e))?; - let disperser: Disperser = match config.clone() { - EigenConfig::Disperser(config) => { - let client = RawEigenClient::new(private_key, config).await?; - Disperser::Remote(Arc::new(client)) - } - EigenConfig::MemStore(config) => Disperser::Memory(MemStore::new(config)), - }; - Ok(Self { client: disperser }) + let client = RawEigenClient::new(private_key, config).await?; + Ok(Self { + client: Arc::new(client), + }) } } @@ -54,17 +50,11 @@ impl DataAvailabilityClient for EigenClient { } } - let blob_id = match &self.client { - Disperser::Remote(remote_disperser) => remote_disperser - .dispatch_blob(data) - .await - .map_err(to_non_retriable_da_error)?, - Disperser::Memory(memstore) => memstore - .clone() - .put_blob(data) - .await - .map_err(to_non_retriable_da_error)?, - }; + let blob_id = self + .client + .dispatch_blob(data) + .await + .map_err(to_non_retriable_da_error)?; Ok(DispatchResponse::from(blob_id)) } @@ -89,28 +79,19 @@ impl DataAvailabilityClient for EigenClient { } fn blob_size_limit(&self) -> Option { - match self.client.clone() { - Disperser::Memory(mem_store) => Some(mem_store.config.max_blob_size_bytes as usize), - Disperser::Remote(raw_eigen_client) => { - Some(raw_eigen_client.config.blob_size_limit as usize) - } - } + Some(self.client.clone().config.blob_size_limit as usize) } } #[cfg(test)] impl EigenClient { pub async fn get_blob_data(&self, blob_id: &str) -> anyhow::Result>, DAError> { - match &self.client { - Disperser::Remote(remote_client) => remote_client.get_blob_data(blob_id).await, - Disperser::Memory(memstore) => memstore.clone().get_blob_data(blob_id).await, - } + self.client.get_blob_data(blob_id).await } } #[cfg(test)] mod tests { use serial_test::serial; - use zksync_config::configs::da_client::eigen::{DisperserConfig, MemStoreConfig}; use zksync_types::secrets::PrivateKey; use super::*; @@ -119,7 +100,7 @@ mod tests { #[tokio::test] #[serial] async fn test_non_auth_dispersal() { - let config = EigenConfig::Disperser(DisperserConfig { + let config = EigenConfig { disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), eth_confirmation_depth: -1, eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), @@ -131,7 +112,7 @@ mod tests { authenticated: false, verify_cert: true, path_to_points: "../../../resources".to_string(), - }); + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", @@ -158,7 +139,7 @@ mod tests { #[tokio::test] #[serial] async fn test_auth_dispersal() { - let config = EigenConfig::Disperser(DisperserConfig { + let config = EigenConfig { disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), eth_confirmation_depth: -1, eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), @@ -170,7 +151,7 @@ mod tests { authenticated: true, verify_cert: true, path_to_points: "../../../resources".to_string(), - }); + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", @@ -194,42 +175,10 @@ mod tests { assert_eq!(retrieved_data.unwrap(), data); } - #[tokio::test] - async fn test_eigenda_memory_disperser() { - let config = EigenConfig::MemStore(MemStoreConfig { - max_blob_size_bytes: 2 * 1024 * 1024, // 2MB, - blob_expiration: 60 * 2, - get_latency: 0, - put_latency: 0, - }); - let secrets = EigenSecrets { - private_key: PrivateKey::from_str( - "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", - ) - .unwrap(), - }; - let client = EigenClient::new(config, secrets).await.unwrap(); - let data = vec![1u8; 100]; - let result = client.dispatch_blob(0, data.clone()).await.unwrap(); - - let blob_info: BlobInfo = - rlp::decode(&hex::decode(result.blob_id.clone()).unwrap()).unwrap(); - let expected_inclusion_data = blob_info.blob_verification_proof.inclusion_proof; - let actual_inclusion_data = client - .get_inclusion_data(&result.blob_id) - .await - .unwrap() - .unwrap() - .data; - assert_eq!(expected_inclusion_data, actual_inclusion_data); - - let retrieved_data = client.get_blob_data(&result.blob_id).await.unwrap(); - assert_eq!(retrieved_data.unwrap(), data); - } #[tokio::test] #[serial] async fn test_wait_for_finalization() { - let config = EigenConfig::Disperser(DisperserConfig { + let config = EigenConfig { disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), blob_size_limit: 2 * 1024 * 1024, // 2MB status_query_timeout: 1800000, // 30 minutes @@ -241,7 +190,7 @@ mod tests { eth_confirmation_depth: 0, eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), eigenda_svc_manager_address: "0xD4A7E1Bd8015057293f0D0A557088c286942e84b".to_string(), - }); + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", @@ -267,12 +216,19 @@ mod tests { #[tokio::test] async fn test_eigenda_dispatch_blob_too_large() { - let config = EigenConfig::MemStore(MemStoreConfig { - max_blob_size_bytes: 99, - blob_expiration: 60 * 2, - get_latency: 0, - put_latency: 0, - }); + let config = EigenConfig { + disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), + blob_size_limit: 99, + status_query_timeout: 1800000, // 30 minutes + status_query_interval: 5000, // 5000 ms + wait_for_finalization: true, + authenticated: true, + verify_cert: true, + path_to_points: "../../../resources".to_string(), + eth_confirmation_depth: 0, + eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), + eigenda_svc_manager_address: "0xD4A7E1Bd8015057293f0D0A557088c286942e84b".to_string(), + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", @@ -294,7 +250,7 @@ mod tests { #[tokio::test] #[serial] async fn test_eth_confirmation_depth() { - let config = EigenConfig::Disperser(DisperserConfig { + let config = EigenConfig { disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), eth_confirmation_depth: 5, eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), @@ -306,7 +262,7 @@ mod tests { authenticated: false, verify_cert: true, path_to_points: "../../../resources".to_string(), - }); + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", @@ -333,7 +289,7 @@ mod tests { #[tokio::test] #[serial] async fn test_auth_dispersal_eth_confirmation_depth() { - let config = EigenConfig::Disperser(DisperserConfig { + let config = EigenConfig { disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(), eth_confirmation_depth: 5, eigenda_eth_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), @@ -345,7 +301,7 @@ mod tests { authenticated: true, verify_cert: true, path_to_points: "../../../resources".to_string(), - }); + }; let secrets = EigenSecrets { private_key: PrivateKey::from_str( "d08aa7ae1bb5ddd46c3c2d8cdb5894ab9f54dec467233686ca42629e826ac4c6", diff --git a/core/node/da_clients/src/eigen/eigenda-integration.md b/core/node/da_clients/src/eigen/eigenda-integration.md index ff3957af7251..71de73482bb3 100644 --- a/core/node/da_clients/src/eigen/eigenda-integration.md +++ b/core/node/da_clients/src/eigen/eigenda-integration.md @@ -17,35 +17,20 @@ Changes needed both for local and mainnet/testnet setup. 1. Add `da_client` to `etc/env/file_based/general.yaml`: -If you want to use memstore: - -```yaml -da_client: - eigen: - mem_store: - max_blob_size_bytes: 2097152 - blob_expiration: 100000 - get_latency: 100 - put_latency: 100 -``` - -If you want to use disperser: - ```yaml da_client: eigen: - disperser: - disperser_rpc: - eth_confirmation_depth: -1 - eigenda_eth_rpc: - eigenda_svc_manager_address: '0xD4A7E1Bd8015057293f0D0A557088c286942e84b' - blob_size_limit: 2097152 - status_query_timeout: 1800000 # ms - status_query_interval: 5 # ms - wait_for_finalization: false - authenticated: false - verify_cert: true - path_to_points: ./resources + disperser_rpc: + eth_confirmation_depth: -1 + eigenda_eth_rpc: + eigenda_svc_manager_address: '0xD4A7E1Bd8015057293f0D0A557088c286942e84b' + blob_size_limit: 2097152 + status_query_timeout: 1800000 # ms + status_query_interval: 5 # ms + wait_for_finalization: false + authenticated: false + verify_cert: true + path_to_points: ./resources ``` Also set the private key in `etc/env/file_based/secrets.yaml`: diff --git a/core/node/da_clients/src/eigen/memstore.rs b/core/node/da_clients/src/eigen/memstore.rs deleted file mode 100644 index 8a10137a2b93..000000000000 --- a/core/node/da_clients/src/eigen/memstore.rs +++ /dev/null @@ -1,221 +0,0 @@ -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, - time::{Duration, Instant}, -}; - -use anyhow::Error; -use rand::{rngs::OsRng, Rng, RngCore}; -use sha3::{Digest, Keccak256}; -use tokio::time::interval; -use zksync_config::configs::da_client::eigen::MemStoreConfig; -use zksync_da_client::types::{DAError, InclusionData}; - -use super::blob_info::{self, BlobInfo}; - -#[derive(Debug, PartialEq)] -pub enum MemStoreError { - BlobToLarge, - BlobAlreadyExists, - IncorrectCommitment, - #[cfg(test)] - BlobNotFound, -} - -impl From for Error { - fn from(val: MemStoreError) -> Self { - match val { - MemStoreError::BlobToLarge => Error::msg("Blob too large"), - MemStoreError::BlobAlreadyExists => Error::msg("Blob already exists"), - MemStoreError::IncorrectCommitment => Error::msg("Incorrect commitment"), - #[cfg(test)] - MemStoreError::BlobNotFound => Error::msg("Blob not found"), - } - } -} - -#[derive(Debug)] -struct MemStoreData { - store: HashMap>, - key_starts: HashMap, -} - -/// This struct represents a memory store for blobs. -/// It should be used for testing purposes only. -#[derive(Clone, Debug)] -pub struct MemStore { - pub config: MemStoreConfig, - data: Arc>, -} - -impl MemStore { - pub fn new(config: MemStoreConfig) -> Arc { - let memstore = Arc::new(Self { - config, - data: Arc::new(RwLock::new(MemStoreData { - store: HashMap::new(), - key_starts: HashMap::new(), - })), - }); - let store_clone = Arc::clone(&memstore); - tokio::spawn(async move { - store_clone.pruning_loop().await; - }); - memstore - } - - /// Saves a blob to the memory store, it harcodes the blob info, since we don't care about it in a memory based store - pub async fn put_blob(self: Arc, value: Vec) -> Result { - tokio::time::sleep(Duration::from_millis(self.config.put_latency)).await; - if value.len() as u64 > self.config.max_blob_size_bytes { - return Err(MemStoreError::BlobToLarge); - } - - let mut entropy = [0u8; 10]; - OsRng.fill_bytes(&mut entropy); - - let mut hasher = Keccak256::new(); - hasher.update(entropy); - let mock_batch_root = hasher.finalize().to_vec(); - - let block_num = OsRng.gen_range(0u32..1000); - - let blob_info = blob_info::BlobInfo { - blob_header: blob_info::BlobHeader { - commitment: blob_info::G1Commitment { - // todo: generate real commitment - x: vec![0u8; 32], - y: vec![0u8; 32], - }, - data_length: value.len() as u32, - blob_quorum_params: vec![blob_info::BlobQuorumParam { - quorum_number: 1, - adversary_threshold_percentage: 29, - confirmation_threshold_percentage: 30, - chunk_length: 300, - }], - }, - blob_verification_proof: blob_info::BlobVerificationProof { - batch_medatada: blob_info::BatchMetadata { - batch_header: blob_info::BatchHeader { - batch_root: mock_batch_root.clone(), - quorum_numbers: vec![0x1, 0x0], - quorum_signed_percentages: vec![0x60, 0x90], - reference_block_number: block_num, - }, - signatory_record_hash: mock_batch_root, - fee: vec![], - confirmation_block_number: block_num, - batch_header_hash: vec![], - }, - batch_id: 69, - blob_index: 420, - inclusion_proof: entropy.to_vec(), - quorum_indexes: vec![0x1, 0x0], - }, - }; - - let cert_bytes = rlp::encode(&blob_info).to_vec(); - - let key = String::from_utf8_lossy( - blob_info - .blob_verification_proof - .inclusion_proof - .clone() - .as_slice(), - ) - .to_string(); - - let mut data = self.data.write().unwrap(); - - if data.store.contains_key(key.as_str()) { - return Err(MemStoreError::BlobAlreadyExists); - } - - data.key_starts.insert(key.clone(), Instant::now()); - data.store.insert(key, value); - Ok(hex::encode(cert_bytes)) - } - - /// It returns the inclusion proof - pub async fn get_inclusion_data( - self: Arc, - blob_id: &str, - ) -> anyhow::Result, DAError> { - let rlp_encoded_bytes = hex::decode(blob_id).map_err(|_| DAError { - error: MemStoreError::IncorrectCommitment.into(), - is_retriable: false, - })?; - let blob_info: BlobInfo = rlp::decode(&rlp_encoded_bytes).map_err(|_| DAError { - error: MemStoreError::IncorrectCommitment.into(), - is_retriable: false, - })?; - let inclusion_data = blob_info.blob_verification_proof.inclusion_proof; - Ok(Some(InclusionData { - data: inclusion_data, - })) - } - - /// This function is only used on tests, it returns the blob data - #[cfg(test)] - pub async fn get_blob_data( - self: Arc, - blob_id: &str, - ) -> anyhow::Result>, DAError> { - tokio::time::sleep(Duration::from_millis(self.config.get_latency)).await; - let request_id = hex::decode(blob_id).map_err(|_| DAError { - error: MemStoreError::IncorrectCommitment.into(), - is_retriable: false, - })?; - let blob_info: BlobInfo = rlp::decode(&request_id).map_err(|_| DAError { - error: MemStoreError::IncorrectCommitment.into(), - is_retriable: false, - })?; - let key = String::from_utf8_lossy( - blob_info - .blob_verification_proof - .inclusion_proof - .clone() - .as_slice(), - ) - .to_string(); - - let data = self.data.read().map_err(|_| DAError { - error: MemStoreError::BlobNotFound.into(), - is_retriable: false, - })?; - match data.store.get(&key) { - Some(value) => Ok(Some(value.clone())), - None => Err(DAError { - error: MemStoreError::BlobNotFound.into(), - is_retriable: false, - }), - } - } - - /// After some time has passed, blobs are removed from the store - async fn prune_expired(self: Arc) { - let mut data = self.data.write().unwrap(); - let mut to_remove = vec![]; - for (key, start) in data.key_starts.iter() { - if start.elapsed() > Duration::from_secs(self.config.blob_expiration) { - to_remove.push(key.clone()); - } - } - for key in to_remove { - data.store.remove(&key); - data.key_starts.remove(&key); - } - } - - /// Loop used to prune expired blobs - async fn pruning_loop(self: Arc) { - let mut interval = interval(Duration::from_secs(self.config.blob_expiration)); - - loop { - interval.tick().await; - let self_clone = Arc::clone(&self); - self_clone.prune_expired().await; - } - } -} diff --git a/core/node/da_clients/src/eigen/mod.rs b/core/node/da_clients/src/eigen/mod.rs index 02ec82a70815..9446194f48c7 100644 --- a/core/node/da_clients/src/eigen/mod.rs +++ b/core/node/da_clients/src/eigen/mod.rs @@ -1,15 +1,9 @@ mod blob_info; mod client; mod generated; -mod memstore; mod sdk; mod verifier; -use std::sync::Arc; - -use memstore::MemStore; -use sdk::RawEigenClient; - pub use self::client::EigenClient; #[allow(clippy::all)] @@ -21,9 +15,3 @@ pub(crate) mod disperser { pub(crate) mod common { include!("generated/common.rs"); } - -#[derive(Clone, Debug)] -pub(crate) enum Disperser { - Remote(Arc), - Memory(Arc), -} diff --git a/core/node/da_clients/src/eigen/sdk.rs b/core/node/da_clients/src/eigen/sdk.rs index b7ae37260ff3..d4ea5ada846b 100644 --- a/core/node/da_clients/src/eigen/sdk.rs +++ b/core/node/da_clients/src/eigen/sdk.rs @@ -1,5 +1,6 @@ use std::{str::FromStr, time::Duration}; +use backon::{ConstantBuilder, Retryable}; use secp256k1::{ecdsa::RecoverableSignature, SecretKey}; use tokio::{sync::mpsc, time::Instant}; use tokio_stream::{wrappers::ReceiverStream, StreamExt}; @@ -7,7 +8,7 @@ use tonic::{ transport::{Channel, ClientTlsConfig, Endpoint}, Streaming, }; -use zksync_config::configs::da_client::eigen::DisperserConfig; +use zksync_config::EigenConfig; #[cfg(test)] use zksync_da_client::types::DAError; @@ -30,16 +31,17 @@ use crate::eigen::{ pub(crate) struct RawEigenClient { client: DisperserClient, private_key: SecretKey, - pub config: DisperserConfig, + pub config: EigenConfig, verifier: Verifier, } pub(crate) const DATA_CHUNK_SIZE: usize = 32; +pub(crate) const AVG_BLOCK_TIME: u64 = 12; impl RawEigenClient { pub(crate) const BUFFER_SIZE: usize = 1000; - pub async fn new(private_key: SecretKey, config: DisperserConfig) -> anyhow::Result { + pub async fn new(private_key: SecretKey, config: EigenConfig) -> anyhow::Result { let endpoint = Endpoint::from_str(config.disperser_rpc.as_str())?.tls_config(ClientTlsConfig::new())?; let client = DisperserClient::connect(endpoint) @@ -104,17 +106,18 @@ impl RawEigenClient { blob_info: BlobInfo, disperse_elapsed: Duration, ) -> anyhow::Result<()> { - let start = Instant::now(); - while Instant::now() - start - < (Duration::from_millis(self.config.status_query_timeout) - disperse_elapsed) - { - tokio::time::sleep(Duration::from_secs(12)).await; // avg block time - match self.verifier.verify_certificate(blob_info.clone()).await { - Ok(_) => return Ok(()), - Err(_) => continue, - } - } - Err(anyhow::anyhow!("Failed to validate certificate")) + (|| async { self.verifier.verify_certificate(blob_info.clone()).await }) + .retry( + &ConstantBuilder::default() + .with_delay(Duration::from_secs(AVG_BLOCK_TIME)) + .with_max_times( + (self.config.status_query_timeout + - disperse_elapsed.as_millis() as u64 / AVG_BLOCK_TIME) + as usize, + ), + ) + .await + .map_err(|_| anyhow::anyhow!("Failed to verify certificate")) } async fn dispatch_blob_authenticated(&self, data: Vec) -> anyhow::Result { @@ -177,9 +180,10 @@ impl RawEigenClient { } pub async fn dispatch_blob(&self, data: Vec) -> anyhow::Result { - match self.config.authenticated { - true => self.dispatch_blob_authenticated(data).await, - false => self.dispatch_blob_non_authenticated(data).await, + if self.config.authenticated { + self.dispatch_blob_authenticated(data).await + } else { + self.dispatch_blob_non_authenticated(data).await } } @@ -258,24 +262,24 @@ impl RawEigenClient { async fn await_for_inclusion( &self, - mut client: DisperserClient, + client: DisperserClient, disperse_blob_reply: DisperseBlobReply, ) -> anyhow::Result { let polling_request = disperser::BlobStatusRequest { request_id: disperse_blob_reply.request_id, }; - let start_time = Instant::now(); - while Instant::now() - start_time < Duration::from_millis(self.config.status_query_timeout) - { - tokio::time::sleep(Duration::from_millis(self.config.status_query_interval)).await; - let resp = client + let blob_info = (|| async { + let mut client_clone = client.clone(); + let resp = client_clone .get_blob_status(polling_request.clone()) .await? .into_inner(); match disperser::BlobStatus::try_from(resp.status)? { - disperser::BlobStatus::Processing | disperser::BlobStatus::Dispersing => {} + disperser::BlobStatus::Processing | disperser::BlobStatus::Dispersing => { + return Err(anyhow::anyhow!("Blob is still processing")) + } disperser::BlobStatus::Failed => { return Err(anyhow::anyhow!("Blob dispatch failed")) } @@ -289,6 +293,7 @@ impl RawEigenClient { .ok_or_else(|| anyhow::anyhow!("No blob header in response"))?; return Ok(blob_info); } + return Err(anyhow::anyhow!("Blob is still processing")); } disperser::BlobStatus::Finalized => { let blob_info = resp @@ -299,9 +304,18 @@ impl RawEigenClient { _ => return Err(anyhow::anyhow!("Received unknown blob status")), } - } - - Err(anyhow::anyhow!("Failed to disperse blob (timeout)")) + }) + .retry( + &ConstantBuilder::default() + .with_delay(Duration::from_millis(self.config.status_query_interval)) + .with_max_times( + (self.config.status_query_timeout / self.config.status_query_interval) as usize, + ), + ) + .when(|e| e.to_string().contains("Blob is still processing")) + .await?; + + return Ok(blob_info); } #[cfg(test)] @@ -344,8 +358,8 @@ impl RawEigenClient { is_retriable: false, }); } - //TODO: remove zkgpad_rs - let data = kzgpad_rs::remove_empty_byte_from_padded_bytes(&get_response.data); + + let data = remove_empty_byte_from_padded_bytes(&get_response.data); Ok(Some(data)) } } @@ -383,3 +397,56 @@ fn convert_by_padding_empty_byte(data: &[u8]) -> Vec { valid_data.truncate(valid_end); valid_data } + +#[cfg(test)] +fn remove_empty_byte_from_padded_bytes(data: &[u8]) -> Vec { + let parse_size = DATA_CHUNK_SIZE; + + // Calculate the number of chunks + let data_len = (data.len() + parse_size - 1) / parse_size; + + // Pre-allocate `valid_data` with enough space for all chunks + let mut valid_data = vec![0u8; data_len * (DATA_CHUNK_SIZE - 1)]; + let mut valid_end = data_len * (DATA_CHUNK_SIZE - 1); + + for (i, chunk) in data.chunks(parse_size).enumerate() { + let offset = i * (DATA_CHUNK_SIZE - 1); + + let copy_end = offset + chunk.len() - 1; + valid_data[offset..copy_end].copy_from_slice(&chunk[1..]); + + if i == data_len - 1 && chunk.len() < parse_size { + valid_end = offset + chunk.len() - 1; + } + } + + valid_data.truncate(valid_end); + valid_data +} + +#[cfg(test)] +mod test { + #[test] + fn test_pad_and_unpad() { + let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let padded_data = super::convert_by_padding_empty_byte(&data); + let unpadded_data = super::remove_empty_byte_from_padded_bytes(&padded_data); + assert_eq!(data, unpadded_data); + } + + #[test] + fn test_pad_and_unpad_large() { + let data = vec![1; 1000]; + let padded_data = super::convert_by_padding_empty_byte(&data); + let unpadded_data = super::remove_empty_byte_from_padded_bytes(&padded_data); + assert_eq!(data, unpadded_data); + } + + #[test] + fn test_pad_and_unpad_empty() { + let data = Vec::new(); + let padded_data = super::convert_by_padding_empty_byte(&data); + let unpadded_data = super::remove_empty_byte_from_padded_bytes(&padded_data); + assert_eq!(data, unpadded_data); + } +} diff --git a/core/node/da_clients/src/eigen/verifier.rs b/core/node/da_clients/src/eigen/verifier.rs index 9e70689ad1dc..57b6700827cf 100644 --- a/core/node/da_clients/src/eigen/verifier.rs +++ b/core/node/da_clients/src/eigen/verifier.rs @@ -14,6 +14,11 @@ use super::{ generated::eigendaservicemanager::EigenDAServiceManager, }; +type EigenDAServiceManagerContract = EigenDAServiceManager::EigenDAServiceManagerInstance< + alloy::transports::http::Http, + RootProvider>, +>; + #[derive(Debug)] pub enum VerificationError { ServiceManagerError, @@ -47,10 +52,7 @@ pub struct VerifierConfig { #[derive(Debug, Clone)] pub struct Verifier { kzg: Kzg, - eigenda_svc_manager: EigenDAServiceManager::EigenDAServiceManagerInstance< - alloy::transports::http::Http, - RootProvider>, - >, + eigenda_svc_manager: EigenDAServiceManagerContract, cfg: VerifierConfig, }