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