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