@@ -63,16 +63,22 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
6363
6464 # If requested, ensure txouts are confirmed.
6565 if confirmed :
66- while len (node .getrawmempool ()):
66+ mempool_size = len (node .getrawmempool ())
67+ while mempool_size > 0 :
6768 node .generate (1 )
69+ new_size = len (node .getrawmempool ())
70+ # Error out if we have something stuck in the mempool, as this
71+ # would likely be a bug.
72+ assert (new_size < mempool_size )
73+ mempool_size = new_size
6874
6975 return COutPoint (int (txid , 16 ), 0 )
7076
7177class ReplaceByFeeTest (BitcoinTestFramework ):
7278
7379 def setup_network (self ):
7480 self .nodes = []
75- self .nodes .append (start_node (0 , self .options .tmpdir , ["-maxorphantx=1000" ,
81+ self .nodes .append (start_node (0 , self .options .tmpdir , ["-maxorphantx=1000" , "-debug" ,
7682 "-relaypriority=0" , "-whitelist=127.0.0.1" ,
7783 "-limitancestorcount=50" ,
7884 "-limitancestorsize=101" ,
@@ -108,6 +114,9 @@ def run_test(self):
108114 print "Running test opt-in..."
109115 self .test_opt_in ()
110116
117+ print "Running test prioritised transactions..."
118+ self .test_prioritised_transactions ()
119+
111120 print "Passed\n "
112121
113122 def test_simple_doublespend (self ):
@@ -513,5 +522,72 @@ def test_opt_in(self):
513522 # but make sure it is accepted anyway
514523 self .nodes [0 ].sendrawtransaction (tx3c_hex , True )
515524
525+ def test_prioritised_transactions (self ):
526+ # Ensure that fee deltas used via prioritisetransaction are
527+ # correctly used by replacement logic
528+
529+ # 1. Check that feeperkb uses modified fees
530+ tx0_outpoint = make_utxo (self .nodes [0 ], 1.1 * COIN )
531+
532+ tx1a = CTransaction ()
533+ tx1a .vin = [CTxIn (tx0_outpoint , nSequence = 0 )]
534+ tx1a .vout = [CTxOut (1 * COIN , CScript ([b'a' ]))]
535+ tx1a_hex = txToHex (tx1a )
536+ tx1a_txid = self .nodes [0 ].sendrawtransaction (tx1a_hex , True )
537+
538+ # Higher fee, but the actual fee per KB is much lower.
539+ tx1b = CTransaction ()
540+ tx1b .vin = [CTxIn (tx0_outpoint , nSequence = 0 )]
541+ tx1b .vout = [CTxOut (0.001 * COIN , CScript ([b'a' * 740000 ]))]
542+ tx1b_hex = txToHex (tx1b )
543+
544+ # Verify tx1b cannot replace tx1a.
545+ try :
546+ tx1b_txid = self .nodes [0 ].sendrawtransaction (tx1b_hex , True )
547+ except JSONRPCException as exp :
548+ assert_equal (exp .error ['code' ], - 26 )
549+ else :
550+ assert (False )
551+
552+ # Use prioritisetransaction to set tx1a's fee to 0.
553+ self .nodes [0 ].prioritisetransaction (tx1a_txid , 0 , int (- 0.1 * COIN ))
554+
555+ # Now tx1b should be able to replace tx1a
556+ tx1b_txid = self .nodes [0 ].sendrawtransaction (tx1b_hex , True )
557+
558+ assert (tx1b_txid in self .nodes [0 ].getrawmempool ())
559+
560+ # 2. Check that absolute fee checks use modified fee.
561+ tx1_outpoint = make_utxo (self .nodes [0 ], 1.1 * COIN )
562+
563+ tx2a = CTransaction ()
564+ tx2a .vin = [CTxIn (tx1_outpoint , nSequence = 0 )]
565+ tx2a .vout = [CTxOut (1 * COIN , CScript ([b'a' ]))]
566+ tx2a_hex = txToHex (tx2a )
567+ tx2a_txid = self .nodes [0 ].sendrawtransaction (tx2a_hex , True )
568+
569+ # Lower fee, but we'll prioritise it
570+ tx2b = CTransaction ()
571+ tx2b .vin = [CTxIn (tx1_outpoint , nSequence = 0 )]
572+ tx2b .vout = [CTxOut (1.01 * COIN , CScript ([b'a' ]))]
573+ tx2b .rehash ()
574+ tx2b_hex = txToHex (tx2b )
575+
576+ # Verify tx2b cannot replace tx2a.
577+ try :
578+ tx2b_txid = self .nodes [0 ].sendrawtransaction (tx2b_hex , True )
579+ except JSONRPCException as exp :
580+ assert_equal (exp .error ['code' ], - 26 )
581+ else :
582+ assert (False )
583+
584+ # Now prioritise tx2b to have a higher modified fee
585+ self .nodes [0 ].prioritisetransaction (tx2b .hash , 0 , int (0.1 * COIN ))
586+
587+ # tx2b should now be accepted
588+ tx2b_txid = self .nodes [0 ].sendrawtransaction (tx2b_hex , True )
589+
590+ assert (tx2b_txid in self .nodes [0 ].getrawmempool ())
591+
516592if __name__ == '__main__' :
517593 ReplaceByFeeTest ().main ()
0 commit comments