Skip to content

Commit

Permalink
trie: rework trie database
Browse files Browse the repository at this point in the history
  • Loading branch information
Francesco4203 committed Sep 27, 2024
1 parent 45ee924 commit b23fa68
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 370 deletions.
46 changes: 22 additions & 24 deletions trie/committer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
)

Expand Down Expand Up @@ -182,13 +183,12 @@ func (c *committer) store(path []byte, n node) node {
// We have the hash already, estimate the RLP encoding-size of the node.
// The size is used for mem tracking, does not need to be exact
var (
size = estimateSize(n)
nhash = common.BytesToHash(hash)
node = &nodeWithPrev{
nhash = common.BytesToHash(hash)
blob, _ = rlp.EncodeToBytes(n)
node = &nodeWithPrev{
&memoryNode{
nhash,
uint16(size),
simplifyNode(n),
blob,
},
c.tracer.accessList[string(path)],
}
Expand All @@ -209,31 +209,29 @@ func (c *committer) store(path []byte, n node) node {
return hash
}

// estimateSize estimates the size of an rlp-encoded node, without actually
// rlp-encoding it (zero allocs). This method has been experimentally tried, and with a trie
// with 1000 leafs, the only errors above 1% are on small shortnodes, where this
// method overestimates by 2 or 3 bytes (e.g. 37 instead of 35)
func estimateSize(n node) int {
// mptResolver the children resolver in merkle-patricia-tree.
type mptResolver struct{}

// ForEach implements childResolver, decodes the provided node and
// traverses the children inside.
func (resolver mptResolver) forEach(node []byte, onChild func(common.Hash)) {
forGatherChildren(mustDecodeNode(nil, node), onChild)
}

// forGatherChildren traverses the node hierarchy and invokes the callback
// for all the hashnode children.
func forGatherChildren(n node, onChild func(hash common.Hash)) {
switch n := n.(type) {
case *shortNode:
// A short node contains a compacted key, and a value.
return 3 + len(n.Key) + estimateSize(n.Val)
forGatherChildren(n.Val, onChild)
case *fullNode:
// A full node contains up to 16 hashes (some nils), and a key
s := 3
for i := 0; i < 16; i++ {
if child := n.Children[i]; child != nil {
s += estimateSize(child)
} else {
s++
}
forGatherChildren(n.Children[i], onChild)
}
return s
case valueNode:
return 1 + len(n)
case hashNode:
return 1 + len(n)
onChild(common.BytesToHash(n))
case valueNode, nil:
default:
panic(fmt.Sprintf("node type %T", n))
panic(fmt.Sprintf("unknown node type: %T", n))
}
}
Loading

0 comments on commit b23fa68

Please sign in to comment.