23
23
from test_framework .wallet import MiniWallet
24
24
25
25
MAX_REPLACEMENT_LIMIT = 100
26
-
27
-
28
- def make_utxo (node , amount , confirmed = True , scriptPubKey = DUMMY_P2WPKH_SCRIPT ):
29
- """Create a txout with a given amount and scriptPubKey
30
-
31
- Mines coins as needed.
32
-
33
- confirmed - txouts created will be confirmed in the blockchain;
34
- unconfirmed otherwise.
35
- """
36
- fee = 1 * COIN
37
- while node .getbalance () < satoshi_round ((amount + fee ) / COIN ):
38
- node .generate (COINBASE_MATURITY )
39
-
40
- new_addr = node .getnewaddress ()
41
- txid = node .sendtoaddress (new_addr , satoshi_round ((amount + fee ) / COIN ))
42
- tx1 = node .getrawtransaction (txid , 1 )
43
- txid = int (txid , 16 )
44
- i , _ = next (filter (lambda vout : new_addr == vout [1 ]['scriptPubKey' ]['address' ], enumerate (tx1 ['vout' ])))
45
-
46
- tx2 = CTransaction ()
47
- tx2 .vin = [CTxIn (COutPoint (txid , i ))]
48
- tx2 .vout = [CTxOut (amount , scriptPubKey )]
49
- tx2 .rehash ()
50
-
51
- signed_tx = node .signrawtransactionwithwallet (tx2 .serialize ().hex ())
52
-
53
- txid = node .sendrawtransaction (signed_tx ['hex' ], 0 )
54
-
55
- # If requested, ensure txouts are confirmed.
56
- if confirmed :
57
- mempool_size = len (node .getrawmempool ())
58
- while mempool_size > 0 :
59
- node .generate (1 )
60
- new_size = len (node .getrawmempool ())
61
- # Error out if we have something stuck in the mempool, as this
62
- # would likely be a bug.
63
- assert new_size < mempool_size
64
- mempool_size = new_size
65
-
66
- return COutPoint (int (txid , 16 ), 0 )
67
-
68
-
69
26
class ReplaceByFeeTest (BitcoinTestFramework ):
70
27
def set_test_params (self ):
71
28
self .num_nodes = 1
@@ -129,6 +86,46 @@ def run_test(self):
129
86
130
87
self .log .info ("Passed" )
131
88
89
+ def make_utxo (self , node , amount , confirmed = True , scriptPubKey = DUMMY_P2WPKH_SCRIPT ):
90
+ """Create a txout with a given amount and scriptPubKey
91
+
92
+ Mines coins as needed.
93
+
94
+ confirmed - txouts created will be confirmed in the blockchain;
95
+ unconfirmed otherwise.
96
+ """
97
+ fee = 1 * COIN
98
+ while node .getbalance () < satoshi_round ((amount + fee ) / COIN ):
99
+ self .generate (node , COINBASE_MATURITY )
100
+
101
+ new_addr = node .getnewaddress ()
102
+ txid = node .sendtoaddress (new_addr , satoshi_round ((amount + fee ) / COIN ))
103
+ tx1 = node .getrawtransaction (txid , 1 )
104
+ txid = int (txid , 16 )
105
+ i , _ = next (filter (lambda vout : new_addr == vout [1 ]['scriptPubKey' ]['address' ], enumerate (tx1 ['vout' ])))
106
+
107
+ tx2 = CTransaction ()
108
+ tx2 .vin = [CTxIn (COutPoint (txid , i ))]
109
+ tx2 .vout = [CTxOut (amount , scriptPubKey )]
110
+ tx2 .rehash ()
111
+
112
+ signed_tx = node .signrawtransactionwithwallet (tx2 .serialize ().hex ())
113
+
114
+ txid = node .sendrawtransaction (signed_tx ['hex' ], 0 )
115
+
116
+ # If requested, ensure txouts are confirmed.
117
+ if confirmed :
118
+ mempool_size = len (node .getrawmempool ())
119
+ while mempool_size > 0 :
120
+ self .generate (node , 1 )
121
+ new_size = len (node .getrawmempool ())
122
+ # Error out if we have something stuck in the mempool, as this
123
+ # would likely be a bug.
124
+ assert new_size < mempool_size
125
+ mempool_size = new_size
126
+
127
+ return COutPoint (int (txid , 16 ), 0 )
128
+
132
129
def test_simple_doublespend (self ):
133
130
"""Simple doublespend"""
134
131
# we use MiniWallet to create a transaction template with inputs correctly set,
@@ -165,7 +162,7 @@ def test_doublespend_chain(self):
165
162
"""Doublespend of a long chain"""
166
163
167
164
initial_nValue = 50 * COIN
168
- tx0_outpoint = make_utxo (self .nodes [0 ], initial_nValue )
165
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], initial_nValue )
169
166
170
167
prevout = tx0_outpoint
171
168
remaining_value = initial_nValue
@@ -205,7 +202,7 @@ def test_doublespend_tree(self):
205
202
"""Doublespend of a big tree of transactions"""
206
203
207
204
initial_nValue = 50 * COIN
208
- tx0_outpoint = make_utxo (self .nodes [0 ], initial_nValue )
205
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], initial_nValue )
209
206
210
207
def branch (prevout , initial_value , max_txs , tree_width = 5 , fee = 0.0001 * COIN , _total_txs = None ):
211
208
if _total_txs is None :
@@ -268,7 +265,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001 * COIN, _to
268
265
# double-spent at once" anti-DoS limit.
269
266
for n in (MAX_REPLACEMENT_LIMIT + 1 , MAX_REPLACEMENT_LIMIT * 2 ):
270
267
fee = int (0.0001 * COIN )
271
- tx0_outpoint = make_utxo (self .nodes [0 ], initial_nValue )
268
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], initial_nValue )
272
269
tree_txs = list (branch (tx0_outpoint , initial_nValue , n , fee = fee ))
273
270
assert_equal (len (tree_txs ), n )
274
271
@@ -285,7 +282,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001 * COIN, _to
285
282
286
283
def test_replacement_feeperkb (self ):
287
284
"""Replacement requires fee-per-KB to be higher"""
288
- tx0_outpoint = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
285
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
289
286
290
287
tx1a = CTransaction ()
291
288
tx1a .vin = [CTxIn (tx0_outpoint , nSequence = 0 )]
@@ -305,8 +302,8 @@ def test_replacement_feeperkb(self):
305
302
306
303
def test_spends_of_conflicting_outputs (self ):
307
304
"""Replacements that spend conflicting tx outputs are rejected"""
308
- utxo1 = make_utxo (self .nodes [0 ], int (1.2 * COIN ))
309
- utxo2 = make_utxo (self .nodes [0 ], 3 * COIN )
305
+ utxo1 = self . make_utxo (self .nodes [0 ], int (1.2 * COIN ))
306
+ utxo2 = self . make_utxo (self .nodes [0 ], 3 * COIN )
310
307
311
308
tx1a = CTransaction ()
312
309
tx1a .vin = [CTxIn (utxo1 , nSequence = 0 )]
@@ -345,8 +342,8 @@ def test_spends_of_conflicting_outputs(self):
345
342
346
343
def test_new_unconfirmed_inputs (self ):
347
344
"""Replacements that add new unconfirmed inputs are rejected"""
348
- confirmed_utxo = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
349
- unconfirmed_utxo = make_utxo (self .nodes [0 ], int (0.1 * COIN ), False )
345
+ confirmed_utxo = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
346
+ unconfirmed_utxo = self . make_utxo (self .nodes [0 ], int (0.1 * COIN ), False )
350
347
351
348
tx1 = CTransaction ()
352
349
tx1 .vin = [CTxIn (confirmed_utxo )]
@@ -369,7 +366,7 @@ def test_too_many_replacements(self):
369
366
370
367
# Start by creating a single transaction with many outputs
371
368
initial_nValue = 10 * COIN
372
- utxo = make_utxo (self .nodes [0 ], initial_nValue )
369
+ utxo = self . make_utxo (self .nodes [0 ], initial_nValue )
373
370
fee = int (0.0001 * COIN )
374
371
split_value = int ((initial_nValue - fee ) / (MAX_REPLACEMENT_LIMIT + 1 ))
375
372
@@ -417,7 +414,7 @@ def test_too_many_replacements(self):
417
414
418
415
def test_opt_in (self ):
419
416
"""Replacing should only work if orig tx opted in"""
420
- tx0_outpoint = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
417
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
421
418
422
419
# Create a non-opting in transaction
423
420
tx1a = CTransaction ()
@@ -438,7 +435,7 @@ def test_opt_in(self):
438
435
# This will raise an exception
439
436
assert_raises_rpc_error (- 26 , "txn-mempool-conflict" , self .nodes [0 ].sendrawtransaction , tx1b_hex , 0 )
440
437
441
- tx1_outpoint = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
438
+ tx1_outpoint = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
442
439
443
440
# Create a different non-opting in transaction
444
441
tx2a = CTransaction ()
@@ -494,7 +491,7 @@ def test_prioritised_transactions(self):
494
491
# correctly used by replacement logic
495
492
496
493
# 1. Check that feeperkb uses modified fees
497
- tx0_outpoint = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
494
+ tx0_outpoint = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
498
495
499
496
tx1a = CTransaction ()
500
497
tx1a .vin = [CTxIn (tx0_outpoint , nSequence = 0 )]
@@ -520,7 +517,7 @@ def test_prioritised_transactions(self):
520
517
assert tx1b_txid in self .nodes [0 ].getrawmempool ()
521
518
522
519
# 2. Check that absolute fee checks use modified fee.
523
- tx1_outpoint = make_utxo (self .nodes [0 ], int (1.1 * COIN ))
520
+ tx1_outpoint = self . make_utxo (self .nodes [0 ], int (1.1 * COIN ))
524
521
525
522
tx2a = CTransaction ()
526
523
tx2a .vin = [CTxIn (tx1_outpoint , nSequence = 0 )]
0 commit comments