mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie, snap/sync: fix quirk preventing in storage healing
This commit is contained in:
parent
34faed3cf0
commit
5dd6ceb3c4
2 changed files with 57 additions and 8 deletions
|
|
@ -2108,15 +2108,21 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||||
// Large contracts could have generated new trie nodes, flush them to disk
|
// Large contracts could have generated new trie nodes, flush them to disk
|
||||||
if res.subTask != nil {
|
if res.subTask != nil {
|
||||||
if res.subTask.done {
|
if res.subTask.done {
|
||||||
if root, err := res.subTask.genTrie.Commit(); err != nil {
|
if _, err := res.subTask.genTrie.Commit(); err != nil {
|
||||||
log.Error("Failed to commit stack slots", "err", err)
|
log.Error("Failed to commit stack slots", "err", err)
|
||||||
} else if root == res.subTask.root {
|
// The genTrie.Commit()-operation, if initialized from a proof, will
|
||||||
// If the chunk's root is an overflown but full delivery, clear the heal request
|
// return the correct root. However, it will also _avoid_ comitting
|
||||||
for i, account := range res.mainTask.res.hashes {
|
// nodes along the chunk-lines / boundaries, hence we _do_ need
|
||||||
if account == res.accounts[len(res.accounts)-1] {
|
// to perform healing anyway.
|
||||||
res.mainTask.needHeal[i] = false
|
//
|
||||||
}
|
//} else if root == res.subTask.root {
|
||||||
}
|
// // If the chunk's root is an overflown but full delivery, clear the heal request
|
||||||
|
// for i, account := range res.mainTask.res.hashes {
|
||||||
|
// if account == res.accounts[len(res.accounts)-1] {
|
||||||
|
// res.mainTask.needHeal[i] = false
|
||||||
|
// fmt.Printf("Marking needHeal as false %x\n", account)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize || res.subTask.done {
|
if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize || res.subTask.done {
|
||||||
|
|
|
||||||
|
|
@ -788,6 +788,49 @@ func testSyncWithStorage(t *testing.T, scheme string) {
|
||||||
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSyncWithLargeStorage tests basic sync using accounts + storage + code, where
|
||||||
|
// storage is large enough to trigger chunking.
|
||||||
|
func TestSyncWithLargeStorage(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("hash", func(t *testing.T) {
|
||||||
|
testSyncWithLargeStorage(t, rawdb.HashScheme)
|
||||||
|
})
|
||||||
|
t.Run("path", func(t *testing.T) {
|
||||||
|
testSyncWithLargeStorage(t, rawdb.PathScheme)
|
||||||
|
})
|
||||||
|
//testSyncWithStorage(t, rawdb.PathScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSyncWithLargeStorage(t *testing.T, scheme string) {
|
||||||
|
var (
|
||||||
|
once sync.Once
|
||||||
|
cancel = make(chan struct{})
|
||||||
|
term = func() {
|
||||||
|
once.Do(func() {
|
||||||
|
close(cancel)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 30000, true, false)
|
||||||
|
|
||||||
|
mkSource := func(name string) *testPeer {
|
||||||
|
source := newTestPeer(name, t, term)
|
||||||
|
source.accountTrie = sourceAccountTrie.Copy()
|
||||||
|
source.accountValues = elems
|
||||||
|
source.setStorageTries(storageTries)
|
||||||
|
source.storageValues = storageElems
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
syncer := setupSyncer(nodeScheme, mkSource("sourceA"))
|
||||||
|
done := checkStall(t, term)
|
||||||
|
if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil {
|
||||||
|
t.Fatalf("sync failed: %v", err)
|
||||||
|
}
|
||||||
|
close(done)
|
||||||
|
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
|
||||||
|
}
|
||||||
|
|
||||||
// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all
|
// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all
|
||||||
func TestMultiSyncManyUseless(t *testing.T) {
|
func TestMultiSyncManyUseless(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue