trie: polish

This commit is contained in:
Gary Rong 2025-05-26 09:25:29 +08:00
parent 4c85ff8ca5
commit e7e19e7ff1
4 changed files with 15 additions and 17 deletions

View file

@ -65,9 +65,11 @@ func (h *hasher) hash(n node, force bool) []byte {
case *shortNode: case *shortNode:
enc := h.encodeShortNode(n) enc := h.encodeShortNode(n)
if len(enc) < 32 && !force { if len(enc) < 32 && !force {
// Nodes smaller than 32 bytes are embedded directly in their parent.
// In such cases, return the raw encoded blob instead of the node hash.
buf := make([]byte, len(enc)) buf := make([]byte, len(enc))
copy(buf, enc) copy(buf, enc)
return buf // Nodes smaller than 32 bytes are stored inside their parent return buf
} }
hash := h.hashData(enc) hash := h.hashData(enc)
n.flags.hash = hash n.flags.hash = hash
@ -76,9 +78,11 @@ func (h *hasher) hash(n node, force bool) []byte {
case *fullNode: case *fullNode:
enc := h.encodeFullNode(n) enc := h.encodeFullNode(n)
if len(enc) < 32 && !force { if len(enc) < 32 && !force {
// Nodes smaller than 32 bytes are embedded directly in their parent.
// In such cases, return the raw encoded blob instead of the node hash.
buf := make([]byte, len(enc)) buf := make([]byte, len(enc))
copy(buf, enc) copy(buf, enc)
return buf // Nodes smaller than 32 bytes are stored inside their parent return buf
} }
hash := h.hashData(enc) hash := h.hashData(enc)
n.flags.hash = hash n.flags.hash = hash
@ -110,6 +114,8 @@ func (h *hasher) encodeShortNode(n *shortNode) []byte {
return h.encodedBytes() return h.encodedBytes()
} }
// fnEncoderPool is the pool for storing shared fullNode encoder to mitigate
// the significant memory allocation overhead.
var fnEncoderPool = sync.Pool{ var fnEncoderPool = sync.Pool{
New: func() interface{} { New: func() interface{} {
var enc fullnodeEncoder var enc fullnodeEncoder
@ -189,10 +195,7 @@ func (h *hasher) hashDataTo(dst, data []byte) {
h.sha.Read(dst) h.sha.Read(dst)
} }
// proofHash is used to construct trie proofs, and returns the 'collapsed' // proofHash is used to construct trie proofs, returning the rlp-encoded node blobs.
// node (for later RLP encoding) as well as the hashed node -- unless the
// node is smaller than 32 bytes, in which case it will be returned as is.
// This method does not do anything on value- or hash-nodes.
func (h *hasher) proofHash(original node) []byte { func (h *hasher) proofHash(original node) []byte {
switch n := original.(type) { switch n := original.(type) {
case *shortNode: case *shortNode:

View file

@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"container/heap" "container/heap"
"errors" "errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )

View file

@ -46,14 +46,11 @@ func (n *fullnodeEncoder) encode(w rlp.EncoderBuffer) {
if len(c) == 0 { if len(c) == 0 {
w.Write(rlp.EmptyString) w.Write(rlp.EmptyString)
} else { } else {
if i == 16 { // valueNode or hashNode
w.WriteBytes(c) // valueNode if i == 16 || len(c) >= 32 {
w.WriteBytes(c)
} else { } else {
if len(c) < 32 {
w.Write(c) // rawNode w.Write(c) // rawNode
} else {
w.WriteBytes(c) // hashNode
}
} }
} }
} }
@ -84,7 +81,7 @@ func (n *extNodeEncoder) encode(w rlp.EncoderBuffer) {
w.WriteBytes(n.Key) w.WriteBytes(n.Key)
if n.Val == nil { if n.Val == nil {
w.Write(rlp.EmptyString) w.Write(rlp.EmptyString) // theoretically impossible to happen
} else if len(n.Val) < 32 { } else if len(n.Val) < 32 {
w.Write(n.Val) // rawNode w.Write(n.Val) // rawNode
} else { } else {

View file

@ -87,9 +87,6 @@ func (t *Trie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
for i, n := range nodes { for i, n := range nodes {
enc := hasher.proofHash(n) enc := hasher.proofHash(n)
if len(enc) == 32 {
fmt.Println("DEBUG")
}
if len(enc) >= 32 || i == 0 { if len(enc) >= 32 || i == 0 {
proofDb.Put(crypto.Keccak256(enc), enc) proofDb.Put(crypto.Keccak256(enc), enc)
} }