-
Notifications
You must be signed in to change notification settings - Fork 131
chore(l2): optimize trie hashing and BranchNode encoding for zkVMs
#4723
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
Changes from all commits
a503cdb
cc65ec9
0d87f5b
2475090
9731165
bf46e33
9433e3c
7132ea0
71519ea
04faadd
f7195f2
3cbe873
b99f697
0c3571c
451b340
2f6f981
dfa1d27
d8e77d9
7d9aaac
b6cc6f6
0641b1f
fa6cd12
24b6804
5d3fa97
edf7050
44035c4
4f0e036
3dca224
86ae6a0
c2ed4d0
1df875c
538c2ab
caadcd2
deef7e0
cd19ec5
4b0af4b
90b17c2
85e88ae
8bd9ca3
98da8c1
0bc34be
7723608
f9accd3
44d134c
910d3cb
5e64c72
b1ccd89
4b9209a
2a1bab8
66c70c6
42e638d
68f9875
e701c6c
2720954
2815096
c3d8a8d
d7dadad
8bccc0c
951c6be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,8 +3,9 @@ use std::array; | |
| // Contains RLP encoding and decoding implementations for Trie Nodes | ||
| // This encoding is only used to store the nodes in the DB, it is not the encoding used for hash computation | ||
| use ethrex_rlp::{ | ||
| constants::RLP_NULL, | ||
| decode::{RLPDecode, decode_bytes}, | ||
| encode::RLPEncode, | ||
| encode::{RLPEncode, encode_length}, | ||
| error::RLPDecodeError, | ||
| structs::{Decoder, Encoder}, | ||
| }; | ||
|
|
@@ -14,18 +15,45 @@ use crate::{Nibbles, NodeHash}; | |
|
|
||
| impl RLPEncode for BranchNode { | ||
| fn encode(&self, buf: &mut dyn bytes::BufMut) { | ||
| let mut encoder = Encoder::new(buf); | ||
| let value_len = <[u8] as RLPEncode>::length(&self.value); | ||
| let payload_len = self.choices.iter().fold(value_len, |acc, child| { | ||
| acc + RLPEncode::length(child.compute_hash_ref()) | ||
| }); | ||
|
|
||
| encode_length(payload_len, buf); | ||
| for child in self.choices.iter() { | ||
| match child.compute_hash_ref() { | ||
| NodeHash::Hashed(hash) => hash.0.encode(buf), | ||
| NodeHash::Inline((_, 0)) => buf.put_u8(RLP_NULL), | ||
| NodeHash::Inline((encoded, len)) => buf.put_slice(&encoded[..*len as usize]), | ||
| } | ||
| } | ||
| <[u8] as RLPEncode>::encode(&self.value, buf); | ||
| } | ||
|
|
||
| // Duplicated to prealloc the buffer and avoid calculating the payload length twice | ||
| fn encode_to_vec(&self) -> Vec<u8> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should make
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing with that is that the generic If we call the current |
||
| let value_len = <[u8] as RLPEncode>::length(&self.value); | ||
| let choices_len = self.choices.iter().fold(0, |acc, child| { | ||
| acc + RLPEncode::length(child.compute_hash_ref()) | ||
| }); | ||
| let payload_len = choices_len + value_len; | ||
|
|
||
| let mut buf: Vec<u8> = Vec::with_capacity(payload_len + 3); // 3 byte prefix headroom | ||
|
|
||
| encode_length(payload_len, &mut buf); | ||
| for child in self.choices.iter() { | ||
| match child.compute_hash() { | ||
| NodeHash::Hashed(hash) => encoder = encoder.encode_bytes(&hash.0), | ||
| child @ NodeHash::Inline(raw) if raw.1 != 0 => { | ||
| encoder = encoder.encode_raw(child.as_ref()) | ||
| match child.compute_hash_ref() { | ||
| NodeHash::Hashed(hash) => hash.0.encode(&mut buf), | ||
| NodeHash::Inline((_, 0)) => buf.push(RLP_NULL), | ||
| NodeHash::Inline((encoded, len)) => { | ||
| buf.extend_from_slice(&encoded[..*len as usize]) | ||
| } | ||
| _ => encoder = encoder.encode_bytes(&[]), | ||
| } | ||
| } | ||
| encoder = encoder.encode_bytes(&self.value); | ||
| encoder.finish(); | ||
| <[u8] as RLPEncode>::encode(&self.value, &mut buf); | ||
|
|
||
| buf | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we build a vec to encode here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm not sure, maybe to take advantage of
NodeHash::as_ref()? might try changing it now that you mentioned itThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll do it in a different PR