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

core, eth, trie: prepare trie sync for path based operation #21504

Merged
merged 1 commit into from
Sep 2, 2020

Conversation

karalabe
Copy link
Member

@karalabe karalabe commented Aug 31, 2020

This is a small prep PR that separates trie node and byte code scheduling in trie.Sync and also starts tracking the Merkle paths belonging to a specific trie request. The goal is to prepare the code for snap sync, which has these two concepts separated and will also work on trie paths, not on hashes.

The "paths" pointing to a specific trie node (returned by trie.Sync.Missing) are either 1-tuple if the trie node belongs to the account trie; or a 2-tuple if it's a storage trie node. Partial paths (i.e. last items of both tuples) are stored in compact-encoded form, since they need to be able to represent odd nibbles. The first item of the 2-tuple (account hash) is simple binary encoding because we know it's always 32 bytes.

The reason for using 2-tuple instead of 1 long concatenated path is because it's simpler to look it up by serving code, which doesn't need to interpret the compact-encoding, rather can delegate it to the trie (a concatenated path would cross multiple tries, so the trie package along is not meant to handle it). It also helps keep the downloader scheduler simpler and permits it (or snap) to group storage requests and not send the account hash for each one individually (not implemented in this PR).

response [][]byte // Response data of the peer (nil for timeouts)
dropped bool // Flag whether the peer dropped off early
nItems uint16 // Number of items requested for download (max is 384, so uint16 is sufficient)
trieTasks map[common.Hash]*trieTask // Trie node ownload tasks to track previous attempts
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
trieTasks map[common.Hash]*trieTask // Trie node ownload tasks to track previous attempts
trieTasks map[common.Hash]*trieTask // Trie node download tasks to track previous attempts

eth/downloader/statesync.go Outdated Show resolved Hide resolved
eth/downloader/statesync.go Outdated Show resolved Hide resolved
eth/downloader/statesync.go Outdated Show resolved Hide resolved
trie/sync.go Outdated Show resolved Hide resolved
@@ -344,7 +377,7 @@ func (s *Sync) children(req *request, object node) ([]*request, error) {
// Notify any external watcher of a new key/value node
if req.callback != nil {
if node, ok := (child.node).(valueNode); ok {
if err := req.callback(req.path, node, req.hash); err != nil {
if err := req.callback(child.path, node, req.hash); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

This change looks like it's pretty substantial -- like this was previously wrong. What's the impact of changing this here?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was completely wrong before. It didn't pass in the full path to the leaf, rather omitted the suffix of the short node that ends in the leaf.

Copy link
Member Author

@karalabe karalabe Sep 2, 2020

Choose a reason for hiding this comment

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

So if we had a path like:

FullNode --0--> FullNode --1--> ShortNode --23456--> Account

Then the callback used the path 01 instead of 0123456 because the delivered request req was the ShortNode, but we're calling the callback on the value child of the short node.

Copy link
Contributor

Choose a reason for hiding this comment

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

And now, does it use 23456 or 0123456 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

trie/trie.go Show resolved Hide resolved
trie/trie.go Show resolved Hide resolved
trie/sync.go Outdated Show resolved Hide resolved
trie/sync.go Outdated Show resolved Hide resolved
Copy link
Contributor

@holiman holiman left a comment

Choose a reason for hiding this comment

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

Code LGTM, I've reached the limit of what I can review by eyes alone. Tests in production environment needed

@karalabe karalabe changed the title eth/downloader, trie: start exposing state sync paths @karalabe core, eth, trie: prepare trie sync for path based operation Sep 2, 2020
@karalabe karalabe changed the title @karalabe core, eth, trie: prepare trie sync for path based operation core, eth, trie: prepare trie sync for path based operation Sep 2, 2020
case *shortNode:
if len(path)-pos < len(n.Key) || !bytes.Equal(n.Key, path[pos:pos+len(n.Key)]) {
// Path branches off from short node
return nil, n, 0, nil
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure, but I have a hunch that this should be nil, n, 1, nil?
Because otherwise we don't set the root in line 157 properly.
Please disregard if I just didn't get it^^

Copy link
Member Author

@karalabe karalabe Sep 2, 2020

Choose a reason for hiding this comment

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

No, it's correct. That counter is meant to count how many hash nodes we've resolved (pulled up from the database). We only need to replace the root if we actually did expand the trie. This path doesn't expand the trie, it just reports a missing node.

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