core: define and test chain rewind corner cases (#21409)

* core: define and test chain reparation cornercases

* core: write up a variety of set-head tests

* core, eth: unify chain rollbacks, handle all the cases

* core: make linter smile

* core: remove commented out legacy code

* core, eth/downloader: fix review comments

* core: revert a removed recovery mechanism
This commit is contained in:
Péter Szilágyi
2020-08-20 13:01:24 +03:00
committed by GitHub
parent 0bdd295cc0
commit 8cbdc8638f
13 changed files with 3953 additions and 215 deletions

View File

@ -341,25 +341,52 @@ func (dl *downloadTester) InsertReceiptChain(blocks types.Blocks, receipts []typ
return len(blocks), nil
}
// Rollback removes some recently added elements from the chain.
func (dl *downloadTester) Rollback(hashes []common.Hash) {
// SetHead rewinds the local chain to a new head.
func (dl *downloadTester) SetHead(head uint64) error {
dl.lock.Lock()
defer dl.lock.Unlock()
for i := len(hashes) - 1; i >= 0; i-- {
if dl.ownHashes[len(dl.ownHashes)-1] == hashes[i] {
dl.ownHashes = dl.ownHashes[:len(dl.ownHashes)-1]
// Find the hash of the head to reset to
var hash common.Hash
for h, header := range dl.ownHeaders {
if header.Number.Uint64() == head {
hash = h
}
delete(dl.ownChainTd, hashes[i])
delete(dl.ownHeaders, hashes[i])
delete(dl.ownReceipts, hashes[i])
delete(dl.ownBlocks, hashes[i])
delete(dl.ancientChainTd, hashes[i])
delete(dl.ancientHeaders, hashes[i])
delete(dl.ancientReceipts, hashes[i])
delete(dl.ancientBlocks, hashes[i])
}
for h, header := range dl.ancientHeaders {
if header.Number.Uint64() == head {
hash = h
}
}
if hash == (common.Hash{}) {
return fmt.Errorf("unknown head to set: %d", head)
}
// Find the offset in the header chain
var offset int
for o, h := range dl.ownHashes {
if h == hash {
offset = o
break
}
}
// Remove all the hashes and associated data afterwards
for i := offset + 1; i < len(dl.ownHashes); i++ {
delete(dl.ownChainTd, dl.ownHashes[i])
delete(dl.ownHeaders, dl.ownHashes[i])
delete(dl.ownReceipts, dl.ownHashes[i])
delete(dl.ownBlocks, dl.ownHashes[i])
delete(dl.ancientChainTd, dl.ownHashes[i])
delete(dl.ancientHeaders, dl.ownHashes[i])
delete(dl.ancientReceipts, dl.ownHashes[i])
delete(dl.ancientBlocks, dl.ownHashes[i])
}
dl.ownHashes = dl.ownHashes[:offset+1]
return nil
}
// Rollback removes some recently added elements from the chain.
func (dl *downloadTester) Rollback(hashes []common.Hash) {
}
// newPeer registers a new block download source into the downloader.