Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion XDCx/tradingstate/XDCx_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import (
"fmt"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/trie"
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

// XDCXTrie wraps a trie with key hashing. In a secure trie, all
Expand Down Expand Up @@ -165,7 +167,7 @@ func (t *XDCXTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
// TODO(daniel): The following code may be incorrect, ref PR #25320:
root, nodes := t.trie.Commit(false)
if nodes != nil {
if err := t.trie.UpdateDb(trie.NewWithNodeSet(nodes)); err != nil {
if err := t.trie.UpdateDb(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes)); err != nil {
return common.Hash{}, err
}
}
Expand Down
4 changes: 3 additions & 1 deletion XDCxlending/lendingstate/XDCx_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import (
"fmt"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/trie"
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

// XDCXTrie wraps a trie with key hashing. In a secure trie, all
Expand Down Expand Up @@ -161,7 +163,7 @@ func (t *XDCXTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
// TODO(daniel): The following code may be incorrect, ref PR #25320:
root, nodes := t.trie.Commit(false)
if nodes != nil {
if err := t.trie.UpdateDb(trie.NewWithNodeSet(nodes)); err != nil {
if err := t.trie.UpdateDb(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes)); err != nil {
return common.Hash{}, err
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -957,8 +957,8 @@ func (bc *BlockChain) Stop() {
bc.logger.OnClose()
}
// Flush the collected preimages to disk
if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil {
log.Error("Failed to commit trie preimages", "err", err)
if err := bc.stateCache.TrieDB().Close(); err != nil {
log.Error("Failed to close trie db", "err", err)
}
log.Info("Blockchain manager stopped")
}
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ func TestTrieForkGC(t *testing.T) {
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
}
if len(chain.stateCache.TrieDB().Nodes()) > 0 {
if nodes, _ := chain.TrieDB().Size(); nodes > 0 {
t.Fatalf("stale tries still alive after garbase collection")

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

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

The spelling "garbase" is incorrect and should be "garbage".

Suggested change
t.Fatalf("stale tries still alive after garbase collection")
t.Fatalf("stale tries still alive after garbage collection")

Copilot uses AI. Check for mistakes.
}
}
Expand Down
48 changes: 47 additions & 1 deletion core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"encoding/binary"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/metrics"
)

Expand Down Expand Up @@ -64,7 +65,7 @@ var (
// used by old db, now only used for conversion
oldReceiptsPrefix = []byte("receipts-")

// Path-based trie node scheme.
// Path-based storage scheme of merkle patricia trie.
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node

Expand Down Expand Up @@ -211,6 +212,51 @@ func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte {
return append(append(trieNodeStoragePrefix, accountHash.Bytes()...), path...)
}

// IsLegacyTrieNode reports whether a provided database entry is a legacy trie
// node. The characteristics of legacy trie node are:
// - the key length is 32 bytes
// - the key is the hash of val
func IsLegacyTrieNode(key []byte, val []byte) bool {
if len(key) != common.HashLength {
return false
}
return bytes.Equal(key, crypto.Keccak256(val))
}

// IsAccountTrieNode reports whether a provided database entry is an account
// trie node in path-based state scheme.
func IsAccountTrieNode(key []byte) (bool, []byte) {
if !bytes.HasPrefix(key, trieNodeAccountPrefix) {
return false, nil
}
// The remaining key should only consist a hex node path
// whose length is in the range 0 to 64 (64 is excluded
// since leaves are always wrapped with shortNode).
if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 {
return false, nil
}
return true, key[len(trieNodeAccountPrefix):]
}

// IsStorageTrieNode reports whether a provided database entry is a storage
// trie node in path-based state scheme.
func IsStorageTrieNode(key []byte) (bool, common.Hash, []byte) {
if !bytes.HasPrefix(key, trieNodeStoragePrefix) {
return false, common.Hash{}, nil
}
// The remaining key consists of 2 parts:
// - 32 bytes account hash
// - hex node path whose length is in the range 0 to 64
if len(key) < len(trieNodeStoragePrefix)+common.HashLength {
return false, common.Hash{}, nil
}
if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 {
return false, common.Hash{}, nil
}
accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength])
return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:]
}

// xdposV1Key = xdposV1Prefix + hash
func xdposV1Key(hash common.Hash) []byte {
return append(xdposV1Prefix, hash.Bytes()...)
Expand Down
3 changes: 2 additions & 1 deletion core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/trie"
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

const (
Expand Down Expand Up @@ -109,7 +110,7 @@ type Trie interface {
// The returned nodeset can be nil if the trie is clean(nothing to commit).
// Once the trie is committed, it's not usable anymore. A new trie must
// be created with new root and updated trie database for following usage
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet)
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)

// NodeIterator returns an iterator that returns nodes of the trie. Iteration
// starts at the key after the given start key.
Expand Down
12 changes: 11 additions & 1 deletion core/state/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/crypto"
)

// Tests that the node iterator indeed walks over the entire database contents.
Expand Down Expand Up @@ -85,9 +86,18 @@ func TestNodeIteratorCoverage(t *testing.T) {
// database entry belongs to a trie node or not.
func isTrieNode(scheme string, key, val []byte) (bool, common.Hash) {
if scheme == rawdb.HashScheme {
if len(key) == common.HashLength {
if rawdb.IsLegacyTrieNode(key, val) {
return true, common.BytesToHash(key)
}
} else {
ok, _ := rawdb.IsAccountTrieNode(key)
if ok {
return true, crypto.Keccak256Hash(val)
}
ok, _, _ = rawdb.IsStorageTrieNode(key)
if ok {
return true, crypto.Keccak256Hash(val)
}
}
return false, common.Hash{}
}
6 changes: 3 additions & 3 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

type Code []byte
Expand Down Expand Up @@ -298,9 +298,9 @@ func (s *stateObject) updateRoot() {
s.data.Root = tr.Hash()
}

// CommitTrie the storage trie of the object to dwb.
// commitTrie the storage trie of the object to dwb.
// This updates the trie root.
func (s *stateObject) commitTrie() (*trie.NodeSet, error) {
func (s *stateObject) commitTrie() (*trienode.NodeSet, error) {
// If nothing changed, don't bother with hashing anything
tr, err := s.updateTrie()
if err != nil {
Expand Down
7 changes: 4 additions & 3 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

type revision struct {
Expand Down Expand Up @@ -900,7 +901,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
accountTrieNodesDeleted int
storageTrieNodesUpdated int
storageTrieNodesDeleted int
nodes = trie.NewMergedNodeSet()
nodes = trienode.NewMergedNodeSet()
codeWriter = s.db.DiskDB().NewBatch()
)
for addr := range s.stateObjectsDirty {
Expand All @@ -915,7 +916,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
if err != nil {
return common.Hash{}, err
}
// Merge the dirty nodes of storage trie into global set
// Merge the dirty nodes of storage trie into global set.
if set != nil {
if err := nodes.Merge(set); err != nil {
return common.Hash{}, err
Expand Down Expand Up @@ -976,7 +977,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
}
if root != origin {
start := time.Now()
if err := s.db.TrieDB().Update(block, nodes); err != nil {
if err := s.db.TrieDB().Update(root, origin, block, nodes); err != nil {
return common.Hash{}, err
}
s.originalRoot = root
Expand Down
3 changes: 2 additions & 1 deletion core/state/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,8 @@ func TestIncompleteStateSync(t *testing.T) {
if len(nodeQueue) > 0 {
results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
for path, element := range nodeQueue {
data, err := srcDb.TrieDB().Node(element.hash)
owner, inner := trie.ResolvePath([]byte(element.path))
data, err := srcDb.TrieDB().Reader(srcRoot).Node(owner, inner, element.hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x", element.hash)
}
Expand Down
4 changes: 3 additions & 1 deletion internal/ethapi/trie_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
Expand All @@ -30,7 +31,8 @@ func (n *proofPairList) Delete(key []byte) error {
// modified from core/types/derive_sha.go
func deriveTrie(list types.DerivableList) *trie.Trie {
buf := new(bytes.Buffer)
trie := trie.NewEmpty(nil)
db := trie.NewDatabase(rawdb.NewMemoryDatabase())
trie := trie.NewEmpty(db)
for i := range list.Len() {
buf.Reset()
rlp.Encode(buf, uint(i))
Expand Down
18 changes: 6 additions & 12 deletions trie/committer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,17 @@ import (
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
)

// leaf represents a trie leaf node
type leaf struct {
blob []byte // raw blob of leaf
parent common.Hash // the hash of parent node
}

// committer is the tool used for the trie Commit operation. The committer will
// capture all dirty nodes during the commit process and keep them cached in
// insertion order.
type committer struct {
nodes *NodeSet
nodes *trienode.NodeSet
tracer *tracer
collectLeaf bool
}

// newCommitter creates a new committer or picks one from the pool.
func newCommitter(nodeset *NodeSet, tracer *tracer, collectLeaf bool) *committer {
func newCommitter(nodeset *trienode.NodeSet, tracer *tracer, collectLeaf bool) *committer {
return &committer{
nodes: nodeset,
tracer: tracer,
Expand Down Expand Up @@ -139,7 +133,7 @@ func (c *committer) store(path []byte, n node) node {
// deleted only if the node was existent in database before.
prev, ok := c.tracer.accessList[string(path)]
if ok {
c.nodes.addNode(path, trienode.NewWithPrev(common.Hash{}, nil, prev))
c.nodes.AddNode(path, trienode.NewWithPrev(common.Hash{}, nil, prev))
}
return n
}
Expand All @@ -152,15 +146,15 @@ func (c *committer) store(path []byte, n node) node {
c.tracer.accessList[string(path)],
)
)
c.nodes.addNode(path, node)
c.nodes.AddNode(path, node)

// Collect the corresponding leaf node if it's required. We don't check
// full node since it's impossible to store value in fullNode. The key
// length of leaves should be exactly same.
if c.collectLeaf {
if sn, ok := n.(*shortNode); ok {
if val, ok := sn.Val.(valueNode); ok {
c.nodes.addLeaf(&leaf{blob: val, parent: nhash})
c.nodes.AddLeaf(nhash, val)
}
}
}
Expand All @@ -172,7 +166,7 @@ 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)) {
func (resolver mptResolver) ForEach(node []byte, onChild func(common.Hash)) {
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
}

Expand Down
20 changes: 11 additions & 9 deletions trie/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@
package trie

import (
"testing"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/trie/triedb/hashdb"
)

// Tests that the trie database returns a missing trie Node error if attempting
// to retrieve the meta root.
func TestDatabaseMetarootFetch(t *testing.T) {
db := NewDatabase(rawdb.NewMemoryDatabase())
if _, err := db.Node(common.Hash{}); err == nil {
t.Fatalf("metaroot retrieval succeeded")
// newTestDatabase initializes the trie database with specified scheme.
func newTestDatabase(diskdb ethdb.Database, scheme string) *Database {
db := prepare(diskdb, nil)
if scheme == rawdb.HashScheme {
db.backend = hashdb.New(diskdb, db.cleans, mptResolver{})
}
//} else {
// db.backend = snap.New(diskdb, db.cleans, nil)
//}
return db
}
Loading