2 # Copyright (c) 2014-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 BIP68 implementation."""
7 from test_framework
.test_framework
import BitcoinTestFramework
8 from test_framework
.util
import *
9 from test_framework
.blocktools
import *
11 SEQUENCE_LOCKTIME_DISABLE_FLAG
= (1<<31)
12 SEQUENCE_LOCKTIME_TYPE_FLAG
= (1<<22) # this means use time (0 means height)
13 SEQUENCE_LOCKTIME_GRANULARITY
= 9 # this is a bit-shift
14 SEQUENCE_LOCKTIME_MASK
= 0x0000ffff
16 # RPC error for non-BIP68 final transactions
17 NOT_FINAL_ERROR
= "64: non-BIP68-final"
19 class BIP68Test(BitcoinTestFramework
):
23 self
.setup_clean_chain
= False
25 def setup_network(self
):
27 self
.nodes
.append(start_node(0, self
.options
.tmpdir
))
28 self
.nodes
.append(start_node(1, self
.options
.tmpdir
, ["-acceptnonstdtxn=0"]))
29 self
.is_network_split
= False
30 self
.relayfee
= self
.nodes
[0].getnetworkinfo()["relayfee"]
31 connect_nodes(self
.nodes
[0], 1)
35 self
.nodes
[0].generate(110)
37 self
.log
.info("Running test disable flag")
38 self
.test_disable_flag()
40 self
.log
.info("Running test sequence-lock-confirmed-inputs")
41 self
.test_sequence_lock_confirmed_inputs()
43 self
.log
.info("Running test sequence-lock-unconfirmed-inputs")
44 self
.test_sequence_lock_unconfirmed_inputs()
46 self
.log
.info("Running test BIP68 not consensus before versionbits activation")
47 self
.test_bip68_not_consensus()
49 self
.log
.info("Activating BIP68 (and 112/113)")
52 self
.log
.info("Verifying nVersion=2 transactions are standard.")
53 self
.log
.info("Note that nVersion=2 transactions are always standard (independent of BIP68 activation status).")
54 self
.test_version2_relay()
56 self
.log
.info("Passed")
58 # Test that BIP68 is not in effect if tx version is 1, or if
59 # the first sequence bit is set.
60 def test_disable_flag(self
):
61 # Create some unconfirmed inputs
62 new_addr
= self
.nodes
[0].getnewaddress()
63 self
.nodes
[0].sendtoaddress(new_addr
, 2) # send 2 BTC
65 utxos
= self
.nodes
[0].listunspent(0, 0)
66 assert(len(utxos
) > 0)
71 value
= int(satoshi_round(utxo
["amount"] - self
.relayfee
)*COIN
)
73 # Check that the disable flag disables relative locktime.
74 # If sequence locks were used, this would require 1 block for the
76 sequence_value
= SEQUENCE_LOCKTIME_DISABLE_FLAG |
1
77 tx1
.vin
= [CTxIn(COutPoint(int(utxo
["txid"], 16), utxo
["vout"]), nSequence
=sequence_value
)]
78 tx1
.vout
= [CTxOut(value
, CScript([b
'a']))]
80 tx1_signed
= self
.nodes
[0].signrawtransaction(ToHex(tx1
))["hex"]
81 tx1_id
= self
.nodes
[0].sendrawtransaction(tx1_signed
)
82 tx1_id
= int(tx1_id
, 16)
84 # This transaction will enable sequence-locks, so this transaction should
88 sequence_value
= sequence_value
& 0x7fffffff
89 tx2
.vin
= [CTxIn(COutPoint(tx1_id
, 0), nSequence
=sequence_value
)]
90 tx2
.vout
= [CTxOut(int(value
-self
.relayfee
*COIN
), CScript([b
'a']))]
93 assert_raises_jsonrpc(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, ToHex(tx2
))
95 # Setting the version back down to 1 should disable the sequence lock,
96 # so this should be accepted.
99 self
.nodes
[0].sendrawtransaction(ToHex(tx2
))
101 # Calculate the median time past of a prior block ("confirmations" before
103 def get_median_time_past(self
, confirmations
):
104 block_hash
= self
.nodes
[0].getblockhash(self
.nodes
[0].getblockcount()-confirmations
)
105 return self
.nodes
[0].getblockheader(block_hash
)["mediantime"]
107 # Test that sequence locks are respected for transactions spending confirmed inputs.
108 def test_sequence_lock_confirmed_inputs(self
):
109 # Create lots of confirmed utxos, and use them to generate lots of random
113 while len(addresses
) < max_outputs
:
114 addresses
.append(self
.nodes
[0].getnewaddress())
115 while len(self
.nodes
[0].listunspent()) < 200:
117 random
.shuffle(addresses
)
118 num_outputs
= random
.randint(1, max_outputs
)
120 for i
in range(num_outputs
):
121 outputs
[addresses
[i
]] = random
.randint(1, 20)*0.01
122 self
.nodes
[0].sendmany("", outputs
)
123 self
.nodes
[0].generate(1)
125 utxos
= self
.nodes
[0].listunspent()
127 # Try creating a lot of random transactions.
128 # Each time, choose a random number of inputs, and randomly set
129 # some of those inputs to be sequence locked (and randomly choose
130 # between height/time locking). Small random chance of making the locks
133 # Randomly choose up to 10 inputs
134 num_inputs
= random
.randint(1, 10)
135 random
.shuffle(utxos
)
137 # Track whether any sequence locks used should fail
140 # Track whether this transaction was built with sequence locks
141 using_sequence_locks
= False
146 for j
in range(num_inputs
):
147 sequence_value
= 0xfffffffe # this disables sequence locks
149 # 50% chance we enable sequence locks
150 if random
.randint(0,1):
151 using_sequence_locks
= True
153 # 10% of the time, make the input sequence value pass
154 input_will_pass
= (random
.randint(1,10) == 1)
155 sequence_value
= utxos
[j
]["confirmations"]
156 if not input_will_pass
:
160 # Figure out what the median-time-past was for the confirmed input
161 # Note that if an input has N confirmations, we're going back N blocks
162 # from the tip so that we're looking up MTP of the block
163 # PRIOR to the one the input appears in, as per the BIP68 spec.
164 orig_time
= self
.get_median_time_past(utxos
[j
]["confirmations"])
165 cur_time
= self
.get_median_time_past(0) # MTP of the tip
167 # can only timelock this input if it's not too old -- otherwise use height
169 if ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
) >= SEQUENCE_LOCKTIME_MASK
:
170 can_time_lock
= False
172 # if time-lockable, then 50% chance we make this a time lock
173 if random
.randint(0,1) and can_time_lock
:
174 # Find first time-lock value that fails, or latest one that succeeds
175 time_delta
= sequence_value
<< SEQUENCE_LOCKTIME_GRANULARITY
176 if input_will_pass
and time_delta
> cur_time
- orig_time
:
177 sequence_value
= ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
)
178 elif (not input_will_pass
and time_delta
<= cur_time
- orig_time
):
179 sequence_value
= ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
)+1
180 sequence_value |
= SEQUENCE_LOCKTIME_TYPE_FLAG
181 tx
.vin
.append(CTxIn(COutPoint(int(utxos
[j
]["txid"], 16), utxos
[j
]["vout"]), nSequence
=sequence_value
))
182 value
+= utxos
[j
]["amount"]*COIN
183 # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
184 tx_size
= len(ToHex(tx
))//2 + 120*num_inputs
+ 50
185 tx
.vout
.append(CTxOut(int(value
-self
.relayfee
*tx_size
*COIN
/1000), CScript([b
'a'])))
186 rawtx
= self
.nodes
[0].signrawtransaction(ToHex(tx
))["hex"]
188 if (using_sequence_locks
and not should_pass
):
189 # This transaction should be rejected
190 assert_raises_jsonrpc(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, rawtx
)
192 # This raw transaction should be accepted
193 self
.nodes
[0].sendrawtransaction(rawtx
)
194 utxos
= self
.nodes
[0].listunspent()
196 # Test that sequence locks on unconfirmed inputs must have nSequence
197 # height or time of 0 to be accepted.
198 # Then test that BIP68-invalid transactions are removed from the mempool
200 def test_sequence_lock_unconfirmed_inputs(self
):
201 # Store height so we can easily reset the chain at the end of the test
202 cur_height
= self
.nodes
[0].getblockcount()
204 # Create a mempool tx.
205 txid
= self
.nodes
[0].sendtoaddress(self
.nodes
[0].getnewaddress(), 2)
206 tx1
= FromHex(CTransaction(), self
.nodes
[0].getrawtransaction(txid
))
209 # Anyone-can-spend mempool tx.
210 # Sequence lock of 0 should pass.
213 tx2
.vin
= [CTxIn(COutPoint(tx1
.sha256
, 0), nSequence
=0)]
214 tx2
.vout
= [CTxOut(int(tx1
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
215 tx2_raw
= self
.nodes
[0].signrawtransaction(ToHex(tx2
))["hex"]
216 tx2
= FromHex(tx2
, tx2_raw
)
219 self
.nodes
[0].sendrawtransaction(tx2_raw
)
221 # Create a spend of the 0th output of orig_tx with a sequence lock
222 # of 1, and test what happens when submitting.
223 # orig_tx.vout[0] must be an anyone-can-spend output
224 def test_nonzero_locks(orig_tx
, node
, relayfee
, use_height_lock
):
226 if not use_height_lock
:
227 sequence_value |
= SEQUENCE_LOCKTIME_TYPE_FLAG
231 tx
.vin
= [CTxIn(COutPoint(orig_tx
.sha256
, 0), nSequence
=sequence_value
)]
232 tx
.vout
= [CTxOut(int(orig_tx
.vout
[0].nValue
- relayfee
*COIN
), CScript([b
'a']))]
235 if (orig_tx
.hash in node
.getrawmempool()):
236 # sendrawtransaction should fail if the tx is in the mempool
237 assert_raises_jsonrpc(-26, NOT_FINAL_ERROR
, node
.sendrawtransaction
, ToHex(tx
))
239 # sendrawtransaction should succeed if the tx is not in the mempool
240 node
.sendrawtransaction(ToHex(tx
))
244 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
245 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
247 # Now mine some blocks, but make sure tx2 doesn't get mined.
248 # Use prioritisetransaction to lower the effective feerate to 0
249 self
.nodes
[0].prioritisetransaction(tx2
.hash, int(-self
.relayfee
*COIN
))
250 cur_time
= int(time
.time())
252 self
.nodes
[0].setmocktime(cur_time
+ 600)
253 self
.nodes
[0].generate(1)
256 assert(tx2
.hash in self
.nodes
[0].getrawmempool())
258 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
259 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
261 # Mine tx2, and then try again
262 self
.nodes
[0].prioritisetransaction(tx2
.hash, int(self
.relayfee
*COIN
))
264 # Advance the time on the node so that we can test timelocks
265 self
.nodes
[0].setmocktime(cur_time
+600)
266 self
.nodes
[0].generate(1)
267 assert(tx2
.hash not in self
.nodes
[0].getrawmempool())
269 # Now that tx2 is not in the mempool, a sequence locked spend should
271 tx3
= test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
272 assert(tx3
.hash in self
.nodes
[0].getrawmempool())
274 self
.nodes
[0].generate(1)
275 assert(tx3
.hash not in self
.nodes
[0].getrawmempool())
277 # One more test, this time using height locks
278 tx4
= test_nonzero_locks(tx3
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
279 assert(tx4
.hash in self
.nodes
[0].getrawmempool())
281 # Now try combining confirmed and unconfirmed inputs
282 tx5
= test_nonzero_locks(tx4
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
283 assert(tx5
.hash not in self
.nodes
[0].getrawmempool())
285 utxos
= self
.nodes
[0].listunspent()
286 tx5
.vin
.append(CTxIn(COutPoint(int(utxos
[0]["txid"], 16), utxos
[0]["vout"]), nSequence
=1))
287 tx5
.vout
[0].nValue
+= int(utxos
[0]["amount"]*COIN
)
288 raw_tx5
= self
.nodes
[0].signrawtransaction(ToHex(tx5
))["hex"]
290 assert_raises_jsonrpc(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, raw_tx5
)
292 # Test mempool-BIP68 consistency after reorg
294 # State of the transactions in the last blocks:
295 # ... -> [ tx2 ] -> [ tx3 ]
297 # And currently tx4 is in the mempool.
299 # If we invalidate the tip, tx3 should get added to the mempool, causing
300 # tx4 to be removed (fails sequence-lock).
301 self
.nodes
[0].invalidateblock(self
.nodes
[0].getbestblockhash())
302 assert(tx4
.hash not in self
.nodes
[0].getrawmempool())
303 assert(tx3
.hash in self
.nodes
[0].getrawmempool())
305 # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
307 # This would cause tx2 to be added back to the mempool, which in turn causes
309 tip
= int(self
.nodes
[0].getblockhash(self
.nodes
[0].getblockcount()-1), 16)
310 height
= self
.nodes
[0].getblockcount()
312 block
= create_block(tip
, create_coinbase(height
), cur_time
)
318 self
.nodes
[0].submitblock(ToHex(block
))
321 mempool
= self
.nodes
[0].getrawmempool()
322 assert(tx3
.hash not in mempool
)
323 assert(tx2
.hash in mempool
)
325 # Reset the chain and get rid of the mocktimed-blocks
326 self
.nodes
[0].setmocktime(0)
327 self
.nodes
[0].invalidateblock(self
.nodes
[0].getblockhash(cur_height
+1))
328 self
.nodes
[0].generate(10)
330 # Make sure that BIP68 isn't being used to validate blocks, prior to
331 # versionbits activation. If more blocks are mined prior to this test
332 # being run, then it's possible the test has activated the soft fork, and
333 # this test should be moved to run earlier, or deleted.
334 def test_bip68_not_consensus(self
):
335 assert(get_bip9_status(self
.nodes
[0], 'csv')['status'] != 'active')
336 txid
= self
.nodes
[0].sendtoaddress(self
.nodes
[0].getnewaddress(), 2)
338 tx1
= FromHex(CTransaction(), self
.nodes
[0].getrawtransaction(txid
))
341 # Make an anyone-can-spend transaction
344 tx2
.vin
= [CTxIn(COutPoint(tx1
.sha256
, 0), nSequence
=0)]
345 tx2
.vout
= [CTxOut(int(tx1
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
348 tx2_raw
= self
.nodes
[0].signrawtransaction(ToHex(tx2
))["hex"]
349 tx2
= FromHex(tx2
, tx2_raw
)
352 self
.nodes
[0].sendrawtransaction(ToHex(tx2
))
354 # Now make an invalid spend of tx2 according to BIP68
355 sequence_value
= 100 # 100 block relative locktime
359 tx3
.vin
= [CTxIn(COutPoint(tx2
.sha256
, 0), nSequence
=sequence_value
)]
360 tx3
.vout
= [CTxOut(int(tx2
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
363 assert_raises_jsonrpc(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, ToHex(tx3
))
365 # make a block that violates bip68; ensure that the tip updates
366 tip
= int(self
.nodes
[0].getbestblockhash(), 16)
367 block
= create_block(tip
, create_coinbase(self
.nodes
[0].getblockcount()+1))
369 block
.vtx
.extend([tx1
, tx2
, tx3
])
370 block
.hashMerkleRoot
= block
.calc_merkle_root()
374 self
.nodes
[0].submitblock(ToHex(block
))
375 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
377 def activateCSV(self
):
378 # activation should happen at block height 432 (3 periods)
379 min_activation_height
= 432
380 height
= self
.nodes
[0].getblockcount()
381 assert(height
< min_activation_height
)
382 self
.nodes
[0].generate(min_activation_height
-height
)
383 assert(get_bip9_status(self
.nodes
[0], 'csv')['status'] == 'active')
384 sync_blocks(self
.nodes
)
386 # Use self.nodes[1] to test that version 2 transactions are standard.
387 def test_version2_relay(self
):
389 outputs
= { self
.nodes
[1].getnewaddress() : 1.0 }
390 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
391 rawtxfund
= self
.nodes
[1].fundrawtransaction(rawtx
)['hex']
392 tx
= FromHex(CTransaction(), rawtxfund
)
394 tx_signed
= self
.nodes
[1].signrawtransaction(ToHex(tx
))["hex"]
395 tx_id
= self
.nodes
[1].sendrawtransaction(tx_signed
)
397 if __name__
== '__main__':