2 # Copyright (c) 2014-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 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
):
20 def set_test_params(self
):
22 self
.extra_args
= [[], ["-acceptnonstdtxn=0"]]
25 self
.relayfee
= self
.nodes
[0].getnetworkinfo()["relayfee"]
28 self
.nodes
[0].generate(110)
30 self
.log
.info("Running test disable flag")
31 self
.test_disable_flag()
33 self
.log
.info("Running test sequence-lock-confirmed-inputs")
34 self
.test_sequence_lock_confirmed_inputs()
36 self
.log
.info("Running test sequence-lock-unconfirmed-inputs")
37 self
.test_sequence_lock_unconfirmed_inputs()
39 self
.log
.info("Running test BIP68 not consensus before versionbits activation")
40 self
.test_bip68_not_consensus()
42 self
.log
.info("Activating BIP68 (and 112/113)")
45 self
.log
.info("Verifying nVersion=2 transactions are standard.")
46 self
.log
.info("Note that nVersion=2 transactions are always standard (independent of BIP68 activation status).")
47 self
.test_version2_relay()
49 self
.log
.info("Passed")
51 # Test that BIP68 is not in effect if tx version is 1, or if
52 # the first sequence bit is set.
53 def test_disable_flag(self
):
54 # Create some unconfirmed inputs
55 new_addr
= self
.nodes
[0].getnewaddress()
56 self
.nodes
[0].sendtoaddress(new_addr
, 2) # send 2 BTC
58 utxos
= self
.nodes
[0].listunspent(0, 0)
59 assert(len(utxos
) > 0)
64 value
= int(satoshi_round(utxo
["amount"] - self
.relayfee
)*COIN
)
66 # Check that the disable flag disables relative locktime.
67 # If sequence locks were used, this would require 1 block for the
69 sequence_value
= SEQUENCE_LOCKTIME_DISABLE_FLAG |
1
70 tx1
.vin
= [CTxIn(COutPoint(int(utxo
["txid"], 16), utxo
["vout"]), nSequence
=sequence_value
)]
71 tx1
.vout
= [CTxOut(value
, CScript([b
'a']))]
73 tx1_signed
= self
.nodes
[0].signrawtransaction(ToHex(tx1
))["hex"]
74 tx1_id
= self
.nodes
[0].sendrawtransaction(tx1_signed
)
75 tx1_id
= int(tx1_id
, 16)
77 # This transaction will enable sequence-locks, so this transaction should
81 sequence_value
= sequence_value
& 0x7fffffff
82 tx2
.vin
= [CTxIn(COutPoint(tx1_id
, 0), nSequence
=sequence_value
)]
83 tx2
.vout
= [CTxOut(int(value
-self
.relayfee
*COIN
), CScript([b
'a']))]
86 assert_raises_rpc_error(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, ToHex(tx2
))
88 # Setting the version back down to 1 should disable the sequence lock,
89 # so this should be accepted.
92 self
.nodes
[0].sendrawtransaction(ToHex(tx2
))
94 # Calculate the median time past of a prior block ("confirmations" before
96 def get_median_time_past(self
, confirmations
):
97 block_hash
= self
.nodes
[0].getblockhash(self
.nodes
[0].getblockcount()-confirmations
)
98 return self
.nodes
[0].getblockheader(block_hash
)["mediantime"]
100 # Test that sequence locks are respected for transactions spending confirmed inputs.
101 def test_sequence_lock_confirmed_inputs(self
):
102 # Create lots of confirmed utxos, and use them to generate lots of random
106 while len(addresses
) < max_outputs
:
107 addresses
.append(self
.nodes
[0].getnewaddress())
108 while len(self
.nodes
[0].listunspent()) < 200:
110 random
.shuffle(addresses
)
111 num_outputs
= random
.randint(1, max_outputs
)
113 for i
in range(num_outputs
):
114 outputs
[addresses
[i
]] = random
.randint(1, 20)*0.01
115 self
.nodes
[0].sendmany("", outputs
)
116 self
.nodes
[0].generate(1)
118 utxos
= self
.nodes
[0].listunspent()
120 # Try creating a lot of random transactions.
121 # Each time, choose a random number of inputs, and randomly set
122 # some of those inputs to be sequence locked (and randomly choose
123 # between height/time locking). Small random chance of making the locks
126 # Randomly choose up to 10 inputs
127 num_inputs
= random
.randint(1, 10)
128 random
.shuffle(utxos
)
130 # Track whether any sequence locks used should fail
133 # Track whether this transaction was built with sequence locks
134 using_sequence_locks
= False
139 for j
in range(num_inputs
):
140 sequence_value
= 0xfffffffe # this disables sequence locks
142 # 50% chance we enable sequence locks
143 if random
.randint(0,1):
144 using_sequence_locks
= True
146 # 10% of the time, make the input sequence value pass
147 input_will_pass
= (random
.randint(1,10) == 1)
148 sequence_value
= utxos
[j
]["confirmations"]
149 if not input_will_pass
:
153 # Figure out what the median-time-past was for the confirmed input
154 # Note that if an input has N confirmations, we're going back N blocks
155 # from the tip so that we're looking up MTP of the block
156 # PRIOR to the one the input appears in, as per the BIP68 spec.
157 orig_time
= self
.get_median_time_past(utxos
[j
]["confirmations"])
158 cur_time
= self
.get_median_time_past(0) # MTP of the tip
160 # can only timelock this input if it's not too old -- otherwise use height
162 if ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
) >= SEQUENCE_LOCKTIME_MASK
:
163 can_time_lock
= False
165 # if time-lockable, then 50% chance we make this a time lock
166 if random
.randint(0,1) and can_time_lock
:
167 # Find first time-lock value that fails, or latest one that succeeds
168 time_delta
= sequence_value
<< SEQUENCE_LOCKTIME_GRANULARITY
169 if input_will_pass
and time_delta
> cur_time
- orig_time
:
170 sequence_value
= ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
)
171 elif (not input_will_pass
and time_delta
<= cur_time
- orig_time
):
172 sequence_value
= ((cur_time
- orig_time
) >> SEQUENCE_LOCKTIME_GRANULARITY
)+1
173 sequence_value |
= SEQUENCE_LOCKTIME_TYPE_FLAG
174 tx
.vin
.append(CTxIn(COutPoint(int(utxos
[j
]["txid"], 16), utxos
[j
]["vout"]), nSequence
=sequence_value
))
175 value
+= utxos
[j
]["amount"]*COIN
176 # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
177 tx_size
= len(ToHex(tx
))//2 + 120*num_inputs
+ 50
178 tx
.vout
.append(CTxOut(int(value
-self
.relayfee
*tx_size
*COIN
/1000), CScript([b
'a'])))
179 rawtx
= self
.nodes
[0].signrawtransaction(ToHex(tx
))["hex"]
181 if (using_sequence_locks
and not should_pass
):
182 # This transaction should be rejected
183 assert_raises_rpc_error(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, rawtx
)
185 # This raw transaction should be accepted
186 self
.nodes
[0].sendrawtransaction(rawtx
)
187 utxos
= self
.nodes
[0].listunspent()
189 # Test that sequence locks on unconfirmed inputs must have nSequence
190 # height or time of 0 to be accepted.
191 # Then test that BIP68-invalid transactions are removed from the mempool
193 def test_sequence_lock_unconfirmed_inputs(self
):
194 # Store height so we can easily reset the chain at the end of the test
195 cur_height
= self
.nodes
[0].getblockcount()
197 # Create a mempool tx.
198 txid
= self
.nodes
[0].sendtoaddress(self
.nodes
[0].getnewaddress(), 2)
199 tx1
= FromHex(CTransaction(), self
.nodes
[0].getrawtransaction(txid
))
202 # Anyone-can-spend mempool tx.
203 # Sequence lock of 0 should pass.
206 tx2
.vin
= [CTxIn(COutPoint(tx1
.sha256
, 0), nSequence
=0)]
207 tx2
.vout
= [CTxOut(int(tx1
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
208 tx2_raw
= self
.nodes
[0].signrawtransaction(ToHex(tx2
))["hex"]
209 tx2
= FromHex(tx2
, tx2_raw
)
212 self
.nodes
[0].sendrawtransaction(tx2_raw
)
214 # Create a spend of the 0th output of orig_tx with a sequence lock
215 # of 1, and test what happens when submitting.
216 # orig_tx.vout[0] must be an anyone-can-spend output
217 def test_nonzero_locks(orig_tx
, node
, relayfee
, use_height_lock
):
219 if not use_height_lock
:
220 sequence_value |
= SEQUENCE_LOCKTIME_TYPE_FLAG
224 tx
.vin
= [CTxIn(COutPoint(orig_tx
.sha256
, 0), nSequence
=sequence_value
)]
225 tx
.vout
= [CTxOut(int(orig_tx
.vout
[0].nValue
- relayfee
*COIN
), CScript([b
'a']))]
228 if (orig_tx
.hash in node
.getrawmempool()):
229 # sendrawtransaction should fail if the tx is in the mempool
230 assert_raises_rpc_error(-26, NOT_FINAL_ERROR
, node
.sendrawtransaction
, ToHex(tx
))
232 # sendrawtransaction should succeed if the tx is not in the mempool
233 node
.sendrawtransaction(ToHex(tx
))
237 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
238 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
240 # Now mine some blocks, but make sure tx2 doesn't get mined.
241 # Use prioritisetransaction to lower the effective feerate to 0
242 self
.nodes
[0].prioritisetransaction(txid
=tx2
.hash, fee_delta
=int(-self
.relayfee
*COIN
))
243 cur_time
= int(time
.time())
245 self
.nodes
[0].setmocktime(cur_time
+ 600)
246 self
.nodes
[0].generate(1)
249 assert(tx2
.hash in self
.nodes
[0].getrawmempool())
251 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
252 test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
254 # Mine tx2, and then try again
255 self
.nodes
[0].prioritisetransaction(txid
=tx2
.hash, fee_delta
=int(self
.relayfee
*COIN
))
257 # Advance the time on the node so that we can test timelocks
258 self
.nodes
[0].setmocktime(cur_time
+600)
259 self
.nodes
[0].generate(1)
260 assert(tx2
.hash not in self
.nodes
[0].getrawmempool())
262 # Now that tx2 is not in the mempool, a sequence locked spend should
264 tx3
= test_nonzero_locks(tx2
, self
.nodes
[0], self
.relayfee
, use_height_lock
=False)
265 assert(tx3
.hash in self
.nodes
[0].getrawmempool())
267 self
.nodes
[0].generate(1)
268 assert(tx3
.hash not in self
.nodes
[0].getrawmempool())
270 # One more test, this time using height locks
271 tx4
= test_nonzero_locks(tx3
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
272 assert(tx4
.hash in self
.nodes
[0].getrawmempool())
274 # Now try combining confirmed and unconfirmed inputs
275 tx5
= test_nonzero_locks(tx4
, self
.nodes
[0], self
.relayfee
, use_height_lock
=True)
276 assert(tx5
.hash not in self
.nodes
[0].getrawmempool())
278 utxos
= self
.nodes
[0].listunspent()
279 tx5
.vin
.append(CTxIn(COutPoint(int(utxos
[0]["txid"], 16), utxos
[0]["vout"]), nSequence
=1))
280 tx5
.vout
[0].nValue
+= int(utxos
[0]["amount"]*COIN
)
281 raw_tx5
= self
.nodes
[0].signrawtransaction(ToHex(tx5
))["hex"]
283 assert_raises_rpc_error(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, raw_tx5
)
285 # Test mempool-BIP68 consistency after reorg
287 # State of the transactions in the last blocks:
288 # ... -> [ tx2 ] -> [ tx3 ]
290 # And currently tx4 is in the mempool.
292 # If we invalidate the tip, tx3 should get added to the mempool, causing
293 # tx4 to be removed (fails sequence-lock).
294 self
.nodes
[0].invalidateblock(self
.nodes
[0].getbestblockhash())
295 assert(tx4
.hash not in self
.nodes
[0].getrawmempool())
296 assert(tx3
.hash in self
.nodes
[0].getrawmempool())
298 # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
300 # This would cause tx2 to be added back to the mempool, which in turn causes
302 tip
= int(self
.nodes
[0].getblockhash(self
.nodes
[0].getblockcount()-1), 16)
303 height
= self
.nodes
[0].getblockcount()
305 block
= create_block(tip
, create_coinbase(height
), cur_time
)
311 self
.nodes
[0].submitblock(ToHex(block
))
314 mempool
= self
.nodes
[0].getrawmempool()
315 assert(tx3
.hash not in mempool
)
316 assert(tx2
.hash in mempool
)
318 # Reset the chain and get rid of the mocktimed-blocks
319 self
.nodes
[0].setmocktime(0)
320 self
.nodes
[0].invalidateblock(self
.nodes
[0].getblockhash(cur_height
+1))
321 self
.nodes
[0].generate(10)
323 # Make sure that BIP68 isn't being used to validate blocks, prior to
324 # versionbits activation. If more blocks are mined prior to this test
325 # being run, then it's possible the test has activated the soft fork, and
326 # this test should be moved to run earlier, or deleted.
327 def test_bip68_not_consensus(self
):
328 assert(get_bip9_status(self
.nodes
[0], 'csv')['status'] != 'active')
329 txid
= self
.nodes
[0].sendtoaddress(self
.nodes
[0].getnewaddress(), 2)
331 tx1
= FromHex(CTransaction(), self
.nodes
[0].getrawtransaction(txid
))
334 # Make an anyone-can-spend transaction
337 tx2
.vin
= [CTxIn(COutPoint(tx1
.sha256
, 0), nSequence
=0)]
338 tx2
.vout
= [CTxOut(int(tx1
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
341 tx2_raw
= self
.nodes
[0].signrawtransaction(ToHex(tx2
))["hex"]
342 tx2
= FromHex(tx2
, tx2_raw
)
345 self
.nodes
[0].sendrawtransaction(ToHex(tx2
))
347 # Now make an invalid spend of tx2 according to BIP68
348 sequence_value
= 100 # 100 block relative locktime
352 tx3
.vin
= [CTxIn(COutPoint(tx2
.sha256
, 0), nSequence
=sequence_value
)]
353 tx3
.vout
= [CTxOut(int(tx2
.vout
[0].nValue
- self
.relayfee
*COIN
), CScript([b
'a']))]
356 assert_raises_rpc_error(-26, NOT_FINAL_ERROR
, self
.nodes
[0].sendrawtransaction
, ToHex(tx3
))
358 # make a block that violates bip68; ensure that the tip updates
359 tip
= int(self
.nodes
[0].getbestblockhash(), 16)
360 block
= create_block(tip
, create_coinbase(self
.nodes
[0].getblockcount()+1))
362 block
.vtx
.extend([tx1
, tx2
, tx3
])
363 block
.hashMerkleRoot
= block
.calc_merkle_root()
367 self
.nodes
[0].submitblock(ToHex(block
))
368 assert_equal(self
.nodes
[0].getbestblockhash(), block
.hash)
370 def activateCSV(self
):
371 # activation should happen at block height 432 (3 periods)
372 # getblockchaininfo will show CSV as active at block 431 (144 * 3 -1) since it's returning whether CSV is active for the next block.
373 min_activation_height
= 432
374 height
= self
.nodes
[0].getblockcount()
375 assert_greater_than(min_activation_height
- height
, 2)
376 self
.nodes
[0].generate(min_activation_height
- height
- 2)
377 assert_equal(get_bip9_status(self
.nodes
[0], 'csv')['status'], "locked_in")
378 self
.nodes
[0].generate(1)
379 assert_equal(get_bip9_status(self
.nodes
[0], 'csv')['status'], "active")
380 sync_blocks(self
.nodes
)
382 # Use self.nodes[1] to test that version 2 transactions are standard.
383 def test_version2_relay(self
):
385 outputs
= { self
.nodes
[1].getnewaddress() : 1.0 }
386 rawtx
= self
.nodes
[1].createrawtransaction(inputs
, outputs
)
387 rawtxfund
= self
.nodes
[1].fundrawtransaction(rawtx
)['hex']
388 tx
= FromHex(CTransaction(), rawtxfund
)
390 tx_signed
= self
.nodes
[1].signrawtransaction(ToHex(tx
))["hex"]
391 self
.nodes
[1].sendrawtransaction(tx_signed
)
393 if __name__
== '__main__':