Skip to content

Commit

Permalink
[FIX] Add test case for rewind with lack of parent
Browse files Browse the repository at this point in the history
  • Loading branch information
KonradStaniec committed Sep 3, 2020
1 parent dc859ad commit af48fb8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
15 changes: 7 additions & 8 deletions src/main/scala/io/iohk/ethereum/blockchain/sync/FastSync.scala
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,8 @@ class FastSync(
blockchain.getTotalDifficultyByHash(header.parentHash).toRight(ParentDifficultyNotFound(header))
}

private def handleRewind(header: BlockHeader, peer: Option[Peer], N: Int): Unit = {
peer.foreach(p =>
blacklist(p.id, blacklistDuration, "block header validation failed")
)
private def handleRewind(header: BlockHeader, peer: Peer, N: Int): Unit = {
blacklist(peer.id, blacklistDuration, "block header validation failed")
if (header.number <= syncState.safeDownloadTarget) {
discardLastBlocks(header.number, N)
syncState = syncState.updateDiscardedBlocks(header, N)
Expand All @@ -317,17 +315,18 @@ class FastSync(
if (checkHeadersChain(headers)) {
processHeaders(peer, headers) match {
case ParentDifficultyNotFound(header) =>
// We could end in wrong fork and get blocked. Correct course of action is to not blacklist anyone and not
// rewind fast sync a litte
// We could end in wrong fork and get blocked so we should rewind our state a little
// we blacklist peer just in case we got malicious peer which would send us bad blocks, forcing us to rollback
// to genesis
log.info("Parent difficulty not found for block {}, not processing rest of headers", header.idTag)
handleRewind(header, None, syncConfig.fastSyncBlockValidationN)
handleRewind(header, peer, syncConfig.fastSyncBlockValidationN)
case HeadersProcessingFinished =>
processSyncing()
case ImportedTargetBlock =>
updateTargetBlock(ImportedLastBlock)
case ValidationFailed(header, peerToBlackList) =>
log.info(s"validation fo header ${header.idTag} failed")
handleRewind(header, Some(peerToBlackList), syncConfig.fastSyncBlockValidationN)
handleRewind(header, peerToBlackList, syncConfig.fastSyncBlockValidationN)
}
} else {
blacklist(peer.id, blacklistDuration, "error in block headers response")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,35 @@ class SyncControllerSpec extends FlatSpec with Matchers with BeforeAndAfter with
syncState.receiptsQueue.isEmpty shouldBe true
}

it should "rewind fast-sync state if received header have no known parent" in new TestSetup() {

val bestBlockNumber = defaultExpectedTargetBlock - 1

startWithState(defaultState.copy(bestBlockHeaderNumber = bestBlockNumber))

Thread.sleep(1.seconds.toMillis)

syncController ! SyncController.Start

updateHandshakedPeers(HandshakedPeers(singlePeer))

sendBlockHeaders(
defaultTargetBlockHeader.number,
Seq(defaultTargetBlockHeader.copy(number = defaultExpectedTargetBlock, parentHash = ByteString(0,1))),
peer1,
defaultExpectedTargetBlock - bestBlockNumber)

persistState()

val syncState = storagesInstance.storages.fastSyncStateStorage.getSyncState().get

syncState.bestBlockHeaderNumber shouldBe (bestBlockNumber - syncConfig.fastSyncBlockValidationN)
syncState.nextBlockToFullyValidate shouldBe (bestBlockNumber - syncConfig.fastSyncBlockValidationN + 1)
syncState.blockBodiesQueue.isEmpty shouldBe true
syncState.receiptsQueue.isEmpty shouldBe true
}


it should "not change best block after receiving faraway block" in new TestSetup(_validators = new Mocks.MockValidatorsAlwaysSucceed {
override val blockHeaderValidator: BlockHeaderValidator = { (blockHeader, getBlockHeaderByHash) => Left(HeaderParentNotFoundError) }
}) {
Expand Down

0 comments on commit af48fb8

Please sign in to comment.