2 # Copyright (c) 2016 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test NULLDUMMY softfork.
7 Connect to a single node.
8 Generate 2 blocks (save the coinbases for later).
9 Generate 427 more blocks.
10 [Policy/Consensus] Check that NULLDUMMY compliant transactions are accepted in the 430th block.
11 [Policy] Check that non-NULLDUMMY transactions are rejected before activation.
12 [Consensus] Check that the new NULLDUMMY rules are not enforced on the 431st block.
13 [Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block.
16 from test_framework
.test_framework
import BitcoinTestFramework
17 from test_framework
.util
import *
18 from test_framework
.mininode
import CTransaction
, network_thread_start
19 from test_framework
.blocktools
import create_coinbase
, create_block
, add_witness_commitment
20 from test_framework
.script
import CScript
21 from io
import BytesIO
24 NULLDUMMY_ERROR
= "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
27 scriptSig
= CScript(tx
.vin
[0].scriptSig
)
30 if (len(newscript
) == 0):
32 newscript
.append(b
'\x51')
35 tx
.vin
[0].scriptSig
= CScript(newscript
)
38 class NULLDUMMYTest(BitcoinTestFramework
):
40 def set_test_params(self
):
42 self
.setup_clean_chain
= True
43 # This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
44 # normal segwit activation here (and don't use the default always-on behaviour).
45 self
.extra_args
= [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999']]
48 self
.address
= self
.nodes
[0].getnewaddress()
49 self
.ms_address
= self
.nodes
[0].addmultisigaddress(1,[self
.address
])
50 self
.wit_address
= self
.nodes
[0].addwitnessaddress(self
.address
)
51 self
.wit_ms_address
= self
.nodes
[0].addwitnessaddress(self
.ms_address
)
53 network_thread_start()
54 self
.coinbase_blocks
= self
.nodes
[0].generate(2) # Block 2
56 for i
in self
.coinbase_blocks
:
57 coinbase_txid
.append(self
.nodes
[0].getblock(i
)['tx'][0])
58 self
.nodes
[0].generate(427) # Block 429
59 self
.lastblockhash
= self
.nodes
[0].getbestblockhash()
60 self
.tip
= int("0x" + self
.lastblockhash
, 0)
61 self
.lastblockheight
= 429
62 self
.lastblocktime
= int(time
.time()) + 429
64 self
.log
.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]")
65 test1txs
= [self
.create_transaction(self
.nodes
[0], coinbase_txid
[0], self
.ms_address
, 49)]
66 txid1
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[0].serialize_with_witness()), True)
67 test1txs
.append(self
.create_transaction(self
.nodes
[0], txid1
, self
.ms_address
, 48))
68 txid2
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[1].serialize_with_witness()), True)
69 test1txs
.append(self
.create_transaction(self
.nodes
[0], coinbase_txid
[1], self
.wit_ms_address
, 49))
70 txid3
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[2].serialize_with_witness()), True)
71 self
.block_submit(self
.nodes
[0], test1txs
, False, True)
73 self
.log
.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
74 test2tx
= self
.create_transaction(self
.nodes
[0], txid2
, self
.ms_address
, 47)
76 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test2tx
.serialize_with_witness()), True)
78 self
.log
.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]")
79 self
.block_submit(self
.nodes
[0], [test2tx
], False, True)
81 self
.log
.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
82 test4tx
= self
.create_transaction(self
.nodes
[0], test2tx
.hash, self
.address
, 46)
83 test6txs
=[CTransaction(test4tx
)]
85 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test4tx
.serialize_with_witness()), True)
86 self
.block_submit(self
.nodes
[0], [test4tx
])
88 self
.log
.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
89 test5tx
= self
.create_transaction(self
.nodes
[0], txid3
, self
.wit_address
, 48)
90 test6txs
.append(CTransaction(test5tx
))
91 test5tx
.wit
.vtxinwit
[0].scriptWitness
.stack
[0] = b
'\x01'
92 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test5tx
.serialize_with_witness()), True)
93 self
.block_submit(self
.nodes
[0], [test5tx
], True)
95 self
.log
.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]")
97 self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(i
.serialize_with_witness()), True)
98 self
.block_submit(self
.nodes
[0], test6txs
, True, True)
101 def create_transaction(self
, node
, txid
, to_address
, amount
):
102 inputs
= [{ "txid" : txid
, "vout" : 0}]
103 outputs
= { to_address
: amount
}
104 rawtx
= node
.createrawtransaction(inputs
, outputs
)
105 signresult
= node
.signrawtransaction(rawtx
)
107 f
= BytesIO(hex_str_to_bytes(signresult
['hex']))
112 def block_submit(self
, node
, txs
, witness
= False, accept
= False):
113 block
= create_block(self
.tip
, create_coinbase(self
.lastblockheight
+ 1), self
.lastblocktime
+ 1)
118 block
.hashMerkleRoot
= block
.calc_merkle_root()
119 witness
and add_witness_commitment(block
)
122 node
.submitblock(bytes_to_hex_str(block
.serialize(True)))
124 assert_equal(node
.getbestblockhash(), block
.hash)
125 self
.tip
= block
.sha256
126 self
.lastblockhash
= block
.hash
127 self
.lastblocktime
+= 1
128 self
.lastblockheight
+= 1
130 assert_equal(node
.getbestblockhash(), self
.lastblockhash
)
132 if __name__
== '__main__':
133 NULLDUMMYTest().main()