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

statemanager: add put/delete test case #3787

Merged
merged 14 commits into from
Nov 6, 2024

Conversation

gabrocheleau
Copy link
Contributor

@gabrocheleau gabrocheleau commented Nov 3, 2024

This PR adds a test case that does the following:

  1. Creates a new verkleTree
  2. Puts an account into the verkleTree and gets the stateRoot (stateRoot1)
  3. Puts another account into the verkle tree and ensures that the stateRoot (stateRoot2) differs from stateRoot1
  4. Deletes account2 from the verkle tree and ensures that stateRoot now matches stateRoot1

This is currently failing and I suspect that this causes some failures that we are seeing in the test fixtures, most likely related to the handling of Untouched values and account deletion

Copy link

codecov bot commented Nov 3, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 48.93%. Comparing base (e38dccc) to head (aa8335b).
Report is 1 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 73.74% <ø> (ø)
blockchain 83.25% <ø> (ø)
client 0.00% <ø> (ø)
common 89.89% <ø> (ø)
devp2p 71.95% <ø> (ø)
evm 64.89% <ø> (ø)
genesis 100.00% <ø> (ø)
mpt 52.09% <ø> (+0.21%) ⬆️
statemanager 68.94% <ø> (+0.07%) ⬆️
tx 76.70% <ø> (ø)
util 72.78% <ø> (ø)
vm 57.37% <ø> (ø)
wallet 79.67% <ø> (ø)

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

@acolytec3
Copy link
Contributor

Additional changes I've added to this PR

  1. new dumpNodeHashes helper for viewing the hashes and paths of all nodes in a trie
  2. New logic branches in put to remove leaf nodes when all leaf values are written as untouched
  3. New logic to collapse inner nodes when it only has one leaf node value after deleting another leaf node and replace parent node reference with the surviving leaf node

Note, 2-3 should only ever happen when we are reverting an ephemeral state change (i.e. an account gets touched in the course of block execution but the tx reverts or an account is otherwise deleted prior to being written to state)

I'm not 100% confident this is the longterm approach we want since it would preferable to always just do our account updates ephemerally in a cache and only write to the trie once we are ready to "commit" and "flush" values to the db.

equalsBytes(startingNode, tree.root()) && entries.push(['0x', bytesToHex(startingNode)])
if (node instanceof LeafVerkleNode) {
// Leaf node paths/hashes were added in the previous inner node's iteration
return []
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 we could simplify a bit by just pushing the hashes if( node instanceOf InternalNode), and then returning entries (which would be the empty array in the case of a leafverkleNode, since it's been initialized as that)

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've pushed that change and made some minor simplifications/added some comments. Let me know how you like it.

let entries: [PrefixedHexString, PrefixedHexString][] = []
// Retrieve starting node from DB
const rawNode = await tree['_db'].get(startingNode)
if (rawNode === undefined) return
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do we want to return undefined here instead of [] ?

@@ -217,8 +217,20 @@ export class VerkleTree {
['put'],
)
}
// Push new/updated leafNode to putStack
putStack.push([leafNode.hash(), leafNode])
if (leafNode.values.filter((val) => val !== LeafVerkleNodeValue.Untouched).length === 0) {
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 was wondering, when troubleshooting over the weekend, if there should be another way to mark a node as "to be deleted" that does not require to "put untouched on all leafNode values".

I think your intuition of a lifecycle where we "commit" and "flush" sounds right. I don't think it's necessarily what we should do now (maybe worth discussing that tomorrow on the call?) as this PR definitely brings enough improvements to be merged (and can get us to iterate on verkle tests quicker), but I also feel like we need, in the end, a better architecture.

Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

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

LGTM

@acolytec3 acolytec3 merged commit 0440d5b into master Nov 6, 2024
41 checks passed
@acolytec3 acolytec3 deleted the statemanager/add-delete-stateRoott-test-case branch November 6, 2024 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants