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

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