forked from cerc-io/plugeth
core, eth, les, tests, trie: abstract node scheme (#25532)
This PR introduces a node scheme abstraction. The interface is only implemented by `hashScheme` at the moment, but will be extended by `pathScheme` very soon. Apart from that, a few changes are also included which is worth mentioning: - port the changes in the stacktrie, tracking the path prefix of nodes during commit - use ethdb.Database for constructing trie.Database. This is not necessary right now, but it is required for path-based used to open reverse diff freezer
This commit is contained in:
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -206,6 +207,10 @@ type BlockChain interface {
|
||||
|
||||
// Snapshots returns the blockchain snapshot tree to paused it during sync.
|
||||
Snapshots() *snapshot.Tree
|
||||
|
||||
// TrieDB retrieves the low level trie database used for interacting
|
||||
// with trie nodes.
|
||||
TrieDB() *trie.Database
|
||||
}
|
||||
|
||||
// New creates a new downloader to fetch hashes and blocks from remote peers.
|
||||
@@ -224,7 +229,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl
|
||||
dropPeer: dropPeer,
|
||||
headerProcCh: make(chan *headerTask, 1),
|
||||
quitCh: make(chan struct{}),
|
||||
SnapSyncer: snap.NewSyncer(stateDb),
|
||||
SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()),
|
||||
stateSyncStart: make(chan *stateSync),
|
||||
}
|
||||
dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success))
|
||||
|
||||
+25
-12
@@ -417,7 +417,8 @@ type SyncPeer interface {
|
||||
// - The peer delivers a stale response after a previous timeout
|
||||
// - The peer delivers a refusal to serve the requested state
|
||||
type Syncer struct {
|
||||
db ethdb.KeyValueStore // Database to store the trie nodes into (and dedup)
|
||||
db ethdb.KeyValueStore // Database to store the trie nodes into (and dedup)
|
||||
scheme trie.NodeScheme // Node scheme used in node database
|
||||
|
||||
root common.Hash // Current state trie root being synced
|
||||
tasks []*accountTask // Current account task set being synced
|
||||
@@ -485,9 +486,10 @@ type Syncer struct {
|
||||
|
||||
// NewSyncer creates a new snapshot syncer to download the Ethereum state over the
|
||||
// snap protocol.
|
||||
func NewSyncer(db ethdb.KeyValueStore) *Syncer {
|
||||
func NewSyncer(db ethdb.KeyValueStore, scheme trie.NodeScheme) *Syncer {
|
||||
return &Syncer{
|
||||
db: db,
|
||||
db: db,
|
||||
scheme: scheme,
|
||||
|
||||
peers: make(map[string]SyncPeer),
|
||||
peerJoin: new(event.Feed),
|
||||
@@ -581,7 +583,7 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
|
||||
s.lock.Lock()
|
||||
s.root = root
|
||||
s.healer = &healTask{
|
||||
scheduler: state.NewStateSync(root, s.db, s.onHealState),
|
||||
scheduler: state.NewStateSync(root, s.db, s.onHealState, s.scheme),
|
||||
trieTasks: make(map[string]common.Hash),
|
||||
codeTasks: make(map[common.Hash]struct{}),
|
||||
}
|
||||
@@ -743,8 +745,9 @@ func (s *Syncer) loadSyncStatus() {
|
||||
s.accountBytes += common.StorageSize(len(key) + len(value))
|
||||
},
|
||||
}
|
||||
task.genTrie = trie.NewStackTrie(task.genBatch)
|
||||
|
||||
task.genTrie = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(task.genBatch, owner, path, hash, val)
|
||||
})
|
||||
for accountHash, subtasks := range task.SubTasks {
|
||||
for _, subtask := range subtasks {
|
||||
subtask.genBatch = ethdb.HookedBatch{
|
||||
@@ -753,7 +756,9 @@ func (s *Syncer) loadSyncStatus() {
|
||||
s.storageBytes += common.StorageSize(len(key) + len(value))
|
||||
},
|
||||
}
|
||||
subtask.genTrie = trie.NewStackTrieWithOwner(subtask.genBatch, accountHash)
|
||||
subtask.genTrie = trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(subtask.genBatch, owner, path, hash, val)
|
||||
}, accountHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -810,7 +815,9 @@ func (s *Syncer) loadSyncStatus() {
|
||||
Last: last,
|
||||
SubTasks: make(map[common.Hash][]*storageTask),
|
||||
genBatch: batch,
|
||||
genTrie: trie.NewStackTrie(batch),
|
||||
genTrie: trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(batch, owner, path, hash, val)
|
||||
}),
|
||||
})
|
||||
log.Debug("Created account sync task", "from", next, "last", last)
|
||||
next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1))
|
||||
@@ -1835,7 +1842,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
|
||||
}
|
||||
// Check if the account is a contract with an unknown storage trie
|
||||
if account.Root != emptyRoot {
|
||||
if ok, err := s.db.Has(account.Root[:]); err != nil || !ok {
|
||||
if !s.scheme.HasTrieNode(s.db, res.hashes[i], nil, account.Root) {
|
||||
// If there was a previous large state retrieval in progress,
|
||||
// don't restart it from scratch. This happens if a sync cycle
|
||||
// is interrupted and resumed later. However, *do* update the
|
||||
@@ -2007,7 +2014,9 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||
Last: r.End(),
|
||||
root: acc.Root,
|
||||
genBatch: batch,
|
||||
genTrie: trie.NewStackTrieWithOwner(batch, account),
|
||||
genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(batch, owner, path, hash, val)
|
||||
}, account),
|
||||
})
|
||||
for r.Next() {
|
||||
batch := ethdb.HookedBatch{
|
||||
@@ -2021,7 +2030,9 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||
Last: r.End(),
|
||||
root: acc.Root,
|
||||
genBatch: batch,
|
||||
genTrie: trie.NewStackTrieWithOwner(batch, account),
|
||||
genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(batch, owner, path, hash, val)
|
||||
}, account),
|
||||
})
|
||||
}
|
||||
for _, task := range tasks {
|
||||
@@ -2066,7 +2077,9 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||
slots += len(res.hashes[i])
|
||||
|
||||
if i < len(res.hashes)-1 || res.subTask == nil {
|
||||
tr := trie.NewStackTrieWithOwner(batch, account)
|
||||
tr := trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) {
|
||||
s.scheme.WriteTrieNode(batch, owner, path, hash, val)
|
||||
}, account)
|
||||
for j := 0; j < len(res.hashes[i]); j++ {
|
||||
tr.Update(res.hashes[i][j][:], res.slots[i][j])
|
||||
}
|
||||
|
||||
@@ -159,6 +159,13 @@ func newTestPeer(id string, t *testing.T, term func()) *testPeer {
|
||||
return peer
|
||||
}
|
||||
|
||||
func (t *testPeer) setStorageTries(tries map[common.Hash]*trie.Trie) {
|
||||
t.storageTries = make(map[common.Hash]*trie.Trie)
|
||||
for root, trie := range tries {
|
||||
t.storageTries[root] = trie.Copy()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *testPeer) ID() string { return t.id }
|
||||
func (t *testPeer) Log() log.Logger { return t.logger }
|
||||
|
||||
@@ -562,9 +569,9 @@ func TestSyncBloatedProof(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
source := newTestPeer("source", t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
|
||||
source.accountRequestHandler = func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error {
|
||||
@@ -610,15 +617,15 @@ func TestSyncBloatedProof(t *testing.T) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
syncer := setupSyncer(source)
|
||||
syncer := setupSyncer(nodeScheme, source)
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err == nil {
|
||||
t.Fatal("No error returned from incomplete/cancelled sync")
|
||||
}
|
||||
}
|
||||
|
||||
func setupSyncer(peers ...*testPeer) *Syncer {
|
||||
func setupSyncer(scheme trie.NodeScheme, peers ...*testPeer) *Syncer {
|
||||
stateDb := rawdb.NewMemoryDatabase()
|
||||
syncer := NewSyncer(stateDb)
|
||||
syncer := NewSyncer(stateDb, scheme)
|
||||
for _, peer := range peers {
|
||||
syncer.Register(peer)
|
||||
peer.remote = syncer
|
||||
@@ -639,15 +646,15 @@ func TestSync(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(mkSource("source"))
|
||||
syncer := setupSyncer(nodeScheme, mkSource("source"))
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
@@ -668,15 +675,15 @@ func TestSyncTinyTriePanic(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(1)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(mkSource("source"))
|
||||
syncer := setupSyncer(nodeScheme, mkSource("source"))
|
||||
done := checkStall(t, term)
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
@@ -698,15 +705,15 @@ func TestMultiSync(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(mkSource("sourceA"), mkSource("sourceB"))
|
||||
syncer := setupSyncer(nodeScheme, mkSource("sourceA"), mkSource("sourceB"))
|
||||
done := checkStall(t, term)
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
@@ -728,17 +735,17 @@ func TestSyncWithStorage(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(3, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(3, 3000, true, false)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(mkSource("sourceA"))
|
||||
syncer := setupSyncer(nodeScheme, mkSource("sourceA"))
|
||||
done := checkStall(t, term)
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
@@ -760,13 +767,13 @@ func TestMultiSyncManyUseless(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
|
||||
if !noAccount {
|
||||
@@ -782,6 +789,7 @@ func TestMultiSyncManyUseless(t *testing.T) {
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("full", true, true, true),
|
||||
mkSource("noAccounts", false, true, true),
|
||||
mkSource("noStorage", true, false, true),
|
||||
@@ -806,13 +814,13 @@ func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
|
||||
if !noAccount {
|
||||
@@ -828,6 +836,7 @@ func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("full", true, true, true),
|
||||
mkSource("noAccounts", false, true, true),
|
||||
mkSource("noStorage", true, false, true),
|
||||
@@ -857,13 +866,13 @@ func TestMultiSyncManyUnresponsive(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
|
||||
if !noAccount {
|
||||
@@ -879,6 +888,7 @@ func TestMultiSyncManyUnresponsive(t *testing.T) {
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("full", true, true, true),
|
||||
mkSource("noAccounts", false, true, true),
|
||||
mkSource("noStorage", true, false, true),
|
||||
@@ -923,15 +933,16 @@ func TestSyncBoundaryAccountTrie(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeBoundaryAccountTrie(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(3000)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("peer-a"),
|
||||
mkSource("peer-b"),
|
||||
)
|
||||
@@ -957,11 +968,11 @@ func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
|
||||
mkSource := func(name string, slow bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
|
||||
if slow {
|
||||
@@ -971,6 +982,7 @@ func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("nice-a", false),
|
||||
mkSource("nice-b", false),
|
||||
mkSource("nice-c", false),
|
||||
@@ -998,11 +1010,11 @@ func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
|
||||
mkSource := func(name string, codeFn codeHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.codeRequestHandler = codeFn
|
||||
return source
|
||||
@@ -1012,6 +1024,7 @@ func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) {
|
||||
// non-corrupt peer, which delivers everything in one go, and makes the
|
||||
// test moot
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("capped", cappedCodeRequestHandler),
|
||||
mkSource("corrupt", corruptCodeRequestHandler),
|
||||
)
|
||||
@@ -1035,11 +1048,11 @@ func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
|
||||
mkSource := func(name string, accFn accountHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.accountRequestHandler = accFn
|
||||
return source
|
||||
@@ -1049,6 +1062,7 @@ func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
// non-corrupt peer, which delivers everything in one go, and makes the
|
||||
// test moot
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("capped", defaultAccountRequestHandler),
|
||||
mkSource("corrupt", corruptAccountRequestHandler),
|
||||
)
|
||||
@@ -1074,11 +1088,11 @@ func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
|
||||
mkSource := func(name string, codeFn codeHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.codeRequestHandler = codeFn
|
||||
return source
|
||||
@@ -1087,6 +1101,7 @@ func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
// so it shouldn't be more than that
|
||||
var counter int
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("capped", func(t *testPeer, id uint64, hashes []common.Hash, max uint64) error {
|
||||
counter++
|
||||
return cappedCodeRequestHandler(t, id, hashes, max)
|
||||
@@ -1124,17 +1139,18 @@ func TestSyncBoundaryStorageTrie(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(10, 1000, false, true)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(10, 1000, false, true)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("peer-a"),
|
||||
mkSource("peer-b"),
|
||||
)
|
||||
@@ -1160,13 +1176,13 @@ func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(300, 1000, false, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(300, 1000, false, false)
|
||||
|
||||
mkSource := func(name string, slow bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
|
||||
if slow {
|
||||
@@ -1176,6 +1192,7 @@ func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("nice-a", false),
|
||||
mkSource("slow", true),
|
||||
)
|
||||
@@ -1201,19 +1218,20 @@ func TestSyncWithStorageAndCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, handler storageHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
source.storageRequestHandler = handler
|
||||
return source
|
||||
}
|
||||
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("nice-a", defaultStorageRequestHandler),
|
||||
mkSource("nice-b", defaultStorageRequestHandler),
|
||||
mkSource("nice-c", defaultStorageRequestHandler),
|
||||
@@ -1239,18 +1257,19 @@ func TestSyncWithStorageAndNonProvingPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, handler storageHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
source.storageRequestHandler = handler
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(
|
||||
nodeScheme,
|
||||
mkSource("nice-a", defaultStorageRequestHandler),
|
||||
mkSource("nice-b", defaultStorageRequestHandler),
|
||||
mkSource("nice-c", defaultStorageRequestHandler),
|
||||
@@ -1279,18 +1298,18 @@ func TestSyncWithStorageMisbehavingProve(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(10, 30, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(10, 30, false)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
source.storageTries = storageTries
|
||||
source.setStorageTries(storageTries)
|
||||
source.storageValues = storageElems
|
||||
source.storageRequestHandler = proofHappyStorageRequestHandler
|
||||
return source
|
||||
}
|
||||
syncer := setupSyncer(mkSource("sourceA"))
|
||||
syncer := setupSyncer(nodeScheme, mkSource("sourceA"))
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
@@ -1347,7 +1366,7 @@ func getCodeByHash(hash common.Hash) []byte {
|
||||
}
|
||||
|
||||
// makeAccountTrieNoStorage spits out a trie, along with the leafs
|
||||
func makeAccountTrieNoStorage(n int) (*trie.Trie, entrySlice) {
|
||||
func makeAccountTrieNoStorage(n int) (trie.NodeScheme, *trie.Trie, entrySlice) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
accTrie = trie.NewEmpty(db)
|
||||
@@ -1373,13 +1392,13 @@ func makeAccountTrieNoStorage(n int) (*trie.Trie, entrySlice) {
|
||||
db.Update(trie.NewWithNodeSet(nodes))
|
||||
|
||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||
return accTrie, entries
|
||||
return db.Scheme(), accTrie, entries
|
||||
}
|
||||
|
||||
// makeBoundaryAccountTrie constructs an account trie. Instead of filling
|
||||
// accounts normally, this function will fill a few accounts which have
|
||||
// boundary hash.
|
||||
func makeBoundaryAccountTrie(n int) (*trie.Trie, entrySlice) {
|
||||
func makeBoundaryAccountTrie(n int) (trie.NodeScheme, *trie.Trie, entrySlice) {
|
||||
var (
|
||||
entries entrySlice
|
||||
boundaries []common.Hash
|
||||
@@ -1435,12 +1454,12 @@ func makeBoundaryAccountTrie(n int) (*trie.Trie, entrySlice) {
|
||||
db.Update(trie.NewWithNodeSet(nodes))
|
||||
|
||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||
return accTrie, entries
|
||||
return db.Scheme(), accTrie, entries
|
||||
}
|
||||
|
||||
// makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts
|
||||
// has a unique storage set.
|
||||
func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (*trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
||||
func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (trie.NodeScheme, *trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
accTrie = trie.NewEmpty(db)
|
||||
@@ -1491,11 +1510,11 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
||||
trie, _ := trie.New(id, db)
|
||||
storageTries[common.BytesToHash(key)] = trie
|
||||
}
|
||||
return accTrie, entries, storageTries, storageEntries
|
||||
return db.Scheme(), accTrie, entries, storageTries, storageEntries
|
||||
}
|
||||
|
||||
// makeAccountTrieWithStorage spits out a trie, along with the leafs
|
||||
func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (*trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
||||
func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (trie.NodeScheme, *trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
accTrie = trie.NewEmpty(db)
|
||||
@@ -1562,7 +1581,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (*trie
|
||||
}
|
||||
storageTries[common.BytesToHash(key)] = trie
|
||||
}
|
||||
return accTrie, entries, storageTries, storageEntries
|
||||
return db.Scheme(), accTrie, entries, storageTries, storageEntries
|
||||
}
|
||||
|
||||
// makeStorageTrieWithSeed fills a storage trie with n items, returning the
|
||||
@@ -1641,7 +1660,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
|
||||
|
||||
func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
|
||||
t.Helper()
|
||||
triedb := trie.NewDatabase(db)
|
||||
triedb := trie.NewDatabase(rawdb.NewDatabase(db))
|
||||
accTrie, err := trie.New(trie.StateTrieID(root), triedb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1697,16 +1716,16 @@ func TestSyncAccountPerformance(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
source.accountTrie = sourceAccountTrie
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
return source
|
||||
}
|
||||
src := mkSource("source")
|
||||
syncer := setupSyncer(src)
|
||||
syncer := setupSyncer(nodeScheme, src)
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user