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
):
67 self
.extra_args
= [['-promiscuousmempoolflags=1', '-whitelist=127.0.0.1']]
68 self
.setup_clean_chain
= True
73 connections
.append(NodeConn('127.0.0.1', p2p_port(0), self
.nodes
[0], node0
))
74 node0
.add_connection(connections
[0])
76 NetworkThread().start() # Start up network handling in another thread
78 # wait_for_verack ensures that the P2P connection is fully up.
79 node0
.wait_for_verack()
81 self
.log
.info("Mining %d blocks", CLTV_HEIGHT
- 2)
82 self
.coinbase_blocks
= self
.nodes
[0].generate(CLTV_HEIGHT
- 2)
83 self
.nodeaddress
= self
.nodes
[0].getnewaddress()
85 self
.log
.info("Test that an invalid-according-to-CLTV transaction can still appear in a block")
87 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[0],
88 self
.nodeaddress
, 1.0)
89 cltv_invalidate(spendtx
)
92 tip
= self
.nodes
[0].getbestblockhash()
93 block_time
= self
.nodes
[0].getblockheader(tip
)['mediantime'] + 1
94 block
= create_block(int(tip
, 16), create_coinbase(CLTV_HEIGHT
- 1), block_time
)
96 block
.vtx
.append(spendtx
)
97 block
.hashMerkleRoot
= block
.calc_merkle_root()
100 node0
.send_and_ping(msg_block(block
))
101 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
103 self
.log
.info("Test that blocks must now be at least version 4")
106 block
= create_block(tip
, create_coinbase(CLTV_HEIGHT
), block_time
)
109 node0
.send_and_ping(msg_block(block
))
110 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
112 wait_until(lambda: "reject" in node0
.last_message
.keys(), lock
=mininode_lock
)
114 assert_equal(node0
.last_message
["reject"].code
, REJECT_OBSOLETE
)
115 assert_equal(node0
.last_message
["reject"].reason
, b
'bad-version(0x00000003)')
116 assert_equal(node0
.last_message
["reject"].data
, block
.sha256
)
117 del node0
.last_message
["reject"]
119 self
.log
.info("Test that invalid-according-to-cltv transactions cannot appear in a block")
122 spendtx
= create_transaction(self
.nodes
[0], self
.coinbase_blocks
[1],
123 self
.nodeaddress
, 1.0)
124 cltv_invalidate(spendtx
)
127 # First we show that this tx is valid except for CLTV by getting it
128 # accepted to the mempool (which we can achieve with
129 # -promiscuousmempoolflags).
130 node0
.send_and_ping(msg_tx(spendtx
))
131 assert spendtx
.hash in self
.nodes
[0].getrawmempool()
133 # Now we verify that a block with this transaction is invalid.
134 block
.vtx
.append(spendtx
)
135 block
.hashMerkleRoot
= block
.calc_merkle_root()
138 node0
.send_and_ping(msg_block(block
))
139 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), tip
)
141 wait_until(lambda: "reject" in node0
.last_message
.keys(), lock
=mininode_lock
)
143 assert node0
.last_message
["reject"].code
in [REJECT_INVALID
, REJECT_NONSTANDARD
]
144 assert_equal(node0
.last_message
["reject"].data
, block
.sha256
)
145 if node0
.last_message
["reject"].code
== REJECT_INVALID
:
146 # Generic rejection when a block is invalid
147 assert_equal(node0
.last_message
["reject"].reason
, b
'block-validation-failed')
149 assert b
'Negative locktime' in node0
.last_message
["reject"].reason
151 self
.log
.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
152 spendtx
= cltv_validate(self
.nodes
[0], spendtx
, CLTV_HEIGHT
- 1)
156 block
.vtx
.append(spendtx
)
157 block
.hashMerkleRoot
= block
.calc_merkle_root()
160 node0
.send_and_ping(msg_block(block
))
161 assert_equal(int(self
.nodes
[0].getbestblockhash(), 16), block
.sha256
)
164 if __name__
== '__main__':