From bfb6d370f9b1d52182ea54b03ec65dc66f301a6c Mon Sep 17 00:00:00 2001 From: owen Date: Fri, 11 Sep 2026 13:00:50 +0100 Subject: [PATCH] bumping ethrex to v26 --- Cargo.lock | 180 ++++++++++++++++++---- Cargo.toml | 20 +-- crates/builder/src/cli.rs | 5 +- crates/builder/src/node.rs | 37 +++-- crates/builder/src/testing.rs | 2 +- crates/builder/src/validation/tests.rs | 4 +- crates/vendored/ethrex-crypto/Cargo.toml | 2 +- crates/vendored/ethrex-crypto/VENDORED.md | 2 +- crates/vendored/ethrex-crypto/kzg.rs | 87 +++++++++++ crates/vendored/ethrex-crypto/provider.rs | 36 +++++ 10 files changed, 309 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29058e855..21fbe9308 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2446,7 +2446,7 @@ dependencies = [ "bitflags 2.13.1", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.10.5", "proc-macro2", "quote", "regex", @@ -5117,18 +5117,21 @@ dependencies = [ [[package]] name = "ethrex-blockchain" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "bytes", "crossbeam", "ethrex-common", "ethrex-crypto", + "ethrex-guest-program", "ethrex-metrics", "ethrex-rlp", "ethrex-storage", "ethrex-trie", "ethrex-vm", + "libssz", + "libssz-merkle", "rayon", "rustc-hash", "thiserror 2.0.20", @@ -5139,8 +5142,8 @@ dependencies = [ [[package]] name = "ethrex-common" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "bytes", "crc32fast", @@ -5154,9 +5157,12 @@ dependencies = [ "indexmap 2.14.0", "lazy_static", "libc", + "libssz", + "libssz-derive", + "libssz-merkle", + "libssz-types", "lru 0.16.4", "once_cell", - "rayon", "rkyv", "rustc-hash", "secp256k1 0.30.0", @@ -5169,8 +5175,8 @@ dependencies = [ [[package]] name = "ethrex-config" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "ethrex-common", "ethrex-p2p", @@ -5181,7 +5187,7 @@ dependencies = [ [[package]] name = "ethrex-crypto" -version = "20.0.0" +version = "26.0.0" dependencies = [ "ark-bn254", "ark-ec", @@ -5202,18 +5208,59 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "ethrex-guest-program" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" +dependencies = [ + "bytes", + "ethereum-types 0.15.1", + "ethrex-common", + "ethrex-crypto", + "ethrex-l2-common", + "ethrex-rlp", + "ethrex-vm", + "hex", + "libssz", + "libssz-derive", + "libssz-merkle", + "libssz-types", + "rkyv", + "serde", + "serde_with 3.22.0", + "thiserror 2.0.20", +] + +[[package]] +name = "ethrex-l2-common" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" +dependencies = [ + "bytes", + "ethereum-types 0.15.1", + "ethrex-common", + "ethrex-crypto", + "k256", + "lambdaworks-crypto", + "rkyv", + "serde", + "serde_with 3.22.0", + "thiserror 2.0.20", + "tracing", +] + [[package]] name = "ethrex-levm" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "bytes", "derive_more 1.0.0", "ethrex-common", "ethrex-crypto", "ethrex-rlp", + "libssz", "malachite", - "rayon", "rustc-hash", "serde", "strum 0.27.2", @@ -5222,8 +5269,8 @@ dependencies = [ [[package]] name = "ethrex-metrics" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "axum 0.8.9", "ethrex-common", @@ -5238,8 +5285,8 @@ dependencies = [ [[package]] name = "ethrex-p2p" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "aes", "aes-gcm", @@ -5282,8 +5329,8 @@ dependencies = [ [[package]] name = "ethrex-rlp" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "bytes", "ethereum-types 0.15.1", @@ -5292,8 +5339,8 @@ dependencies = [ [[package]] name = "ethrex-rpc" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "axum 0.8.9", "axum-extra", @@ -5332,8 +5379,8 @@ dependencies = [ [[package]] name = "ethrex-storage" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "anyhow", "bytes", @@ -5355,8 +5402,8 @@ dependencies = [ [[package]] name = "ethrex-trie" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "anyhow", "bytes", @@ -5364,18 +5411,19 @@ dependencies = [ "ethereum-types 0.15.1", "ethrex-crypto", "ethrex-rlp", - "lazy_static", + "hashbrown 0.15.5", "rayon", "rkyv", "rustc-hash", "serde", + "spin 0.9.9", "thiserror 2.0.20", ] [[package]] name = "ethrex-vm" -version = "20.0.0" -source = "git+https://github.com/lambdaclass/ethrex?rev=b4d5677812fdf58cb3e439c77906dda4d9b6f91a#b4d5677812fdf58cb3e439c77906dda4d9b6f91a" +version = "26.0.0" +source = "git+https://github.com/lambdaclass/ethrex?rev=ee98e879880aee80440bcd59936c384c26629814#ee98e879880aee80440bcd59936c384c26629814" dependencies = [ "bytes", "derive_more 1.0.0", @@ -5384,7 +5432,6 @@ dependencies = [ "ethrex-crypto", "ethrex-levm", "ethrex-rlp", - "rayon", "rustc-hash", "serde", "thiserror 2.0.20", @@ -8434,6 +8481,34 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "lambdaworks-crypto" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b1a1c1102a5a7fbbda117b79fb3a01e033459c738a3c1642269603484fd1c1" +dependencies = [ + "lambdaworks-math", + "rand 0.8.7", + "rand_chacha 0.3.1", + "serde", + "sha2 0.10.9", + "sha3 0.10.9", +] + +[[package]] +name = "lambdaworks-math" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "018a95aa873eb49896a858dee0d925c33f3978d073c64b08dd4f2c9b35a017c6" +dependencies = [ + "getrandom 0.2.17", + "num-bigint 0.4.8", + "num-traits", + "rand 0.8.7", + "serde", + "serde_json", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -8827,6 +8902,47 @@ dependencies = [ "zstd-sys", ] +[[package]] +name = "libssz" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4bdd6d63ed811ae164966de20810be780e07de784a4834ccfe6be90480c369e" +dependencies = [ + "smallvec", +] + +[[package]] +name = "libssz-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeee1b9ac9200429f7e9830492765445989ea61c3fb9028ad5a96e1dd5f5e913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "libssz-merkle" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863eca32d1a43e5ec41106a515552efa8307768d37c68d26b7f21ff13cfee1a7" +dependencies = [ + "libssz", + "sha2 0.10.9", +] + +[[package]] +name = "libssz-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4231ac301726840a3fe111f11bd4619d3c97ed155cb94c88dbf92b70e04e017" +dependencies = [ + "libssz", + "libssz-merkle", + "smallvec", +] + [[package]] name = "libyaml-rs" version = "0.3.0" @@ -11240,7 +11356,7 @@ checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -11260,7 +11376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.119", @@ -11273,7 +11389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.119", @@ -11286,7 +11402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.119", diff --git a/Cargo.toml b/Cargo.toml index c6d25d00f..d32c38304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,17 +46,17 @@ ethers = "2.0.14" # ethrex-crypto's `aws-lc-rs` feature, whose cc >=1.2.26 requirement conflicts with # reth-mdbx-sys's exact `cc = 1.2.15` pin (via helix-simulator). The node is # assembled from the library crates instead. -ethrex-blockchain = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", default-features = false, features = ["secp256k1", "c-kzg", "metrics"] } -ethrex-common = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", default-features = false, features = ["secp256k1", "c-kzg"] } -ethrex-config = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a" } +ethrex-blockchain = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", default-features = false, features = ["secp256k1", "c-kzg", "metrics"] } +ethrex-common = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", default-features = false, features = ["secp256k1", "c-kzg"] } +ethrex-config = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814" } # default features minus `aws-lc-rs` (see note above); P-256 verify uses the portable fallback -ethrex-crypto = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", default-features = false, features = ["std", "kzg-rs", "secp256k1", "blst", "c-kzg"] } -ethrex-metrics = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a" } -ethrex-p2p = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", features = ["c-kzg", "rocksdb", "metrics"] } -ethrex-rlp = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a" } -ethrex-rpc = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a" } -ethrex-storage = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", features = ["rocksdb"] } -ethrex-vm = { git = "https://github.com/lambdaclass/ethrex", rev = "b4d5677812fdf58cb3e439c77906dda4d9b6f91a", default-features = false, features = ["secp256k1", "c-kzg"] } +ethrex-crypto = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", default-features = false, features = ["std", "kzg-rs", "secp256k1", "blst", "c-kzg"] } +ethrex-metrics = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814" } +ethrex-p2p = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", features = ["c-kzg", "rocksdb", "metrics"] } +ethrex-rlp = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814" } +ethrex-rpc = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814" } +ethrex-storage = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", features = ["rocksdb"] } +ethrex-vm = { git = "https://github.com/lambdaclass/ethrex", rev = "ee98e879880aee80440bcd59936c384c26629814", default-features = false, features = ["secp256k1", "c-kzg"] } eyre = "0.6.12" aws-sdk-s3 = "=1.35.0" diff --git a/crates/builder/src/cli.rs b/crates/builder/src/cli.rs index 041d5398b..5f07c85f3 100644 --- a/crates/builder/src/cli.rs +++ b/crates/builder/src/cli.rs @@ -59,12 +59,11 @@ pub struct NodeOptions { #[arg( long = "rocksdb.block-cache-size", value_name = "BYTES", - default_value_t = ethrex_storage::DEFAULT_ROCKSDB_BLOCK_CACHE_SIZE_BYTES, - help = "RocksDB shared block cache size in bytes.", + help = "RocksDB shared block cache size in bytes. Defaults to a fraction of available memory.", env = "ETHREX_ROCKSDB_BLOCK_CACHE_SIZE", help_heading = "Storage options" )] - pub rocksdb_block_cache_size: usize, + pub rocksdb_block_cache_size: Option, #[arg( long = "skip-genesis-validation", action = clap::ArgAction::SetTrue, diff --git a/crates/builder/src/node.rs b/crates/builder/src/node.rs index 83e3d954e..04a1d6c32 100644 --- a/crates/builder/src/node.rs +++ b/crates/builder/src/node.rs @@ -8,7 +8,7 @@ use std::{ net::{IpAddr, Ipv4Addr}, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, RwLock}, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -20,9 +20,9 @@ use ethrex_p2p::{ network::P2PContext, peer_handler::PeerHandler, peer_table::{PeerTable, PeerTableServer, PeerTableServerProtocol as _}, - sync::SyncMode, + sync::{BackfillConfig, HistoryChain, SyncMode}, sync_manager::SyncManager, - types::{NetworkConfig, Node, NodeRecord}, + types::{LocalNode, NetworkConfig, Node, NodeRecord, SharedLocalNode}, utils::public_key_from_signing_key, }; use ethrex_storage::{EngineType, Store, StoreConfig}; @@ -54,7 +54,7 @@ pub struct NodeHandle { pub head: watch::Receiver, pub datadir: PathBuf, peer_table: PeerTable, - node_record: NodeRecord, + local_node: SharedLocalNode, } /// Boots the embedded ethrex node. Must be called from within a tokio runtime. @@ -81,10 +81,10 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { debug!("Preloading KZG trusted setup"); ethrex_crypto::kzg::warm_up_trusted_setup(); - let store_config = StoreConfig { - rocksdb_block_cache_size: opts.rocksdb_block_cache_size, - ..StoreConfig::default() - }; + let store_config = opts + .rocksdb_block_cache_size + .map(StoreConfig::with_rocksdb_block_cache_size) + .unwrap_or_default(); let engine_type = if is_memory_datadir(&datadir) { EngineType::InMemory } else { EngineType::RocksDB }; let mut store = Store::new_with_config(&datadir, engine_type, store_config)?; @@ -112,6 +112,8 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { let signer = get_signer(&datadir); let (local_p2p_node, network_config) = get_local_p2p_node(opts, &signer); let node_record = get_local_node_record(&datadir, &local_p2p_node, &signer); + let local_node: SharedLocalNode = + Arc::new(RwLock::new(LocalNode { node: local_p2p_node.clone(), record: node_record })); let peer_table = PeerTableServer::spawn(local_p2p_node.node_id(), opts.target_peers, store.clone()); @@ -143,6 +145,8 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { blockchain.clone(), store.clone(), datadir.clone(), + BackfillConfig { mode: HistoryChain::Off, tx_index_horizon: 0 }, + tracker.clone(), ) .await; @@ -161,8 +165,7 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { store.clone(), blockchain.clone(), jwt_secret, - local_p2p_node.clone(), - node_record.clone(), + local_node.clone(), syncer, peer_handler.clone(), client_version(), @@ -204,9 +207,9 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { let discovery_config = DiscoveryConfig { discv4_enabled: opts.discv4_enabled, discv5_enabled: opts.discv5_enabled, - ..Default::default() + nat_extip_set: false, }; - ethrex_p2p::start_network(p2p_context, bootnodes, discovery_config) + ethrex_p2p::start_network(p2p_context, bootnodes, discovery_config, local_node.clone()) .await .map_err(|e| eyre::eyre!("Network failed to start: {e}"))?; tracker.spawn(ethrex_p2p::periodically_show_peer_stats( @@ -226,7 +229,7 @@ pub async fn start(opts: &NodeOptions) -> eyre::Result { head, datadir, peer_table, - node_record, + local_node, }) } @@ -238,7 +241,9 @@ impl NodeHandle { self.cancel_token.cancel(); if !is_memory_datadir(&self.datadir) { - let node_config = NodeConfigFile::new(&self.peer_table, self.node_record).await; + let node_record = + self.local_node.read().unwrap_or_else(|e| e.into_inner()).record.clone(); + let node_config = NodeConfigFile::new(&self.peer_table, node_record).await; store_node_config_file(node_config, self.datadir.join(NODE_CONFIG_FILENAME)); } @@ -285,7 +290,7 @@ async fn spawn_head_watcher( } async fn read_head(store: &Store, blockchain: &Blockchain) -> eyre::Result { - let number = store.get_latest_block_number().await?; + let number = store.get_latest_block_number()?; let hash = store .get_canonical_block_hash(number) .await? @@ -298,7 +303,7 @@ async fn read_head(store: &Store, blockchain: &Blockchain) -> eyre::Result) -> eyre::Result<()> { - let head_block_number = store.get_latest_block_number().await?; + let head_block_number = store.get_latest_block_number()?; let Some(last_header) = store.get_block_header(head_block_number)? else { eyre::bail!("database is empty, genesis block should be present"); }; diff --git a/crates/builder/src/testing.rs b/crates/builder/src/testing.rs index 39fe2ed03..70e2e3b88 100644 --- a/crates/builder/src/testing.rs +++ b/crates/builder/src/testing.rs @@ -157,7 +157,7 @@ pub fn signed_blob_transfer( nonce, gas_limit: 100_000, max_fee_per_gas: 100_000_000_000, - max_priority_fee_per_gas: 0, + max_priority_fee_per_gas: 1, to, value: U256::ZERO, access_list: Default::default(), diff --git a/crates/builder/src/validation/tests.rs b/crates/builder/src/validation/tests.rs index 6bb833c28..b85f9ba04 100644 --- a/crates/builder/src/validation/tests.rs +++ b/crates/builder/src/validation/tests.rs @@ -207,7 +207,7 @@ impl Fixture { let number = block.header.number; let timestamp = block.header.timestamp; self.blockchain.add_block(block).unwrap(); - apply_fork_choice(&self.store, parent, parent, parent).await.unwrap(); + apply_fork_choice(&self.store, parent, parent, parent, None).await.unwrap(); self.head.send_replace(HeadInfo { number, hash: parent, timestamp, is_synced: true }); } parent @@ -504,7 +504,7 @@ async fn validating_a_block_does_not_store_it() { .validate(&built.payload, &message, B256::ZERO, &built.requests, &empty_bundle(), false) .expect("a block the fixture built must validate"); - assert_eq!(fixture.store.get_latest_block_number().await.unwrap(), 0); + assert_eq!(fixture.store.get_latest_block_number().unwrap(), 0); assert!( fixture.store.get_block_header_by_hash(h256(message.block_hash)).unwrap().is_none(), "the validated block must not be in the store" diff --git a/crates/vendored/ethrex-crypto/Cargo.toml b/crates/vendored/ethrex-crypto/Cargo.toml index c1f940227..8e26eba71 100644 --- a/crates/vendored/ethrex-crypto/Cargo.toml +++ b/crates/vendored/ethrex-crypto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethrex-crypto" -version = "20.0.0" +version = "26.0.0" edition = "2024" license = "MIT OR Apache-2.0" description = "Cryptographic primitives and precompile backends for the ethrex Ethereum execution client" diff --git a/crates/vendored/ethrex-crypto/VENDORED.md b/crates/vendored/ethrex-crypto/VENDORED.md index 6b978cc0f..52083f3c8 100644 --- a/crates/vendored/ethrex-crypto/VENDORED.md +++ b/crates/vendored/ethrex-crypto/VENDORED.md @@ -2,7 +2,7 @@ Copy of `crates/common/crypto` from [lambdaclass/ethrex](https://github.com/lambdaclass/ethrex) at rev -`b4d5677812fdf58cb3e439c77906dda4d9b6f91a` (MIT OR Apache-2.0), applied to the +`ee98e879880aee80440bcd59936c384c26629814` (MIT OR Apache-2.0), applied to the workspace via `[patch]` in the root `Cargo.toml`. ## Why diff --git a/crates/vendored/ethrex-crypto/kzg.rs b/crates/vendored/ethrex-crypto/kzg.rs index 263a22acd..888eed408 100644 --- a/crates/vendored/ethrex-crypto/kzg.rs +++ b/crates/vendored/ethrex-crypto/kzg.rs @@ -220,6 +220,93 @@ pub fn blob_to_kzg_commitment_and_proof(blob: &Blob) -> Result<(Commitment, Proo Ok((commitment_bytes.into_inner(), proof_bytes.into_inner())) } +/// Reconstruct a blob from its cells. +/// +/// EIP-7594 lays the original blob data in the first `CELLS_PER_EXT_BLOB / 2` +/// cells (columns 0..63); the second half is the Reed-Solomon extension. +/// Concatenating the 64 data cells reproduces the blob's field elements 1:1, +/// so a full data-column set needs no KZG recovery. Verified empirically: +/// `compute_cells(blob)[0..64]` concatenated equals `blob` and yields the same +/// commitment. +/// +/// `all_cells[col]` must hold the cell bytes for column `col`; only columns +/// 0..63 are read, so callers must ensure those are present. +pub fn cells_to_blob( + all_cells: &[[u8; BYTES_PER_CELL]; CELLS_PER_EXT_BLOB], +) -> [u8; BYTES_PER_BLOB] { + let mut blob = [0u8; BYTES_PER_BLOB]; + for col in 0..CELLS_PER_EXT_BLOB / 2 { + let dst = &mut blob[col * BYTES_PER_CELL..(col + 1) * BYTES_PER_CELL]; + dst.copy_from_slice(&all_cells[col]); + } + blob +} + +/// Recover all 128 cells and their KZG proofs from a partial set of cells. +/// `cell_indices` and `cells` must have equal length (≥ 64 for successful recovery). +/// Returns `(all_cells, all_proofs)` each of length 128. +#[cfg(feature = "c-kzg")] +pub fn recover_cells_and_kzg_proofs( + cell_indices: &[u64], + cells: &[[u8; BYTES_PER_CELL]], +) -> Result<(Vec<[u8; BYTES_PER_CELL]>, Vec), KzgError> { + let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE); + let c_cells: Vec = cells.iter().map(|c| c_kzg::Cell::new(*c)).collect(); + let (recovered_cells, recovered_proofs) = + c_kzg_settings.recover_cells_and_kzg_proofs(cell_indices, &c_cells)?; + let out_cells: Vec<[u8; BYTES_PER_CELL]> = + recovered_cells.iter().map(|c| c.to_bytes()).collect(); + let out_proofs: Vec = recovered_proofs + .iter() + .map(|p| p.to_bytes().into_inner()) + .collect(); + Ok((out_cells, out_proofs)) +} + +/// Compute all `CELLS_PER_EXT_BLOB` cells for a blob. +/// Returns one `[u8; BYTES_PER_CELL]` per cell. +#[cfg(feature = "c-kzg")] +pub fn compute_cells(blob: &Blob) -> Result, KzgError> { + let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE); + let c_blob: c_kzg::Blob = (*blob).into(); + let boxed = c_kzg_settings + .compute_cells(&c_blob) + .map_err(KzgError::CKzg)?; + Ok(boxed.iter().map(|cell| cell.to_bytes()).collect()) +} + +/// Verify KZG cell proofs for a subset of cells (partial batch). +/// `commitments`, `cell_indices`, `cells`, and `proofs` must all have the same length. +#[allow(unused_variables)] +pub fn verify_cell_kzg_proof_batch_partial( + commitments: &[Commitment], + cell_indices: &[u64], + cells: &[[u8; BYTES_PER_CELL]], + proofs: &[Proof], +) -> Result { + #[cfg(not(feature = "c-kzg"))] + { + return Err(KzgError::Unimplemented( + "verify_cell_kzg_proof_batch_partial requires the c-kzg feature".into(), + )); + } + #[cfg(feature = "c-kzg")] + { + let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE); + let c_commitments: Vec = commitments.iter().map(|c| (*c).into()).collect(); + let c_cells: Vec = cells.iter().map(|c| c_kzg::Cell::new(*c)).collect(); + let c_proofs: Vec = proofs.iter().map(|p| (*p).into()).collect(); + c_kzg::KzgSettings::verify_cell_kzg_proof_batch( + c_kzg_settings, + &c_commitments, + cell_indices, + &c_cells, + &c_proofs, + ) + .map_err(KzgError::from) + } +} + #[cfg(feature = "c-kzg")] pub fn blob_to_commitment_and_cell_proofs( blob: &Blob, diff --git a/crates/vendored/ethrex-crypto/provider.rs b/crates/vendored/ethrex-crypto/provider.rs index 5eca02782..fbfdcd752 100644 --- a/crates/vendored/ethrex-crypto/provider.rs +++ b/crates/vendored/ethrex-crypto/provider.rs @@ -160,6 +160,42 @@ pub trait Crypto: Send + Sync + core::fmt::Debug { Ok(hash) } + /// Recover the signer's **uncompressed** secp256k1 public key (`0x04 || X || Y`). + /// + /// [`Self::recover_signer`] hashes this and keeps the last 20 bytes; the + /// stateless-validation wire format needs the key itself, so that a guest can + /// verify signatures against a supplied key instead of running `ecrecover`. + /// Applies the same EIP-2 low-s rejection, so the two agree on which + /// signatures are valid. + /// + /// Host-only: this exists to *produce* `SszStatelessInput::public_keys`. Guests + /// only ever consume them, so no zkVM provider needs to override it. + #[cfg(feature = "secp256k1")] + fn recover_public_key(&self, sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 65], CryptoError> { + // EIP-2: reject high-s signatures (s > secp256k1n/2), matching recover_signer. + const SECP256K1_N_HALF: [u8; 32] = + hex_literal::hex!("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0"); + if sig[32..64] > SECP256K1_N_HALF[..] { + return Err(CryptoError::InvalidSignature); + } + + let recovery_id = secp256k1::ecdsa::RecoveryId::try_from(sig[64] as i32) + .map_err(|_| CryptoError::InvalidRecoveryId)?; + let recoverable_sig = secp256k1::ecdsa::RecoverableSignature::from_compact( + sig[..64] + .try_into() + .map_err(|_| CryptoError::InvalidSignature)?, + recovery_id, + ) + .map_err(|_| CryptoError::InvalidSignature)?; + + let public_key = recoverable_sig + .recover(&secp256k1::Message::from_digest(*msg)) + .map_err(|_| CryptoError::RecoveryFailed)?; + + Ok(public_key.serialize_uncompressed()) + } + /// Recover the signer address from a 65-byte signature (r||s||v) + 32-byte message hash. /// Used by transaction validation (tx.sender()) and EIP-7702 authority recovery. fn recover_signer(&self, sig: &[u8; 65], msg: &[u8; 32]) -> Result {