scripted-diff: rename assert_raises_jsonrpc to assert_raises_rpc error
[bitcoinplatinum.git] / test / functional / bip68-sequence.py
blob5f8f21701f934fa558810b6a399ef8e022b92bde
1 #!/usr/bin/env python3
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):
20 def set_test_params(self):
21 self.num_nodes = 2
22 self.extra_args = [[], ["-acceptnonstdtxn=0"]]
24 def run_test(self):
25 self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
27 # Generate some coins
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)")
43 self.activateCSV()
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)
61 utxo = utxos[0]
63 tx1 = CTransaction()
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
68 # input to mature.
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
78 # fail
79 tx2 = CTransaction()
80 tx2.nVersion = 2
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']))]
84 tx2.rehash()
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.
90 tx2.nVersion = 1
92 self.nodes[0].sendrawtransaction(ToHex(tx2))
94 # Calculate the median time past of a prior block ("confirmations" before
95 # the current tip).
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
103 # transactions.
104 max_outputs = 50
105 addresses = []
106 while len(addresses) < max_outputs:
107 addresses.append(self.nodes[0].getnewaddress())
108 while len(self.nodes[0].listunspent()) < 200:
109 import random
110 random.shuffle(addresses)
111 num_outputs = random.randint(1, max_outputs)
112 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
124 # all pass.
125 for i in range(400):
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
131 should_pass = True
133 # Track whether this transaction was built with sequence locks
134 using_sequence_locks = False
136 tx = CTransaction()
137 tx.nVersion = 2
138 value = 0
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:
150 sequence_value += 1
151 should_pass = False
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
161 can_time_lock = True
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)
184 else:
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
192 # after a reorg.
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))
200 tx1.rehash()
202 # Anyone-can-spend mempool tx.
203 # Sequence lock of 0 should pass.
204 tx2 = CTransaction()
205 tx2.nVersion = 2
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)
210 tx2.rehash()
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):
218 sequence_value = 1
219 if not use_height_lock:
220 sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
222 tx = CTransaction()
223 tx.nVersion = 2
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']))]
226 tx.rehash()
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))
231 else:
232 # sendrawtransaction should succeed if the tx is not in the mempool
233 node.sendrawtransaction(ToHex(tx))
235 return 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())
244 for i in range(10):
245 self.nodes[0].setmocktime(cur_time + 600)
246 self.nodes[0].generate(1)
247 cur_time += 600
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
263 # succeed
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 ]
289 # tip-1 tip
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
299 # diagram above).
300 # This would cause tx2 to be added back to the mempool, which in turn causes
301 # tx3 to be removed.
302 tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16)
303 height = self.nodes[0].getblockcount()
304 for i in range(2):
305 block = create_block(tip, create_coinbase(height), cur_time)
306 block.nVersion = 3
307 block.rehash()
308 block.solve()
309 tip = block.sha256
310 height += 1
311 self.nodes[0].submitblock(ToHex(block))
312 cur_time += 1
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))
332 tx1.rehash()
334 # Make an anyone-can-spend transaction
335 tx2 = CTransaction()
336 tx2.nVersion = 1
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']))]
340 # sign tx2
341 tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
342 tx2 = FromHex(tx2, tx2_raw)
343 tx2.rehash()
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
350 tx3 = CTransaction()
351 tx3.nVersion = 2
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']))]
354 tx3.rehash()
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))
361 block.nVersion = 3
362 block.vtx.extend([tx1, tx2, tx3])
363 block.hashMerkleRoot = block.calc_merkle_root()
364 block.rehash()
365 block.solve()
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):
384 inputs = [ ]
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)
389 tx.nVersion = 2
390 tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
391 self.nodes[1].sendrawtransaction(tx_signed)
393 if __name__ == '__main__':
394 BIP68Test().main()