2 # Copyright (c) 2015-2017 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 BIP66 (DER SIG).
7 Test that the DERSIG soft-fork activates at (regtest) height 1251.
10 from test_framework
.test_framework
import BitcoinTestFramework
11 from test_framework
.util
import *
12 from test_framework
.mininode
import *
13 from test_framework
.blocktools
import create_coinbase
, create_block
14 from test_framework
.script
import CScript
15 from io
import BytesIO
19 # Reject codes that we might receive in this test
22 REJECT_NONSTANDARD
= 64
24 # A canonical signature consists of:
25 # <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
28 Make the signature in vin 0 of a tx non-DER-compliant,
29 by adding padding after the S-value.
31 scriptSig
= CScript(tx
.vin
[0].scriptSig
)
34 if (len(newscript
) == 0):
35 newscript
.append(i
[0:-1] + b
'\0' + i
[-1:])
38 tx
.vin
[0].scriptSig
= CScript(newscript
)
40 def create_transaction(node
, coinbase
, to_address
, amount
):
41 from_txid
= node
.getblock(coinbase
)['tx'][0]
42 inputs
= [{ "txid" : from_txid
, "vout" : 0}]
43 outputs
= { to_address
: amount
}
44 rawtx
= node
.createrawtransaction(inputs
, outputs
)
45 signresult
= node
.signrawtransaction(rawtx
)
47 tx
.deserialize(BytesIO(hex_str_to_bytes(signresult
['hex'])))
50 class BIP66Test(BitcoinTestFramework
):
51 def set_test_params(self
):
53 self
.extra_args
= [['-promiscuousmempoolflags=1', '-whitelist=127.0.0.1']]
54 self
.setup_clean_chain
= True
57 self
.nodes
[0].add_p2p_connection(P2PInterface())
59 network_thread_start()
61 # wait_for_verack ensures that the P2P connection is fully up.
62 self
.nodes
[0].p2p
.wait_for_verack()
64 self
.log
.info("Mining %d blocks", DERSIG_HEIGHT
- 2)
65 self
.coinbase_blocks
= self
.nodes
[0].generate(DERSIG_HEIGHT
- 2)
66 self
.nodeaddress
= self
.nodes
[0].getnewaddress()
68 self
.log
.info("Test that a transaction with non-DER signature can still appear in a block")
70 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[0],
71 self
.nodeaddress
, 1.0)
75 tip
= self
.nodes
[0].getbestblockhash()
76 block_time
= self
.nodes
[0].getblockheader(tip
)['mediantime'] + 1
77 block
= create_block(int(tip
, 16), create_coinbase(DERSIG_HEIGHT
- 1), block_time
)
79 block
.vtx
.append(spendtx
)
80 block
.hashMerkleRoot
= block
.calc_merkle_root()
84 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
85 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
87 self
.log
.info("Test that blocks must now be at least version 3")
90 block
= create_block(tip
, create_coinbase(DERSIG_HEIGHT
), block_time
)
94 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
95 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
97 wait_until(lambda: "reject" in self
.nodes
[0].p2p
.last_message
.keys(), lock
=mininode_lock
)
99 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].code
, REJECT_OBSOLETE
)
100 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].reason
, b
'bad-version(0x00000002)')
101 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].data
, block
.sha256
)
102 del self
.nodes
[0].p2p
.last_message
["reject"]
104 self
.log
.info("Test that transactions with non-DER signatures cannot appear in a block")
107 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[1],
108 self
.nodeaddress
, 1.0)
112 # First we show that this tx is valid except for DERSIG by getting it
113 # accepted to the mempool (which we can achieve with
114 # -promiscuousmempoolflags).
115 self
.nodes
[0].p2p
.send_and_ping(msg_tx(spendtx
))
116 assert spendtx
.hash in self
.nodes
[0].getrawmempool()
118 # Now we verify that a block with this transaction is invalid.
119 block
.vtx
.append(spendtx
)
120 block
.hashMerkleRoot
= block
.calc_merkle_root()
124 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
125 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
127 wait_until(lambda: "reject" in self
.nodes
[0].p2p
.last_message
.keys(), lock
=mininode_lock
)
129 # We can receive different reject messages depending on whether
130 # bitcoind is running with multiple script check threads. If script
131 # check threads are not in use, then transaction script validation
132 # happens sequentially, and bitcoind produces more specific reject
134 assert self
.nodes
[0].p2p
.last_message
["reject"].code
in [REJECT_INVALID
, REJECT_NONSTANDARD
]
135 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].data
, block
.sha256
)
136 if self
.nodes
[0].p2p
.last_message
["reject"].code
== REJECT_INVALID
:
137 # Generic rejection when a block is invalid
138 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].reason
, b
'block-validation-failed')
140 assert b
'Non-canonical DER signature' in self
.nodes
[0].p2p
.last_message
["reject"].reason
142 self
.log
.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
143 block
.vtx
[1] = create_transaction(self
.nodes
[0],
144 self
.coinbase_blocks
[1], self
.nodeaddress
, 1.0)
145 block
.hashMerkleRoot
= block
.calc_merkle_root()
149 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
150 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), block
.sha256
)
152 if __name__
== '__main__':