From 233c4d1e3ea3024a6b8038662b776c67075575e4 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 2 Nov 2022 00:39:47 +0700 Subject: [PATCH] feat: improved functional tests for asset locks feature - reconsider/invalide blocks - manually created block with invalid transaction --- test/functional/feature_asset_locks.py | 59 ++++++++++++++++++++------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/test/functional/feature_asset_locks.py b/test/functional/feature_asset_locks.py index 6503167053ee79..684fb412811a99 100755 --- a/test/functional/feature_asset_locks.py +++ b/test/functional/feature_asset_locks.py @@ -8,6 +8,10 @@ from decimal import Decimal from io import BytesIO +from test_framework.blocktools import ( + create_block, + create_coinbase, +) from test_framework.authproxy import JSONRPCException from test_framework.key import ECKey from test_framework.messages import ( @@ -158,6 +162,7 @@ def run_test(self): coins = node.listunspent() coin = coins.pop() locked_1 = 10 * COIN + 141421 + locked_2 = 10 * COIN + 314159 asset_lock_tx = create_assetlock(node, coin, locked_1, pubkey) self.check_mempool_result( @@ -189,15 +194,18 @@ def run_test(self): self.sync_all() assert_equal(get_credit_pool_amount(node), 0) self.log.info("Resubmit asset lock tx to new chain...") - txid_in_block = node.sendrawtransaction(hexstring=asset_lock_tx.serialize().hex(), maxfeerate=0) - node.generate(3) + # NEW tx appears + asset_lock_tx_2 = create_assetlock(node, coin, locked_2, pubkey) + + txid_in_block = node.sendrawtransaction(hexstring=asset_lock_tx_2.serialize().hex(), maxfeerate=0) + node.generate(1) self.sync_all() - assert_equal(get_credit_pool_amount(node), locked_1) + assert_equal(get_credit_pool_amount(node), locked_2) node.generate(3) self.sync_all() - assert_equal(get_credit_pool_amount(node), locked_1) + assert_equal(get_credit_pool_amount(node), locked_2) self.log.info("Reconsider old blocks...") for inode in self.nodes: inode.reconsiderblock(block_hash_1) @@ -237,17 +245,7 @@ def run_test(self): except JSONRPCException as e: assert "Transaction already in block chain" in e.error['message'] - self.log.info("Invalidate block with asset unlock tx...") block_asset_unlock = node.getbestblockhash() - for inode in self.nodes: - inode.invalidateblock(block_asset_unlock) - assert_equal(get_credit_pool_amount(node), locked_1) - # TODO: strange, fails if generate there new blocks - #node.generate(3) - #self.sync_all() - for inode in self.nodes: - inode.reconsiderblock(block_asset_unlock) - assert_equal(get_credit_pool_amount(node), locked_1 - COIN) # mine next quorum, tx should be still accepted self.mine_quorum() @@ -279,6 +277,39 @@ def run_test(self): result_expected=[{'txid': asset_unlock_tx_inactive_quorum.rehash(), 'allowed': False, 'reject-reason' : '16: bad-assetunlock-not-active-quorum'}], rawtxs=[asset_unlock_tx_inactive_quorum.serialize().hex()], ) + block_to_reconsider = node.getbestblockhash() + self.log.info("Test block invalidation with asset unlock tx...") + for inode in self.nodes: + inode.invalidateblock(block_asset_unlock) + assert_equal(get_credit_pool_amount(node), locked_1) + # generate some new blocks + node.generate(90) + self.sync_all() + assert_equal(get_credit_pool_amount(node), locked_1) + for inode in self.nodes: + inode.reconsiderblock(block_to_reconsider) + assert_equal(get_credit_pool_amount(node), locked_1 - 2 * COIN) + + # Forcibly mine asset_unlock_tx_too_late and ensure block is invalid + hh = node.getbestblockhash() + best_block = node.getblock(hh) + tip = int(node.getbestblockhash(), 16) + height = best_block["height"] + 1 + block_time = best_block["time"] + 1 + + + cbb = create_coinbase(height, dip4_activated=True, dip27_activated=True) + block = create_block(tip, cbb, block_time, version=3) + block.vtx.append(asset_unlock_tx_too_late) + block.hashMerkleRoot = block.calc_merkle_root() + block.solve() + result = node.submitblock(block.serialize().hex()) + # Expect an error here + expected_error = "bad-assetunlock-not-active-quorum" + if result != expected_error: + raise AssertionError('mining the block should have failed with error %s, but submitblock returned %s' % (expected_error, result)) + + # ---- node.generate(13) self.sync_all()