mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
parent
93c2745b7b
commit
45d89bd4d1
13 changed files with 61 additions and 29 deletions
|
|
@ -136,7 +136,7 @@ func (l *liquidationPriceState) updateRoot(db Database) error {
|
|||
if l.dbErr != nil {
|
||||
return l.dbErr
|
||||
}
|
||||
root, err := l.trie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := l.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ func (te *tradingExchanges) CommitAsksTrie(db Database) error {
|
|||
if te.dbErr != nil {
|
||||
return te.dbErr
|
||||
}
|
||||
root, err := te.asksTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := te.asksTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -307,7 +307,7 @@ func (te *tradingExchanges) CommitBidsTrie(db Database) error {
|
|||
if te.dbErr != nil {
|
||||
return te.dbErr
|
||||
}
|
||||
root, err := te.bidsTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := te.bidsTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -783,7 +783,7 @@ func (t *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
|
|||
if t.dbErr != nil {
|
||||
return t.dbErr
|
||||
}
|
||||
root, err := t.liquidationPriceTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := t.liquidationPriceTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -589,7 +589,7 @@ func (t *TradingStateDB) Commit() (root common.Hash, err error) {
|
|||
}
|
||||
}
|
||||
// Write trie changes.
|
||||
root, err = t.trie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err = t.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var exchange tradingExchangeObject
|
||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ func (le *lendingExchangeState) CommitInvestingTrie(db Database) error {
|
|||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := le.investingTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := le.investingTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -493,7 +493,7 @@ func (le *lendingExchangeState) CommitBorrowingTrie(db Database) error {
|
|||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := le.borrowingTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := le.borrowingTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -514,7 +514,7 @@ func (le *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
|||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := le.liquidationTimeTrie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err := le.liquidationTimeTrie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ func (ls *LendingStateDB) Commit() (root common.Hash, err error) {
|
|||
}
|
||||
}
|
||||
// Write trie changes.
|
||||
root, err = ls.trie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
root, err = ls.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var exchange lendingObject
|
||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -840,7 +840,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
|||
// Write the account trie changes, measuing the amount of wasted time
|
||||
defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now())
|
||||
|
||||
return s.trie.Commit(func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
return s.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
var account Account
|
||||
if err := rlp.DecodeBytes(leaf, &account); err != nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -26,17 +26,31 @@ import (
|
|||
)
|
||||
|
||||
// NewStateSync create a new state trie download scheduler.
|
||||
func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.SyncBloom) *trie.Sync {
|
||||
func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.SyncBloom, onLeaf func(paths [][]byte, leaf []byte) error) *trie.Sync {
|
||||
// Register the storage slot callback if the external callback is specified.
|
||||
var onSlot func(paths [][]byte, hexpath []byte, leaf []byte, parent common.Hash) error
|
||||
if onLeaf != nil {
|
||||
onSlot = func(paths [][]byte, hexpath []byte, leaf []byte, parent common.Hash) error {
|
||||
return onLeaf(paths, leaf)
|
||||
}
|
||||
}
|
||||
// Register the account callback to connect the state trie and the storage
|
||||
// trie belongs to the contract.
|
||||
var syncer *trie.Sync
|
||||
callback := func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
onAccount := func(paths [][]byte, hexpath []byte, leaf []byte, parent common.Hash) error {
|
||||
if onLeaf != nil {
|
||||
if err := onLeaf(paths, leaf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var obj Account
|
||||
if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
|
||||
return err
|
||||
}
|
||||
syncer.AddSubTrie(obj.Root, path, parent, nil)
|
||||
syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), path, parent)
|
||||
syncer.AddSubTrie(obj.Root, hexpath, parent, onSlot)
|
||||
syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), hexpath, parent)
|
||||
return nil
|
||||
}
|
||||
syncer = trie.NewSync(root, database, callback, bloom)
|
||||
syncer = trie.NewSync(root, database, onAccount, bloom)
|
||||
return syncer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
|||
|
||||
// Tests that an empty state is not scheduled for syncing.
|
||||
func TestEmptyStateSync(t *testing.T) {
|
||||
if req := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), trie.NewSyncBloom(1, memorydb.New())).Missing(1); len(req) != 0 {
|
||||
if req := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), trie.NewSyncBloom(1, memorydb.New()), nil).Missing(1); len(req) != 0 {
|
||||
t.Errorf("content requested for empty state: %v", req)
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool) {
|
|||
}
|
||||
// Create a destination state and sync with the scheduler
|
||||
dstDb := rawdb.NewMemoryDatabase()
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||
|
||||
queue := append([]common.Hash{}, sched.Missing(count)...)
|
||||
for len(queue) > 0 {
|
||||
|
|
@ -185,7 +185,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
|||
|
||||
// Create a destination state and sync with the scheduler
|
||||
dstDb := rawdb.NewMemoryDatabase()
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||
|
||||
queue := append([]common.Hash{}, sched.Missing(0)...)
|
||||
for len(queue) > 0 {
|
||||
|
|
@ -229,7 +229,7 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
|
|||
|
||||
// Create a destination state and sync with the scheduler
|
||||
dstDb := rawdb.NewMemoryDatabase()
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||
|
||||
queue := make(map[common.Hash]struct{})
|
||||
for _, hash := range sched.Missing(count) {
|
||||
|
|
@ -276,7 +276,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
|||
|
||||
// Create a destination state and sync with the scheduler
|
||||
dstDb := rawdb.NewMemoryDatabase()
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||
|
||||
queue := make(map[common.Hash]struct{})
|
||||
for _, hash := range sched.Missing(0) {
|
||||
|
|
@ -339,7 +339,7 @@ func TestIncompleteStateSync(t *testing.T) {
|
|||
|
||||
// Create a destination state and sync with the scheduler
|
||||
dstDb := rawdb.NewMemoryDatabase()
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||
|
||||
added := []common.Hash{}
|
||||
queue := append([]common.Hash{}, sched.Missing(1)...)
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ type stateTask struct {
|
|||
func newStateSync(d *Downloader, root common.Hash) *stateSync {
|
||||
return &stateSync{
|
||||
d: d,
|
||||
sched: state.NewStateSync(root, d.stateDB, trie.NewSyncBloom(1, memorydb.New())),
|
||||
sched: state.NewStateSync(root, d.stateDB, trie.NewSyncBloom(1, memorydb.New()), nil),
|
||||
keccak: sha3.NewLegacyKeccak256(),
|
||||
tasks: make(map[common.Hash]*stateTask),
|
||||
deliver: make(chan *stateReq),
|
||||
|
|
|
|||
|
|
@ -218,13 +218,13 @@ func (c *committer) commitLoop(db *Database) {
|
|||
switch n := n.(type) {
|
||||
case *shortNode:
|
||||
if child, ok := n.Val.(valueNode); ok {
|
||||
c.onleaf(nil, child, hash)
|
||||
c.onleaf(nil, nil, child, hash)
|
||||
}
|
||||
case *fullNode:
|
||||
// For children in range [0, 15], it's impossible
|
||||
// to contain valuenode. Only check the 17th child.
|
||||
if n.Children[16] != nil {
|
||||
c.onleaf(nil, n.Children[16].(valueNode), hash)
|
||||
c.onleaf(nil, nil, n.Children[16].(valueNode), hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,7 +349,14 @@ func (s *Sync) children(req *request, object node) ([]*request, error) {
|
|||
// Notify any external watcher of a new key/value Node
|
||||
if req.callback != nil {
|
||||
if node, ok := (child.node).(valueNode); ok {
|
||||
if err := req.callback(req.path, node, req.hash); err != nil {
|
||||
var paths [][]byte
|
||||
if len(child.path) == 2*common.HashLength {
|
||||
paths = append(paths, hexToKeybytes(child.path))
|
||||
} else if len(child.path) == 4*common.HashLength {
|
||||
paths = append(paths, hexToKeybytes(child.path[:2*common.HashLength]))
|
||||
paths = append(paths, hexToKeybytes(child.path[2*common.HashLength:]))
|
||||
}
|
||||
if err := req.callback(paths, child.path, node, req.hash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
trie/trie.go
17
trie/trie.go
|
|
@ -28,9 +28,20 @@ import (
|
|||
)
|
||||
|
||||
// LeafCallback is a callback type invoked when a trie operation reaches a leaf
|
||||
// Node. It's used by state sync and commit to allow handling external references
|
||||
// between account and storage tries.
|
||||
type LeafCallback func(path []byte, leaf []byte, parent common.Hash) error
|
||||
// node.
|
||||
//
|
||||
// The paths is a path tuple identifying a particular trie node either in a single
|
||||
// trie (account) or a layered trie (account -> storage). Each path in the tuple
|
||||
// is in the raw format(32 bytes).
|
||||
//
|
||||
// The hexpath is a composite hexary path identifying the trie node. All the key
|
||||
// bytes are converted to the hexary nibbles and composited with the parent path
|
||||
// if the trie node is in a layered trie.
|
||||
//
|
||||
// It's used by state sync and commit to allow handling external references
|
||||
// between account and storage tries. And also it's used in the state healing
|
||||
// for extracting the raw states(leaf nodes) with corresponding paths.
|
||||
type LeafCallback func(paths [][]byte, hexpath []byte, leaf []byte, parent common.Hash) error
|
||||
|
||||
// Trie is a Merkle Patricia Trie.
|
||||
// The zero value is an empty trie with no database.
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ func BenchmarkCommitAfterHash(b *testing.B) {
|
|||
benchmarkCommitAfterHash(b, nil)
|
||||
})
|
||||
var a account
|
||||
onleaf := func(path []byte, leaf []byte, parent common.Hash) error {
|
||||
onleaf := func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
|
||||
rlp.DecodeBytes(leaf, &a)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue