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

fix: exclude deleted values from proof #12390

Merged
merged 7 commits into from
Nov 8, 2024

Conversation

Longarithm
Copy link
Member

@Longarithm Longarithm commented Nov 5, 2024

TLDR: the change is very small, majority is the test.

Before recording resharding proof, I want to slightly improve MemTrieUpdate::to_trie_changes API. It returns TrieAccesses which includes values which were read during processing state changes. But in fact, we don't need the removed values at all, to generate proof. Because we have hash uniqueness, it's enough to find that node has a value with arbitrary hash.

Currently it adds weird dependency on DBCol::State, as memtries don't have long values, so I completely remove values from the proof.

If we don't consider migration, then for correctness it is enough to maintain the same behaviour on memtrie, disk and partial storage processing. I achieve that by removing value accesses simultaneously, with removing values.insert and internal_retrieve_trie_node.

Migration could be annoying - it's possible that chunk producers may have this adopted and chunk validators may not, then CV would receive insufficient proof. But I checked all TrieUpdate::remove calls, and, surprisingly, each remove is prepended with getting value. For VMLogic' storage remove API requires to get previous value, for account removal we iterate over all keys and values because that's how iterator works. So with current runtime this change is even no-op.

I still find it worthy to write a test triggering test_create_delete_account because we don't have any integration test exercising this path. I tried to write it in intuitive way and manually checked that if runtime removes value without reading, and my change is inconsistent, then test fails.

@Longarithm Longarithm changed the title draft: exclude deleted values from proof fix: exclude deleted values from proof Nov 6, 2024
@Longarithm Longarithm marked this pull request as ready for review November 6, 2024 23:11
@Longarithm Longarithm requested a review from a team as a code owner November 6, 2024 23:11
@@ -1675,15 +1660,6 @@ impl Trie {
for (node_hash, serialized_node) in trie_accesses.nodes {
recorder.borrow_mut().record(&node_hash, serialized_node);
}
for (value_hash, value) in trie_accesses.values {
Copy link
Contributor

@tayfunelmas tayfunelmas Nov 7, 2024

Choose a reason for hiding this comment

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

I guess by exclude deleted values you mean the previous values being replaced with new values at the corresponding keys? is the reason this is safe because the validator will run the code that will provide the new value anyways?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, these are all deleted values. Let me explain that:

If you are validator, you trust to the root first, because it was signed by validators on the previous step. And then you trust its children, because they hash into the root and we have uniqueness, then we trust their children, etc.
And when we reach the ValueRef, we don't actually need the whole value. We need ValueRef::length to recompute memory usage, which we trust already, and after that we just set value to None and squash necessary nodes on the way.

Intermediate nodes are still required to prove that value exists, though.

Side note - inserted values are not part of the proof, because they are result of previous state proof + chunk execution.

Copy link
Contributor

Choose a reason for hiding this comment

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

got it, thanks for explaining. lgtm

Copy link
Contributor

@tayfunelmas tayfunelmas left a comment

Choose a reason for hiding this comment

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

Looks ok, but need other's reviews to see if I miss anything. Also thanks for the nice refactoring in the testloop utils.

Copy link

codecov bot commented Nov 7, 2024

Codecov Report

Attention: Patch coverage is 93.85965% with 7 lines in your changes missing coverage. Please review.

Project coverage is 71.62%. Comparing base (9c29bc3) to head (235177c).
Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
...egration-tests/src/test_loop/utils/transactions.rs 93.57% 1 Missing and 6 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12390      +/-   ##
==========================================
+ Coverage   71.60%   71.62%   +0.01%     
==========================================
  Files         842      842              
  Lines      170717   170804      +87     
  Branches   170717   170804      +87     
==========================================
+ Hits       122243   122338      +95     
+ Misses      43101    43084      -17     
- Partials     5373     5382       +9     
Flag Coverage Δ
backward-compatibility 0.16% <0.00%> (+<0.01%) ⬆️
db-migration 0.16% <0.00%> (+<0.01%) ⬆️
genesis-check 1.27% <0.00%> (+<0.01%) ⬆️
integration-tests 39.28% <91.22%> (+0.11%) ⬆️
linux 70.63% <93.85%> (+0.02%) ⬆️
linux-nightly 71.20% <93.85%> (+0.01%) ⬆️
macos 50.60% <100.00%> (-0.01%) ⬇️
pytests 1.57% <0.00%> (+<0.01%) ⬆️
sanity-checks 1.38% <0.00%> (+<0.01%) ⬆️
unittests 64.23% <100.00%> (-0.01%) ⬇️
upgradability 0.21% <0.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines -1678 to -1686
for (value_hash, value) in trie_accesses.values {
let value = match value {
FlatStateValue::Ref(_) => {
self.storage.retrieve_raw_bytes(&value_hash)?
}
FlatStateValue::Inlined(value) => value.into(),
};
recorder.borrow_mut().record(&value_hash, value);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that we don't need the values for removed nodes. However here it seems like you don't record any values at all, including the ones that were just read. Are those stored elsewhere? I do see that the tests are still passing so I think believe the change is good, I'm just trying to understand it.

Copy link
Member Author

Choose a reason for hiding this comment

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

We can say that trie nodes are recorded in two phases - 1) during trie lookups on chunk processing, 2) during trie updates. This is the 2nd phase.

1st happens mainly in lookup_from_memory for memtries or internal_retrieve_trie_node for trie storage.

From other perspective, if value was just read but not modified, it wouldn't appear here, so this part is incomplete anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alright, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

nice new utilities!

Copy link
Contributor

@wacban wacban left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines -1678 to -1686
for (value_hash, value) in trie_accesses.values {
let value = match value {
FlatStateValue::Ref(_) => {
self.storage.retrieve_raw_bytes(&value_hash)?
}
FlatStateValue::Inlined(value) => value.into(),
};
recorder.borrow_mut().record(&value_hash, value);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Alright, thanks!

@Longarithm Longarithm added this pull request to the merge queue Nov 8, 2024
Merged via the queue into near:master with commit 5d3008b Nov 8, 2024
29 checks passed
@Longarithm Longarithm deleted the no-record-values branch November 8, 2024 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants