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
, NetworkThread
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 self
.extra_args
= [['-whitelist=127.0.0.1', '-walletprematurewitness']]
46 self
.address
= self
.nodes
[0].getnewaddress()
47 self
.ms_address
= self
.nodes
[0].addmultisigaddress(1,[self
.address
])
48 self
.wit_address
= self
.nodes
[0].addwitnessaddress(self
.address
)
49 self
.wit_ms_address
= self
.nodes
[0].addwitnessaddress(self
.ms_address
)
51 NetworkThread().start() # Start up network handling in another thread
52 self
.coinbase_blocks
= self
.nodes
[0].generate(2) # Block 2
54 for i
in self
.coinbase_blocks
:
55 coinbase_txid
.append(self
.nodes
[0].getblock(i
)['tx'][0])
56 self
.nodes
[0].generate(427) # Block 429
57 self
.lastblockhash
= self
.nodes
[0].getbestblockhash()
58 self
.tip
= int("0x" + self
.lastblockhash
, 0)
59 self
.lastblockheight
= 429
60 self
.lastblocktime
= int(time
.time()) + 429
62 self
.log
.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]")
63 test1txs
= [self
.create_transaction(self
.nodes
[0], coinbase_txid
[0], self
.ms_address
, 49)]
64 txid1
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[0].serialize_with_witness()), True)
65 test1txs
.append(self
.create_transaction(self
.nodes
[0], txid1
, self
.ms_address
, 48))
66 txid2
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[1].serialize_with_witness()), True)
67 test1txs
.append(self
.create_transaction(self
.nodes
[0], coinbase_txid
[1], self
.wit_ms_address
, 49))
68 txid3
= self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(test1txs
[2].serialize_with_witness()), True)
69 self
.block_submit(self
.nodes
[0], test1txs
, False, True)
71 self
.log
.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
72 test2tx
= self
.create_transaction(self
.nodes
[0], txid2
, self
.ms_address
, 47)
74 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test2tx
.serialize_with_witness()), True)
76 self
.log
.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]")
77 self
.block_submit(self
.nodes
[0], [test2tx
], False, True)
79 self
.log
.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
80 test4tx
= self
.create_transaction(self
.nodes
[0], test2tx
.hash, self
.address
, 46)
81 test6txs
=[CTransaction(test4tx
)]
83 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test4tx
.serialize_with_witness()), True)
84 self
.block_submit(self
.nodes
[0], [test4tx
])
86 self
.log
.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
87 test5tx
= self
.create_transaction(self
.nodes
[0], txid3
, self
.wit_address
, 48)
88 test6txs
.append(CTransaction(test5tx
))
89 test5tx
.wit
.vtxinwit
[0].scriptWitness
.stack
[0] = b
'\x01'
90 assert_raises_rpc_error(-26, NULLDUMMY_ERROR
, self
.nodes
[0].sendrawtransaction
, bytes_to_hex_str(test5tx
.serialize_with_witness()), True)
91 self
.block_submit(self
.nodes
[0], [test5tx
], True)
93 self
.log
.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]")
95 self
.nodes
[0].sendrawtransaction(bytes_to_hex_str(i
.serialize_with_witness()), True)
96 self
.block_submit(self
.nodes
[0], test6txs
, True, True)
99 def create_transaction(self
, node
, txid
, to_address
, amount
):
100 inputs
= [{ "txid" : txid
, "vout" : 0}]
101 outputs
= { to_address
: amount
}
102 rawtx
= node
.createrawtransaction(inputs
, outputs
)
103 signresult
= node
.signrawtransaction(rawtx
)
105 f
= BytesIO(hex_str_to_bytes(signresult
['hex']))
110 def block_submit(self
, node
, txs
, witness
= False, accept
= False):
111 block
= create_block(self
.tip
, create_coinbase(self
.lastblockheight
+ 1), self
.lastblocktime
+ 1)
116 block
.hashMerkleRoot
= block
.calc_merkle_root()
117 witness
and add_witness_commitment(block
)
120 node
.submitblock(bytes_to_hex_str(block
.serialize(True)))
122 assert_equal(node
.getbestblockhash(), block
.hash)
123 self
.tip
= block
.sha256
124 self
.lastblockhash
= block
.hash
125 self
.lastblocktime
+= 1
126 self
.lastblockheight
+= 1
128 assert_equal(node
.getbestblockhash(), self
.lastblockhash
)
130 if __name__
== '__main__':
131 NULLDUMMYTest().main()