forked from cerc-io/plugeth
all: implement path-based state scheme (#25963)
* all: implement path-based state scheme * all: edits from review * core/rawdb, trie/triedb/pathdb: review changes * core, light, trie, eth, tests: reimplement pbss history * core, trie/triedb/pathdb: track block number in state history * trie/triedb/pathdb: add history documentation * core, trie/triedb/pathdb: address comments from Peter's review Important changes to list: - Cache trie nodes by path in clean cache - Remove root->id mappings when history is truncated * trie/triedb/pathdb: fallback to disk if unexpect node in clean cache * core/rawdb: fix tests * trie/triedb/pathdb: rename metrics, change clean cache key * trie/triedb: manage the clean cache inside of disk layer * trie/triedb/pathdb: move journal function * trie/triedb/path: fix tests * trie/triedb/pathdb: fix journal * trie/triedb/pathdb: fix history * trie/triedb/pathdb: try to fix tests on windows * core, trie: address comments * trie/triedb/pathdb: fix test issues --------- Co-authored-by: Felix Lange <fjl@twurst.com> Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
co-authored by
Felix Lange
Martin Holst Swende
parent
9d744f0ca8
commit
7de748d3f6
+22
-40
@@ -25,8 +25,8 @@ import (
|
||||
)
|
||||
|
||||
// Node is a wrapper which contains the encoded blob of the trie node and its
|
||||
// unique hash identifier. It is general enough that can be used to represent
|
||||
// trie nodes corresponding to different trie implementations.
|
||||
// node hash. It is general enough that can be used to represent trie node
|
||||
// corresponding to different trie implementations.
|
||||
type Node struct {
|
||||
Hash common.Hash // Node hash, empty for deleted node
|
||||
Blob []byte // Encoded node blob, nil for the deleted node
|
||||
@@ -42,35 +42,13 @@ func (n *Node) IsDeleted() bool {
|
||||
return n.Hash == (common.Hash{})
|
||||
}
|
||||
|
||||
// WithPrev wraps the Node with the previous node value attached.
|
||||
type WithPrev struct {
|
||||
*Node
|
||||
Prev []byte // Encoded original value, nil means it's non-existent
|
||||
}
|
||||
|
||||
// Unwrap returns the internal Node object.
|
||||
func (n *WithPrev) Unwrap() *Node {
|
||||
return n.Node
|
||||
}
|
||||
|
||||
// Size returns the total memory size used by this node. It overloads
|
||||
// the function in Node by counting the size of previous value as well.
|
||||
func (n *WithPrev) Size() int {
|
||||
return n.Node.Size() + len(n.Prev)
|
||||
}
|
||||
|
||||
// New constructs a node with provided node information.
|
||||
func New(hash common.Hash, blob []byte) *Node {
|
||||
return &Node{Hash: hash, Blob: blob}
|
||||
}
|
||||
|
||||
// NewWithPrev constructs a node with provided node information.
|
||||
func NewWithPrev(hash common.Hash, blob []byte, prev []byte) *WithPrev {
|
||||
return &WithPrev{
|
||||
Node: New(hash, blob),
|
||||
Prev: prev,
|
||||
}
|
||||
}
|
||||
// NewDeleted constructs a node which is deleted.
|
||||
func NewDeleted() *Node { return New(common.Hash{}, nil) }
|
||||
|
||||
// leaf represents a trie leaf node
|
||||
type leaf struct {
|
||||
@@ -83,7 +61,7 @@ type leaf struct {
|
||||
type NodeSet struct {
|
||||
Owner common.Hash
|
||||
Leaves []*leaf
|
||||
Nodes map[string]*WithPrev
|
||||
Nodes map[string]*Node
|
||||
updates int // the count of updated and inserted nodes
|
||||
deletes int // the count of deleted nodes
|
||||
}
|
||||
@@ -93,7 +71,7 @@ type NodeSet struct {
|
||||
func NewNodeSet(owner common.Hash) *NodeSet {
|
||||
return &NodeSet{
|
||||
Owner: owner,
|
||||
Nodes: make(map[string]*WithPrev),
|
||||
Nodes: make(map[string]*Node),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,17 +82,17 @@ func (set *NodeSet) ForEachWithOrder(callback func(path string, n *Node)) {
|
||||
for path := range set.Nodes {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
// Bottom-up, longest path first
|
||||
// Bottom-up, the longest path first
|
||||
slices.SortFunc(paths, func(a, b string) bool {
|
||||
return a > b // Sort in reverse order
|
||||
})
|
||||
for _, path := range paths {
|
||||
callback(path, set.Nodes[path].Unwrap())
|
||||
callback(path, set.Nodes[path])
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds the provided node into set.
|
||||
func (set *NodeSet) AddNode(path []byte, n *WithPrev) {
|
||||
func (set *NodeSet) AddNode(path []byte, n *Node) {
|
||||
if n.IsDeleted() {
|
||||
set.deletes += 1
|
||||
} else {
|
||||
@@ -124,7 +102,7 @@ func (set *NodeSet) AddNode(path []byte, n *WithPrev) {
|
||||
}
|
||||
|
||||
// Merge adds a set of nodes into the set.
|
||||
func (set *NodeSet) Merge(owner common.Hash, nodes map[string]*WithPrev) error {
|
||||
func (set *NodeSet) Merge(owner common.Hash, nodes map[string]*Node) error {
|
||||
if set.Owner != owner {
|
||||
return fmt.Errorf("nodesets belong to different owner are not mergeable %x-%x", set.Owner, owner)
|
||||
}
|
||||
@@ -172,16 +150,11 @@ func (set *NodeSet) Summary() string {
|
||||
for path, n := range set.Nodes {
|
||||
// Deletion
|
||||
if n.IsDeleted() {
|
||||
fmt.Fprintf(out, " [-]: %x prev: %x\n", path, n.Prev)
|
||||
fmt.Fprintf(out, " [-]: %x\n", path)
|
||||
continue
|
||||
}
|
||||
// Insertion
|
||||
if len(n.Prev) == 0 {
|
||||
fmt.Fprintf(out, " [+]: %x -> %v\n", path, n.Hash)
|
||||
continue
|
||||
}
|
||||
// Update
|
||||
fmt.Fprintf(out, " [*]: %x -> %v prev: %x\n", path, n.Hash, n.Prev)
|
||||
// Insertion or update
|
||||
fmt.Fprintf(out, " [+/*]: %x -> %v \n", path, n.Hash)
|
||||
}
|
||||
}
|
||||
for _, n := range set.Leaves {
|
||||
@@ -217,3 +190,12 @@ func (set *MergedNodeSet) Merge(other *NodeSet) error {
|
||||
set.Sets[other.Owner] = other
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flatten returns a two-dimensional map for internal nodes.
|
||||
func (set *MergedNodeSet) Flatten() map[common.Hash]map[string]*Node {
|
||||
nodes := make(map[common.Hash]map[string]*Node)
|
||||
for owner, set := range set.Sets {
|
||||
nodes[owner] = set.Nodes
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user