Skip to content
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

Fixed trie hash collision issue when constructing storage tries #75

Merged
merged 6 commits into from
Mar 12, 2024

Conversation

BGluth
Copy link
Contributor

@BGluth BGluth commented Mar 1, 2024

Fixes the issue with hitting a hash node on block 17735424.

Essentially the issue was we were making the assumption that a trie's root would always uniquely identify it, which is not the case when you have two otherwise identical tries except different nodes are hashed/unhashed. The previous impl did not have access to the account key when parsing the embedded storage trie within the account trie and relied on creating a temporary map between trie_hash --> trie. This map would at the end of the decoding process be used to connect accounts with their storage tries.

However, with the above issue, this meant that sometimes (apparently extremely rarely) an account's storage trie would get swapped out with another "identical" trie that had different nodes hashed out. In the case of 17735424, an account was getting a trie that was entirely hashed out due to another storage trie overwriting it in the map.

A lot of the work in this PR is removing this old map of trie_hash --> trie and instead embedding the trie directly in AccountNodeData itself. Also needed to change compact_to_partial_trie.rs (which is used to parse both compact state and storage tries) to use a bit of specific logic for each.

- Previously we did not have access to the account key when we were
    constructing an account's storage trie from compact. To get around
    this, we made the "bad" assumption that a trie's root would uniquely
    identify the storage trie and used a mapping of `trie_root` --> `trie`
    to connect tries with accounts at the end of the decoding process.
- However, it is possible for a trie with hashed out nodes to have
    the same hash as one that does not.
- This was causing accounts with a specific trie to be rarely swapped
    out with one that had different nodes hashed/unhashed.
) -> CompactParsingResult<()> {
for (i, slot) in children.iter().enumerate().take(16) {
if let Some(child) = slot {
// TODO: Seriously update `mpt_trie` to have a better API...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about what you have in mind here!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this case I was not that happy that this was two lines:

let mut new_k = curr_key;
new_k.push_nibble_back(i as Nibble);

What might be kind of nice here is to have another method type coexisting with push_* that clones and does an operation to the Nibbles (maybe append_*?).

/// A type alias around `u64` for a block height.
pub type BlockHeight = u64;
/// A type alias around `[U256; 8]` for a bloom filter.
pub type Bloom = [U256; 8];
/// A type alias around `H256` for a code hash.
pub type CodeHash = H256;
/// A type alias for `H256` for an account address's hash.
/// A type alias around `H256` for an account address's hash.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "for" is correct here (and below). :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I'm indeed not a fan of the double for

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could replace the second for with of maybe?

trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
@Nashtare Nashtare added the crate: trace_decoder Anything related to the trace_decoder crate. label Mar 4, 2024
Copy link
Collaborator

@Nashtare Nashtare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Brendan, LGTM minus a few nits!

let remaining_node = remaining_entry
.into_node()
.expect("Final node in compact entries was not a node! This is a bug!");
fn process_code(&mut self, c_bytes: Vec<u8>) -> CompactParsingResult<()>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some doc on what the methods are doing for this new trait would be nice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah fair I agree. Let me add this.

trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
/// A type alias around `u64` for a block height.
pub type BlockHeight = u64;
/// A type alias around `[U256; 8]` for a bloom filter.
pub type Bloom = [U256; 8];
/// A type alias around `H256` for a code hash.
pub type CodeHash = H256;
/// A type alias for `H256` for an account address's hash.
/// A type alias around `H256` for an account address's hash.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I'm indeed not a fan of the double for

trace_decoder/src/compact/compact_to_partial_trie.rs Outdated Show resolved Hide resolved
Co-authored-by: Robin Salen <30937548+Nashtare@users.noreply.github.com>
Copy link
Contributor

@muursh muursh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the other comments have been addressed looks good to me

- Not directly releated to this PR, but it came up in the PR discussion
  that the comments for these types could be better.
@BGluth BGluth changed the base branch from main to develop March 12, 2024 15:33
@BGluth BGluth enabled auto-merge (squash) March 12, 2024 15:38
@BGluth BGluth merged commit 6dd642d into develop Mar 12, 2024
6 checks passed
@BGluth BGluth deleted the compact_storage_trie_collision_fix branch March 12, 2024 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crate: trace_decoder Anything related to the trace_decoder crate.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants