Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
9565da9
initial steps for replay with add block
JereSalo Sep 9, 2025
0c45d47
add a lot of prints...
JereSalo Sep 9, 2025
fb7928d
add more prints i guess
JereSalo Sep 9, 2025
8dfe9c6
add no backend to replayer
JereSalo Sep 10, 2025
49b098c
fix some stuff regarding rlp encoding
JereSalo Sep 10, 2025
53eaa3d
merge main
JereSalo Sep 10, 2025
fec2842
start with storage stuff
JereSalo Sep 10, 2025
299a513
add fix for mistake
JereSalo Sep 10, 2025
b22f7ca
comment a lot of prints that i use for debugging
JereSalo Sep 10, 2025
a47d427
tidy up code and improve genesis stuff
JereSalo Sep 10, 2025
5fc0e2f
remove prints
JereSalo Sep 10, 2025
baac10a
add prints of time
JereSalo Sep 10, 2025
7337926
remove 0x80 for reth nodes and add some prints commented
JereSalo Sep 11, 2025
29c8d4d
uncomment stuff
JereSalo Sep 11, 2025
b0d8b66
improve getting embedded root
JereSalo Sep 11, 2025
a19bf66
improve code quality
JereSalo Sep 11, 2025
e148f8f
improve code quality
JereSalo Sep 11, 2025
bfb3462
remove some stuff
JereSalo Sep 11, 2025
232096a
remove a lot of prints
JereSalo Sep 11, 2025
c8ff6cd
make improvements in code
JereSalo Sep 11, 2025
58959a8
leave a todo
JereSalo Sep 11, 2025
0cb25c5
add feature no backend to replayer
JereSalo Sep 12, 2025
bc898c7
modify cargo.toml
JereSalo Sep 15, 2025
161eb80
stop using hashed address fixed
JereSalo Sep 15, 2025
8d089d8
change comment
JereSalo Sep 15, 2025
f0a38fb
add replay feature flag
JereSalo Sep 15, 2025
50c85ef
remove todo
JereSalo Sep 15, 2025
a2aa4a3
add help to no_backend
JereSalo Sep 15, 2025
93acd40
merge main
JereSalo Sep 15, 2025
8a9be6c
fix clippy lint
JereSalo Sep 16, 2025
8e38d87
merge main
JereSalo Sep 16, 2025
b170ef3
add docs
JereSalo Sep 16, 2025
1c04c6e
remove clone chain config
JereSalo Sep 16, 2025
dd6eee3
change something in replayer_mode
JereSalo Sep 16, 2025
371d755
remove some unwraps
JereSalo Sep 16, 2025
9dd5334
replace unnecessary unwraps
JereSalo Sep 16, 2025
9f8324e
replace no-backend for no-zkvm
JereSalo Sep 16, 2025
ce55287
merge replay add fallback
JereSalo Sep 16, 2025
74db98c
merge main
JereSalo Sep 16, 2025
2bdb387
remove more references to prover backend
JereSalo Sep 16, 2025
a87c935
merge main
JereSalo Sep 17, 2025
c29eea5
remove into
JereSalo Sep 17, 2025
9bbbe7f
Revert "add replay feature flag"
JereSalo Sep 17, 2025
ef52f4d
start debugging
JereSalo Sep 17, 2025
dd97748
try inserting an arbitrary node in the trie
JereSalo Sep 18, 2025
0d0f03a
comment some stuff
JereSalo Sep 18, 2025
ccd80ad
comment some stuff
JereSalo Sep 18, 2025
eafecad
make some improvements in debugging
JereSalo Sep 18, 2025
3b18de9
first iteration that works I think
JereSalo Sep 18, 2025
0ec9838
remove commented prints
JereSalo Sep 18, 2025
f08cc7d
tidy code
JereSalo Sep 18, 2025
1e2cd88
tidy the code a bit more
JereSalo Sep 18, 2025
48f6d6e
remove added stuff
JereSalo Sep 18, 2025
530b998
improve code quality
JereSalo Sep 19, 2025
fdb829f
improve code quality part 10
JereSalo Sep 19, 2025
0baf727
keep on improving code
JereSalo Sep 19, 2025
e46ae23
Merge branch 'main' into replay_add_block
JereSalo Sep 19, 2025
7574c7b
add inner block because replayer wont compile otherwise
JereSalo Sep 19, 2025
cd9a580
clippy lint
JereSalo Sep 19, 2025
c1d39a9
Merge branch 'main' into replay_add_block
JereSalo Sep 19, 2025
ddc2f7b
remove unwant empty nodes
JereSalo Sep 19, 2025
7f07512
Merge branch 'replay_add_block' of github.com:lambdaclass/ethrex into…
JereSalo Sep 19, 2025
a8747b6
remove it
JereSalo Sep 19, 2025
5382c50
propagate error
JereSalo Sep 19, 2025
301829e
chain the ifs in chain config
JereSalo Sep 20, 2025
69fc90c
insert to state nodes
JereSalo Sep 22, 2025
254eaa8
quick and dirty fix
JereSalo Sep 23, 2025
b5447ad
improve some code
JereSalo Sep 23, 2025
1b076c7
improve code hash thing
JereSalo Sep 23, 2025
ecf6dc6
improve code quality
JereSalo Sep 23, 2025
7cad88a
add some comments
JereSalo Sep 23, 2025
182f298
merge main
JereSalo Sep 23, 2025
3ec04b2
Update cmd/ethrex_replay/src/cli.rs
JereSalo Sep 24, 2025
cd843f0
return error instead of unreachable
JereSalo Sep 24, 2025
d68ce59
merge main
JereSalo Sep 24, 2025
53ccee6
Merge branch 'main' into debugging_eth_getProof
JereSalo Sep 24, 2025
c2a9e37
Merge branch 'main' into debugging_eth_getProof
JereSalo Sep 24, 2025
b243784
Merge branch 'main' into debugging_eth_getProof
JereSalo Sep 25, 2025
fe773e6
Merge branch 'main' into debugging_eth_getProof
JereSalo Sep 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 32 additions & 36 deletions cmd/ethrex_replay/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,28 @@ use ethrex_storage::{
};
#[cfg(feature = "l2")]
use ethrex_storage_rollup::EngineTypeRollup;
use ethrex_trie::{InMemoryTrieDB, Node, NodeHash, NodeRef, node::LeafNode};
use ethrex_trie::{
InMemoryTrieDB, Node,
node::{BranchNode, LeafNode},
};
use reqwest::Url;
#[cfg(feature = "l2")]
use std::path::Path;
use std::{
cmp::max,
collections::HashSet,
io::Write,
sync::{Arc, RwLock},
time::{Instant, SystemTime},
};
use tracing::info;

use crate::bench::run_and_measure;
use crate::fetcher::get_blockdata;
#[cfg(not(feature = "l2"))]
use crate::fetcher::get_rangedata;
#[cfg(not(feature = "l2"))]
use crate::plot_composition::plot;
use crate::run::{exec, prove, run_tx};
use crate::{bench::run_and_measure, helpers::get_referenced_hashes};
use crate::{
block_run_report::{BlockRunReport, ReplayerMode},
cache::Cache,
Expand Down Expand Up @@ -463,7 +465,7 @@ async fn replay_no_zkvm(cache: Cache, opts: &EthrexReplayOptions) -> eyre::Resul
let guest_program = GuestProgramState::try_from(witness.clone())?;

// This will contain all code hashes with the corresponding bytecode
// For the code hashes that we don't have we'll will it with <CodeHash, Bytes::new()>
// For the code hashes that we don't have we'll fill it with <CodeHash, Bytes::new()>
let mut all_codes_hashed = guest_program.codes_hashed.clone();

let in_memory_store = InMemoryStore::new();
Expand All @@ -479,42 +481,16 @@ async fn replay_no_zkvm(cache: Cache, opts: &EthrexReplayOptions) -> eyre::Resul
// 2. Get all code hashes that exist in the accounts that we have so that if we don't have the code we set it to empty bytes.
// We do these things because sometimes the witness may be incomplete and in those cases we don't want failures for missing data.
// This only applies when we use the InMemoryDatabase and not when we use the ExecutionWitness as database, that's because in the latter failures are dismissed and we fall back to default values.
let mut nodes = state_trie_nodes.lock().unwrap();
let mut referenced_node_hashes: HashSet<NodeHash> = HashSet::new(); // All hashes referenced in the trie (by Branch or Ext nodes).

for (_node_hash, node_rlp) in nodes.iter() {
let node = Node::decode(node_rlp)?;
match node {
Node::Branch(node) => {
for choice in &node.choices {
let NodeRef::Hash(hash) = *choice else {
unreachable!()
};

referenced_node_hashes.insert(hash);
}
}
Node::Extension(node) => {
let NodeRef::Hash(hash) = node.child else {
unreachable!()
};

referenced_node_hashes.insert(hash);
}
Node::Leaf(node) => {
let info = AccountState::decode(&node.value)?;
all_codes_hashed.entry(info.code_hash).or_insert(vec![]);
}
}
}
let mut state_nodes = state_trie_nodes.lock().unwrap();
let referenced_node_hashes = get_referenced_hashes(&state_nodes)?;

let dummy_leaf = Node::from(LeafNode::default()).encode_to_vec();
// Insert arbitrary leaf nodes to state trie.
for hash in referenced_node_hashes {
let dummy_leaf: Node = LeafNode::default().into();
nodes.entry(hash).or_insert(dummy_leaf.encode_to_vec());
state_nodes.entry(hash).or_insert(dummy_leaf.clone());
}

drop(nodes);
drop(state_nodes);

let mut inner_store = in_memory_store.inner()?;

Expand All @@ -541,13 +517,33 @@ async fn replay_no_zkvm(cache: Cache, opts: &EthrexReplayOptions) -> eyre::Resul
continue;
};

let storage_root = AccountState::decode(&account_state_rlp)?.storage_root;
let account_state = AccountState::decode(&account_state_rlp)?;

// If code hash of account isn't present insert empty code so that if not found the execution doesn't break.
let code_hash = account_state.code_hash;
all_codes_hashed.entry(code_hash).or_insert(vec![]);

let storage_root = account_state.storage_root;
let storage_trie = match InMemoryTrieDB::from_nodes(storage_root, all_nodes) {
Ok(trie) => trie.inner,
Err(_) => continue,
};

// Fill storage trie with dummy branch nodes that have the hash of the missing nodes
// This is useful for eth_getProofs when we want to restructure the trie after removing a node whose sibling isn't known
// We assume the sibling is a branch node because we already covered the cases in which it's a Leaf or Extension node by injecting nodes in the witness.
// For more info read: https://github.com/kkrt-labs/zk-pig/blob/v0.8.0/docs/modified-mpt.md
{
let mut storage_nodes = storage_trie.lock().unwrap();
let dummy_branch = Node::from(BranchNode::default()).encode_to_vec();

let referenced_storage_node_hashes = get_referenced_hashes(&storage_nodes)?;

for hash in referenced_storage_node_hashes {
storage_nodes.entry(hash).or_insert(dummy_branch.clone());
}
}

inner_store
.storage_trie_nodes
.insert(H256::from_slice(&hashed_address), storage_trie);
Expand Down
36 changes: 36 additions & 0 deletions cmd/ethrex_replay/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::collections::{BTreeMap, HashSet};

use ethrex_rlp::decode::RLPDecode;
use ethrex_trie::{Node, NodeHash, NodeRef};

/// Given a mapping of nodes with their corresponding hash get all hashes referenced by branch and extension nodes.
pub fn get_referenced_hashes(
nodes: &BTreeMap<NodeHash, Vec<u8>>,
) -> eyre::Result<HashSet<NodeHash>> {
let mut referenced_hashes: HashSet<NodeHash> = HashSet::new();

for (_node_hash, node_rlp) in nodes.iter() {
let node = Node::decode(node_rlp)?;
match node {
Node::Branch(node) => {
for choice in &node.choices {
if let NodeRef::Hash(hash) = *choice {
referenced_hashes.insert(hash);
} else {
return Err(eyre::eyre!("Branch node contains non-hash reference"));
}
}
}
Node::Extension(node) => {
if let NodeRef::Hash(hash) = node.child {
referenced_hashes.insert(hash);
} else {
return Err(eyre::eyre!("Extension node contains non-hash reference"));
}
}
Node::Leaf(_node) => {}
}
}

Ok(referenced_hashes)
}
1 change: 1 addition & 0 deletions cmd/ethrex_replay/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod block_run_report;
mod cache;
pub mod cli;
mod fetcher;
mod helpers;
#[cfg(not(feature = "l2"))]
mod plot_composition;
pub mod rpc;
Expand Down
4 changes: 3 additions & 1 deletion cmd/ethrex_replay/src/rpc/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,9 @@ pub fn get_potential_child_nodes(proof: &[NodeRLP], key: &PathRLP) -> Option<Vec
}

let hash = if let Some(root) = proof.first() {
H256::from_slice(&Keccak256::digest(root))
let hash = H256::from_slice(&Keccak256::digest(root));
state_nodes.insert(hash, root.clone());
hash
} else {
*EMPTY_KECCACK_HASH
};
Expand Down
1 change: 0 additions & 1 deletion crates/common/trie/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,3 @@ path = "./trie.rs"
[[bench]]
name = "trie_bench"
harness = false

2 changes: 1 addition & 1 deletion crates/common/trie/node/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{ExtensionNode, LeafNode, Node, NodeRef, ValueOrHash};

/// Branch Node of an an Ethereum Compatible Patricia Merkle Trie
/// Contains the node's value and the hash of its children nodes
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BranchNode {
pub choices: [NodeRef; 16],
pub value: ValueRLP,
Expand Down