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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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 __init__(self):
  50. super().__init__()
  51. self.num_nodes = 1
  52. self.setup_clean_chain = False
  53. def setup_network(self):
  54. self.nodes = []
  55. self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
  56. "-whitelist=127.0.0.1",
  57. "-limitancestorcount=50",
  58. "-limitancestorsize=101",
  59. "-limitdescendantcount=200",
  60. "-limitdescendantsize=101"
  61. ]))
  62. self.is_network_split = False
  63. def run_test(self):
  64. make_utxo(self.nodes[0], 1*COIN)
  65. self.log.info("Running test simple doublespend...")
  66. self.test_simple_doublespend()
  67. self.log.info("Running test doublespend chain...")
  68. self.test_doublespend_chain()
  69. self.log.info("Running test doublespend tree...")
  70. self.test_doublespend_tree()
  71. self.log.info("Running test replacement feeperkb...")
  72. self.test_replacement_feeperkb()
  73. self.log.info("Running test spends of conflicting outputs...")
  74. self.test_spends_of_conflicting_outputs()
  75. self.log.info("Running test new unconfirmed inputs...")
  76. self.test_new_unconfirmed_inputs()
  77. self.log.info("Running test too many replacements...")
  78. self.test_too_many_replacements()
  79. self.log.info("Running test opt-in...")
  80. self.test_opt_in()
  81. self.log.info("Running test prioritised transactions...")
  82. self.test_prioritised_transactions()
  83. self.log.info("Passed")
  84. def test_simple_doublespend(self):
  85. """Simple doublespend"""
  86. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  87. tx1a = CTransaction()
  88. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  89. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  90. tx1a_hex = txToHex(tx1a)
  91. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  92. # Should fail because we haven't changed the fee
  93. tx1b = CTransaction()
  94. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  95. tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
  96. tx1b_hex = txToHex(tx1b)
  97. # This will raise an exception due to insufficient fee
  98. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  99. # Extra 0.1 BTC fee
  100. tx1b = CTransaction()
  101. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  102. tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  103. tx1b_hex = txToHex(tx1b)
  104. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  105. mempool = self.nodes[0].getrawmempool()
  106. assert (tx1a_txid not in mempool)
  107. assert (tx1b_txid in mempool)
  108. assert_equal(tx1b_hex, self.nodes[0].getrawtransaction(tx1b_txid))
  109. def test_doublespend_chain(self):
  110. """Doublespend of a long chain"""
  111. initial_nValue = 50*COIN
  112. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  113. prevout = tx0_outpoint
  114. remaining_value = initial_nValue
  115. chain_txids = []
  116. while remaining_value > 10*COIN:
  117. remaining_value -= 1*COIN
  118. tx = CTransaction()
  119. tx.vin = [CTxIn(prevout, nSequence=0)]
  120. tx.vout = [CTxOut(remaining_value, CScript([1]))]
  121. tx_hex = txToHex(tx)
  122. txid = self.nodes[0].sendrawtransaction(tx_hex, True)
  123. chain_txids.append(txid)
  124. prevout = COutPoint(int(txid, 16), 0)
  125. # Whether the double-spend is allowed is evaluated by including all
  126. # child fees - 40 BTC - so this attempt is rejected.
  127. dbl_tx = CTransaction()
  128. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  129. dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
  130. dbl_tx_hex = txToHex(dbl_tx)
  131. # This will raise an exception due to insufficient fee
  132. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  133. # Accepted with sufficient fee
  134. dbl_tx = CTransaction()
  135. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  136. dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
  137. dbl_tx_hex = txToHex(dbl_tx)
  138. self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
  139. mempool = self.nodes[0].getrawmempool()
  140. for doublespent_txid in chain_txids:
  141. assert(doublespent_txid not in mempool)
  142. def test_doublespend_tree(self):
  143. """Doublespend of a big tree of transactions"""
  144. initial_nValue = 50*COIN
  145. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  146. def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _total_txs=None):
  147. if _total_txs is None:
  148. _total_txs = [0]
  149. if _total_txs[0] >= max_txs:
  150. return
  151. txout_value = (initial_value - fee) // tree_width
  152. if txout_value < fee:
  153. return
  154. vout = [CTxOut(txout_value, CScript([i+1]))
  155. for i in range(tree_width)]
  156. tx = CTransaction()
  157. tx.vin = [CTxIn(prevout, nSequence=0)]
  158. tx.vout = vout
  159. tx_hex = txToHex(tx)
  160. assert(len(tx.serialize()) < 100000)
  161. txid = self.nodes[0].sendrawtransaction(tx_hex, True)
  162. yield tx
  163. _total_txs[0] += 1
  164. txid = int(txid, 16)
  165. for i, txout in enumerate(tx.vout):
  166. for x in branch(COutPoint(txid, i), txout_value,
  167. max_txs,
  168. tree_width=tree_width, fee=fee,
  169. _total_txs=_total_txs):
  170. yield x
  171. fee = int(0.0001*COIN)
  172. n = MAX_REPLACEMENT_LIMIT
  173. tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
  174. assert_equal(len(tree_txs), n)
  175. # Attempt double-spend, will fail because too little fee paid
  176. dbl_tx = CTransaction()
  177. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  178. dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
  179. dbl_tx_hex = txToHex(dbl_tx)
  180. # This will raise an exception due to insufficient fee
  181. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  182. # 1 BTC fee is enough
  183. dbl_tx = CTransaction()
  184. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  185. dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
  186. dbl_tx_hex = txToHex(dbl_tx)
  187. self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
  188. mempool = self.nodes[0].getrawmempool()
  189. for tx in tree_txs:
  190. tx.rehash()
  191. assert (tx.hash not in mempool)
  192. # Try again, but with more total transactions than the "max txs
  193. # double-spent at once" anti-DoS limit.
  194. for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2):
  195. fee = int(0.0001*COIN)
  196. tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
  197. tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
  198. assert_equal(len(tree_txs), n)
  199. dbl_tx = CTransaction()
  200. dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  201. dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
  202. dbl_tx_hex = txToHex(dbl_tx)
  203. # This will raise an exception
  204. assert_raises_jsonrpc(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
  205. for tx in tree_txs:
  206. tx.rehash()
  207. self.nodes[0].getrawtransaction(tx.hash)
  208. def test_replacement_feeperkb(self):
  209. """Replacement requires fee-per-KB to be higher"""
  210. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  211. tx1a = CTransaction()
  212. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  213. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  214. tx1a_hex = txToHex(tx1a)
  215. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  216. # Higher fee, but the fee per KB is much lower, so the replacement is
  217. # rejected.
  218. tx1b = CTransaction()
  219. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  220. tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))]
  221. tx1b_hex = txToHex(tx1b)
  222. # This will raise an exception due to insufficient fee
  223. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  224. def test_spends_of_conflicting_outputs(self):
  225. """Replacements that spend conflicting tx outputs are rejected"""
  226. utxo1 = make_utxo(self.nodes[0], int(1.2*COIN))
  227. utxo2 = make_utxo(self.nodes[0], 3*COIN)
  228. tx1a = CTransaction()
  229. tx1a.vin = [CTxIn(utxo1, nSequence=0)]
  230. tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
  231. tx1a_hex = txToHex(tx1a)
  232. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  233. tx1a_txid = int(tx1a_txid, 16)
  234. # Direct spend an output of the transaction we're replacing.
  235. tx2 = CTransaction()
  236. tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
  237. tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
  238. tx2.vout = tx1a.vout
  239. tx2_hex = txToHex(tx2)
  240. # This will raise an exception
  241. assert_raises_jsonrpc(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
  242. # Spend tx1a's output to test the indirect case.
  243. tx1b = CTransaction()
  244. tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
  245. tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
  246. tx1b_hex = txToHex(tx1b)
  247. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  248. tx1b_txid = int(tx1b_txid, 16)
  249. tx2 = CTransaction()
  250. tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0),
  251. CTxIn(COutPoint(tx1b_txid, 0))]
  252. tx2.vout = tx1a.vout
  253. tx2_hex = txToHex(tx2)
  254. # This will raise an exception
  255. assert_raises_jsonrpc(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True)
  256. def test_new_unconfirmed_inputs(self):
  257. """Replacements that add new unconfirmed inputs are rejected"""
  258. confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN))
  259. unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False)
  260. tx1 = CTransaction()
  261. tx1.vin = [CTxIn(confirmed_utxo)]
  262. tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
  263. tx1_hex = txToHex(tx1)
  264. tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
  265. tx2 = CTransaction()
  266. tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
  267. tx2.vout = tx1.vout
  268. tx2_hex = txToHex(tx2)
  269. # This will raise an exception
  270. assert_raises_jsonrpc(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, True)
  271. def test_too_many_replacements(self):
  272. """Replacements that evict too many transactions are rejected"""
  273. # Try directly replacing more than MAX_REPLACEMENT_LIMIT
  274. # transactions
  275. # Start by creating a single transaction with many outputs
  276. initial_nValue = 10*COIN
  277. utxo = make_utxo(self.nodes[0], initial_nValue)
  278. fee = int(0.0001*COIN)
  279. split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
  280. outputs = []
  281. for i in range(MAX_REPLACEMENT_LIMIT+1):
  282. outputs.append(CTxOut(split_value, CScript([1])))
  283. splitting_tx = CTransaction()
  284. splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
  285. splitting_tx.vout = outputs
  286. splitting_tx_hex = txToHex(splitting_tx)
  287. txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, True)
  288. txid = int(txid, 16)
  289. # Now spend each of those outputs individually
  290. for i in range(MAX_REPLACEMENT_LIMIT+1):
  291. tx_i = CTransaction()
  292. tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
  293. tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
  294. tx_i_hex = txToHex(tx_i)
  295. self.nodes[0].sendrawtransaction(tx_i_hex, True)
  296. # Now create doublespend of the whole lot; should fail.
  297. # Need a big enough fee to cover all spending transactions and have
  298. # a higher fee rate
  299. double_spend_value = (split_value-100*fee)*(MAX_REPLACEMENT_LIMIT+1)
  300. inputs = []
  301. for i in range(MAX_REPLACEMENT_LIMIT+1):
  302. inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
  303. double_tx = CTransaction()
  304. double_tx.vin = inputs
  305. double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
  306. double_tx_hex = txToHex(double_tx)
  307. # This will raise an exception
  308. assert_raises_jsonrpc(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, True)
  309. # If we remove an input, it should pass
  310. double_tx = CTransaction()
  311. double_tx.vin = inputs[0:-1]
  312. double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
  313. double_tx_hex = txToHex(double_tx)
  314. self.nodes[0].sendrawtransaction(double_tx_hex, True)
  315. def test_opt_in(self):
  316. """Replacing should only work if orig tx opted in"""
  317. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  318. # Create a non-opting in transaction
  319. tx1a = CTransaction()
  320. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
  321. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  322. tx1a_hex = txToHex(tx1a)
  323. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  324. # Shouldn't be able to double-spend
  325. tx1b = CTransaction()
  326. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  327. tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  328. tx1b_hex = txToHex(tx1b)
  329. # This will raise an exception
  330. assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  331. tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  332. # Create a different non-opting in transaction
  333. tx2a = CTransaction()
  334. tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
  335. tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  336. tx2a_hex = txToHex(tx2a)
  337. tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
  338. # Still shouldn't be able to double-spend
  339. tx2b = CTransaction()
  340. tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  341. tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
  342. tx2b_hex = txToHex(tx2b)
  343. # This will raise an exception
  344. assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, True)
  345. # Now create a new transaction that spends from tx1a and tx2a
  346. # opt-in on one of the inputs
  347. # Transaction should be replaceable on either input
  348. tx1a_txid = int(tx1a_txid, 16)
  349. tx2a_txid = int(tx2a_txid, 16)
  350. tx3a = CTransaction()
  351. tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
  352. CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
  353. tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
  354. tx3a_hex = txToHex(tx3a)
  355. self.nodes[0].sendrawtransaction(tx3a_hex, True)
  356. tx3b = CTransaction()
  357. tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
  358. tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
  359. tx3b_hex = txToHex(tx3b)
  360. tx3c = CTransaction()
  361. tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
  362. tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
  363. tx3c_hex = txToHex(tx3c)
  364. self.nodes[0].sendrawtransaction(tx3b_hex, True)
  365. # If tx3b was accepted, tx3c won't look like a replacement,
  366. # but make sure it is accepted anyway
  367. self.nodes[0].sendrawtransaction(tx3c_hex, True)
  368. def test_prioritised_transactions(self):
  369. # Ensure that fee deltas used via prioritisetransaction are
  370. # correctly used by replacement logic
  371. # 1. Check that feeperkb uses modified fees
  372. tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  373. tx1a = CTransaction()
  374. tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  375. tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  376. tx1a_hex = txToHex(tx1a)
  377. tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
  378. # Higher fee, but the actual fee per KB is much lower.
  379. tx1b = CTransaction()
  380. tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
  381. tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))]
  382. tx1b_hex = txToHex(tx1b)
  383. # Verify tx1b cannot replace tx1a.
  384. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
  385. # Use prioritisetransaction to set tx1a's fee to 0.
  386. self.nodes[0].prioritisetransaction(tx1a_txid, int(-0.1*COIN))
  387. # Now tx1b should be able to replace tx1a
  388. tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
  389. assert(tx1b_txid in self.nodes[0].getrawmempool())
  390. # 2. Check that absolute fee checks use modified fee.
  391. tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
  392. tx2a = CTransaction()
  393. tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  394. tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
  395. tx2a_hex = txToHex(tx2a)
  396. tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
  397. # Lower fee, but we'll prioritise it
  398. tx2b = CTransaction()
  399. tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
  400. tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
  401. tx2b.rehash()
  402. tx2b_hex = txToHex(tx2b)
  403. # Verify tx2b cannot replace tx2a.
  404. assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True)
  405. # Now prioritise tx2b to have a higher modified fee
  406. self.nodes[0].prioritisetransaction(tx2b.hash, int(0.1*COIN))
  407. # tx2b should now be accepted
  408. tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
  409. assert(tx2b_txid in self.nodes[0].getrawmempool())
  410. if __name__ == '__main__':
  411. ReplaceByFeeTest().main()