2 # Copyright (c) 2015-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 BIP65 (CHECKLOCKTIMEVERIFY).
7 Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height
11 from test_framework
.test_framework
import BitcoinTestFramework
12 from test_framework
.util
import *
13 from test_framework
.mininode
import *
14 from test_framework
.blocktools
import create_coinbase
, create_block
15 from test_framework
.script
import CScript
, OP_1NEGATE
, OP_CHECKLOCKTIMEVERIFY
, OP_DROP
, CScriptNum
16 from io
import BytesIO
20 # Reject codes that we might receive in this test
23 REJECT_NONSTANDARD
= 64
25 def cltv_invalidate(tx
):
26 '''Modify the signature in vin 0 of the tx to fail CLTV
28 Prepends -1 CLTV DROP in the scriptSig itself.
30 TODO: test more ways that transactions using CLTV could be invalid (eg
31 locktime requirements fail, sequence time requirements fail, etc).
33 tx
.vin
[0].scriptSig
= CScript([OP_1NEGATE
, OP_CHECKLOCKTIMEVERIFY
, OP_DROP
] +
34 list(CScript(tx
.vin
[0].scriptSig
)))
36 def cltv_validate(node
, tx
, height
):
37 '''Modify the signature in vin 0 of the tx to pass CLTV
38 Prepends <height> CLTV DROP in the scriptSig, and sets
39 the locktime to height'''
40 tx
.vin
[0].nSequence
= 0
43 # Need to re-sign, since nSequence and nLockTime changed
44 signed_result
= node
.signrawtransaction(ToHex(tx
))
45 new_tx
= CTransaction()
46 new_tx
.deserialize(BytesIO(hex_str_to_bytes(signed_result
['hex'])))
48 new_tx
.vin
[0].scriptSig
= CScript([CScriptNum(height
), OP_CHECKLOCKTIMEVERIFY
, OP_DROP
] +
49 list(CScript(new_tx
.vin
[0].scriptSig
)))
52 def create_transaction(node
, coinbase
, to_address
, amount
):
53 from_txid
= node
.getblock(coinbase
)['tx'][0]
54 inputs
= [{ "txid" : from_txid
, "vout" : 0}]
55 outputs
= { to_address
: amount
}
56 rawtx
= node
.createrawtransaction(inputs
, outputs
)
57 signresult
= node
.signrawtransaction(rawtx
)
59 tx
.deserialize(BytesIO(hex_str_to_bytes(signresult
['hex'])))
62 class BIP65Test(BitcoinTestFramework
):
63 def set_test_params(self
):
65 self
.extra_args
= [['-promiscuousmempoolflags=1', '-whitelist=127.0.0.1']]
66 self
.setup_clean_chain
= True
71 connections
.append(NodeConn('127.0.0.1', p2p_port(0), self
.nodes
[0], node0
))
72 node0
.add_connection(connections
[0])
74 NetworkThread().start() # Start up network handling in another thread
76 # wait_for_verack ensures that the P2P connection is fully up.
77 node0
.wait_for_verack()
79 self
.log
.info("Mining %d blocks", CLTV_HEIGHT
- 2)
80 self
.coinbase_blocks
= self
.nodes
[0].generate(CLTV_HEIGHT
- 2)
81 self
.nodeaddress
= self
.nodes
[0].getnewaddress()
83 self
.log
.info("Test that an invalid-according-to-CLTV transaction can still appear in a block")
85 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[0],
86 self
.nodeaddress
, 1.0)
87 cltv_invalidate(spendtx
)
90 tip
= self
.nodes
[0].getbestblockhash()
91 block_time
= self
.nodes
[0].getblockheader(tip
)['mediantime'] + 1
92 block
= create_block(int(tip
, 16), create_coinbase(CLTV_HEIGHT
- 1), block_time
)
94 block
.vtx
.append(spendtx
)
95 block
.hashMerkleRoot
= block
.calc_merkle_root()
98 node0
.send_and_ping(msg_block(block
))
99 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
101 self
.log
.info("Test that blocks must now be at least version 4")
104 block
= create_block(tip
, create_coinbase(CLTV_HEIGHT
), block_time
)
107 node0
.send_and_ping(msg_block(block
))
108 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
110 wait_until(lambda: "reject" in node0
.last_message
.keys(), lock
=mininode_lock
)
112 assert_equal(node0
.last_message
["reject"].code
, REJECT_OBSOLETE
)
113 assert_equal(node0
.last_message
["reject"].reason
, b
'bad-version(0x00000003)')
114 assert_equal(node0
.last_message
["reject"].data
, block
.sha256
)
115 del node0
.last_message
["reject"]
117 self
.log
.info("Test that invalid-according-to-cltv transactions cannot appear in a block")
120 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[1],
121 self
.nodeaddress
, 1.0)
122 cltv_invalidate(spendtx
)
125 # First we show that this tx is valid except for CLTV by getting it
126 # accepted to the mempool (which we can achieve with
127 # -promiscuousmempoolflags).
128 node0
.send_and_ping(msg_tx(spendtx
))
129 assert spendtx
.hash in self
.nodes
[0].getrawmempool()
131 # Now we verify that a block with this transaction is invalid.
132 block
.vtx
.append(spendtx
)
133 block
.hashMerkleRoot
= block
.calc_merkle_root()
136 node0
.send_and_ping(msg_block(block
))
137 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
139 wait_until(lambda: "reject" in node0
.last_message
.keys(), lock
=mininode_lock
)
141 assert node0
.last_message
["reject"].code
in [REJECT_INVALID
, REJECT_NONSTANDARD
]
142 assert_equal(node0
.last_message
["reject"].data
, block
.sha256
)
143 if node0
.last_message
["reject"].code
== REJECT_INVALID
:
144 # Generic rejection when a block is invalid
145 assert_equal(node0
.last_message
["reject"].reason
, b
'block-validation-failed')
147 assert b
'Negative locktime' in node0
.last_message
["reject"].reason
149 self
.log
.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
150 spendtx
= cltv_validate(self
.nodes
[0], spendtx
, CLTV_HEIGHT
- 1)
154 block
.vtx
.append(spendtx
)
155 block
.hashMerkleRoot
= block
.calc_merkle_root()
158 node0
.send_and_ping(msg_block(block
))
159 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), block
.sha256
)
162 if __name__
== '__main__':