eth, eth/fetcher: use an import queue to store out of order blocks

This commit is contained in:
Péter Szilágyi
2015-06-16 17:39:04 +03:00
parent 8b64e041d6
commit 057bc237ad
3 changed files with 91 additions and 33 deletions

View File

@ -77,7 +77,7 @@ func newTester() *fetcherTester {
ownHashes: []common.Hash{knownHash},
ownBlocks: map[common.Hash]*types.Block{knownHash: genesis},
}
tester.fetcher = New(tester.hasBlock, tester.importBlock)
tester.fetcher = New(tester.hasBlock, tester.importBlock, tester.chainHeight)
tester.fetcher.Start()
return tester
@ -99,6 +99,11 @@ func (f *fetcherTester) importBlock(peer string, block *types.Block) error {
return nil
}
// chainHeight retrieves the current height (block number) of the chain.
func (f *fetcherTester) chainHeight() uint64 {
return f.ownBlocks[f.ownHashes[len(f.ownHashes)-1]].NumberU64()
}
// peerFetcher retrieves a fetcher associated with a simulated peer.
func (f *fetcherTester) makeFetcher(blocks map[common.Hash]*types.Block) blockRequesterFn {
// Copy all the blocks to ensure they are not tampered with
@ -238,3 +243,31 @@ func TestPendingDeduplication(t *testing.T) {
t.Fatalf("retrieval count mismatch: have %v, want %v", counter, 1)
}
}
// Tests that announcements retrieved in a random order are cached and eventually
// imported when all the gaps are filled in.
func TestRandomArrivalImport(t *testing.T) {
// Create a chain of blocks to import, and choose one to delay
targetBlocks := 24
hashes := createHashes(targetBlocks, knownHash)
blocks := createBlocksFromHashes(hashes)
skip := targetBlocks / 2
tester := newTester()
fetcher := tester.makeFetcher(blocks)
// Iteratively announce blocks, skipping one entry
for i := len(hashes) - 1; i >= 0; i-- {
if i != skip {
tester.fetcher.Notify("valid", hashes[i], time.Now().Add(-arriveTimeout), fetcher)
time.Sleep(50 * time.Millisecond)
}
}
// Finally announce the skipped entry and check full import
tester.fetcher.Notify("valid", hashes[skip], time.Now().Add(-arriveTimeout), fetcher)
time.Sleep(50 * time.Millisecond)
if imported := len(tester.ownBlocks); imported != targetBlocks+1 {
t.Fatalf("synchronised block mismatch: have %v, want %v", imported, targetBlocks+1)
}
}