refactor(l1): remove keys dependency, pin ethrex deps, and add NativeCrypto#68
refactor(l1): remove keys dependency, pin ethrex deps, and add NativeCrypto#68avilagaston9 wants to merge 5 commits intomainfrom
Conversation
Instead of iterating witness.keys to get addresses and then looking up each in the state trie, enumerate accounts directly from the state trie's InMemoryTrieDB. After commit(), leaf entries have paths of 65 nibbles (64 for keccak256(address) + 1 leaf flag 0x10) with raw RLP-encoded AccountState as values. The first 64 nibbles are converted back to the 32-byte hashed address needed by the Store.
is_empty() check on storage_trie_nodes since get_trie_nodes_with_dummies always injects dummy branch nodes for every existing path.
There was a problem hiding this comment.
Pull request overview
This PR updates the L1 --no-zkvm replay state preparation to stop depending on the soon-to-be-removed ExecutionWitness.keys field by deriving the set of accounts from the state trie instead.
Changes:
- Removes usage of
witness.keys(and theethrex_storage::hash_addressimport) inprepare_no_zkvm_state. - Attempts to enumerate state-trie leaf entries from
InMemoryTrieDBand derive the hashed-address from the leaf path to write storage trie nodes.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let Ok(account_state) = AccountState::decode(account_state_rlp) else { | ||
| continue; | ||
| }; | ||
|
|
There was a problem hiding this comment.
account_state_rlp here is coming directly from InMemoryTrieDB::inner() which (as used in get_trie_nodes_with_dummies) stores RLP-encoded trie nodes at each path, not raw RLP-encoded AccountState. Decoding it as AccountState will fail (and you continue), so no storage tries get written and add_block_pipeline will likely read missing storage.
Instead, decode the value as a trie Node first, select only Leaf nodes, extract the leaf’s embedded value bytes, and then RLP-decode those bytes into AccountState before proceeding.
| let Ok(account_state) = AccountState::decode(account_state_rlp) else { | |
| continue; | |
| }; | |
| // `account_state_rlp` is actually an RLP-encoded trie `Node`, not a raw `AccountState`. | |
| let Ok(node) = Node::decode(account_state_rlp) else { | |
| continue; | |
| }; | |
| // Only leaf nodes contain account state; extract the embedded value bytes. | |
| let leaf_value = match &node { | |
| Node::Leaf(_, value) => value, | |
| _ => continue, | |
| }; | |
| let Ok(account_state) = AccountState::decode(leaf_value) else { | |
| continue; | |
| }; |
…ness branch and add NativeCrypto parameter to all call sites that now require it (sender, execute_block, prepare_block, get_transactions_with_sender, new_for_l1, new_for_l2). Also add ethrex-crypto as a direct dependency.
## Motivation The `keys` field in `ExecutionWitness` / `RpcExecutionWitness` is being phased out of the RPC spec. Our `execution_witness_from_rpc_chain_config` function (used by ethrex-replay) depended on `keys` to rebuild `storage_trie_roots`, which meant it would silently produce empty storage tries when `keys` was missing or empty. Follows up on #6338. ## Description - Remove `keys` from `ExecutionWitness`. Keep it in `RpcExecutionWitness` with `#[serde(default)]` for interoperability, but always emit it empty. - Change `storage_trie_roots` key from `Address` to `H256` (the keccak256 hash of the address). This aligns with how the state trie stores account paths. - Replace the `keys`-based loop in `execution_witness_from_rpc_chain_config` with a recursive state trie walker that discovers accounts and their storage roots directly from the trie leaves. - Update `GuestProgramState` fields (`storage_tries`, `verified_storage_roots`, `account_hashes_by_address`) to use `H256` keys consistently. ## How to Test - `cargo check --all-targets` - `cargo clippy --all-targets -- -D warnings` - Existing execution witness tests should pass unchanged ### End-to-end test with ethrex-replay 1. **Start an L1 dev node** (from the ethrex repo, on this branch): ```bash make -C crates/l2 init-l1 ``` 2. **Send a transaction** to produce a non-empty block: ```bash PRIVATE_KEY=0x850643a0224065ecce3882673c21f56bcf6eef86274cc21cadff15930b59fc8c rex send 0x0000000000000000000000000000000000000001 \ --value 1000000000000000000 \ -k $PRIVATE_KEY \ --rpc-url http://localhost:8545 ``` Note the block number from the receipt. 3. **Build ethrex-replay** (from [PR #68](lambdaclass/ethrex-replay#68)): ```bash cd ~/Documents/ethrex-replay git checkout fix/remove-keys-dependency cargo build --release ``` 4. **Run replay — no-zkvm path** (uses `Blockchain::add_block` directly): ```bash RUST_LOG=info ./target/release/ethrex-replay block <BLOCK_NUMBER> \ --rpc-url http://localhost:8545 \ --no-zkvm ``` 5. **Run replay — exec mode** (builds `ExecutionWitness` → `GuestProgramState`, runs guest program natively): ```bash RUST_LOG=info ./target/release/ethrex-replay block <BLOCK_NUMBER> \ --rpc-url http://localhost:8545 ``` Both should exit 0 with a successful replay.
…ss#6356) ## Motivation The `keys` field in `ExecutionWitness` / `RpcExecutionWitness` is being phased out of the RPC spec. Our `execution_witness_from_rpc_chain_config` function (used by ethrex-replay) depended on `keys` to rebuild `storage_trie_roots`, which meant it would silently produce empty storage tries when `keys` was missing or empty. Follows up on lambdaclass#6338. ## Description - Remove `keys` from `ExecutionWitness`. Keep it in `RpcExecutionWitness` with `#[serde(default)]` for interoperability, but always emit it empty. - Change `storage_trie_roots` key from `Address` to `H256` (the keccak256 hash of the address). This aligns with how the state trie stores account paths. - Replace the `keys`-based loop in `execution_witness_from_rpc_chain_config` with a recursive state trie walker that discovers accounts and their storage roots directly from the trie leaves. - Update `GuestProgramState` fields (`storage_tries`, `verified_storage_roots`, `account_hashes_by_address`) to use `H256` keys consistently. ## How to Test - `cargo check --all-targets` - `cargo clippy --all-targets -- -D warnings` - Existing execution witness tests should pass unchanged ### End-to-end test with ethrex-replay 1. **Start an L1 dev node** (from the ethrex repo, on this branch): ```bash make -C crates/l2 init-l1 ``` 2. **Send a transaction** to produce a non-empty block: ```bash PRIVATE_KEY=0x850643a0224065ecce3882673c21f56bcf6eef86274cc21cadff15930b59fc8c rex send 0x0000000000000000000000000000000000000001 \ --value 1000000000000000000 \ -k $PRIVATE_KEY \ --rpc-url http://localhost:8545 ``` Note the block number from the receipt. 3. **Build ethrex-replay** (from [PR lambdaclass#68](lambdaclass/ethrex-replay#68)): ```bash cd ~/Documents/ethrex-replay git checkout fix/remove-keys-dependency cargo build --release ``` 4. **Run replay — no-zkvm path** (uses `Blockchain::add_block` directly): ```bash RUST_LOG=info ./target/release/ethrex-replay block <BLOCK_NUMBER> \ --rpc-url http://localhost:8545 \ --no-zkvm ``` 5. **Run replay — exec mode** (builds `ExecutionWitness` → `GuestProgramState`, runs guest program natively): ```bash RUST_LOG=info ./target/release/ethrex-replay block <BLOCK_NUMBER> \ --rpc-url http://localhost:8545 ``` Both should exit 0 with a successful replay.
on main instead of tracking the now-merged branch. Also remove HOLESKY_CHAIN_ID and PublicNetwork::Holesky references which were removed from ethrex at that commit.
Motivation
The
ExecutionWitnessstruct in ethrex no longer includes akeysfield (removed in lambdaclass/ethrex#6356). The--no-zkvmreplay path relied onwitness.keysto discover account addresses and set up storage tries. This PR adapts ethrex-replay to the new API and pins dependencies to the merge commit.Description
Remove keys dependency in
--no-zkvmpath: Instead of iteratingwitness.keysto get addresses and then looking up each in the state trie, enumerate accounts directly from the state trie'sInMemoryTrieDB. Aftercommit(), leaf entries have paths of 65 nibbles (64 forkeccak256(address)+ 1 leaf flag0x10) with raw RLP-encodedAccountStateas values. The first 64 nibbles are converted back to the 32-byte hashed address needed by the Store.Add
NativeCryptoparameter: The ethrex refactor made theCryptoprovider injectable. All call sites that require it (sender,execute_block,prepare_block,get_transactions_with_sender,new_for_l1,new_for_l2) now passNativeCrypto. Addedethrex-cryptoas a direct dependency.Pin ethrex deps to a specific commit: Dependencies now use
rev = "b962fbfb..."(the merge commit of #6356 on main) instead of tracking a branch. This avoids unexpected breakage from upstream changes.Remove Holesky references:
HOLESKY_CHAIN_IDandPublicNetwork::Holeskywere removed from ethrex at the pinned commit (replaced by Hoodi).