From 8eee33a5b5b267984480daf09d016bb85f9e169f Mon Sep 17 00:00:00 2001 From: Ivan Mashonskii Date: Tue, 3 Oct 2023 16:10:37 +0300 Subject: [PATCH] NODE-2609 Add test --- .../state/BlockchainUpdaterImpl.scala | 7 ++-- .../com/wavesplatform/history/Domain.scala | 6 ++- .../state/BlockChallengeTest.scala | 41 +++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala index e137b378c1..90ccafbdb2 100644 --- a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala +++ b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala @@ -274,15 +274,16 @@ class BlockchainUpdaterImpl( s"Better liquid block(timestamp=${block.header.timestamp}) received and applied instead of existing(timestamp=${ng.base.header.timestamp})" ) BlockStats.replaced(ng.base, block) - val (mbs, diffs) = ng.allSnapshots.unzip - log.trace(s"Discarded microblocks = $mbs, diffs = ${diffs.map(_.hashString)}") + val (mbs, mbSnapshots) = ng.allSnapshots.unzip + val allSnapshots = ng.baseBlockSnapshot +: mbSnapshots + log.trace(s"Discarded microblocks = $mbs, snapshots = ${allSnapshots.map(_.hashString)}") val updatedBlockchain = SnapshotBlockchain(referencedBlockchain, r.snapshot, block, hitSource, r.carry, None, None) miner.scheduleMining(Some(updatedBlockchain)) blockchainUpdateTriggers.onRollback(this, ng.base.header.reference, rocksdb.height) blockchainUpdateTriggers.onProcessBlock(block, r.keyBlockSnapshot, ng.reward, hitSource, referencedBlockchain) - Some((r, diffs, ng.reward, hitSource)) + Some((r, allSnapshots, ng.reward, hitSource)) } } else if (areVersionsOfSameBlock(block, ng.base)) { // silently ignore diff --git a/node/src/test/scala/com/wavesplatform/history/Domain.scala b/node/src/test/scala/com/wavesplatform/history/Domain.scala index ab2401b7c5..97db038dee 100644 --- a/node/src/test/scala/com/wavesplatform/history/Domain.scala +++ b/node/src/test/scala/com/wavesplatform/history/Domain.scala @@ -498,7 +498,8 @@ case class Domain(rdb: RDB, blockchainUpdater: BlockchainUpdaterImpl, rocksDBWri stateHash: Option[Option[ByteStr]] = None, ref: Option[ByteStr] = None, txs: Option[Seq[Transaction]] = None, - challengedHeader: Option[ChallengedHeader] = None + challengedHeader: Option[ChallengedHeader] = None, + timestamp: Option[Long] = None ): Block = { createBlock( Block.ProtoBlockVersion, @@ -520,7 +521,8 @@ case class Domain(rdb: RDB, blockchainUpdater: BlockchainUpdaterImpl, rocksDBWri challengedBlock.signature ) ) - ) + ), + timestamp = timestamp ) } diff --git a/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala b/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala index 50819fcc40..3d9841c28c 100644 --- a/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala @@ -1825,6 +1825,47 @@ class BlockChallengeTest extends PropSpec with WithDomain with ScalatestRouteTes } } + property("NODE-1177. Transactions should return to UTX after replacing current liquid block by better block") { + val challengedMiner = TxHelpers.signer(1) + val sender = TxHelpers.signer(2) + val currentBlockSender = TxHelpers.signer(3) + val betterBlockSender = TxHelpers.signer(4) + withDomain(settings, balances = AddrWithBalance.enoughBalances(sender, currentBlockSender, betterBlockSender)) { d => + val challengingMiner = d.wallet.generateNewAccount().get + d.appendBlock( + TxHelpers.transfer(sender, challengingMiner.toAddress, 1000.waves), + TxHelpers.transfer(sender, challengedMiner.toAddress, 2000.waves) + ) + (1 to 999).foreach(_ => d.appendBlock()) + + val txs = Seq( + TxHelpers.transfer(sender, TxHelpers.defaultAddress, amount = 1.waves), + TxHelpers.transfer(sender, TxHelpers.defaultAddress, amount = 2.waves) + ) + val betterBlock = d.createBlock(Block.ProtoBlockVersion, Seq.empty, strictTime = true, generator = betterBlockSender) + val originalBlock = + d.createBlock( + Block.ProtoBlockVersion, + txs, + strictTime = true, + generator = challengedMiner, + stateHash = Some(Some(invalidStateHash)) + ) + val challengingBlock = d.createChallengingBlock(challengingMiner, originalBlock, strictTime = true, timestamp = Some(Long.MaxValue)) + + d.appendBlockE(challengingBlock) should beRight + d.lastBlock shouldBe challengingBlock + d.utxPool.size shouldBe 0 + + val appender = createBlockAppender(d) + testTime.setTime(betterBlock.header.timestamp) + appender(betterBlock).runSyncUnsafe() should beRight + d.lastBlock shouldBe betterBlock + d.utxPool.priorityPool.priorityTransactions.size shouldBe txs.size + d.utxPool.priorityPool.priorityTransactions.toSet shouldBe txs.toSet + } + } + private def appendAndCheck(block: Block, d: Domain)(check: Block => Unit): Unit = { val channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE) val channel1 = new EmbeddedChannel(new MessageCodec(PeerDatabase.NoOp))