forked from cerc-io/plugeth
all: activate pbss as experimental feature (#26274)
* all: activate pbss * core/rawdb: fix compilation error * cma, core, eth, les, trie: address comments * cmd, core, eth, trie: polish code * core, cmd, eth: address comments * cmd, core, eth, les, light, tests: address comment * cmd/utils: shorten log message * trie/triedb/pathdb: limit node buffer size to 1gb * cmd/utils: fix opening non-existing db * cmd/utils: rename flag name * cmd, core: group chain history flags and fix tests * core, eth, trie: fix memory leak in snapshot generation * cmd, eth, internal: deprecate flags * all: enable state tests for pathdb, fixes * cmd, core: polish code * trie/triedb/pathdb: limit the node buffer size to 256mb --------- Co-authored-by: Martin Holst Swende <martin@swende.se> Co-authored-by: Péter Szilágyi <peterke@gmail.com>
This commit is contained in:
co-authored by
Martin Holst Swende
Péter Szilágyi
parent
5e89ff4d6b
commit
503f1f7ada
@@ -112,7 +112,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
|
||||
panic(err)
|
||||
}
|
||||
for _, block := range bs {
|
||||
chain.StateCache().TrieDB().Commit(block.Root(), false)
|
||||
chain.TrieDB().Commit(block.Root(), false)
|
||||
}
|
||||
txconfig := legacypool.DefaultConfig
|
||||
txconfig.Journal = "" // Don't litter the disk with test journals
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@@ -246,6 +247,10 @@ func handleGetNodeData66(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// ServiceGetNodeDataQuery assembles the response to a node data query. It is
|
||||
// exposed to allow external packages to test protocol behavior.
|
||||
func ServiceGetNodeDataQuery(chain *core.BlockChain, query GetNodeDataPacket) [][]byte {
|
||||
// Request nodes by hash is not supported in path-based scheme.
|
||||
if chain.TrieDB().Scheme() == rawdb.PathScheme {
|
||||
return nil
|
||||
}
|
||||
// Gather state data until the fetch or network limits is reached
|
||||
var (
|
||||
bytes int
|
||||
@@ -257,7 +262,7 @@ func ServiceGetNodeDataQuery(chain *core.BlockChain, query GetNodeDataPacket) []
|
||||
break
|
||||
}
|
||||
// Retrieve the requested state entry
|
||||
entry, err := chain.TrieNode(hash)
|
||||
entry, err := chain.TrieDB().Node(hash)
|
||||
if len(entry) == 0 || err != nil {
|
||||
// Read the contract code with prefix only to save unnecessary lookups.
|
||||
entry, err = chain.ContractCodeWithPrefix(hash)
|
||||
|
||||
@@ -284,7 +284,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac
|
||||
req.Bytes = softResponseLimit
|
||||
}
|
||||
// Retrieve the requested state and bail out if non existent
|
||||
tr, err := trie.New(trie.StateTrieID(req.Root), chain.StateCache().TrieDB())
|
||||
tr, err := trie.New(trie.StateTrieID(req.Root), chain.TrieDB())
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -414,7 +414,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
|
||||
if origin != (common.Hash{}) || (abort && len(storage) > 0) {
|
||||
// Request started at a non-zero hash or was capped prematurely, add
|
||||
// the endpoint Merkle proofs
|
||||
accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), chain.StateCache().TrieDB())
|
||||
accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), chain.TrieDB())
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -423,7 +423,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
|
||||
return nil, nil
|
||||
}
|
||||
id := trie.StorageTrieID(req.Root, account, acc.Root)
|
||||
stTrie, err := trie.NewStateTrie(id, chain.StateCache().TrieDB())
|
||||
stTrie, err := trie.NewStateTrie(id, chain.TrieDB())
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -487,7 +487,7 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s
|
||||
req.Bytes = softResponseLimit
|
||||
}
|
||||
// Make sure we have the state associated with the request
|
||||
triedb := chain.StateCache().TrieDB()
|
||||
triedb := chain.TrieDB()
|
||||
|
||||
accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), triedb)
|
||||
if err != nil {
|
||||
|
||||
+157
-47
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"golang.org/x/exp/slices"
|
||||
@@ -561,6 +562,11 @@ func noProofStorageRequestHandler(t *testPeer, requestId uint64, root common.Has
|
||||
func TestSyncBloatedProof(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncBloatedProof(t, rawdb.HashScheme)
|
||||
testSyncBloatedProof(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncBloatedProof(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -570,7 +576,7 @@ func TestSyncBloatedProof(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)
|
||||
source := newTestPeer("source", t, term)
|
||||
source.accountTrie = sourceAccountTrie.Copy()
|
||||
source.accountValues = elems
|
||||
@@ -638,6 +644,11 @@ func setupSyncer(scheme string, peers ...*testPeer) *Syncer {
|
||||
func TestSync(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSync(t, rawdb.HashScheme)
|
||||
testSync(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSync(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -647,7 +658,7 @@ func TestSync(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -659,7 +670,7 @@ func TestSync(t *testing.T) {
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncTinyTriePanic tests a basic sync with one peer, and a tiny trie. This caused a
|
||||
@@ -667,6 +678,11 @@ func TestSync(t *testing.T) {
|
||||
func TestSyncTinyTriePanic(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncTinyTriePanic(t, rawdb.HashScheme)
|
||||
testSyncTinyTriePanic(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncTinyTriePanic(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -676,7 +692,7 @@ func TestSyncTinyTriePanic(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1, scheme)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -690,13 +706,18 @@ func TestSyncTinyTriePanic(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestMultiSync tests a basic sync with multiple peers
|
||||
func TestMultiSync(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testMultiSync(t, rawdb.HashScheme)
|
||||
testMultiSync(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testMultiSync(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -706,7 +727,7 @@ func TestMultiSync(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -720,13 +741,18 @@ func TestMultiSync(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncWithStorage tests basic sync using accounts + storage + code
|
||||
func TestSyncWithStorage(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncWithStorage(t, rawdb.HashScheme)
|
||||
testSyncWithStorage(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncWithStorage(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -736,7 +762,7 @@ func TestSyncWithStorage(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(3, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 3000, true, false)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -752,13 +778,18 @@ func TestSyncWithStorage(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all
|
||||
func TestMultiSyncManyUseless(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testMultiSyncManyUseless(t, rawdb.HashScheme)
|
||||
testMultiSyncManyUseless(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testMultiSyncManyUseless(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -768,7 +799,7 @@ func TestMultiSyncManyUseless(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -801,11 +832,18 @@ func TestMultiSyncManyUseless(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all
|
||||
func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testMultiSyncManyUselessWithLowTimeout(t, rawdb.HashScheme)
|
||||
testMultiSyncManyUselessWithLowTimeout(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testMultiSyncManyUselessWithLowTimeout(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -815,7 +853,7 @@ func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -853,11 +891,18 @@ func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestMultiSyncManyUnresponsive contains one good peer, and many which doesn't respond at all
|
||||
func TestMultiSyncManyUnresponsive(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testMultiSyncManyUnresponsive(t, rawdb.HashScheme)
|
||||
testMultiSyncManyUnresponsive(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testMultiSyncManyUnresponsive(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -867,7 +912,7 @@ func TestMultiSyncManyUnresponsive(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -903,7 +948,7 @@ func TestMultiSyncManyUnresponsive(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
func checkStall(t *testing.T, term func()) chan struct{} {
|
||||
@@ -925,6 +970,11 @@ func checkStall(t *testing.T, term func()) chan struct{} {
|
||||
func TestSyncBoundaryAccountTrie(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncBoundaryAccountTrie(t, rawdb.HashScheme)
|
||||
testSyncBoundaryAccountTrie(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncBoundaryAccountTrie(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -934,7 +984,7 @@ func TestSyncBoundaryAccountTrie(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(scheme, 3000)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -952,7 +1002,7 @@ func TestSyncBoundaryAccountTrie(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncNoStorageAndOneCappedPeer tests sync using accounts and no storage, where one peer is
|
||||
@@ -960,6 +1010,11 @@ func TestSyncBoundaryAccountTrie(t *testing.T) {
|
||||
func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncNoStorageAndOneCappedPeer(t, rawdb.HashScheme)
|
||||
testSyncNoStorageAndOneCappedPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncNoStorageAndOneCappedPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -969,7 +1024,7 @@ func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)
|
||||
|
||||
mkSource := func(name string, slow bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -994,7 +1049,7 @@ func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncNoStorageAndOneCodeCorruptPeer has one peer which doesn't deliver
|
||||
@@ -1002,6 +1057,11 @@ func TestSyncNoStorageAndOneCappedPeer(t *testing.T) {
|
||||
func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.HashScheme)
|
||||
testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncNoStorageAndOneCodeCorruptPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1011,7 +1071,7 @@ func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)
|
||||
|
||||
mkSource := func(name string, codeFn codeHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1034,12 +1094,17 @@ func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.HashScheme)
|
||||
testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncNoStorageAndOneAccountCorruptPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1049,7 +1114,7 @@ func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)
|
||||
|
||||
mkSource := func(name string, accFn accountHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1072,7 +1137,7 @@ func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncNoStorageAndOneCodeCappedPeer has one peer which delivers code hashes
|
||||
@@ -1080,6 +1145,11 @@ func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) {
|
||||
func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.HashScheme)
|
||||
testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncNoStorageAndOneCodeCappedPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1089,7 +1159,7 @@ func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)
|
||||
|
||||
mkSource := func(name string, codeFn codeHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1123,7 +1193,7 @@ func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
if threshold := 100; counter > threshold {
|
||||
t.Logf("Error, expected < %d invocations, got %d", threshold, counter)
|
||||
}
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncBoundaryStorageTrie tests sync against a few normal peers, but the
|
||||
@@ -1131,6 +1201,11 @@ func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) {
|
||||
func TestSyncBoundaryStorageTrie(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncBoundaryStorageTrie(t, rawdb.HashScheme)
|
||||
testSyncBoundaryStorageTrie(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncBoundaryStorageTrie(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1140,7 +1215,7 @@ func TestSyncBoundaryStorageTrie(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(10, 1000, false, true)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 10, 1000, false, true)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1160,7 +1235,7 @@ func TestSyncBoundaryStorageTrie(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncWithStorageAndOneCappedPeer tests sync using accounts + storage, where one peer is
|
||||
@@ -1168,6 +1243,11 @@ func TestSyncBoundaryStorageTrie(t *testing.T) {
|
||||
func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncWithStorageAndOneCappedPeer(t, rawdb.HashScheme)
|
||||
testSyncWithStorageAndOneCappedPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncWithStorageAndOneCappedPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1177,7 +1257,7 @@ func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(300, 1000, false, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 300, 1000, false, false)
|
||||
|
||||
mkSource := func(name string, slow bool) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1202,7 +1282,7 @@ func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncWithStorageAndCorruptPeer tests sync using accounts + storage, where one peer is
|
||||
@@ -1210,6 +1290,11 @@ func TestSyncWithStorageAndOneCappedPeer(t *testing.T) {
|
||||
func TestSyncWithStorageAndCorruptPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncWithStorageAndCorruptPeer(t, rawdb.HashScheme)
|
||||
testSyncWithStorageAndCorruptPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncWithStorageAndCorruptPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1219,7 +1304,7 @@ func TestSyncWithStorageAndCorruptPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, handler storageHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1243,12 +1328,17 @@ func TestSyncWithStorageAndCorruptPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
func TestSyncWithStorageAndNonProvingPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncWithStorageAndNonProvingPeer(t, rawdb.HashScheme)
|
||||
testSyncWithStorageAndNonProvingPeer(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncWithStorageAndNonProvingPeer(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1258,7 +1348,7 @@ func TestSyncWithStorageAndNonProvingPeer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false)
|
||||
|
||||
mkSource := func(name string, handler storageHandlerFunc) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1281,7 +1371,7 @@ func TestSyncWithStorageAndNonProvingPeer(t *testing.T) {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
close(done)
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
// TestSyncWithStorage tests basic sync using accounts + storage + code, against
|
||||
@@ -1290,6 +1380,12 @@ func TestSyncWithStorageAndNonProvingPeer(t *testing.T) {
|
||||
// did not mark the account for healing.
|
||||
func TestSyncWithStorageMisbehavingProve(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncWithStorageMisbehavingProve(t, rawdb.HashScheme)
|
||||
testSyncWithStorageMisbehavingProve(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncWithStorageMisbehavingProve(t *testing.T, scheme string) {
|
||||
var (
|
||||
once sync.Once
|
||||
cancel = make(chan struct{})
|
||||
@@ -1299,7 +1395,7 @@ func TestSyncWithStorageMisbehavingProve(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(10, 30, false)
|
||||
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(scheme, 10, 30, false)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1314,7 +1410,7 @@ func TestSyncWithStorageMisbehavingProve(t *testing.T) {
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
}
|
||||
|
||||
type kv struct {
|
||||
@@ -1364,9 +1460,9 @@ func getCodeByHash(hash common.Hash) []byte {
|
||||
}
|
||||
|
||||
// makeAccountTrieNoStorage spits out a trie, along with the leafs
|
||||
func makeAccountTrieNoStorage(n int) (string, *trie.Trie, []*kv) {
|
||||
func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
|
||||
accTrie = trie.NewEmpty(db)
|
||||
entries []*kv
|
||||
)
|
||||
@@ -1396,12 +1492,12 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, []*kv) {
|
||||
// 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) (string, *trie.Trie, []*kv) {
|
||||
func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
|
||||
var (
|
||||
entries []*kv
|
||||
boundaries []common.Hash
|
||||
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
|
||||
accTrie = trie.NewEmpty(db)
|
||||
)
|
||||
// Initialize boundaries
|
||||
@@ -1457,9 +1553,9 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, []*kv) {
|
||||
|
||||
// makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts
|
||||
// has a unique storage set.
|
||||
func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||
func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
|
||||
accTrie = trie.NewEmpty(db)
|
||||
entries []*kv
|
||||
storageRoots = make(map[common.Hash]common.Hash)
|
||||
@@ -1512,9 +1608,9 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
||||
}
|
||||
|
||||
// makeAccountTrieWithStorage spits out a trie, along with the leafs
|
||||
func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||
func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, boundary bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||
var (
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
|
||||
accTrie = trie.NewEmpty(db)
|
||||
entries []*kv
|
||||
storageRoots = make(map[common.Hash]common.Hash)
|
||||
@@ -1656,9 +1752,9 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
|
||||
return root, nodes, entries
|
||||
}
|
||||
|
||||
func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
|
||||
func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
|
||||
t.Helper()
|
||||
triedb := trie.NewDatabase(rawdb.NewDatabase(db))
|
||||
triedb := trie.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme))
|
||||
accTrie, err := trie.New(trie.StateTrieID(root), triedb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1700,6 +1796,13 @@ func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
|
||||
// TestSyncAccountPerformance tests how efficient the snap algo is at minimizing
|
||||
// state healing
|
||||
func TestSyncAccountPerformance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testSyncAccountPerformance(t, rawdb.HashScheme)
|
||||
testSyncAccountPerformance(t, rawdb.PathScheme)
|
||||
}
|
||||
|
||||
func testSyncAccountPerformance(t *testing.T, scheme string) {
|
||||
// Set the account concurrency to 1. This _should_ result in the
|
||||
// range root to become correct, and there should be no healing needed
|
||||
defer func(old int) { accountConcurrency = old }(accountConcurrency)
|
||||
@@ -1714,7 +1817,7 @@ func TestSyncAccountPerformance(t *testing.T) {
|
||||
})
|
||||
}
|
||||
)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
source := newTestPeer(name, t, term)
|
||||
@@ -1727,7 +1830,7 @@ func TestSyncAccountPerformance(t *testing.T) {
|
||||
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||
t.Fatalf("sync failed: %v", err)
|
||||
}
|
||||
verifyTrie(syncer.db, sourceAccountTrie.Hash(), t)
|
||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||
// The trie root will always be requested, since it is added when the snap
|
||||
// sync cycle starts. When popping the queue, we do not look it up again.
|
||||
// Doing so would bring this number down to zero in this artificial testcase,
|
||||
@@ -1787,3 +1890,10 @@ func TestSlotEstimation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newDbConfig(scheme string) *trie.Config {
|
||||
if scheme == rawdb.HashScheme {
|
||||
return &trie.Config{}
|
||||
}
|
||||
return &trie.Config{PathDB: pathdb.Defaults}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user