From aeac4f4490002b53a0abb7ea9613f7fc876d86d8 Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Thu, 6 Feb 2025 13:40:10 +0530 Subject: [PATCH 1/4] fix: ensure logs returned by RPC match filter --- core/src/execution/errors.rs | 2 + core/src/execution/mod.rs | 77 +++++++++++++++++++++++++++++++----- core/src/execution/state.rs | 5 ++- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/core/src/execution/errors.rs b/core/src/execution/errors.rs index 3f53a704..bb569500 100644 --- a/core/src/execution/errors.rs +++ b/core/src/execution/errors.rs @@ -31,6 +31,8 @@ pub enum ExecutionError { BlockReceiptsRootMismatch(BlockTag), #[error("filter not found: 0x{0:x}")] FilterNotFound(U256), + #[error("log does not match filter")] + LogDoesNotMatchFilter(), } /// Errors that can occur during evm.rs calls diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 7ade53bf..dcfc6c89 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -331,7 +331,7 @@ impl> ExecutionClient { ExecutionError::TooManyLogsToProve(logs.len(), MAX_SUPPORTED_LOGS_NUMBER).into(), ); } - + self.ensure_logs_match_filter(&logs, &filter).await?; self.verify_logs(&logs).await?; Ok(logs) } @@ -344,7 +344,7 @@ impl> ExecutionClient { // only concerned with filters created via helios return Err(ExecutionError::FilterNotFound(filter_id).into()); } - Some(FilterType::Logs) => { + Some(FilterType::Logs(filter)) => { // underlying RPC takes care of keeping track of changes let filter_changes = self.rpc.get_filter_changes(filter_id).await?; let logs = filter_changes.as_logs().unwrap_or(&[]); @@ -355,6 +355,7 @@ impl> ExecutionClient { ) .into()); } + self.ensure_logs_match_filter(logs, filter).await?; self.verify_logs(logs).await?; FilterChanges::Logs(logs.to_vec()) } @@ -386,14 +387,27 @@ impl> ExecutionClient { } pub async fn get_filter_logs(&self, filter_id: U256) -> Result> { - let logs = self.rpc.get_filter_logs(filter_id).await?; - if logs.len() > MAX_SUPPORTED_LOGS_NUMBER { - return Err( - ExecutionError::TooManyLogsToProve(logs.len(), MAX_SUPPORTED_LOGS_NUMBER).into(), - ); + let filter_type = self.state.get_filter(&filter_id).await; + + match &filter_type { + Some(FilterType::Logs(filter)) => { + let logs = self.rpc.get_filter_logs(filter_id).await?; + if logs.len() > MAX_SUPPORTED_LOGS_NUMBER { + return Err(ExecutionError::TooManyLogsToProve( + logs.len(), + MAX_SUPPORTED_LOGS_NUMBER, + ) + .into()); + } + self.ensure_logs_match_filter(&logs, filter).await?; + self.verify_logs(&logs).await?; + Ok(logs) + } + _ => { + // only concerned with filters created via helios + return Err(ExecutionError::FilterNotFound(filter_id).into()); + } } - self.verify_logs(&logs).await?; - Ok(logs) } pub async fn uninstall_filter(&self, filter_id: U256) -> Result { @@ -420,7 +434,9 @@ impl> ExecutionClient { let filter_id = self.rpc.new_filter(&filter).await?; // record the filter in the state - self.state.push_filter(filter_id, FilterType::Logs).await; + self.state + .push_filter(filter_id, FilterType::Logs(filter)) + .await; Ok(filter_id) } @@ -448,6 +464,47 @@ impl> ExecutionClient { Ok(filter_id) } + /// Ensure that each log entry in the given array of logs match the given filter. + async fn ensure_logs_match_filter(&self, logs: &[Log], filter: &Filter) -> Result<()> { + fn log_matches_filter(log: &Log, filter: &Filter) -> bool { + if let Some(block_hash) = filter.get_block_hash() { + if log.block_hash.unwrap() != block_hash { + return false; + } + } + if let Some(from_block) = filter.get_from_block() { + if log.block_number.unwrap() < from_block { + return false; + } + } + if let Some(to_block) = filter.get_to_block() { + if log.block_number.unwrap() > to_block { + return false; + } + } + if !filter.address.matches(&log.address()) { + return false; + } + for (i, topic) in filter.topics.iter().enumerate() { + if let Some(log_topic) = log.topics().get(i) { + if !topic.matches(log_topic) { + return false; + } + } + } + true + } + for log in logs { + if !log_matches_filter(log, filter) { + return Err(ExecutionError::LogDoesNotMatchFilter().into()); + } + } + Ok(()) + } + + /// Verify the integrity of each log entry in the given array of logs by + /// checking its inclusion in the corresponding transaction receipt + /// and verifying the transaction receipt itself against the block's receipt root. async fn verify_logs(&self, logs: &[Log]) -> Result<()> { // Collect all (unique) block numbers let block_nums = logs diff --git a/core/src/execution/state.rs b/core/src/execution/state.rs index c9f509c5..7802b462 100644 --- a/core/src/execution/state.rs +++ b/core/src/execution/state.rs @@ -7,7 +7,7 @@ use alloy::{ consensus::BlockHeader, network::{primitives::HeaderResponse, BlockResponse}, primitives::{Address, B256, U256}, - rpc::types::BlockTransactions, + rpc::types::{BlockTransactions, Filter}, }; use eyre::{eyre, Result}; use tokio::{ @@ -373,7 +373,8 @@ struct TransactionLocation { #[derive(Clone)] pub enum FilterType { - Logs, + // filter content + Logs(Filter), // block number when the filter was created or last queried NewBlock(u64), PendingTransactions, From 2c1a8b0adf5b23875c751c8c15dc8626d16d9abe Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Thu, 6 Feb 2025 15:14:30 +0530 Subject: [PATCH 2/4] replace custom proof impl and triehash with alloy-trie --- Cargo.lock | 348 ++++++------------------------------ Cargo.toml | 6 +- core/Cargo.toml | 2 +- core/src/execution/mod.rs | 79 ++++---- core/src/execution/proof.rs | 204 --------------------- ethereum/Cargo.toml | 2 +- ethereum/src/consensus.rs | 19 +- opstack/Cargo.toml | 2 +- opstack/src/consensus.rs | 73 ++++---- 9 files changed, 158 insertions(+), 577 deletions(-) delete mode 100644 core/src/execution/proof.rs diff --git a/Cargo.lock b/Cargo.lock index c10c3dc5..8b5d6f0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,12 +354,12 @@ dependencies = [ "keccak-asm", "paste", "proptest", - "rand 0.8.5", + "rand", "ruint", "rustc-hash 2.1.0", "serde", "sha3", - "tiny-keccak 2.0.2", + "tiny-keccak", ] [[package]] @@ -428,7 +428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" dependencies = [ "alloy-rlp-derive", - "arrayvec 0.7.6", + "arrayvec", "bytes", ] @@ -585,7 +585,7 @@ dependencies = [ "alloy-signer", "async-trait", "k256", - "rand 0.8.5", + "rand", "thiserror 2.0.9", ] @@ -619,7 +619,7 @@ dependencies = [ "quote", "syn 2.0.91", "syn-solidity", - "tiny-keccak 2.0.2", + "tiny-keccak", ] [[package]] @@ -736,13 +736,13 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e428104b2445a4f929030891b3dbf8c94433a8349ba6480946bf6af7975c2f6" +checksum = "6917c79e837aa7b77b7a6dae9f89cbe15313ac161c4d3cfaf8909ef21f3d22d8" dependencies = [ "alloy-primitives", "alloy-rlp", - "arrayvec 0.7.6", + "arrayvec", "derive_more", "nybbles", "serde", @@ -937,7 +937,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ "num-traits", - "rand 0.8.5", + "rand", ] [[package]] @@ -947,7 +947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.5", + "rand", ] [[package]] @@ -956,12 +956,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.6" @@ -1305,16 +1299,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitvec" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -dependencies = [ - "either", - "radium 0.3.0", -] - [[package]] name = "bitvec" version = "1.0.1" @@ -1322,7 +1306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", - "radium 0.7.0", + "radium", "serde", "tap", "wyz", @@ -1403,12 +1387,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "byte-slice-cast" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" - [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -2127,7 +2105,7 @@ dependencies = [ "aes", "aes-gcm", "alloy-rlp", - "arrayvec 0.7.6", + "arrayvec", "ctr", "delay_map", "enr", @@ -2140,12 +2118,12 @@ dependencies = [ "lru", "more-asserts", "parking_lot 0.11.2", - "rand 0.8.5", + "rand", "smallvec", "socket2 0.4.10", "tokio", "tracing", - "uint 0.9.5", + "uint", "zeroize", ] @@ -2297,7 +2275,7 @@ dependencies = [ "hex", "k256", "log", - "rand 0.8.5", + "rand", "serde", "sha3", "zeroize", @@ -2342,33 +2320,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ethbloom" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cfe1c169414b709cf28aa30c74060bdb830a03a8ba473314d079ac79d80a5f" -dependencies = [ - "crunchy", - "fixed-hash 0.5.2", - "impl-rlp", - "impl-serde 0.2.3", - "tiny-keccak 1.5.0", -] - -[[package]] -name = "ethereum-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba744248e3553a393143d5ebb68939fc3a4ec0c22a269682535f5ffe7fed728c" -dependencies = [ - "ethbloom", - "fixed-hash 0.5.2", - "impl-rlp", - "impl-serde 0.2.3", - "primitive-types 0.6.2", - "uint 0.8.5", -] - [[package]] name = "ethereum_hashing" version = "0.7.0" @@ -2467,7 +2418,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "arrayvec 0.7.6", + "arrayvec", "auto_impl", "bytes", ] @@ -2487,7 +2438,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "bitvec 1.0.1", + "bitvec", "rand_core 0.6.4", "subtle", ] @@ -2512,18 +2463,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "fixed-hash" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" -dependencies = [ - "byteorder", - "rand 0.7.3", - "rustc-hex", - "static_assertions", -] - [[package]] name = "fixed-hash" version = "0.8.0" @@ -2531,7 +2470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand 0.8.5", + "rand", "rustc-hex", "static_assertions", ] @@ -2979,12 +2918,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" - [[package]] name = "hashbrown" version = "0.13.2" @@ -3049,7 +2982,7 @@ dependencies = [ "hex", "plotters", "pretty_assertions", - "rand 0.8.5", + "rand", "serde", "tempfile", "tokio", @@ -3110,6 +3043,7 @@ name = "helios-core" version = "0.7.0" dependencies = [ "alloy", + "alloy-trie", "async-trait", "eyre", "futures", @@ -3125,7 +3059,6 @@ dependencies = [ "thiserror 1.0.65", "tokio", "tracing", - "triehash-ethereum", "wasm-bindgen-futures", "wasmtimer 0.2.0", ] @@ -3135,6 +3068,7 @@ name = "helios-ethereum" version = "0.7.0" dependencies = [ "alloy", + "alloy-trie", "async-trait", "chrono", "dirs", @@ -3159,7 +3093,6 @@ dependencies = [ "tokio", "tracing", "tree_hash", - "triehash-ethereum", "typenum", "url", "wasm-bindgen-futures", @@ -3171,6 +3104,7 @@ version = "0.7.0" dependencies = [ "alloy", "alloy-rlp", + "alloy-trie", "axum", "clap", "discv5", @@ -3199,7 +3133,6 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", - "triehash-ethereum", "typenum", "unsigned-varint", "url", @@ -3584,49 +3517,13 @@ dependencies = [ "png", ] -[[package]] -name = "impl-codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -dependencies = [ - "parity-scale-codec 1.3.7", -] - [[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", -] - -[[package]] -name = "impl-rlp" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" -dependencies = [ - "rlp 0.4.6", -] - -[[package]] -name = "impl-serde" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", + "parity-scale-codec", ] [[package]] @@ -3825,7 +3722,7 @@ dependencies = [ "hyper 0.14.31", "jsonrpsee-types", "parking_lot 0.12.3", - "rand 0.8.5", + "rand", "rustc-hash 1.1.0", "serde", "serde_json", @@ -3959,17 +3856,6 @@ dependencies = [ "sha3-asm", ] -[[package]] -name = "keccak-hasher" -version = "0.1.1" -source = "git+https://github.com/openethereum/parity-ethereum?rev=55c90d4016505317034e3e98f699af07f5404b63#55c90d4016505317034e3e98f699af07f5404b63" -dependencies = [ - "ethereum-types", - "hash-db", - "plain_hasher", - "tiny-keccak 1.5.0", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -4074,7 +3960,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "quick-protobuf", - "rand 0.8.5", + "rand", "rw-stream-sink", "smallvec", "thiserror 1.0.65", @@ -4118,7 +4004,7 @@ dependencies = [ "prometheus-client", "quick-protobuf", "quick-protobuf-codec", - "rand 0.8.5", + "rand", "regex", "sha2 0.10.8", "smallvec", @@ -4142,7 +4028,7 @@ dependencies = [ "multiaddr", "multihash", "quick-protobuf", - "rand 0.8.5", + "rand", "sha2 0.10.8", "thiserror 1.0.65", "zeroize", @@ -4161,7 +4047,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand 0.8.5", + "rand", "smallvec", "socket2 0.4.10", "tokio", @@ -4195,7 +4081,7 @@ dependencies = [ "log", "nohash-hasher", "parking_lot 0.12.3", - "rand 0.8.5", + "rand", "smallvec", "unsigned-varint", ] @@ -4214,7 +4100,7 @@ dependencies = [ "log", "once_cell", "quick-protobuf", - "rand 0.8.5", + "rand", "sha2 0.10.8", "snow", "static_assertions", @@ -4236,7 +4122,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand 0.8.5", + "rand", "void", ] @@ -4256,7 +4142,7 @@ dependencies = [ "log", "parking_lot 0.12.3", "quinn-proto", - "rand 0.8.5", + "rand", "rustls 0.20.9", "thiserror 1.0.65", "tokio", @@ -4277,7 +4163,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "log", - "rand 0.8.5", + "rand", "smallvec", "tokio", "void", @@ -4352,7 +4238,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.5", + "rand", "serde", "sha2 0.9.9", "typenum", @@ -4829,9 +4715,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55a62e678a89501192cc5ebf47dcbc656b608ae5e1c61c9251fe35230f119fe3" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" dependencies = [ "alloy-rlp", "const-hex", @@ -5000,27 +4886,15 @@ dependencies = [ "group", ] -[[package]] -name = "parity-scale-codec" -version = "1.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b26b16c7687c3075982af47719e481815df30bc544f7a6690763a25ca16e9d" -dependencies = [ - "arrayvec 0.5.2", - "bitvec 0.17.4", - "byte-slice-cast 0.3.5", - "serde", -] - [[package]] name = "parity-scale-codec" version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.6", - "bitvec 1.0.1", - "byte-slice-cast 1.2.2", + "arrayvec", + "bitvec", + "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", "serde", @@ -5224,15 +5098,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" -[[package]] -name = "plain_hasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc" -dependencies = [ - "crunchy", -] - [[package]] name = "plotters" version = "0.3.7" @@ -5355,28 +5220,15 @@ dependencies = [ "yansi", ] -[[package]] -name = "primitive-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" -dependencies = [ - "fixed-hash 0.5.2", - "impl-codec 0.4.2", - "impl-rlp", - "impl-serde 0.3.2", - "uint 0.8.5", -] - [[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", - "uint 0.9.5", + "fixed-hash", + "impl-codec", + "uint", ] [[package]] @@ -5500,8 +5352,8 @@ dependencies = [ "bitflags 2.6.0", "lazy_static", "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "rand_xorshift", "regex-syntax 0.8.5", "rusty-fork", @@ -5544,7 +5396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", - "rand 0.8.5", + "rand", "ring 0.16.20", "rustc-hash 1.1.0", "rustls 0.20.9", @@ -5564,31 +5416,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" - [[package]] name = "radium" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -5596,21 +5429,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", + "rand_chacha", "rand_core 0.6.4", "serde", ] -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -5639,15 +5462,6 @@ dependencies = [ "getrandom 0.2.15", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_xorshift" version = "0.3.0" @@ -5884,7 +5698,7 @@ dependencies = [ "alloy-primitives", "auto_impl", "bitflags 2.6.0", - "bitvec 1.0.1", + "bitvec", "c-kzg", "cfg-if", "dyn-clone", @@ -5942,15 +5756,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "rlp" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73" -dependencies = [ - "rustc-hex", -] - [[package]] name = "rlp" version = "0.5.2" @@ -5989,11 +5794,11 @@ dependencies = [ "fastrlp", "num-bigint", "num-traits", - "parity-scale-codec 3.6.12", - "primitive-types 0.12.2", + "parity-scale-codec", + "primitive-types", "proptest", - "rand 0.8.5", - "rlp 0.5.2", + "rand", + "rlp", "ruint-macro", "serde", "valuable", @@ -6271,7 +6076,7 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "rand 0.8.5", + "rand", "secp256k1-sys", ] @@ -6640,7 +6445,7 @@ dependencies = [ "http 0.2.12", "httparse", "log", - "rand 0.8.5", + "rand", "sha-1", ] @@ -6731,7 +6536,7 @@ dependencies = [ "byteorder", "crunchy", "lazy_static", - "rand 0.8.5", + "rand", "rustc-hex", ] @@ -6967,15 +6772,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" -dependencies = [ - "crunchy", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -7307,26 +7103,6 @@ dependencies = [ "syn 2.0.91", ] -[[package]] -name = "triehash" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" -dependencies = [ - "hash-db", - "rlp 0.5.2", -] - -[[package]] -name = "triehash-ethereum" -version = "0.2.0" -source = "git+https://github.com/openethereum/parity-ethereum?rev=55c90d4016505317034e3e98f699af07f5404b63#55c90d4016505317034e3e98f699af07f5404b63" -dependencies = [ - "ethereum-types", - "keccak-hasher", - "triehash", -] - [[package]] name = "trust-dns-proto" version = "0.22.0" @@ -7343,7 +7119,7 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "rand 0.8.5", + "rand", "smallvec", "socket2 0.4.10", "thiserror 1.0.65", @@ -7397,7 +7173,7 @@ dependencies = [ "http 1.1.0", "httparse", "log", - "rand 0.8.5", + "rand", "rustls 0.23.15", "rustls-pki-types", "sha1", @@ -7417,18 +7193,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "uint" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" -dependencies = [ - "byteorder", - "crunchy", - "rustc-hex", - "static_assertions", -] - [[package]] name = "uint" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 932530ee..ca72a744 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,8 @@ alloy = { version = "0.9.1", features = [ "ssz", "json-rpc", "signers", -]} +] } +alloy-trie = "0.7.8" op-alloy-rpc-types = "0.9.0" revm = { version = "18.0.0", default-features = false, features = [ "std", @@ -51,8 +52,7 @@ revm = { version = "18.0.0", default-features = false, features = [ "optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee", -]} -triehash-ethereum = { git = "https://github.com/openethereum/parity-ethereum", rev = "55c90d4016505317034e3e98f699af07f5404b63" } +] } # async/futures async-trait = "0.1.57" diff --git a/core/Cargo.toml b/core/Cargo.toml index c95b2441..74eef842 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] # execution alloy.workspace = true +alloy-trie.workspace = true revm.workspace = true -triehash-ethereum.workspace = true # async/futures futures.workspace = true diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 7ade53bf..21111774 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -4,21 +4,24 @@ use alloy::consensus::BlockHeader; use alloy::network::primitives::HeaderResponse; use alloy::network::{BlockResponse, ReceiptResponse}; use alloy::primitives::{keccak256, Address, B256, U256}; -use alloy::rlp::encode; +use alloy::rlp; use alloy::rpc::types::{BlockTransactions, Filter, FilterChanges, Log}; +use alloy_trie::{ + proof::verify_proof as mpt_verify_proof, + root::ordered_trie_root_with_encoder, + {Nibbles, TrieAccount}, +}; use constants::{BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS}; use eyre::Result; use futures::future::try_join_all; use revm::primitives::KECCAK_EMPTY; use tracing::warn; -use triehash_ethereum::ordered_trie_root; use crate::network_spec::NetworkSpec; use crate::types::BlockTag; use self::constants::MAX_SUPPORTED_LOGS_NUMBER; use self::errors::ExecutionError; -use self::proof::{encode_account, verify_proof}; use self::rpc::ExecutionRpc; use self::state::{FilterType, State}; use self::types::Account; @@ -26,7 +29,6 @@ use self::types::Account; pub mod constants; pub mod errors; pub mod evm; -pub mod proof; pub mod rpc; pub mod state; pub mod types; @@ -69,41 +71,45 @@ impl> ExecutionClient { .get_proof(address, slots, block.header().number().into()) .await?; - let account_path = keccak256(address).to_vec(); - let account_encoded = encode_account(&proof); + // Verify the account proof + let account_key = Nibbles::unpack(keccak256(proof.address)); + let account = TrieAccount { + nonce: proof.nonce, + balance: proof.balance, + storage_root: proof.storage_hash, + code_hash: proof.code_hash, + }; + let account_encoded = rlp::encode(account); - let is_valid = verify_proof( + mpt_verify_proof( + block.header().state_root(), + account_key, + account_encoded.into(), &proof.account_proof, - block.header().state_root().as_slice(), - &account_path, - &account_encoded, - ); - - if !is_valid { - return Err(ExecutionError::InvalidAccountProof(address).into()); - } + ) + .map_err(|_| ExecutionError::InvalidAccountProof(address))?; + // Verify the storage proofs, collecting the slot values let mut slot_map = HashMap::new(); for storage_proof in proof.storage_proof { let key = storage_proof.key.as_b256(); let key_hash = keccak256(key); - let value = encode(storage_proof.value); + let key_nibbles = Nibbles::unpack(key_hash); + let encoded_value = rlp::encode(storage_proof.value); - let is_valid = verify_proof( + mpt_verify_proof( + proof.storage_hash, + key_nibbles, + encoded_value.into(), &storage_proof.proof, - proof.storage_hash.as_slice(), - key_hash.as_slice(), - &value, - ); - - if !is_valid { - return Err(ExecutionError::InvalidStorageProof(address, key).into()); - } + ) + .map_err(|_| ExecutionError::InvalidStorageProof(address, key))?; slot_map.insert(key, storage_proof.value); } + // Verify the code hash let code = if proof.code_hash == KECCAK_EMPTY || proof.code_hash == B256::ZERO { Vec::new() } else { @@ -256,8 +262,7 @@ impl> ExecutionClient { .ok_or(eyre::eyre!(ExecutionError::NoReceiptsForBlock(tag)))?; let receipts_encoded = receipts.iter().map(N::encode_receipt).collect::>(); - let expected_receipt_root = ordered_trie_root(receipts_encoded.clone()); - let expected_receipt_root = B256::from_slice(&expected_receipt_root.to_fixed_bytes()); + let expected_receipt_root = ordered_trie_root(&receipts_encoded); if expected_receipt_root != block.header().receipts_root() // Note: Some RPC providers return different response in `eth_getTransactionReceipt` vs `eth_getBlockReceipts` @@ -295,8 +300,7 @@ impl> ExecutionClient { .ok_or(eyre::eyre!(ExecutionError::NoReceiptsForBlock(tag)))?; let receipts_encoded = receipts.iter().map(N::encode_receipt).collect::>(); - let expected_receipt_root = ordered_trie_root(receipts_encoded); - let expected_receipt_root = B256::from_slice(&expected_receipt_root.to_fixed_bytes()); + let expected_receipt_root = ordered_trie_root(&receipts_encoded); if expected_receipt_root != block.header().receipts_root() { return Err(ExecutionError::BlockReceiptsRootMismatch(tag).into()); @@ -476,7 +480,10 @@ impl> ExecutionClient { None } else { let tx_hash = logs[0].transaction_hash.unwrap(); - let encoded_logs = logs.iter().map(|l| encode(&l.inner)).collect::>(); + let encoded_logs = logs + .iter() + .map(|l| rlp::encode(&l.inner)) + .collect::>(); Some((tx_hash, encoded_logs)) } }) @@ -486,7 +493,7 @@ impl> ExecutionClient { // Check if the receipt contains the desired log // Encoding logs for comparison let tx_hash = log.transaction_hash.unwrap(); - let log_encoded = encode(&log.inner); + let log_encoded = rlp::encode(&log.inner); let receipt_logs_encoded = receipts_logs_encoded.get(&tx_hash).unwrap(); if !receipt_logs_encoded.contains(&log_encoded) { @@ -500,3 +507,13 @@ impl> ExecutionClient { Ok(()) } } + +/// Compute a trie root of a collection of encoded items. +/// Ref: https://github.com/alloy-rs/trie/blob/main/src/root.rs. +fn ordered_trie_root(items: &[Vec]) -> B256 { + fn noop_encoder(item: &Vec, buffer: &mut Vec) { + buffer.extend_from_slice(item); + } + + ordered_trie_root_with_encoder(items, noop_encoder) +} diff --git a/core/src/execution/proof.rs b/core/src/execution/proof.rs deleted file mode 100644 index 44170a4d..00000000 --- a/core/src/execution/proof.rs +++ /dev/null @@ -1,204 +0,0 @@ -use alloy::consensus::Account; -use alloy::primitives::{b256, keccak256, Bytes, B256, U256}; -use alloy::rlp::{encode, Decodable}; -use alloy::rpc::types::EIP1186AccountProofResponse; - -pub fn verify_proof(proof: &[Bytes], root: &[u8], path: &[u8], value: &[u8]) -> bool { - let mut expected_hash = root.to_vec(); - let mut path_offset = 0; - - for (i, node) in proof.iter().enumerate() { - if expected_hash != keccak256(node).to_vec() { - return false; - } - - let mut node = &node[..]; - let node_list: Vec = Vec::decode(&mut node).unwrap(); - - if node_list.len() == 17 { - if i == proof.len() - 1 { - // exclusion proof - let nibble = get_nibble(path, path_offset); - let node = &node_list[nibble as usize]; - - if node.is_empty() && is_empty_value(value) { - return true; - } - } else { - let nibble = get_nibble(path, path_offset); - expected_hash.clone_from(&node_list[nibble as usize].to_vec()); - - path_offset += 1; - } - } else if node_list.len() == 2 { - if i == proof.len() - 1 { - // exclusion proof - if !paths_match(&node_list[0], skip_length(&node_list[0]), path, path_offset) - && is_empty_value(value) - { - return true; - } - - // inclusion proof - if &node_list[1] == value { - return paths_match( - &node_list[0], - skip_length(&node_list[0]), - path, - path_offset, - ); - } - } else { - let node_path = &node_list[0]; - let prefix_length = shared_prefix_length(path, path_offset, node_path); - if prefix_length < node_path.len() * 2 - skip_length(node_path) { - // The proof shows a divergent path, but we're not - // at the end of the proof, so something's wrong. - return false; - } - path_offset += prefix_length; - expected_hash.clone_from(&node_list[1].to_vec()); - } - } else { - return false; - } - } - - false -} - -fn paths_match(p1: &[u8], s1: usize, p2: &[u8], s2: usize) -> bool { - let len1 = p1.len() * 2 - s1; - let len2 = p2.len() * 2 - s2; - - if len1 != len2 { - return false; - } - - for offset in 0..len1 { - let n1 = get_nibble(p1, s1 + offset); - let n2 = get_nibble(p2, s2 + offset); - - if n1 != n2 { - return false; - } - } - - true -} - -#[allow(dead_code)] -fn get_rest_path(p: &[u8], s: usize) -> String { - let mut ret = String::new(); - for i in s..p.len() * 2 { - let n = get_nibble(p, i); - ret += &format!("{n:01x}"); - } - ret -} - -fn is_empty_value(value: &[u8]) -> bool { - let empty_account = Account { - nonce: 0, - balance: U256::ZERO, - storage_root: b256!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), - code_hash: b256!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), - }; - - let new_empty_account = Account { - nonce: 0, - balance: U256::ZERO, - storage_root: B256::ZERO, - code_hash: B256::ZERO, - }; - - let empty_account = encode(empty_account); - let new_empty_account = encode(new_empty_account); - - let is_empty_slot = value.len() == 1 && value[0] == 0x80; - let is_empty_account = value == empty_account || value == new_empty_account; - is_empty_slot || is_empty_account -} - -fn shared_prefix_length(path: &[u8], path_offset: usize, node_path: &[u8]) -> usize { - let skip_length = skip_length(node_path); - - let len = std::cmp::min( - node_path.len() * 2 - skip_length, - path.len() * 2 - path_offset, - ); - let mut prefix_len = 0; - - for i in 0..len { - let path_nibble = get_nibble(path, i + path_offset); - let node_path_nibble = get_nibble(node_path, i + skip_length); - - if path_nibble == node_path_nibble { - prefix_len += 1; - } else { - break; - } - } - - prefix_len -} - -fn skip_length(node: &[u8]) -> usize { - if node.is_empty() { - return 0; - } - - let nibble = get_nibble(node, 0); - match nibble { - 0 => 2, - 1 => 1, - 2 => 2, - 3 => 1, - _ => 0, - } -} - -fn get_nibble(path: &[u8], offset: usize) -> u8 { - let byte = path[offset / 2]; - if offset % 2 == 0 { - byte >> 4 - } else { - byte & 0xF - } -} - -pub fn encode_account(proof: &EIP1186AccountProofResponse) -> Vec { - let account = Account { - nonce: proof.nonce, - balance: proof.balance, - storage_root: proof.storage_hash, - code_hash: proof.code_hash, - }; - - encode(account) -} - -#[cfg(test)] -mod tests { - use crate::execution::proof::shared_prefix_length; - - #[tokio::test] - async fn test_shared_prefix_length() { - // We compare the path starting from the 6th nibble i.e. the 6 in 0x6f - let path: Vec = vec![0x12, 0x13, 0x14, 0x6f, 0x6c, 0x64, 0x21]; - let path_offset = 6; - // Our node path matches only the first 5 nibbles of the path - let node_path: Vec = vec![0x6f, 0x6c, 0x63, 0x21]; - let shared_len = shared_prefix_length(&path, path_offset, &node_path); - assert_eq!(shared_len, 5); - - // Now we compare the path starting from the 5th nibble i.e. the 4 in 0x14 - let path: Vec = vec![0x12, 0x13, 0x14, 0x6f, 0x6c, 0x64, 0x21]; - let path_offset = 5; - // Our node path matches only the first 7 nibbles of the path - // Note the first nibble is 1, so we skip 1 nibble - let node_path: Vec = vec![0x14, 0x6f, 0x6c, 0x64, 0x11]; - let shared_len = shared_prefix_length(&path, path_offset, &node_path); - assert_eq!(shared_len, 7); - } -} diff --git a/ethereum/Cargo.toml b/ethereum/Cargo.toml index 3b3fdef2..49651e22 100644 --- a/ethereum/Cargo.toml +++ b/ethereum/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] # consensus +alloy-trie.workspace = true tree_hash.workspace = true revm.workspace = true -triehash-ethereum.workspace = true # config figment = { version = "0.10.7", features = ["toml", "env"] } diff --git a/ethereum/src/consensus.rs b/ethereum/src/consensus.rs index 79048a94..b87460f8 100644 --- a/ethereum/src/consensus.rs +++ b/ethereum/src/consensus.rs @@ -2,10 +2,11 @@ use std::marker::PhantomData; use std::process; use std::sync::Arc; +use alloy::consensus::proofs::{calculate_transaction_root, calculate_withdrawals_root}; use alloy::consensus::{Header as ConsensusHeader, Transaction as TxTrait, TxEnvelope}; use alloy::eips::eip4895::{Withdrawal, Withdrawals}; use alloy::primitives::{b256, fixed_bytes, Bloom, BloomInput, B256, U256}; -use alloy::rlp::{encode, Decodable}; +use alloy::rlp::Decodable; use alloy::rpc::types::{Block, BlockTransactions, Header, Transaction}; use chrono::Duration; use eyre::eyre; @@ -13,7 +14,6 @@ use eyre::Result; use futures::future::join_all; use tracing::{debug, error, info, warn}; use tree_hash::TreeHash; -use triehash_ethereum::ordered_trie_root; use tokio::sync::mpsc::channel; use tokio::sync::mpsc::Receiver; @@ -601,7 +601,9 @@ fn payload_to_block(value: ExecutionPayload) -> Block>(); + .collect::>(); + let tx_envelopes = txs.iter().map(|tx| tx.inner.clone()).collect::>(); + let txs_root = calculate_transaction_root(&tx_envelopes); let withdrawals: Vec = value .withdrawals() @@ -609,12 +611,7 @@ fn payload_to_block(value: ExecutionPayload) -> Block(value: ExecutionPayload) -> Block>) { // Verify unsafe signer // with account proof - let account_path = keccak256(proof.address).to_vec(); - let account_encoded = encode_account(&proof); - let is_valid = verify_proof( + let account_key = Nibbles::unpack(keccak256(proof.address)); + let account = TrieAccount { + nonce: proof.nonce, + balance: proof.balance, + storage_root: proof.storage_hash, + code_hash: proof.code_hash, + }; + let account_encoded = rlp::encode(account); + + let is_valid = mpt_verify_proof( + block.header.state_root, + account_key, + account_encoded.into(), &proof.account_proof, - block.header.state_root.as_slice(), - &account_path, - &account_encoded, - ); + ) + .is_ok(); if !is_valid { warn!(target: "helios::opstack", "account proof invalid"); @@ -229,13 +239,15 @@ fn verify_unsafe_signer(config: Config, signer: Arc>) { } let key_hash = keccak256(key); - let value = encode(storage_proof.value); - let is_valid = verify_proof( + let key_nibbles = Nibbles::unpack(key_hash); + let encoded_value = rlp::encode(storage_proof.value); + let is_valid = mpt_verify_proof( + proof.storage_hash, + key_nibbles, + encoded_value.into(), &storage_proof.proof, - proof.storage_hash.as_slice(), - key_hash.as_slice(), - &value, - ); + ) + .is_ok(); if !is_valid { warn!(target: "helios::opstack", "storage proof invalid"); @@ -339,19 +351,14 @@ fn payload_to_block(value: ExecutionPayload) -> Result> { }) }) .collect::>>()?; + let tx_envelopes = txs + .iter() + .map(|tx| tx.inner.inner.clone()) + .collect::>(); + let txs_root = calculate_transaction_root(&tx_envelopes); - let withdrawals: Vec = value - .withdrawals - .clone() - .into_iter() - .map(|w| w.clone().into()) - .collect(); - - let raw_txs = value.transactions.iter().map(|tx| tx.to_vec()); - let txs_root = ordered_trie_root(raw_txs); - - let raw_withdrawals = value.withdrawals.iter().map(|v| encode(v)); - let withdrawals_root = ordered_trie_root(raw_withdrawals); + let withdrawals: Vec = value.withdrawals.into_iter().map(|w| w.into()).collect(); + let withdrawals_root = calculate_withdrawals_root(&withdrawals); let logs_bloom: Bloom = Bloom::from(BloomInput::Raw(&value.logs_bloom.to_vec())); @@ -360,9 +367,9 @@ fn payload_to_block(value: ExecutionPayload) -> Result> { ommers_hash: empty_uncle_hash, beneficiary: Address::from(*value.fee_recipient), state_root: value.state_root.into(), - transactions_root: B256::from_slice(txs_root.as_bytes()), + transactions_root: txs_root, receipts_root: value.receipts_root.into(), - withdrawals_root: Some(B256::from_slice(withdrawals_root.as_bytes())), + withdrawals_root: Some(withdrawals_root), logs_bloom: logs_bloom, difficulty: U256::ZERO, number: value.block_number, From 05a2771b79f59c234afd40b7550cf3b3c56eb9c9 Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Thu, 6 Feb 2025 15:30:13 +0530 Subject: [PATCH 3/4] fix some clippy warnings --- core/src/execution/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 21111774..521a4cf3 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -113,10 +113,7 @@ impl> ExecutionClient { let code = if proof.code_hash == KECCAK_EMPTY || proof.code_hash == B256::ZERO { Vec::new() } else { - let code = self - .rpc - .get_code(address, block.header().number().into()) - .await?; + let code = self.rpc.get_code(address, block.header().number()).await?; let code_hash = keccak256(&code); if proof.code_hash != code_hash { @@ -291,7 +288,7 @@ impl> ExecutionClient { return Ok(None); }; - let tag = BlockTag::Number(block.header().number().into()); + let tag = BlockTag::Number(block.header().number()); let receipts = self .rpc @@ -373,7 +370,7 @@ impl> ExecutionClient { self.state .push_filter( filter_id, - FilterType::NewBlock(blocks.last().unwrap().header().number().into()), + FilterType::NewBlock(blocks.last().unwrap().header().number()), ) .await; } From ce945c59bc339397594a3e019db90abc09dc6814 Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Mon, 10 Feb 2025 13:36:13 +0530 Subject: [PATCH 4/4] address review comments --- core/src/execution/errors.rs | 2 +- core/src/execution/mod.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/execution/errors.rs b/core/src/execution/errors.rs index bb569500..812206b8 100644 --- a/core/src/execution/errors.rs +++ b/core/src/execution/errors.rs @@ -32,7 +32,7 @@ pub enum ExecutionError { #[error("filter not found: 0x{0:x}")] FilterNotFound(U256), #[error("log does not match filter")] - LogDoesNotMatchFilter(), + LogFilterMismatch(), } /// Errors that can occur during evm.rs calls diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 63576e80..53ac0c81 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -491,13 +491,16 @@ impl> ExecutionClient { if !topic.matches(log_topic) { return false; } + } else { + // if filter topic is not present in log, it's a mismatch + return false; } } true } for log in logs { if !log_matches_filter(log, filter) { - return Err(ExecutionError::LogDoesNotMatchFilter().into()); + return Err(ExecutionError::LogFilterMismatch().into()); } } Ok(())