-
Notifications
You must be signed in to change notification settings - Fork 71
refactor(core/rawdb): improve db APIs for accessing trie nodes #29362 #2313
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
base: dev-upgrade
Are you sure you want to change the base?
Changes from all commits
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 | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,7 +22,6 @@ import ( | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| "github.com/XinFinOrg/XDPoSChain/common" | ||||||||||||||||||||||||||||
| "github.com/XinFinOrg/XDPoSChain/crypto" | ||||||||||||||||||||||||||||
| "github.com/XinFinOrg/XDPoSChain/crypto/keccak" | ||||||||||||||||||||||||||||
| "github.com/XinFinOrg/XDPoSChain/ethdb" | ||||||||||||||||||||||||||||
| "github.com/XinFinOrg/XDPoSChain/log" | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
@@ -46,45 +45,39 @@ const HashScheme = "hashScheme" | |||||||||||||||||||||||||||
| // on extra state diffs to survive deep reorg. | ||||||||||||||||||||||||||||
| const PathScheme = "pathScheme" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // nodeHasher used to derive the hash of trie node. | ||||||||||||||||||||||||||||
| type nodeHasher struct{ sha crypto.KeccakState } | ||||||||||||||||||||||||||||
| // hasher is used to compute the sha256 hash of the provided data. | ||||||||||||||||||||||||||||
| type hasher struct{ sha crypto.KeccakState } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| var hasherPool = sync.Pool{ | ||||||||||||||||||||||||||||
| New: func() interface{} { return &nodeHasher{sha: keccak.NewLegacyKeccak256().(crypto.KeccakState)} }, | ||||||||||||||||||||||||||||
| New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} }, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func newNodeHasher() *nodeHasher { return hasherPool.Get().(*nodeHasher) } | ||||||||||||||||||||||||||||
| func returnHasherToPool(h *nodeHasher) { hasherPool.Put(h) } | ||||||||||||||||||||||||||||
| func newHasher() *hasher { | ||||||||||||||||||||||||||||
| return hasherPool.Get().(*hasher) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func (h *nodeHasher) hashData(data []byte) (n common.Hash) { | ||||||||||||||||||||||||||||
| h.sha.Reset() | ||||||||||||||||||||||||||||
| h.sha.Write(data) | ||||||||||||||||||||||||||||
| h.sha.Read(n[:]) | ||||||||||||||||||||||||||||
| return n | ||||||||||||||||||||||||||||
| func (h *hasher) hash(data []byte) common.Hash { | ||||||||||||||||||||||||||||
| return crypto.HashData(h.sha, data) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // ReadAccountTrieNode retrieves the account trie node and the associated node | ||||||||||||||||||||||||||||
| // hash with the specified node path. | ||||||||||||||||||||||||||||
| func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) ([]byte, common.Hash) { | ||||||||||||||||||||||||||||
| data, err := db.Get(accountTrieNodeKey(path)) | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| return nil, common.Hash{} | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| hasher := newNodeHasher() | ||||||||||||||||||||||||||||
| defer returnHasherToPool(hasher) | ||||||||||||||||||||||||||||
| return data, hasher.hashData(data) | ||||||||||||||||||||||||||||
| func (h *hasher) release() { | ||||||||||||||||||||||||||||
| hasherPool.Put(h) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // ReadAccountTrieNode retrieves the account trie node with the specified node path. | ||||||||||||||||||||||||||||
| func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) []byte { | ||||||||||||||||||||||||||||
| data, _ := db.Get(accountTrieNodeKey(path)) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
| data, _ := db.Get(accountTrieNodeKey(path)) | |
| key := accountTrieNodeKey(path) | |
| has, err := db.Has(key) | |
| if err != nil { | |
| log.Crit("Failed to check account trie node", "err", err) | |
| } | |
| if !has { | |
| return nil | |
| } | |
| data, err := db.Get(key) | |
| if err != nil { | |
| log.Crit("Failed to read account trie node", "err", err) | |
| } |
Copilot
AI
Apr 17, 2026
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.
ReadStorageTrieNode discards the db.Get error and returns the raw data unconditionally. Callers later treat len(data)==0 as "missing", which is not equivalent to "key not found" and can also mask non-NotFound DB read failures. Consider returning (data, error)/(data, ok) or ensure callers check the Get error.
Copilot
AI
Apr 17, 2026
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.
In the PathScheme branch, existence is inferred via len(blob)==0 after calling Read*TrieNode (which currently ignores db.Get errors). This makes "missing" depend on the stored value length (and treats a present-but-empty value as absent) and also prevents distinguishing genuine DB read errors from NotFound. Prefer checking the db.Get error (or a boolean ok) to decide existence, then hash the returned bytes (even if empty).
Copilot
AI
Apr 17, 2026
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.
This inline comment is misleading: the function returns whether the computed hash matches the provided hash; it doesn't specifically indicate the "exists but not match" case. Please reword the comment (or remove it) so it describes the boolean result accurately.
| return h.hash(blob) == hash // exists but not match | |
| return h.hash(blob) == hash // whether the stored node matches the provided hash |
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.
The comment says this helper computes a sha256 hash, but the implementation uses Keccak (via crypto.NewKeccakState/crypto.HashData). Please update the comment (and any related naming) to avoid misleading future maintainers about the hashing algorithm used here.