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.
6 from test_framework
.test_framework
import BitcoinTestFramework
7 from test_framework
.util
import *
8 from test_framework
.mininode
import CTransaction
, NetworkThread
9 from test_framework
.blocktools
import create_coinbase
, create_block
, add_witness_commitment
10 from test_framework
.script
import CScript
11 from io
import BytesIO
14 NULLDUMMY_ERROR
= "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
17 scriptSig
= CScript(tx
.vin
[0].scriptSig
)
20 if (len(newscript
) == 0):
22 newscript
.append(b
'\x51')
25 tx
.vin
[0].scriptSig
= CScript(newscript
)
29 This test is meant to exercise NULLDUMMY softfork.
30 Connect to a single node.
31 Generate 2 blocks (save the coinbases for later).
32 Generate 427 more blocks.
33 [Policy/Consensus] Check that NULLDUMMY compliant transactions are accepted in the 430th block.
34 [Policy] Check that non-NULLDUMMY transactions are rejected before activation.
35 [Consensus] Check that the new NULLDUMMY rules are not enforced on the 431st block.
36 [Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block.
39 class NULLDUMMYTest(BitcoinTestFramework
):
44 self
.setup_clean_chain
= True
46 def setup_network(self
):
47 # Must set the blockversion for this test
48 self
.nodes
= start_nodes(self
.num_nodes
, self
.options
.tmpdir
,
49 extra_args
=[['-debug', '-whitelist=127.0.0.1', '-walletprematurewitness']])
52 self
.address
= self
.nodes
[0].getnewaddress()
53 self
.ms_address
= self
.nodes
[0].addmultisigaddress(1,[self
.address
])
54 self
.wit_address
= self
.nodes
[0].addwitnessaddress(self
.address
)
55 self
.wit_ms_address
= self
.nodes
[0].addwitnessaddress(self
.ms_address
)
57 NetworkThread().start() # Start up network handling in another thread
58 self
.coinbase_blocks
= self
.nodes
[0].generate(2) # Block 2
60 for i
in self
.coinbase_blocks
:
61 coinbase_txid
.append(self
.nodes
[0].getblock(i
)['tx'][0])
62 self
.nodes
[0].generate(427) # Block 429
63 self
.lastblockhash
= self
.nodes
[0].getbestblockhash()
64 self
.tip
= int("0x" + self
.lastblockhash
, 0)
65 self
.lastblockheight
= 429
66 self
.lastblocktime
= int(time
.time()) + 429
68 print ("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]")
69 test1txs
= [self
.create_transaction(self
.nodes
[0], coinbase_txid
[0], self
.ms_address
, 49)]
70 txid1
= self
.tx_submit(self
.nodes
[0], test1txs
[0])
71 test1txs
.append(self
.create_transaction(self
.nodes
[0], txid1
, self
.ms_address
, 48))
72 txid2
= self
.tx_submit(self
.nodes
[0], test1txs
[1])
73 test1txs
.append(self
.create_transaction(self
.nodes
[0], coinbase_txid
[1], self
.wit_ms_address
, 49))
74 txid3
= self
.tx_submit(self
.nodes
[0], test1txs
[2])
75 self
.block_submit(self
.nodes
[0], test1txs
, False, True)
77 print ("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
78 test2tx
= self
.create_transaction(self
.nodes
[0], txid2
, self
.ms_address
, 48)
80 txid4
= self
.tx_submit(self
.nodes
[0], test2tx
, NULLDUMMY_ERROR
)
82 print ("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]")
83 self
.block_submit(self
.nodes
[0], [test2tx
], False, True)
85 print ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
86 test4tx
= self
.create_transaction(self
.nodes
[0], txid4
, self
.address
, 47)
87 test6txs
=[CTransaction(test4tx
)]
89 self
.tx_submit(self
.nodes
[0], test4tx
, NULLDUMMY_ERROR
)
90 self
.block_submit(self
.nodes
[0], [test4tx
])
92 print ("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
93 test5tx
= self
.create_transaction(self
.nodes
[0], txid3
, self
.wit_address
, 48)
94 test6txs
.append(CTransaction(test5tx
))
95 test5tx
.wit
.vtxinwit
[0].scriptWitness
.stack
[0] = b
'\x01'
96 self
.tx_submit(self
.nodes
[0], test5tx
, NULLDUMMY_ERROR
)
97 self
.block_submit(self
.nodes
[0], [test5tx
], True)
99 print ("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]")
101 self
.tx_submit(self
.nodes
[0], i
)
102 self
.block_submit(self
.nodes
[0], test6txs
, True, True)
105 def create_transaction(self
, node
, txid
, to_address
, amount
):
106 inputs
= [{ "txid" : txid
, "vout" : 0}]
107 outputs
= { to_address
: amount
}
108 rawtx
= node
.createrawtransaction(inputs
, outputs
)
109 signresult
= node
.signrawtransaction(rawtx
)
111 f
= BytesIO(hex_str_to_bytes(signresult
['hex']))
116 def tx_submit(self
, node
, tx
, msg
= ""):
119 node
.sendrawtransaction(bytes_to_hex_str(tx
.serialize_with_witness()), True)
120 except JSONRPCException
as exp
:
121 assert_equal(exp
.error
["message"], msg
)
123 assert_equal('', msg
)
127 def block_submit(self
, node
, txs
, witness
= False, accept
= False):
128 block
= create_block(self
.tip
, create_coinbase(self
.lastblockheight
+ 1), self
.lastblocktime
+ 1)
133 block
.hashMerkleRoot
= block
.calc_merkle_root()
134 witness
and add_witness_commitment(block
)
137 node
.submitblock(bytes_to_hex_str(block
.serialize(True)))
139 assert_equal(node
.getbestblockhash(), block
.hash)
140 self
.tip
= block
.sha256
141 self
.lastblockhash
= block
.hash
142 self
.lastblocktime
+= 1
143 self
.lastblockheight
+= 1
145 assert_equal(node
.getbestblockhash(), self
.lastblockhash
)
147 if __name__
== '__main__':
148 NULLDUMMYTest().main()