-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tracking: SMT in trace decoder #275
Comments
The backend does a bunch of tree reshaping, editing account balances etc, before spitting out some There are two key challenges to face as we add Type 2 🥈 support
The key data structure is this: zk_evm/trace_decoder/src/decoding.rs Lines 203 to 208 in 5315442
All those Here are the API's for the two data structures AIUI: zk_evm/trace_decoder/src/hermez_cdk_erigon.rs Lines 45 to 88 in 5315442
If you squint, they're very similar. Important the rest of this document hinges on them being compatible - I need to know now if they're not in some way I'm missing I think there are two viable approaches for refactoring:
I think With
|
.insert(val_k, updated_account_bytes.to_vec()) |
zk_evm/trace_decoder/src/decoding.rs
Line 597 in 5315442
.insert(h_addr_nibs, rlp::encode(&acc_data).to_vec()) |
plonky2
has deeper knowledge of the tries. Presumably in the SemanticTrie -> MPT
conversion we can ensure we uphold the invariants required. zk_evm/trace_decoder/src/decoding.rs
Lines 460 to 474 in 5315442
/// If a branch collapse occurred after a delete, then we must ensure that | |
/// the other single child that remains also is not hashed when passed into | |
/// plonky2. Returns the key to the remaining child if a collapse occurred. | |
fn delete_node_and_report_remaining_key_if_branch_collapsed( | |
trie: &mut HashedPartialTrie, | |
delete_k: &Nibbles, | |
) -> TrieOpResult<Option<Nibbles>> { | |
let old_trace = get_trie_trace(trie, delete_k); | |
trie.delete(*delete_k)?; | |
let new_trace = get_trie_trace(trie, delete_k); | |
Ok(node_deletion_resulted_in_a_branch_collapse( | |
&old_trace, &new_trace, | |
)) | |
} |
Since the mpt "values" are only ever AccountRlp
, I think a semantically equivalent version of this member looks like this:
zk_evm/trace_decoder/src/hermez_cdk_erigon.rs
Lines 21 to 42 in 5315442
pub struct SemanticTrie<S> { | |
pub hash2hash: HashMap<U256, U256, S>, | |
pub address2account_info: HashMap<Address, AccountInfo, S>, | |
// or should this be hash(address)? ~~^ | |
} | |
impl<S> SemanticTrie<S> { | |
pub fn root_as_mpt(&self) -> U256 { | |
todo!() | |
} | |
pub fn root_as_smt(&self) -> U256 { | |
todo!() | |
} | |
} | |
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] | |
pub struct AccountInfo { | |
pub balance: Option<ethereum_types::U256>, | |
pub nonce: Option<ethereum_types::U256>, | |
pub code_hash: Option<ethereum_types::H256>, | |
pub storage_root: Option<ethereum_types::H256>, | |
} |
storage
I think this is the most challenging
I think it ultimately is a mapping from address (or hash(address)?) to AccountRlp:
zk_evm/trace_decoder/src/lib.rs
Lines 382 to 391 in 5315442
let accounts = state | |
.items() | |
.filter_map(|(address, leaf)| { | |
Some( | |
rlp::decode::<AccountRlp>(leaf.as_val()?) | |
.context("expected `state` trie value leaves to consist only of AccountRlp") | |
.map(|account| (H256::from(address), account)), | |
) | |
}) | |
.collect::<Result<_, _>>()?; |
txn
Is never written
receipt
Is only written in one location:
zk_evm/trace_decoder/src/decoding.rs
Lines 296 to 298 in 5315442
trie_state | |
.receipt | |
.insert(txn_k, meta.receipt_node_bytes.as_ref()) |
Apologies for not looking at this sooner. A few comments that I hope will clarify some items
GenerationInputs::tries uses the (MPT/Type 1 🥇) format: I'm not sure I understand how this can be considered out of scope, as the
Minor clarification, but the last statement is not accurate. Transaction and Receipt tries do not change, and are still That being said, I agree with you that "2. Find some semantic representation, flushing out a hash using the required format when needed." seems the way to go. To clarify on your comment "it implies that plonky2 has deeper knowledge of the tries." on
Yes it is, just above the |
Yeah, I found having redundant type aliases for
Hey could you elaborate a bit more on what this might look like? Are you thinking about using a trait to abstract the common operations away (eg. insert, hash, etc.) between the two trie types? This is what my original attempt at adding smt support was attempting to do, as the delta application logic is nearly identical between |
MVP for this was shipped in #732 |
Motivation
Previous work
trace_decoder
#198Background
Terminology
MPT
andSMT
are two datastructures used by Type 1 🥇 and Type 2 🥈 respectively.Story
zero-bin
makes RPC calls to an Ethereum node.It requests special traces for a block,
and assembles them into some
trace_decoder
structures.zero-bin
askstrace_decoder
to assemble someevm_arithmetization
structures.zero-bin
makesseveral
calls
to
proof_gen
andevm_arithmetization
to actually produce a resultCurrent pieces of the puzzle
0xPolygonZero/erigon @ feat/zero
0xPolygonHermez/cdk-erigon @ zkevm
trace_decoder
0xPolygonZero/zk_evm/trace_decoder @ develop
zero-bin
0xPolygonZero/zero-bin @ develop
evm_arithmetization
0xPolygonZero/zk_evm/evm_arithmetization @ develop
0xPolygonZero/zk_evm/evm_arithmetization @ feat/type2
*proof_gen
0xPolygonZero/zk_evm/proof_gen @ develop
0xPolygonZero/zk_evm/proof_gen @ feat/type2
** marks a non-default branch
How
trace_decoder
worksmpt_trie
evm_arithmetization
Work
This issue tracks filling in the
trace_decoder
for Type 2 🥈.Plan
trace_decoder
#309 also adds a frontend for the Type 2 🥈 wire format.Footnotes
https://vitalik.eth.limo/general/2022/08/04/zkevm.html ↩ ↩2
The text was updated successfully, but these errors were encountered: