From ad47ce1ea7c4d93b0c9fb99f503f52131ef1dbc6 Mon Sep 17 00:00:00 2001 From: oskin1 Date: Sat, 6 Oct 2018 11:26:04 +0300 Subject: [PATCH 1/3] Test for block with invalid extension application. --- .../nodeView/ErgoNodeViewHolderSpec.scala | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala index 5f0d2b5b4f..b3b617822f 100644 --- a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala @@ -118,10 +118,10 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } getBestHeaderOpt shouldBe Some(block.header) - val brokenBlock = generateInvalidFullBlock(block.header, wusAfterBlock) + val brokenBlock = genInvalidFullBlock(block.header, wusAfterBlock) applyBlock(brokenBlock) shouldBe 'success - val brokenBlock2 = generateInvalidFullBlock(block.header, wusAfterBlock) + val brokenBlock2 = genInvalidFullBlock(block.header, wusAfterBlock) brokenBlock2.header should not be brokenBlock.header applyBlock(brokenBlock2) shouldBe 'success @@ -131,11 +131,11 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - private def generateInvalidFullBlock(parentHeader: Header, parentState: WrappedUtxoState) = { + private def genInvalidFullBlock(parentHeader: Header, parentState: WrappedUtxoState) = { val extensionIn = extensionGen.sample.get val brokenBlockIn = validFullBlock(Some(parentHeader), parentState) val headTx = brokenBlockIn.blockTransactions.txs.head - val wrongBoxId: ADKey = ADKey @@ Algos.hash("wrong input") + val wrongBoxId: ADKey = ADKey !@@ Algos.hash("wrong input") val newInput = headTx.inputs.head.copy(boxId = wrongBoxId) val brokenTransactionsIn = brokenBlockIn.blockTransactions .copy(txs = headTx.copy(inputs = newInput +: headTx.inputs.tail) +: brokenBlockIn.blockTransactions.txs.tail) @@ -147,7 +147,48 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with ErgoFullBlock(brokenHeader, brokenTransactions, extension, Some(brokenProofs)) } - private val t8 = TestCase("switching for a better chain") { fixture => + private val t8 = TestCase("apply full block with invalid extension") { fixture => + import fixture._ + val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) + val genesis = validFullBlock(parentOpt = None, us, bh) + val wusAfterGenesis = WrappedUtxoState(us, bh, stateConstants).applyModifier(genesis).get + if (verifyTransactions) { + applyBlock(genesis) shouldBe 'success + + val block = validFullBlock(Some(genesis.header), wusAfterGenesis) + val wusAfterBlock = wusAfterGenesis.applyModifier(block).get + + applyBlock(block) shouldBe 'success + getBestHeaderOpt shouldBe Some(block.header) + if (verifyTransactions) { + getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) + } + getBestHeaderOpt shouldBe Some(block.header) + + val brokenBlock = genBlockWithInvalidExtension(block.header, wusAfterBlock) + applyBlock(brokenBlock) shouldBe 'success + + val brokenBlock2 = genBlockWithInvalidExtension(block.header, wusAfterBlock) + brokenBlock2.header should not be brokenBlock.header + applyBlock(brokenBlock2) shouldBe 'success + + getBestFullBlockOpt shouldBe Some(block) + getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) + getBestHeaderOpt shouldBe Some(block.header) + } + } + + private def genBlockWithInvalidExtension(parentHeader: Header, parentState: WrappedUtxoState) = { + val extensionIn = extensionGen.sample.get + val validBlockIn = validFullBlock(Some(parentHeader), parentState) + val brokenExtension = extensionIn.copy( + mandatoryFields = extensionIn.mandatoryFields :+ extensionIn.mandatoryFields.head, + headerId = validBlockIn.id + ) + validBlockIn.copy(extension = brokenExtension) + } + + private val t9 = TestCase("switching for a better chain") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val genesis = validFullBlock(parentOpt = None, us, bh) @@ -180,7 +221,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getRootHash shouldBe Algos.encode(chain2block2.header.stateRoot) } - private val t9 = TestCase("UTXO state should generate adProofs and put them in history") { fixture => + private val t10 = TestCase("UTXO state should generate adProofs and put them in history") { fixture => import fixture._ if (stateType == StateType.Utxo) { val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) @@ -195,7 +236,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - private val t10 = TestCase("NodeViewHolder start from inconsistent state") { fixture => + private val t11 = TestCase("NodeViewHolder start from inconsistent state") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val genesis = validFullBlock(parentOpt = None, us, bh) @@ -215,7 +256,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getRootHash shouldBe Algos.encode(block1.header.stateRoot) } - private val t11 = TestCase("apply payload in incorrect order") { fixture => + private val t12 = TestCase("apply payload in incorrect order") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val genesis = validFullBlock(parentOpt = None, us, bh) @@ -240,7 +281,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getBestFullBlockEncodedId shouldBe Some(chain2block2.header.encodedId) } - private val t12 = TestCase("Do not apply txs with wrong header id") { fixture => + private val t13 = TestCase("Do not apply txs with wrong header id") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) @@ -291,7 +332,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with expectMsgType[SyntacticallySuccessfulModifier[BlockTransactions]] } - private val t13 = TestCase("Do not apply wrong adProofs") { fixture => + private val t14 = TestCase("Do not apply wrong adProofs") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) @@ -321,7 +362,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with expectMsgType[SyntacticallySuccessfulModifier[ADProofs]] } - private val t14 = TestCase("do not apply genesis block header if " + + private val t15 = TestCase("do not apply genesis block header if " + "it's not equal to genesisId from config") { fixture => import fixture._ updateConfig(genesisIdConfig(modifierIdGen.sample)) @@ -341,7 +382,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getHistoryHeight shouldBe -1 } - private val t15 = TestCase("apply genesis block header if it's equal to genesisId from config") { fixture => + private val t16 = TestCase("apply genesis block header if it's equal to genesisId from config") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val block = validFullBlock(None, us, bh) @@ -359,7 +400,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getHeightOf(block.header.id) shouldBe Some(0) } - val cases: List[TestCase] = List(t1, t2, t3, t4, t5, t6, t7, t8, t9) + val cases: List[TestCase] = List(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) NodeViewTestConfig.allConfigs.foreach { c => cases.foreach { t => property(s"${t.name} - $c") { @@ -368,7 +409,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - val verifyingTxCases = List(t10, t11, t12, t13) + val verifyingTxCases = List(t11, t12, t13, t14) NodeViewTestConfig.verifyTxConfigs.foreach { c => verifyingTxCases.foreach { t => @@ -378,7 +419,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - val genesisIdTestCases = List(t14, t15) + val genesisIdTestCases = List(t15, t16) def genesisIdConfig(expectedGenesisIdOpt: Option[ModifierId])(protoSettings: ErgoSettings): ErgoSettings = { protoSettings.copy(chainSettings = protoSettings.chainSettings.copy(genesisId = expectedGenesisIdOpt)) } From 668fc12c915e1ae6304248a9b53f2cb7c97f017e Mon Sep 17 00:00:00 2001 From: oskin1 Date: Tue, 9 Oct 2018 12:34:00 +0300 Subject: [PATCH 2/3] Duplicated checks removed. --- .../ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala index b3b617822f..7fd458a011 100644 --- a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala @@ -113,9 +113,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with applyBlock(block) shouldBe 'success getBestHeaderOpt shouldBe Some(block.header) - if (verifyTransactions) { - getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) - } + getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) getBestHeaderOpt shouldBe Some(block.header) val brokenBlock = genInvalidFullBlock(block.header, wusAfterBlock) @@ -160,9 +158,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with applyBlock(block) shouldBe 'success getBestHeaderOpt shouldBe Some(block.header) - if (verifyTransactions) { - getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) - } + getRootHash shouldBe Algos.encode(wusAfterBlock.rootHash) getBestHeaderOpt shouldBe Some(block.header) val brokenBlock = genBlockWithInvalidExtension(block.header, wusAfterBlock) From 2d51ab4844ef2026a63bef6a14b36a3a21c39d2a Mon Sep 17 00:00:00 2001 From: oskin1 Date: Wed, 17 Oct 2018 13:45:26 +0300 Subject: [PATCH 3/3] Tests for full block application moved to verifying tx cases. --- .../nodeView/ErgoNodeViewHolderSpec.scala | 104 +++++++++--------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala index 7fd458a011..22f9cc9f76 100644 --- a/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/ErgoNodeViewHolderSpec.scala @@ -99,7 +99,55 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - private val t7 = TestCase("apply invalid full block") { fixture => + private val t7 = TestCase("switching for a better chain") { fixture => + import fixture._ + val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) + val genesis = validFullBlock(parentOpt = None, us, bh) + val wusAfterGenesis = WrappedUtxoState(us, bh, stateConstants).applyModifier(genesis).get + + applyBlock(genesis) shouldBe 'success + getRootHash shouldBe Algos.encode(wusAfterGenesis.rootHash) + + val chain1block1 = validFullBlock(Some(genesis.header), wusAfterGenesis) + val expectedBestFullBlockOpt = if (verifyTransactions) Some(chain1block1) else None + applyBlock(chain1block1) shouldBe 'success + getBestFullBlockOpt shouldBe expectedBestFullBlockOpt + getBestHeaderOpt shouldBe Some(chain1block1.header) + + val chain2block1 = validFullBlock(Some(genesis.header), wusAfterGenesis) + applyBlock(chain2block1) shouldBe 'success + getBestFullBlockOpt shouldBe expectedBestFullBlockOpt + getBestHeaderOpt shouldBe Some(chain1block1.header) + + val wusChain2Block1 = wusAfterGenesis.applyModifier(chain2block1).get + val chain2block2 = validFullBlock(Some(chain2block1.header), wusChain2Block1) + chain2block1.header.stateRoot shouldEqual wusChain2Block1.rootHash + + applyBlock(chain2block2) shouldBe 'success + if (verifyTransactions) { + getBestFullBlockEncodedId shouldBe Some(chain2block2.header.encodedId) + } + + getBestHeaderOpt shouldBe Some(chain2block2.header) + getRootHash shouldBe Algos.encode(chain2block2.header.stateRoot) + } + + private val t8 = TestCase("UTXO state should generate adProofs and put them in history") { fixture => + import fixture._ + if (stateType == StateType.Utxo) { + val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) + val genesis = validFullBlock(parentOpt = None, us, bh) + + nodeViewHolderRef ! LocallyGeneratedModifier(genesis.header) + nodeViewHolderRef ! LocallyGeneratedModifier(genesis.blockTransactions) + nodeViewHolderRef ! LocallyGeneratedModifier(genesis.extension) + + getBestFullBlockOpt shouldBe Some(genesis) + getModifierById(genesis.adProofs.get.id) shouldBe genesis.adProofs + } + } + + private val t9 = TestCase("apply invalid full block") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val genesis = validFullBlock(parentOpt = None, us, bh) @@ -145,7 +193,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with ErgoFullBlock(brokenHeader, brokenTransactions, extension, Some(brokenProofs)) } - private val t8 = TestCase("apply full block with invalid extension") { fixture => + private val t10 = TestCase("apply full block with invalid extension") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) val genesis = validFullBlock(parentOpt = None, us, bh) @@ -184,54 +232,6 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with validBlockIn.copy(extension = brokenExtension) } - private val t9 = TestCase("switching for a better chain") { fixture => - import fixture._ - val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = WrappedUtxoState(us, bh, stateConstants).applyModifier(genesis).get - - applyBlock(genesis) shouldBe 'success - getRootHash shouldBe Algos.encode(wusAfterGenesis.rootHash) - - val chain1block1 = validFullBlock(Some(genesis.header), wusAfterGenesis) - val expectedBestFullBlockOpt = if (verifyTransactions) Some(chain1block1) else None - applyBlock(chain1block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val chain2block1 = validFullBlock(Some(genesis.header), wusAfterGenesis) - applyBlock(chain2block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val wusChain2Block1 = wusAfterGenesis.applyModifier(chain2block1).get - val chain2block2 = validFullBlock(Some(chain2block1.header), wusChain2Block1) - chain2block1.header.stateRoot shouldEqual wusChain2Block1.rootHash - - applyBlock(chain2block2) shouldBe 'success - if (verifyTransactions) { - getBestFullBlockEncodedId shouldBe Some(chain2block2.header.encodedId) - } - - getBestHeaderOpt shouldBe Some(chain2block2.header) - getRootHash shouldBe Algos.encode(chain2block2.header.stateRoot) - } - - private val t10 = TestCase("UTXO state should generate adProofs and put them in history") { fixture => - import fixture._ - if (stateType == StateType.Utxo) { - val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) - val genesis = validFullBlock(parentOpt = None, us, bh) - - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.header) - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.blockTransactions) - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.extension) - - getBestFullBlockOpt shouldBe Some(genesis) - getModifierById(genesis.adProofs.get.id) shouldBe genesis.adProofs - } - } - private val t11 = TestCase("NodeViewHolder start from inconsistent state") { fixture => import fixture._ val (us, bh) = createUtxoState(Some(nodeViewHolderRef)) @@ -396,7 +396,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with getHeightOf(block.header.id) shouldBe Some(0) } - val cases: List[TestCase] = List(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) + val cases: List[TestCase] = List(t1, t2, t3, t4, t5, t6, t7, t8) NodeViewTestConfig.allConfigs.foreach { c => cases.foreach { t => property(s"${t.name} - $c") { @@ -405,7 +405,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with } } - val verifyingTxCases = List(t11, t12, t13, t14) + val verifyingTxCases = List(t9, t10, t11, t12, t13, t14) NodeViewTestConfig.verifyTxConfigs.foreach { c => verifyingTxCases.foreach { t =>