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.

replace-by-fee.py 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  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 the RBF code."""
  6. from test_framework.test_framework import BitcoinTestFramework
  7. from test_framework.util import *
  8. from test_framework.script import *
  9. from test_framework.mininode import *
  10. MAX_REPLACEMENT_LIMIT = 100
  11. def txToHex(tx):
  12. return bytes_to_hex_str(tx.serialize())
  13. def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
  14. """Create a txout with a given amount and scriptPubKey
  15. Mines coins as needed.
  16. confirmed - txouts created will be confirmed in the blockchain;
  17. unconfirmed otherwise.
  18. """
  19. fee = 1*COIN
  20. while node.getbalance() < satoshi_round((amount + fee)/COIN):
  21. node.generate(100)
  22. new_addr = node.getnewaddress()
  23. txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
  24. tx1 = node.getrawtransaction(txid, 1)
  25. txid = int(txid, 16)
  26. i = None
  27. for i, txout in enumerate(tx1['vout']):
  28. if txout['scriptPubKey']['addresses'] == [new_addr]:
  29. break
  30. assert i is not None
  31. tx2 = CTransaction()
  32. tx2.vin = [CTxIn(COutPoint(txid, i))]
  33. tx2.vout = [CTxOut(amount, scriptPubKey)]
  34. tx2.rehash()
  35. signed_tx = node.signrawtransaction(txToHex(tx2))
  36. txid = node.sendrawtransaction(signed_tx['hex'], True)
  37. # If requested, ensure txouts are confirmed.
  38. if confirmed:
  39. mempool_size = len(node.getrawmempool())
  40. while mempool_size > 0:
  41. node.generate(1)
  42. new_size = len(node.getrawmempool())
  43. # Error out if we have something stuck in the mempool, as this
  44. # would likely be a bug.
  45. assert(new_size < mempool_size)
  46. mempool_size = new_size
  47. return COutPoint(int(txid, 16), 0)
  48. class ReplaceByFeeTest(BitcoinTestFramework):
  49. def set_test_params(self):
  50. self.num_nodes = 2
  51. self.extra_args= [["-maxorphantx=1000",
  52. "-whitelist=127.0.0.1",
  53. "-limitancestorcount=50",
  54. "-limitancestorsize=101",
  55. "-limitdescendantcount=200",
  56. "-limitdescendantsize=101"],
  57. ["-mempoolreplacement=0"]]
  58. def run_test(self):
  59. # Leave IBD
  60. self.nodes[0].generate(1)
  61. make_utxo(self.nodes[0], 1*COIN)
  62. # Ensure nodes are synced
  63. self.sync_all()
  64. self.log.info("Running test simple doublespend...")
  65. self.test_simple_doublespend()
  66. self.log.info("Running test doublespend chain...")
  67. self.test_doublespend_chain()
  68. self.log.info("Running test doublespend tree...")
  69. self.test_doublespend_tree()
  70. self.log.info("Running test replacement feeperkb...")
  71. self.test_replacement_feeperkb()
  72. self.log.info("Running test spends of conflicting outputs...")
  73. self.test_spends_of_conflicting_outputs()
  74. self.log.info("Running test new unconfirmed inputs...")
  75. self.test_new_unconfirmed_inputs()
  76. self.log.info("Running test too many replacements...")
  77. self.test_too_many_replacements()
  78. self.log.info("Running test opt-in...")
  79. self.test_opt_in()
  80. self.log.info("Running test RPC...")
  81. self.test_rpc()
  82. self.log.info("Running test prioritised transactions...")
  83. self.test_prioritised_transactions()
  84. self.log.info("Passed")
  85. def test_simple_doublespend(self):
  86. """Simple doublespend"""
  87. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  88. # make_utxo may have generated a bunch of blocks, so we need to sync
  89. # before we can spend the coins generated, or else the resulting
  90. # transactions might not be accepted by our peers.
  91. self.sync_all()
  92. tx1a = CTransaction()
  93. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  94. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  95. tx1a_hex = txToHex(tx1a)
  96. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  97. self.sync_all()
  98. # Should fail because we haven't changed the fee
  99. tx1b = CTransaction()
  100. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  101. tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
  102. tx1b_hex = txToHex(tx1b)
  103. # This will raise an exception due to insufficient fee
  104. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  105. # This will raise an exception due to transaction replacement being disabled
  106. assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
  107. # Extra 0.1 BTC fee
  108. tx1b = CTransaction()
  109. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  110. tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  111. tx1b_hex = txToHex(tx1b)
  112. # Replacement still disabled even with "enough fee"
  113. assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
  114. # Works when enabled
  115. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  116. mempool = self.nodes[0].getrawmempool()
  117. assert (tx1a_txid not in mempool)
  118. assert (tx1b_txid in mempool)
  119. assert_equal(tx1b_hex, self.nodes[0].getrawtransaction(tx1b_txid))
  120. # Second node is running mempoolreplacement=0, will not replace originally-seen txn
  121. mempool = self.nodes[1].getrawmempool()
  122. assert tx1a_txid in mempool
  123. assert tx1b_txid not in mempool
  124. def test_doublespend_chain(self):
  125. """Doublespend of a long chain"""
  126. initial_nValue = 50*COIN
  127. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  128. prevout = tx0_outpoint
  129. remaining_value = initial_nValue
  130. chain_txids = []
  131. while remaining_value > 10*COIN:
  132. remaining_value -= 1*COIN
  133. tx = CTransaction()
  134. tx.vin = [CTxIn(prevout, nSequence=0)]
  135. tx.vout = [CTxOut(remaining_value, CScript([1]))]
  136. tx_hex = txToHex(tx)
  137. txid = self.nodes[0].sendrawtransaction(tx_hex, True)
  138. chain_txids.append(txid)
  139. prevout = COutPoint(int(txid, 16), 0)
  140. # Whether the double-spend is allowed is evaluated by including all
  141. # child fees - 40 BTC - so this attempt is rejected.
  142. dbl_tx = CTransaction()
  143. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  144. dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
  145. dbl_tx_hex = txToHex(dbl_tx)
  146. # This will raise an exception due to insufficient fee
  147. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  148. # Accepted with sufficient fee
  149. dbl_tx = CTransaction()
  150. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  151. dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
  152. dbl_tx_hex = txToHex(dbl_tx)
  153. self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
  154. mempool = self.nodes[0].getrawmempool()
  155. for doublespent_txid in chain_txids:
  156. assert(doublespent_txid not in mempool)
  157. def test_doublespend_tree(self):
  158. """Doublespend of a big tree of transactions"""
  159. initial_nValue = 50*COIN
  160. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  161. def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _total_txs=None):
  162. if _total_txs is None:
  163. _total_txs = [0]
  164. if _total_txs[0] >= max_txs:
  165. return
  166. txout_value = (initial_value - fee) // tree_width
  167. if txout_value < fee:
  168. return
  169. vout = [CTxOut(txout_value, CScript([i+1]))
  170. for i in range(tree_width)]
  171. tx = CTransaction()
  172. tx.vin = [CTxIn(prevout, nSequence=0)]
  173. tx.vout = vout
  174. tx_hex = txToHex(tx)
  175. assert(len(tx.serialize()) < 100000)
  176. txid = self.nodes[0].sendrawtransaction(tx_hex, True)
  177. yield tx
  178. _total_txs[0] += 1
  179. txid = int(txid, 16)
  180. for i, txout in enumerate(tx.vout):
  181. for x in branch(COutPoint(txid, i), txout_value,
  182. max_txs,
  183. tree_width=tree_width, fee=fee,
  184. _total_txs=_total_txs):
  185. yield x
  186. fee = int(0.0001*COIN)
  187. n = MAX_REPLACEMENT_LIMIT
  188. tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
  189. assert_equal(len(tree_txs), n)
  190. # Attempt double-spend, will fail because too little fee paid
  191. dbl_tx = CTransaction()
  192. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  193. dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
  194. dbl_tx_hex = txToHex(dbl_tx)
  195. # This will raise an exception due to insufficient fee
  196. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  197. # 1 BTC fee is enough
  198. dbl_tx = CTransaction()
  199. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  200. dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
  201. dbl_tx_hex = txToHex(dbl_tx)
  202. self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
  203. mempool = self.nodes[0].getrawmempool()
  204. for tx in tree_txs:
  205. tx.rehash()
  206. assert (tx.hash not in mempool)
  207. # Try again, but with more total transactions than the "max txs
  208. # double-spent at once" anti-DoS limit.
  209. for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2):
  210. fee = int(0.0001*COIN)
  211. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  212. tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
  213. assert_equal(len(tree_txs), n)
  214. dbl_tx = CTransaction()
  215. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  216. dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
  217. dbl_tx_hex = txToHex(dbl_tx)
  218. # This will raise an exception
  219. assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  220. for tx in tree_txs:
  221. tx.rehash()
  222. self.nodes[0].getrawtransaction(tx.hash)
  223. def test_replacement_feeperkb(self):
  224. """Replacement requires fee-per-KB to be higher"""
  225. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  226. tx1a = CTransaction()
  227. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  228. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  229. tx1a_hex = txToHex(tx1a)
  230. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  231. # Higher fee, but the fee per KB is much lower, so the replacement is
  232. # rejected.
  233. tx1b = CTransaction()
  234. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  235. tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))]
  236. tx1b_hex = txToHex(tx1b)
  237. # This will raise an exception due to insufficient fee
  238. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  239. def test_spends_of_conflicting_outputs(self):
  240. """Replacements that spend conflicting tx outputs are rejected"""
  241. utxo1 = make_utxo(self.nodes[0], int(1.2*COIN))
  242. utxo2 = make_utxo(self.nodes[0], 3*COIN)
  243. tx1a = CTransaction()
  244. tx1a.vin = [CTxIn(utxo1, nSequence=0)]
  245. tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
  246. tx1a_hex = txToHex(tx1a)
  247. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  248. tx1a_txid = int(tx1a_txid, 16)
  249. # Direct spend an output of the transaction we're replacing.
  250. tx2 = CTransaction()
  251. tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
  252. tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
  253. tx2.vout = tx1a.vout
  254. tx2_hex = txToHex(tx2)
  255. # This will raise an exception
  256. assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
  257. # Spend tx1a's output to test the indirect case.
  258. tx1b = CTransaction()
  259. tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
  260. tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
  261. tx1b_hex = txToHex(tx1b)
  262. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  263. tx1b_txid = int(tx1b_txid, 16)
  264. tx2 = CTransaction()
  265. tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0),
  266. CTxIn(COutPoint(tx1b_txid, 0))]
  267. tx2.vout = tx1a.vout
  268. tx2_hex = txToHex(tx2)
  269. # This will raise an exception
  270. assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
  271. def test_new_unconfirmed_inputs(self):
  272. """Replacements that add new unconfirmed inputs are rejected"""
  273. confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN))
  274. unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False)
  275. tx1 = CTransaction()
  276. tx1.vin = [CTxIn(confirmed_utxo)]
  277. tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
  278. tx1_hex = txToHex(tx1)
  279. tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
  280. tx2 = CTransaction()
  281. tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
  282. tx2.vout = tx1.vout
  283. tx2_hex = txToHex(tx2)
  284. # This will raise an exception
  285. assert_raises_rpc_error(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, True)
  286. def test_too_many_replacements(self):
  287. """Replacements that evict too many transactions are rejected"""
  288. # Try directly replacing more than MAX_REPLACEMENT_LIMIT
  289. # transactions
  290. # Start by creating a single transaction with many outputs
  291. initial_nValue = 10*COIN
  292. utxo = make_utxo(self.nodes[0], initial_nValue)
  293. fee = int(0.0001*COIN)
  294. split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
  295. outputs = []
  296. for i in range(MAX_REPLACEMENT_LIMIT+1):
  297. outputs.append(CTxOut(split_value, CScript([1])))
  298. splitting_tx = CTransaction()
  299. splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
  300. splitting_tx.vout = outputs
  301. splitting_tx_hex = txToHex(splitting_tx)
  302. txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, True)
  303. txid = int(txid, 16)
  304. # Now spend each of those outputs individually
  305. for i in range(MAX_REPLACEMENT_LIMIT+1):
  306. tx_i = CTransaction()
  307. tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
  308. tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
  309. tx_i_hex = txToHex(tx_i)
  310. self.nodes[0].sendrawtransaction(tx_i_hex, True)
  311. # Now create doublespend of the whole lot; should fail.
  312. # Need a big enough fee to cover all spending transactions and have
  313. # a higher fee rate
  314. double_spend_value = (split_value-100*fee)*(MAX_REPLACEMENT_LIMIT+1)
  315. inputs = []
  316. for i in range(MAX_REPLACEMENT_LIMIT+1):
  317. inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
  318. double_tx = CTransaction()
  319. double_tx.vin = inputs
  320. double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
  321. double_tx_hex = txToHex(double_tx)
  322. # This will raise an exception
  323. assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, True)
  324. # If we remove an input, it should pass
  325. double_tx = CTransaction()
  326. double_tx.vin = inputs[0:-1]
  327. double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
  328. double_tx_hex = txToHex(double_tx)
  329. self.nodes[0].sendrawtransaction(double_tx_hex, True)
  330. def test_opt_in(self):
  331. """Replacing should only work if orig tx opted in"""
  332. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  333. # Create a non-opting in transaction
  334. tx1a = CTransaction()
  335. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
  336. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  337. tx1a_hex = txToHex(tx1a)
  338. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  339. # Shouldn't be able to double-spend
  340. tx1b = CTransaction()
  341. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  342. tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  343. tx1b_hex = txToHex(tx1b)
  344. # This will raise an exception
  345. assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  346. tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  347. # Create a different non-opting in transaction
  348. tx2a = CTransaction()
  349. tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
  350. tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  351. tx2a_hex = txToHex(tx2a)
  352. tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
  353. # Still shouldn't be able to double-spend
  354. tx2b = CTransaction()
  355. tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  356. tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  357. tx2b_hex = txToHex(tx2b)
  358. # This will raise an exception
  359. assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, True)
  360. # Now create a new transaction that spends from tx1a and tx2a
  361. # opt-in on one of the inputs
  362. # Transaction should be replaceable on either input
  363. tx1a_txid = int(tx1a_txid, 16)
  364. tx2a_txid = int(tx2a_txid, 16)
  365. tx3a = CTransaction()
  366. tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
  367. CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
  368. tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
  369. tx3a_hex = txToHex(tx3a)
  370. self.nodes[0].sendrawtransaction(tx3a_hex, True)
  371. tx3b = CTransaction()
  372. tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
  373. tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
  374. tx3b_hex = txToHex(tx3b)
  375. tx3c = CTransaction()
  376. tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
  377. tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
  378. tx3c_hex = txToHex(tx3c)
  379. self.nodes[0].sendrawtransaction(tx3b_hex, True)
  380. # If tx3b was accepted, tx3c won't look like a replacement,
  381. # but make sure it is accepted anyway
  382. self.nodes[0].sendrawtransaction(tx3c_hex, True)
  383. def test_prioritised_transactions(self):
  384. # Ensure that fee deltas used via prioritisetransaction are
  385. # correctly used by replacement logic
  386. # 1. Check that feeperkb uses modified fees
  387. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  388. tx1a = CTransaction()
  389. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  390. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  391. tx1a_hex = txToHex(tx1a)
  392. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  393. # Higher fee, but the actual fee per KB is much lower.
  394. tx1b = CTransaction()
  395. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  396. tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))]
  397. tx1b_hex = txToHex(tx1b)
  398. # Verify tx1b cannot replace tx1a.
  399. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  400. # Use prioritisetransaction to set tx1a's fee to 0.
  401. self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1*COIN))
  402. # Now tx1b should be able to replace tx1a
  403. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  404. assert(tx1b_txid in self.nodes[0].getrawmempool())
  405. # 2. Check that absolute fee checks use modified fee.
  406. tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  407. tx2a = CTransaction()
  408. tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  409. tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  410. tx2a_hex = txToHex(tx2a)
  411. tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
  412. # Lower fee, but we'll prioritise it
  413. tx2b = CTransaction()
  414. tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  415. tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
  416. tx2b.rehash()
  417. tx2b_hex = txToHex(tx2b)
  418. # Verify tx2b cannot replace tx2a.
  419. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True)
  420. # Now prioritise tx2b to have a higher modified fee
  421. self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1*COIN))
  422. # tx2b should now be accepted
  423. tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
  424. assert(tx2b_txid in self.nodes[0].getrawmempool())
  425. def test_rpc(self):
  426. us0 = self.nodes[0].listunspent()[0]
  427. ins = [us0]
  428. outs = {self.nodes[0].getnewaddress() : Decimal(1.0000000)}
  429. rawtx0 = self.nodes[0].createrawtransaction(ins, outs, 0, True)
  430. rawtx1 = self.nodes[0].createrawtransaction(ins, outs, 0, False)
  431. json0 = self.nodes[0].decoderawtransaction(rawtx0)
  432. json1 = self.nodes[0].decoderawtransaction(rawtx1)
  433. assert_equal(json0["vin"][0]["sequence"], 4294967293)
  434. assert_equal(json1["vin"][0]["sequence"], 4294967295)
  435. rawtx2 = self.nodes[0].createrawtransaction([], outs)
  436. frawtx2a = self.nodes[0].fundrawtransaction(rawtx2, {"replaceable": True})
  437. frawtx2b = self.nodes[0].fundrawtransaction(rawtx2, {"replaceable": False})
  438. json0 = self.nodes[0].decoderawtransaction(frawtx2a['hex'])
  439. json1 = self.nodes[0].decoderawtransaction(frawtx2b['hex'])
  440. assert_equal(json0["vin"][0]["sequence"], 4294967293)
  441. assert_equal(json1["vin"][0]["sequence"], 4294967294)
  442. if __name__ == '__main__':
  443. ReplaceByFeeTest().main()