Skip to content

Commit ea4c4d9

Browse files
committed
[ETCM-814] Cover treasury reward transfer with unit tests
1 parent 96ceb22 commit ea4c4d9

File tree

4 files changed

+90
-28
lines changed

4 files changed

+90
-28
lines changed

src/main/scala/io/iohk/ethereum/ledger/BlockExecution.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ class BlockExecution(
3232
val blockExecResult = {
3333
if (block.hasCheckpoint) {
3434
// block with checkpoint is not executed normally - it's not need to do after execution validation
35-
preExecValidationResult
36-
.map(_ => Seq.empty[Receipt])
35+
preExecValidationResult.map(_ => Seq.empty[Receipt])
3736
} else {
3837
for {
3938
_ <- preExecValidationResult
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"difficulty": "0x0400",
3+
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
4+
"gasLimit": "0xff1388",
5+
"nonce": "0x0000000000000042",
6+
"ommersHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
7+
"timestamp": "0x0",
8+
"coinbase": "0x0000000000000000000000000000000000000000",
9+
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
10+
"alloc": {
11+
"d7a681378321f472adffb9fdded2712f677e0ba9": {"balance": "1000000000000000000000000000000000000000000"},
12+
"0000000000000000000000000000000000eeeeee": {"balance": "10"},
13+
"0000000000000000000000000000000000000123": {"balance": "20"}
14+
}
15+
}

src/test/scala/io/iohk/ethereum/consensus/blocks/BlockGeneratorSpec.scala

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package io.iohk.ethereum.consensus.blocks
33
import akka.util.ByteString
44
import io.iohk.ethereum.blockchain.data.GenesisDataLoader
55
import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup
6-
import io.iohk.ethereum.consensus.blocks.BlockTimestampProvider
76
import io.iohk.ethereum.consensus.pow.validators.ValidatorsExecutor
87
import io.iohk.ethereum.consensus.validators._
98
import io.iohk.ethereum.crypto
@@ -12,6 +11,7 @@ import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields
1211
import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields.{HefEmpty, HefPostEcip1097}
1312
import io.iohk.ethereum.domain.SignedTransaction.FirstByteOfAddress
1413
import io.iohk.ethereum.domain._
14+
import io.iohk.ethereum.ledger.BlockExecutionError.ValidationAfterExecError
1515
import io.iohk.ethereum.ledger.{BlockExecution, BlockQueue, BlockValidation}
1616
import io.iohk.ethereum.mpt.MerklePatriciaTrie.MPTException
1717
import io.iohk.ethereum.utils._
@@ -496,25 +496,25 @@ class BlockGeneratorSpec extends AnyFlatSpec with Matchers with ScalaCheckProper
496496
}
497497

498498
it should "generate blocks with the correct extra fields" in {
499-
val table = Table[Boolean, Boolean, Boolean, HeaderExtraFields](
500-
("ecip1098Activated", "ecip1097Activated", "selectedOptOut", "expectedExtraFields"),
499+
val table = Table[Boolean, Boolean, HeaderExtraFields](
500+
("ecip1098Activated", "ecip1097Activated", "expectedExtraFields"),
501501
// No ecip activated
502-
(false, false, true, HefEmpty),
503-
(false, false, false, HefEmpty),
502+
(false, false, HefEmpty),
503+
(false, false, HefEmpty),
504504
// ECIP 1098 activated
505-
(true, false, true, HefEmpty),
506-
(true, false, false, HefEmpty),
505+
(true, false, HefEmpty),
506+
(true, false, HefEmpty),
507507
// ECIP 1097 and 1098 activated
508-
(true, true, true, HefPostEcip1097(None)),
509-
(true, true, false, HefPostEcip1097(None))
508+
(true, true, HefPostEcip1097(None)),
509+
(true, true, HefPostEcip1097(None))
510510
)
511511

512-
forAll(table) { case (ecip1098Activated, ecip1097Activated, selectedOptOut, headerExtraFields) =>
512+
forAll(table) { case (ecip1098Activated, ecip1097Activated, headerExtraFields) =>
513513
val testSetup = new TestSetup {
514514
override lazy val blockchainConfig =
515515
baseBlockchainConfig.copy(ecip1098BlockNumber = 1000, ecip1097BlockNumber = 2000)
516516

517-
override lazy val consensusConfig = buildConsensusConfig().copy(treasuryOptOut = selectedOptOut)
517+
override lazy val consensusConfig = buildConsensusConfig()
518518
}
519519
import testSetup._
520520

@@ -531,7 +531,51 @@ class BlockGeneratorSpec extends AnyFlatSpec with Matchers with ScalaCheckProper
531531

532532
generatedBlock.block.header.extraFields shouldBe headerExtraFields
533533
}
534+
}
534535

536+
it should "generate a failure if treasury transfer was not made" in {
537+
val setup1 = new TestSetup {
538+
override lazy val blockchainConfig = baseBlockchainConfig.copy(ecip1098BlockNumber = 20000000, treasuryAddress = treasuryAccount, customGenesisFileOpt = Some("test-genesis-treasury.json"))
539+
override lazy val consensusConfig = buildConsensusConfig()
540+
}
541+
val block = {
542+
import setup1._
543+
blockGenerator.generateBlock(bestBlock.get, Seq.empty, Address(testAddress), blockGenerator.emptyX, None).pendingBlock
544+
}
545+
546+
val setup2 = new TestSetup {
547+
override lazy val blockchainConfig = baseBlockchainConfig.copy(ecip1098BlockNumber = 1, treasuryAddress = treasuryAccount, customGenesisFileOpt = Some("test-genesis-treasury.json"))
548+
override lazy val consensusConfig = buildConsensusConfig()
549+
}
550+
551+
{
552+
import setup2._
553+
554+
blockExecution.executeAndValidateBlock(block.block, alreadyValidated = true) shouldBe
555+
Left(ValidationAfterExecError("Block has invalid state root hash, expected 47344722e6c52a85685f9c1bb1e0fe66cfaf6be00c1a752f43cc835fb7415e81 but got 41b63e59d34b5b35a040d496582fc587887af79f762210f6cf55c24d2c307d61"))
556+
}
557+
}
558+
559+
it should "generate a failure if treasury transfer was made to a different treasury account" in {
560+
val setup1 = new TestSetup {
561+
override lazy val blockchainConfig = baseBlockchainConfig.copy(ecip1098BlockNumber = 1, treasuryAddress = maliciousAccount, customGenesisFileOpt = Some("test-genesis-treasury.json"))
562+
override lazy val consensusConfig = buildConsensusConfig()
563+
}
564+
val block = {
565+
import setup1._
566+
blockGenerator.generateBlock(bestBlock.get, Seq.empty, Address(testAddress), blockGenerator.emptyX, None).pendingBlock
567+
}
568+
569+
val setup2 = new TestSetup {
570+
override lazy val blockchainConfig = baseBlockchainConfig.copy(ecip1098BlockNumber = 1, treasuryAddress = treasuryAccount, customGenesisFileOpt = Some("test-genesis-treasury.json"))
571+
override lazy val consensusConfig = buildConsensusConfig()
572+
}
573+
574+
{
575+
import setup2._
576+
blockExecution.executeAndValidateBlock(block.block, alreadyValidated = true) shouldBe
577+
Left(ValidationAfterExecError("Block has invalid state root hash, expected 5bfc811dfee1fecaefbaef2dba502082a8cc72e52260368d83ed6e4ebcecae75 but got 41b63e59d34b5b35a040d496582fc587887af79f762210f6cf55c24d2c307d61"))
578+
}
535579
}
536580

537581
trait TestSetup extends EphemBlockchainTestSetup {
@@ -553,6 +597,10 @@ class BlockGeneratorSpec extends AnyFlatSpec with Matchers with ScalaCheckProper
553597
payload = ByteString.empty
554598
)
555599

600+
//defined in test-genesis-treasury.json
601+
val treasuryAccount = Address(0xeeeeee)
602+
val maliciousAccount = Address(0x123)
603+
556604
lazy val signedTransaction = SignedTransaction.sign(transaction, keyPair, Some(0x3d.toByte))
557605
lazy val duplicatedSignedTransaction =
558606
SignedTransaction.sign(transaction.copy(gasLimit = 2), keyPair, Some(0x3d.toByte))

src/test/scala/io/iohk/ethereum/consensus/validators/std/StdBlockValidatorSpec.scala

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,21 @@ import org.scalatest.matchers.should.Matchers
1414

1515
class StdBlockValidatorSpec extends AnyFlatSpec with Matchers with SecureRandomBuilder {
1616

17-
"Block" should "created based on valid data" in {
17+
"Block based on valid data" should "pass validation" in {
1818
val block = Block(validBlockHeader, validBlockBody)
1919
val blockWithCheckpoint = Block(validBlockHeaderWithCheckpoint, BlockBody(Nil, Nil))
2020
StdBlockValidator.validate(block, validReceipts) shouldBe Right(BlockValid)
2121
StdBlockValidator.validate(blockWithCheckpoint, Nil) shouldBe Right(BlockValid)
2222
}
2323

24-
it should "return a failure if block with checkpoint body has a tx" in {
24+
it should "correctly handle the case where a block has no receipts" in {
25+
StdBlockValidator.validate(blockWithOutReceipts, Nil) match {
26+
case Right(validated) => succeed
27+
case _ => fail()
28+
}
29+
}
30+
31+
"Invalid block" should "return a failure if block with checkpoint body has a tx" in {
2532
val block = Block(validBlockHeaderWithCheckpoint, validBlockBody)
2633
StdBlockValidator
2734
.validate(block, Nil) shouldBe Left(CheckpointBlockTransactionsNotEmptyError)
@@ -33,55 +40,48 @@ class StdBlockValidatorSpec extends AnyFlatSpec with Matchers with SecureRandomB
3340
.validate(block, Nil) shouldBe Left(CheckpointBlockOmmersNotEmptyError)
3441
}
3542

36-
"Block" should "return a failure if created based on invalid transactions header" in {
43+
it should "return a failure if created based on invalid transactions header" in {
3744
StdBlockValidator.validate(Block(wrongTransactionsRootHeader, validBlockBody), validReceipts) match {
3845
case Left(BlockTransactionsHashError) => succeed
3946
case _ => fail()
4047
}
4148
}
4249

43-
"Block" should "return a failure if created based on invalid ommers header" in {
50+
it should "return a failure if created based on invalid ommers header" in {
4451
StdBlockValidator.validate(Block(wrongOmmersHashHeader, validBlockBody), validReceipts) match {
4552
case Left(BlockOmmersHashError) => succeed
4653
case _ => fail()
4754
}
4855
}
4956

50-
"Block" should "return a failure if created based on invalid receipts header" in {
57+
it should "return a failure if created based on invalid receipts header" in {
5158
StdBlockValidator.validate(Block(wrongReceiptsHeader, validBlockBody), validReceipts) match {
5259
case Left(BlockReceiptsHashError) => succeed
5360
case _ => fail()
5461
}
5562
}
5663

57-
"Block" should "return a failure if created based on invalid log bloom header" in {
64+
it should "return a failure if created based on invalid log bloom header" in {
5865
StdBlockValidator.validate(Block(wrongLogBloomBlockHeader, validBlockBody), validReceipts) match {
5966
case Left(BlockLogBloomError) => succeed
6067
case _ => fail()
6168
}
6269
}
6370

64-
"Block" should "return a failure if a block body doesn't corresponds to a block header due to wrong tx hash" in {
71+
it should "return a failure if a block body doesn't corresponds to a block header due to wrong tx hash" in {
6572
StdBlockValidator.validateHeaderAndBody(wrongTransactionsRootHeader, validBlockBody) match {
6673
case Left(BlockTransactionsHashError) => succeed
6774
case _ => fail()
6875
}
6976
}
7077

71-
"Block" should "return a failure if a block body doesn't corresponds to a block header due to wrong ommers hash" in {
78+
it should "return a failure if a block body doesn't corresponds to a block header due to wrong ommers hash" in {
7279
StdBlockValidator.validateHeaderAndBody(wrongOmmersHashHeader, validBlockBody) match {
7380
case Left(BlockOmmersHashError) => succeed
7481
case _ => fail()
7582
}
7683
}
7784

78-
"Block" should "correctly handle the case where a block has no receipts" in {
79-
StdBlockValidator.validate(blockWithOutReceipts, Nil) match {
80-
case Right(validated) => succeed
81-
case _ => fail()
82-
}
83-
}
84-
8585
val validBlockHeader = BlockHeader(
8686
parentHash = ByteString(Hex.decode("8345d132564b3660aa5f27c9415310634b50dbc92579c65a0825d9a255227a71")),
8787
ommersHash = ByteString(Hex.decode("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")),

0 commit comments

Comments
 (0)