Skip to content

Commit

Permalink
ETCM-720: Added tests for mining block on beginning or end of epoch
Browse files Browse the repository at this point in the history
  • Loading branch information
milenkara committed Mar 24, 2021
1 parent 6e183f8 commit b588fe3
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 40 deletions.
110 changes: 71 additions & 39 deletions src/test/scala/io/iohk/ethereum/consensus/ethash/EthashMinerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,33 @@ class EthashMinerSpec
private implicit val timeout: Duration = 10.minutes

"EthashMiner" should "mine valid blocks" taggedAs (EthashMinerSpecTag) in new TestSetup {
val parent = origin
val bfm = blockForMining(parent.header)

(blockchain.getBestBlock _).expects().returns(Some(parent)).anyNumberOfTimes()
(ethMiningService.submitHashRate _)
.expects(*)
.returns(Task.now(Right(SubmitHashRateResponse(true))))
.atLeastOnce()
(blockGenerator.generateBlock _)
.expects(parent, Nil, consensusConfig.coinbase, Nil, None)
.returning(PendingBlockAndState(PendingBlock(bfm, Nil), fakeWorld))
.atLeastOnce()

ommersPool.setAutoPilot((sender: ActorRef, _: Any) => {
sender ! OmmersPool.Ommers(Nil)
TestActor.KeepRunning
})

pendingTransactionsManager.setAutoPilot((sender: ActorRef, _: Any) => {
sender ! PendingTransactionsManager.PendingTransactionsResponse(Nil)
TestActor.KeepRunning
})

miner ! MinerProtocol.StartMining

val block = waitForMinedBlock

miner ! MinerProtocol.StopMining

block.body.transactionList shouldBe Seq(txToMine)
block.header.nonce.length shouldBe 8
blockHeaderValidator.validate(block.header, parent.header) shouldBe Right(BlockHeaderValid)
val parentBlock: Block = origin
val bfm: Block = blockForMining(parentBlock.header)

executeTest(parentBlock, bfm)
}

it should "mine valid block on the beginning of the new epoch" taggedAs EthashMinerSpecTag in new TestSetup {
val epochLength: Int = EthashUtils.EPOCH_LENGTH_BEFORE_ECIP_1099
val parentBlockNumber: Int = epochLength - 1 // 29999, mined block will be 30000 (first block of the new epoch)
val parentBlock: Block = origin.copy(header = origin.header.copy(number = parentBlockNumber))
val bfm: Block = blockForMining(parentBlock.header)

executeTest(parentBlock, bfm)
}

it should "mine valid blocks on the end of the epoch" taggedAs EthashMinerSpecTag in new TestSetup {
val epochLength: Int = EthashUtils.EPOCH_LENGTH_BEFORE_ECIP_1099
val parentBlockNumber: Int = 2 * epochLength - 2 // 59998, mined block will be 59999 (last block of the current epoch)
val parentBlock: Block = origin.copy(header = origin.header.copy(number = parentBlockNumber))
val bfm: Block = blockForMining(parentBlock.header)

executeTest(parentBlock, bfm)
}

trait TestSetup extends MinerSpecSetup with MockFactory {

override val origin = Block(
override val origin: Block = Block(
Fixtures.Blocks.Genesis.header.copy(
difficulty = UInt256(Hex.decode("0400")).toBigInt,
number = 0,
Expand All @@ -80,11 +70,11 @@ class EthashMinerSpec

val blockHeaderValidator = new EthashBlockHeaderValidator(blockchainConfig)

val ommersPool = TestProbe()
val pendingTransactionsManager = TestProbe()
val ommersPool: TestProbe = TestProbe()
val pendingTransactionsManager: TestProbe = TestProbe()

val ethService = mock[EthInfoService]
val ethMiningService = mock[EthMiningService]
val ethService: EthInfoService = mock[EthInfoService]
val ethMiningService: EthMiningService = mock[EthMiningService]
val getTransactionFromPoolTimeout: FiniteDuration = 5.seconds

override val blockCreator = new EthashBlockCreator(
Expand All @@ -94,7 +84,49 @@ class EthashMinerSpec
ommersPool = ommersPool.ref
)

val miner = TestActorRef(EthashMiner.props(blockchain, blockCreator, sync.ref, ethService, ethMiningService))

val miner: TestActorRef[Nothing] = TestActorRef(EthashMiner.props(blockchain, blockCreator, sync.ref, ethService, ethMiningService))


protected def executeTest(parentBlock: Block, blockForMining: Block): Unit = {
prepareMocks(parentBlock, blockForMining)
val minedBlock = startMining()
checkAssertions(minedBlock, parentBlock)
}

private def prepareMocks(parentBlock: Block, blockForMining: Block): Unit = {
(blockchain.getBestBlock _).expects().returns(Some(parentBlock)).anyNumberOfTimes()
(ethMiningService.submitHashRate _)
.expects(*)
.returns(Task.now(Right(SubmitHashRateResponse(true))))
.atLeastOnce()
(blockGenerator.generateBlock _)
.expects(parentBlock, Nil, consensusConfig.coinbase, Nil, None)
.returning(PendingBlockAndState(PendingBlock(blockForMining, Nil), fakeWorld))
.atLeastOnce()

ommersPool.setAutoPilot((sender: ActorRef, _: Any) => {
sender ! OmmersPool.Ommers(Nil)
TestActor.KeepRunning
})

pendingTransactionsManager.setAutoPilot((sender: ActorRef, _: Any) => {
sender ! PendingTransactionsManager.PendingTransactionsResponse(Nil)
TestActor.KeepRunning
})
}

private def startMining(): Block = {
miner ! MinerProtocol.StartMining
val block = waitForMinedBlock
miner ! MinerProtocol.StopMining

block
}

private def checkAssertions(minedBlock: Block, parentBlock: Block): Unit = {
minedBlock.body.transactionList shouldBe Seq(txToMine)
minedBlock.header.nonce.length shouldBe 8
blockHeaderValidator.validate(minedBlock.header, parentBlock.header) shouldBe Right(BlockHeaderValid)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ abstract class MinerSpecSetup(implicit system: ActorSystem) extends ScenarioSetu
receiptsRoot = parentHeader.receiptsRoot,
logsBloom = parentHeader.logsBloom,
difficulty = difficultyCalc.calculateDifficulty(1, blockForMiningTimestamp, parentHeader),
number = BigInt(1),
number = parentHeader.number + 1,
gasLimit = calculateGasLimit(UInt256(parentHeader.gasLimit)),
gasUsed = BigInt(0),
unixTimestamp = blockForMiningTimestamp,
Expand Down

0 comments on commit b588fe3

Please sign in to comment.