mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +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 {
|
if l.dbErr != nil {
|
||||||
return l.dbErr
|
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
|
var orderList orderList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ func (te *tradingExchanges) CommitAsksTrie(db Database) error {
|
||||||
if te.dbErr != nil {
|
if te.dbErr != nil {
|
||||||
return te.dbErr
|
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
|
var orderList orderList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -307,7 +307,7 @@ func (te *tradingExchanges) CommitBidsTrie(db Database) error {
|
||||||
if te.dbErr != nil {
|
if te.dbErr != nil {
|
||||||
return te.dbErr
|
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
|
var orderList orderList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -783,7 +783,7 @@ func (t *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
|
||||||
if t.dbErr != nil {
|
if t.dbErr != nil {
|
||||||
return t.dbErr
|
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
|
var orderList orderList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -589,7 +589,7 @@ func (t *TradingStateDB) Commit() (root common.Hash, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write trie changes.
|
// 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
|
var exchange tradingExchangeObject
|
||||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ func (le *lendingExchangeState) CommitInvestingTrie(db Database) error {
|
||||||
if le.dbErr != nil {
|
if le.dbErr != nil {
|
||||||
return le.dbErr
|
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
|
var orderList itemList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -493,7 +493,7 @@ func (le *lendingExchangeState) CommitBorrowingTrie(db Database) error {
|
||||||
if le.dbErr != nil {
|
if le.dbErr != nil {
|
||||||
return le.dbErr
|
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
|
var orderList itemList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -514,7 +514,7 @@ func (le *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
||||||
if le.dbErr != nil {
|
if le.dbErr != nil {
|
||||||
return le.dbErr
|
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
|
var orderList itemList
|
||||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -578,7 +578,7 @@ func (ls *LendingStateDB) Commit() (root common.Hash, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write trie changes.
|
// 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
|
var exchange lendingObject
|
||||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||||
return 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
|
// Write the account trie changes, measuing the amount of wasted time
|
||||||
defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now())
|
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
|
var account Account
|
||||||
if err := rlp.DecodeBytes(leaf, &account); err != nil {
|
if err := rlp.DecodeBytes(leaf, &account); err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewStateSync create a new state trie download scheduler.
|
// 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
|
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
|
var obj Account
|
||||||
if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
|
if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
syncer.AddSubTrie(obj.Root, path, parent, nil)
|
syncer.AddSubTrie(obj.Root, hexpath, parent, onSlot)
|
||||||
syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), path, parent)
|
syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), hexpath, parent)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
syncer = trie.NewSync(root, database, callback, bloom)
|
syncer = trie.NewSync(root, database, onAccount, bloom)
|
||||||
return syncer
|
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.
|
// Tests that an empty state is not scheduled for syncing.
|
||||||
func TestEmptyStateSync(t *testing.T) {
|
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)
|
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
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
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)...)
|
queue := append([]common.Hash{}, sched.Missing(count)...)
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
|
|
@ -185,7 +185,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
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)...)
|
queue := append([]common.Hash{}, sched.Missing(0)...)
|
||||||
for len(queue) > 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
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
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{})
|
queue := make(map[common.Hash]struct{})
|
||||||
for _, hash := range sched.Missing(count) {
|
for _, hash := range sched.Missing(count) {
|
||||||
|
|
@ -276,7 +276,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
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{})
|
queue := make(map[common.Hash]struct{})
|
||||||
for _, hash := range sched.Missing(0) {
|
for _, hash := range sched.Missing(0) {
|
||||||
|
|
@ -339,7 +339,7 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
dstDb := rawdb.NewMemoryDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
|
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb), nil)
|
||||||
|
|
||||||
added := []common.Hash{}
|
added := []common.Hash{}
|
||||||
queue := append([]common.Hash{}, sched.Missing(1)...)
|
queue := append([]common.Hash{}, sched.Missing(1)...)
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ type stateTask struct {
|
||||||
func newStateSync(d *Downloader, root common.Hash) *stateSync {
|
func newStateSync(d *Downloader, root common.Hash) *stateSync {
|
||||||
return &stateSync{
|
return &stateSync{
|
||||||
d: d,
|
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(),
|
keccak: sha3.NewLegacyKeccak256(),
|
||||||
tasks: make(map[common.Hash]*stateTask),
|
tasks: make(map[common.Hash]*stateTask),
|
||||||
deliver: make(chan *stateReq),
|
deliver: make(chan *stateReq),
|
||||||
|
|
|
||||||
|
|
@ -218,13 +218,13 @@ func (c *committer) commitLoop(db *Database) {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
case *shortNode:
|
case *shortNode:
|
||||||
if child, ok := n.Val.(valueNode); ok {
|
if child, ok := n.Val.(valueNode); ok {
|
||||||
c.onleaf(nil, child, hash)
|
c.onleaf(nil, nil, child, hash)
|
||||||
}
|
}
|
||||||
case *fullNode:
|
case *fullNode:
|
||||||
// For children in range [0, 15], it's impossible
|
// For children in range [0, 15], it's impossible
|
||||||
// to contain valuenode. Only check the 17th child.
|
// to contain valuenode. Only check the 17th child.
|
||||||
if n.Children[16] != nil {
|
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
|
// Notify any external watcher of a new key/value Node
|
||||||
if req.callback != nil {
|
if req.callback != nil {
|
||||||
if node, ok := (child.node).(valueNode); ok {
|
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
|
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
|
// 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
|
// node.
|
||||||
// between account and storage tries.
|
//
|
||||||
type LeafCallback func(path []byte, leaf []byte, parent common.Hash) error
|
// 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.
|
// Trie is a Merkle Patricia Trie.
|
||||||
// The zero value is an empty trie with no database.
|
// The zero value is an empty trie with no database.
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,7 @@ func BenchmarkCommitAfterHash(b *testing.B) {
|
||||||
benchmarkCommitAfterHash(b, nil)
|
benchmarkCommitAfterHash(b, nil)
|
||||||
})
|
})
|
||||||
var a account
|
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)
|
rlp.DecodeBytes(leaf, &a)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue