dash/test/functional/feature_dip0020_activation.py

115 lines
5.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# Copyright (c) 2015-2023 The Dash Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.blocktools import create_block, create_coinbase
Merge bitcoin/bitcoin#22257: test: refactor: various (de)serialization helpers cleanups/improvements bdb8b9a347e68f80a2e8d44ce5590a2e8214b6bb test: doc: improve doc for `from_hex` helper (mention `to_hex` alternative) (Sebastian Falbesoner) 191405420815d49ab50184513717a303fc2744d6 scripted-diff: test: rename `FromHex` to `from_hex` (Sebastian Falbesoner) a79396fe5f8f81c78cf84117a87074c6ff6c9d95 test: remove `ToHex` helper, use .serialize().hex() instead (Sebastian Falbesoner) 2ce7b47958c4a10ba20dc86c011d71cda4b070a5 test: introduce `tx_from_hex` helper for tx deserialization (Sebastian Falbesoner) Pull request description: There are still many functional tests that perform conversions from a hex-string to a message object (deserialization) manually. This PR identifies all those instances and replaces them with a newly introduced helper `tx_from_hex`. Instances were found via * `git grep "deserialize.*BytesIO"` and some of them manually, when it were not one-liners. Further, the helper `ToHex` was removed and simply replaced by `.serialize().hex()`, since now both variants are in use (sometimes even within the same test) and using the helper doesn't really have an advantage in readability. (see discussion https://github.com/bitcoin/bitcoin/pull/22257#discussion_r652404782) ACKs for top commit: MarcoFalke: review re-ACK bdb8b9a347e68f80a2e8d44ce5590a2e8214b6bb 😁 Tree-SHA512: e25d7dc85918de1d6755a5cea65471b07a743204c20ad1c2f71ff07ef48cc1b9ad3fe5f515c1efaba2b2e3d89384e7980380c5d81895f9826e2046808cd3266e
2021-06-24 12:47:04 +02:00
from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut
from test_framework.p2p import P2PDataStore
from test_framework.script import CScript, OP_CAT, OP_DROP, OP_TRUE
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_raises_rpc_error, softfork_active, satoshi_round
'''
feature_dip0020_activation.py
This test checks activation of DIP0020 opcodes
'''
DISABLED_OPCODE_ERROR = "non-mandatory-script-verify-flag (Attempted to use a disabled opcode)"
DIP0020_HEIGHT = 300
class DIP0020ActivationTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [[
f'-testactivationheight=dip0020@{DIP0020_HEIGHT}',
"-acceptnonstdtxn=1",
]]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def create_test_block(self, txs, tip_hash, tip_height, tip_time):
block = create_block(int(tip_hash, 16), create_coinbase(tip_height + 1), tip_time + 1)
block.nVersion = 4
block.vtx.extend(txs)
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
block.solve()
return block
def run_test(self):
node = self.nodes[0]
relayfee = satoshi_round(node.getnetworkinfo()["relayfee"])
# We should have some coins already
utxos = node.listunspent()
2021-08-27 21:03:02 +02:00
assert len(utxos) > 0
# Lock some coins using disabled opcodes
utxo = utxos[len(utxos) - 1]
value = int(satoshi_round(utxo["amount"] - relayfee) * COIN)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"])))
tx.vout.append(CTxOut(value, CScript([b'1', b'2', OP_CAT])))
tx_signed_hex = node.signrawtransactionwithwallet(tx.serialize().hex())["hex"]
txid = node.sendrawtransaction(tx_signed_hex)
# This tx should be completely valid, should be included in mempool and mined in the next block
assert txid in set(node.getrawmempool())
node.generate(1)
assert txid not in set(node.getrawmempool())
# Create spending tx
value = int(value - relayfee * COIN)
tx0 = CTransaction()
tx0.vin.append(CTxIn(COutPoint(int(txid, 16), 0)))
tx0.vout.append(CTxOut(value, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx0.rehash()
Merge bitcoin/bitcoin#22257: test: refactor: various (de)serialization helpers cleanups/improvements bdb8b9a347e68f80a2e8d44ce5590a2e8214b6bb test: doc: improve doc for `from_hex` helper (mention `to_hex` alternative) (Sebastian Falbesoner) 191405420815d49ab50184513717a303fc2744d6 scripted-diff: test: rename `FromHex` to `from_hex` (Sebastian Falbesoner) a79396fe5f8f81c78cf84117a87074c6ff6c9d95 test: remove `ToHex` helper, use .serialize().hex() instead (Sebastian Falbesoner) 2ce7b47958c4a10ba20dc86c011d71cda4b070a5 test: introduce `tx_from_hex` helper for tx deserialization (Sebastian Falbesoner) Pull request description: There are still many functional tests that perform conversions from a hex-string to a message object (deserialization) manually. This PR identifies all those instances and replaces them with a newly introduced helper `tx_from_hex`. Instances were found via * `git grep "deserialize.*BytesIO"` and some of them manually, when it were not one-liners. Further, the helper `ToHex` was removed and simply replaced by `.serialize().hex()`, since now both variants are in use (sometimes even within the same test) and using the helper doesn't really have an advantage in readability. (see discussion https://github.com/bitcoin/bitcoin/pull/22257#discussion_r652404782) ACKs for top commit: MarcoFalke: review re-ACK bdb8b9a347e68f80a2e8d44ce5590a2e8214b6bb 😁 Tree-SHA512: e25d7dc85918de1d6755a5cea65471b07a743204c20ad1c2f71ff07ef48cc1b9ad3fe5f515c1efaba2b2e3d89384e7980380c5d81895f9826e2046808cd3266e
2021-06-24 12:47:04 +02:00
tx0_hex = tx0.serialize().hex()
tx0id = node.decoderawtransaction(tx0_hex)["txid"]
# flush state to disk before potential crashes below
self.nodes[0].gettxoutsetinfo()
self.log.info("Transactions spending coins with new opcodes aren't accepted before DIP0020 activation")
assert not softfork_active(node, 'dip0020')
2024-10-01 20:13:02 +02:00
assert_raises_rpc_error(-26, DISABLED_OPCODE_ERROR, node.sendrawtransaction, tx0_hex)
helper_peer = node.add_p2p_connection(P2PDataStore())
helper_peer.send_txs_and_test([tx0], node, success=False, reject_reason=DISABLED_OPCODE_ERROR)
tip = node.getblock(node.getbestblockhash(), 1)
test_block = self.create_test_block([tx0], tip["hash"], tip["height"], tip["time"])
helper_peer.send_blocks_and_test([test_block], node, success=False, reject_reason='block-validation-failed', expect_disconnect=True)
self.log.info("Generate enough blocks to activate DIP0020 opcodes")
node.generate(97)
assert not softfork_active(node, 'dip0020')
node.generate(1)
assert softfork_active(node, 'dip0020')
# flush state to disk before potential crashes below
self.nodes[0].gettxoutsetinfo()
# Still need 1 more block for mempool to accept txes spending new opcodes
self.log.info("Transactions spending coins with new opcodes aren't accepted at DIP0020 activation block")
2024-10-01 20:13:02 +02:00
assert_raises_rpc_error(-26, DISABLED_OPCODE_ERROR, node.sendrawtransaction, tx0_hex)
helper_peer = node.add_p2p_connection(P2PDataStore())
helper_peer.send_txs_and_test([tx0], node, success=False, reject_reason=DISABLED_OPCODE_ERROR)
# A block containing new opcodes is accepted however
tip = node.getblock(node.getbestblockhash(), 1)
test_block = self.create_test_block([tx0], tip["hash"], tip["height"], tip["time"])
helper_peer.send_blocks_and_test([test_block], node, success=True)
2024-10-01 20:13:02 +02:00
# txes spending new opcodes still won't be accepted into mempool if we roll back to the previous tip
node.invalidateblock(node.getbestblockhash())
assert tx0id not in set(node.getrawmempool())
node.generate(1)
self.log.info("Transactions spending coins with new opcodes are accepted one block after DIP0020 activation block")
node.sendrawtransaction(tx0_hex)
assert tx0id in set(node.getrawmempool())
if __name__ == '__main__':
DIP0020ActivationTest().main()