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 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
69 self
.nodes
[0].add_p2p_connection(P2PInterface())
71 network_thread_start()
73 # wait_for_verack ensures that the P2P connection is fully up.
74 self
.nodes
[0].p2p
.wait_for_verack()
76 self
.log
.info("Mining %d blocks", CLTV_HEIGHT
- 2)
77 self
.coinbase_blocks
= self
.nodes
[0].generate(CLTV_HEIGHT
- 2)
78 self
.nodeaddress
= self
.nodes
[0].getnewaddress()
80 self
.log
.info("Test that an invalid-according-to-CLTV transaction can still appear in a block")
82 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[0],
83 self
.nodeaddress
, 1.0)
84 cltv_invalidate(spendtx
)
87 tip
= self
.nodes
[0].getbestblockhash()
88 block_time
= self
.nodes
[0].getblockheader(tip
)['mediantime'] + 1
89 block
= create_block(int(tip
, 16), create_coinbase(CLTV_HEIGHT
- 1), block_time
)
91 block
.vtx
.append(spendtx
)
92 block
.hashMerkleRoot
= block
.calc_merkle_root()
95 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
96 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
98 self
.log
.info("Test that blocks must now be at least version 4")
101 block
= create_block(tip
, create_coinbase(CLTV_HEIGHT
), block_time
)
104 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
105 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
107 wait_until(lambda: "reject" in self
.nodes
[0].p2p
.last_message
.keys(), lock
=mininode_lock
)
109 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].code
, REJECT_OBSOLETE
)
110 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].reason
, b
'bad-version(0x00000003)')
111 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].data
, block
.sha256
)
112 del self
.nodes
[0].p2p
.last_message
["reject"]
114 self
.log
.info("Test that invalid-according-to-cltv transactions cannot appear in a block")
117 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[1],
118 self
.nodeaddress
, 1.0)
119 cltv_invalidate(spendtx
)
122 # First we show that this tx is valid except for CLTV by getting it
123 # accepted to the mempool (which we can achieve with
124 # -promiscuousmempoolflags).
125 self
.nodes
[0].p2p
.send_and_ping(msg_tx(spendtx
))
126 assert spendtx
.hash in self
.nodes
[0].getrawmempool()
128 # Now we verify that a block with this transaction is invalid.
129 block
.vtx
.append(spendtx
)
130 block
.hashMerkleRoot
= block
.calc_merkle_root()
133 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
134 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
136 wait_until(lambda: "reject" in self
.nodes
[0].p2p
.last_message
.keys(), lock
=mininode_lock
)
138 assert self
.nodes
[0].p2p
.last_message
["reject"].code
in [REJECT_INVALID
, REJECT_NONSTANDARD
]
139 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].data
, block
.sha256
)
140 if self
.nodes
[0].p2p
.last_message
["reject"].code
== REJECT_INVALID
:
141 # Generic rejection when a block is invalid
142 assert_equal(self
.nodes
[0].p2p
.last_message
["reject"].reason
, b
'block-validation-failed')
144 assert b
'Negative locktime' in self
.nodes
[0].p2p
.last_message
["reject"].reason
146 self
.log
.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
147 spendtx
= cltv_validate(self
.nodes
[0], spendtx
, CLTV_HEIGHT
- 1)
151 block
.vtx
.append(spendtx
)
152 block
.hashMerkleRoot
= block
.calc_merkle_root()
155 self
.nodes
[0].p2p
.send_and_ping(msg_block(block
))
156 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), block
.sha256
)
159 if __name__
== '__main__':