You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bip68-sequence.py 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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."""
  6. from test_framework.test_framework import BitcoinTestFramework
  7. from test_framework.util import *
  8. from test_framework.blocktools import *
  9. SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31)
  10. SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height)
  11. SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift
  12. SEQUENCE_LOCKTIME_MASK = 0x0000ffff
  13. # RPC error for non-BIP68 final transactions
  14. NOT_FINAL_ERROR = "64: non-BIP68-final"
  15. class BIP68Test(BitcoinTestFramework):
  16. def __init__(self):
  17. super().__init__()
  18. self.num_nodes = 2
  19. self.setup_clean_chain = False
  20. def setup_network(self):
  21. self.nodes = []
  22. self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
  23. self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-acceptnonstdtxn=0"]))
  24. self.is_network_split = False
  25. self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
  26. connect_nodes(self.nodes[0], 1)
  27. def run_test(self):
  28. # Generate some coins
  29. self.nodes[0].generate(110)
  30. print("Running test disable flag")
  31. self.test_disable_flag()
  32. print("Running test sequence-lock-confirmed-inputs")
  33. self.test_sequence_lock_confirmed_inputs()
  34. print("Running test sequence-lock-unconfirmed-inputs")
  35. self.test_sequence_lock_unconfirmed_inputs()
  36. print("Running test BIP68 not consensus before versionbits activation")
  37. self.test_bip68_not_consensus()
  38. print("Verifying nVersion=2 transactions aren't standard")
  39. self.test_version2_relay(before_activation=True)
  40. print("Activating BIP68 (and 112/113)")
  41. self.activateCSV()
  42. print("Verifying nVersion=2 transactions are now standard")
  43. self.test_version2_relay(before_activation=False)
  44. print("Passed\n")
  45. # Test that BIP68 is not in effect if tx version is 1, or if
  46. # the first sequence bit is set.
  47. def test_disable_flag(self):
  48. # Create some unconfirmed inputs
  49. new_addr = self.nodes[0].getnewaddress()
  50. self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC
  51. utxos = self.nodes[0].listunspent(0, 0)
  52. assert(len(utxos) > 0)
  53. utxo = utxos[0]
  54. tx1 = CTransaction()
  55. value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN)
  56. # Check that the disable flag disables relative locktime.
  57. # If sequence locks were used, this would require 1 block for the
  58. # input to mature.
  59. sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
  60. tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
  61. tx1.vout = [CTxOut(value, CScript([b'a']))]
  62. tx1_signed = self.nodes[0].signrawtransaction(ToHex(tx1))["hex"]
  63. tx1_id = self.nodes[0].sendrawtransaction(tx1_signed)
  64. tx1_id = int(tx1_id, 16)
  65. # This transaction will enable sequence-locks, so this transaction should
  66. # fail
  67. tx2 = CTransaction()
  68. tx2.nVersion = 2
  69. sequence_value = sequence_value & 0x7fffffff
  70. tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
  71. tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))]
  72. tx2.rehash()
  73. try:
  74. self.nodes[0].sendrawtransaction(ToHex(tx2))
  75. except JSONRPCException as exp:
  76. assert_equal(exp.error["message"], NOT_FINAL_ERROR)
  77. else:
  78. assert(False)
  79. # Setting the version back down to 1 should disable the sequence lock,
  80. # so this should be accepted.
  81. tx2.nVersion = 1
  82. self.nodes[0].sendrawtransaction(ToHex(tx2))
  83. # Calculate the median time past of a prior block ("confirmations" before
  84. # the current tip).
  85. def get_median_time_past(self, confirmations):
  86. block_hash = self.nodes[0].getblockhash(self.nodes[0].getblockcount()-confirmations)
  87. return self.nodes[0].getblockheader(block_hash)["mediantime"]
  88. # Test that sequence locks are respected for transactions spending confirmed inputs.
  89. def test_sequence_lock_confirmed_inputs(self):
  90. # Create lots of confirmed utxos, and use them to generate lots of random
  91. # transactions.
  92. max_outputs = 50
  93. addresses = []
  94. while len(addresses) < max_outputs:
  95. addresses.append(self.nodes[0].getnewaddress())
  96. while len(self.nodes[0].listunspent()) < 200:
  97. import random
  98. random.shuffle(addresses)
  99. num_outputs = random.randint(1, max_outputs)
  100. outputs = {}
  101. for i in range(num_outputs):
  102. outputs[addresses[i]] = random.randint(1, 20)*0.01
  103. self.nodes[0].sendmany("", outputs)
  104. self.nodes[0].generate(1)
  105. utxos = self.nodes[0].listunspent()
  106. # Try creating a lot of random transactions.
  107. # Each time, choose a random number of inputs, and randomly set
  108. # some of those inputs to be sequence locked (and randomly choose
  109. # between height/time locking). Small random chance of making the locks
  110. # all pass.
  111. for i in range(400):
  112. # Randomly choose up to 10 inputs
  113. num_inputs = random.randint(1, 10)
  114. random.shuffle(utxos)
  115. # Track whether any sequence locks used should fail
  116. should_pass = True
  117. # Track whether this transaction was built with sequence locks
  118. using_sequence_locks = False
  119. tx = CTransaction()
  120. tx.nVersion = 2
  121. value = 0
  122. for j in range(num_inputs):
  123. sequence_value = 0xfffffffe # this disables sequence locks
  124. # 50% chance we enable sequence locks
  125. if random.randint(0,1):
  126. using_sequence_locks = True
  127. # 10% of the time, make the input sequence value pass
  128. input_will_pass = (random.randint(1,10) == 1)
  129. sequence_value = utxos[j]["confirmations"]
  130. if not input_will_pass:
  131. sequence_value += 1
  132. should_pass = False
  133. # Figure out what the median-time-past was for the confirmed input
  134. # Note that if an input has N confirmations, we're going back N blocks
  135. # from the tip so that we're looking up MTP of the block
  136. # PRIOR to the one the input appears in, as per the BIP68 spec.
  137. orig_time = self.get_median_time_past(utxos[j]["confirmations"])
  138. cur_time = self.get_median_time_past(0) # MTP of the tip
  139. # can only timelock this input if it's not too old -- otherwise use height
  140. can_time_lock = True
  141. if ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK:
  142. can_time_lock = False
  143. # if time-lockable, then 50% chance we make this a time lock
  144. if random.randint(0,1) and can_time_lock:
  145. # Find first time-lock value that fails, or latest one that succeeds
  146. time_delta = sequence_value << SEQUENCE_LOCKTIME_GRANULARITY
  147. if input_will_pass and time_delta > cur_time - orig_time:
  148. sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)
  149. elif (not input_will_pass and time_delta <= cur_time - orig_time):
  150. sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)+1
  151. sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
  152. tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value))
  153. value += utxos[j]["amount"]*COIN
  154. # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
  155. tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50
  156. tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a'])))
  157. rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"]
  158. try:
  159. self.nodes[0].sendrawtransaction(rawtx)
  160. except JSONRPCException as exp:
  161. assert(not should_pass and using_sequence_locks)
  162. assert_equal(exp.error["message"], NOT_FINAL_ERROR)
  163. else:
  164. assert(should_pass or not using_sequence_locks)
  165. # Recalculate utxos if we successfully sent the transaction
  166. utxos = self.nodes[0].listunspent()
  167. # Test that sequence locks on unconfirmed inputs must have nSequence
  168. # height or time of 0 to be accepted.
  169. # Then test that BIP68-invalid transactions are removed from the mempool
  170. # after a reorg.
  171. def test_sequence_lock_unconfirmed_inputs(self):
  172. # Store height so we can easily reset the chain at the end of the test
  173. cur_height = self.nodes[0].getblockcount()
  174. # Create a mempool tx.
  175. txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
  176. tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
  177. tx1.rehash()
  178. # Anyone-can-spend mempool tx.
  179. # Sequence lock of 0 should pass.
  180. tx2 = CTransaction()
  181. tx2.nVersion = 2
  182. tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
  183. tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
  184. tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
  185. tx2 = FromHex(tx2, tx2_raw)
  186. tx2.rehash()
  187. self.nodes[0].sendrawtransaction(tx2_raw)
  188. # Create a spend of the 0th output of orig_tx with a sequence lock
  189. # of 1, and test what happens when submitting.
  190. # orig_tx.vout[0] must be an anyone-can-spend output
  191. def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
  192. sequence_value = 1
  193. if not use_height_lock:
  194. sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
  195. tx = CTransaction()
  196. tx.nVersion = 2
  197. tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
  198. tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))]
  199. tx.rehash()
  200. try:
  201. node.sendrawtransaction(ToHex(tx))
  202. except JSONRPCException as exp:
  203. assert_equal(exp.error["message"], NOT_FINAL_ERROR)
  204. assert(orig_tx.hash in node.getrawmempool())
  205. else:
  206. # orig_tx must not be in mempool
  207. assert(orig_tx.hash not in node.getrawmempool())
  208. return tx
  209. test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
  210. test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
  211. # Now mine some blocks, but make sure tx2 doesn't get mined.
  212. # Use prioritisetransaction to lower the effective feerate to 0
  213. self.nodes[0].prioritisetransaction(tx2.hash, -1e15, int(-self.relayfee*COIN))
  214. cur_time = int(time.time())
  215. for i in range(10):
  216. self.nodes[0].setmocktime(cur_time + 600)
  217. self.nodes[0].generate(1)
  218. cur_time += 600
  219. assert(tx2.hash in self.nodes[0].getrawmempool())
  220. test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
  221. test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
  222. # Mine tx2, and then try again
  223. self.nodes[0].prioritisetransaction(tx2.hash, 1e15, int(self.relayfee*COIN))
  224. # Advance the time on the node so that we can test timelocks
  225. self.nodes[0].setmocktime(cur_time+600)
  226. self.nodes[0].generate(1)
  227. assert(tx2.hash not in self.nodes[0].getrawmempool())
  228. # Now that tx2 is not in the mempool, a sequence locked spend should
  229. # succeed
  230. tx3 = test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
  231. assert(tx3.hash in self.nodes[0].getrawmempool())
  232. self.nodes[0].generate(1)
  233. assert(tx3.hash not in self.nodes[0].getrawmempool())
  234. # One more test, this time using height locks
  235. tx4 = test_nonzero_locks(tx3, self.nodes[0], self.relayfee, use_height_lock=True)
  236. assert(tx4.hash in self.nodes[0].getrawmempool())
  237. # Now try combining confirmed and unconfirmed inputs
  238. tx5 = test_nonzero_locks(tx4, self.nodes[0], self.relayfee, use_height_lock=True)
  239. assert(tx5.hash not in self.nodes[0].getrawmempool())
  240. utxos = self.nodes[0].listunspent()
  241. tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1))
  242. tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN)
  243. raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"]
  244. try:
  245. self.nodes[0].sendrawtransaction(raw_tx5)
  246. except JSONRPCException as exp:
  247. assert_equal(exp.error["message"], NOT_FINAL_ERROR)
  248. else:
  249. assert(False)
  250. # Test mempool-BIP68 consistency after reorg
  251. #
  252. # State of the transactions in the last blocks:
  253. # ... -> [ tx2 ] -> [ tx3 ]
  254. # tip-1 tip
  255. # And currently tx4 is in the mempool.
  256. #
  257. # If we invalidate the tip, tx3 should get added to the mempool, causing
  258. # tx4 to be removed (fails sequence-lock).
  259. self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
  260. assert(tx4.hash not in self.nodes[0].getrawmempool())
  261. assert(tx3.hash in self.nodes[0].getrawmempool())
  262. # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
  263. # diagram above).
  264. # This would cause tx2 to be added back to the mempool, which in turn causes
  265. # tx3 to be removed.
  266. tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16)
  267. height = self.nodes[0].getblockcount()
  268. for i in range(2):
  269. block = create_block(tip, create_coinbase(height), cur_time)
  270. block.nVersion = 3
  271. block.rehash()
  272. block.solve()
  273. tip = block.sha256
  274. height += 1
  275. self.nodes[0].submitblock(ToHex(block))
  276. cur_time += 1
  277. mempool = self.nodes[0].getrawmempool()
  278. assert(tx3.hash not in mempool)
  279. assert(tx2.hash in mempool)
  280. # Reset the chain and get rid of the mocktimed-blocks
  281. self.nodes[0].setmocktime(0)
  282. self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
  283. self.nodes[0].generate(10)
  284. # Make sure that BIP68 isn't being used to validate blocks, prior to
  285. # versionbits activation. If more blocks are mined prior to this test
  286. # being run, then it's possible the test has activated the soft fork, and
  287. # this test should be moved to run earlier, or deleted.
  288. def test_bip68_not_consensus(self):
  289. assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
  290. txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
  291. tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
  292. tx1.rehash()
  293. # Make an anyone-can-spend transaction
  294. tx2 = CTransaction()
  295. tx2.nVersion = 1
  296. tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
  297. tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
  298. # sign tx2
  299. tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
  300. tx2 = FromHex(tx2, tx2_raw)
  301. tx2.rehash()
  302. self.nodes[0].sendrawtransaction(ToHex(tx2))
  303. # Now make an invalid spend of tx2 according to BIP68
  304. sequence_value = 100 # 100 block relative locktime
  305. tx3 = CTransaction()
  306. tx3.nVersion = 2
  307. tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
  308. tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
  309. tx3.rehash()
  310. try:
  311. self.nodes[0].sendrawtransaction(ToHex(tx3))
  312. except JSONRPCException as exp:
  313. assert_equal(exp.error["message"], NOT_FINAL_ERROR)
  314. else:
  315. assert(False)
  316. # make a block that violates bip68; ensure that the tip updates
  317. tip = int(self.nodes[0].getbestblockhash(), 16)
  318. block = create_block(tip, create_coinbase(self.nodes[0].getblockcount()+1))
  319. block.nVersion = 3
  320. block.vtx.extend([tx1, tx2, tx3])
  321. block.hashMerkleRoot = block.calc_merkle_root()
  322. block.rehash()
  323. block.solve()
  324. self.nodes[0].submitblock(ToHex(block))
  325. assert_equal(self.nodes[0].getbestblockhash(), block.hash)
  326. def activateCSV(self):
  327. # activation should happen at block height 432 (3 periods)
  328. min_activation_height = 432
  329. height = self.nodes[0].getblockcount()
  330. assert(height < 432)
  331. self.nodes[0].generate(432-height)
  332. assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
  333. sync_blocks(self.nodes)
  334. # Use self.nodes[1] to test standardness relay policy
  335. def test_version2_relay(self, before_activation):
  336. inputs = [ ]
  337. outputs = { self.nodes[1].getnewaddress() : 1.0 }
  338. rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
  339. rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
  340. tx = FromHex(CTransaction(), rawtxfund)
  341. tx.nVersion = 2
  342. tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
  343. try:
  344. tx_id = self.nodes[1].sendrawtransaction(tx_signed)
  345. assert(before_activation == False)
  346. except:
  347. assert(before_activation)
  348. if __name__ == '__main__':
  349. BIP68Test().main()