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 16KB

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