Skip to content

Commit e6b2963

Browse files
committed
[qa] Get rid of nondeterminism in bumpfee.py
Change bumpfee tests to use the spend_one_input function instead of the create_fund_sign_send function. The latter function would choose transaction inputs and fees in unpredictable ways depending on the order that tests ran, which meant that adding new tests could cause old tests to fail, and in general made bumpfee.py fragile and unpleasant to work with.
1 parent 94b528b commit e6b2963

File tree

1 file changed

+32
-47
lines changed

1 file changed

+32
-47
lines changed

test/functional/bumpfee.py

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def run_test(self):
7474

7575

7676
def test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address):
77-
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
77+
rbfid = spend_one_input(rbf_node, dest_address)
7878
rbftx = rbf_node.gettransaction(rbfid)
7979
sync_mempools((rbf_node, peer_node))
8080
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
@@ -127,7 +127,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
127127

128128
def test_nonrbf_bumpfee_fails(peer_node, dest_address):
129129
# cannot replace a non RBF transaction (from node which did not enable RBF)
130-
not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00090000})
130+
not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000"))
131131
assert_raises_jsonrpc(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
132132

133133

@@ -155,7 +155,7 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
155155
def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
156156
# cannot bump fee if the transaction has a descendant
157157
# parent is send-to-self, so we don't have to check which output is change when creating the child tx
158-
parent_id = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00050000})
158+
parent_id = spend_one_input(rbf_node, rbf_node_address)
159159
tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
160160
tx = rbf_node.signrawtransaction(tx)
161161
txid = rbf_node.sendrawtransaction(tx["hex"])
@@ -164,68 +164,58 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
164164

165165
def test_small_output_fails(rbf_node, dest_address):
166166
# cannot bump fee with a too-small output
167-
rbfid = spend_one_input(rbf_node,
168-
Decimal("0.00100000"),
169-
{dest_address: 0.00080000,
170-
rbf_node.getrawchangeaddress(): Decimal("0.00010000")})
171-
rbf_node.bumpfee(rbfid, {"totalFee": 20000})
167+
rbfid = spend_one_input(rbf_node, dest_address)
168+
rbf_node.bumpfee(rbfid, {"totalFee": 50000})
172169

173-
rbfid = spend_one_input(rbf_node,
174-
Decimal("0.00100000"),
175-
{dest_address: 0.00080000,
176-
get_change_address(rbf_node): Decimal("0.00010000")})
177-
get_change_address(rbf_node): Decimal("0.00010000")})
178-
rbf_node.getrawchangeaddress(): Decimal("0.00010000")})
179-
assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001})
170+
rbfid = spend_one_input(rbf_node, dest_address)
171+
assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001})
180172

181173

182174
def test_dust_to_fee(rbf_node, dest_address):
183175
# check that if output is reduced to dust, it will be converted to fee
184-
# the bumped tx sets fee=9900, but it converts to 10,000
185-
rbfid = spend_one_input(rbf_node,
186-
Decimal("0.00100000"),
187-
{dest_address: 0.00080000,
188-
rbf_node.getrawchangeaddress(): Decimal("0.00010000")})
176+
# the bumped tx sets fee=49,900, but it converts to 50,000
177+
rbfid = spend_one_input(rbf_node, dest_address)
189178
fulltx = rbf_node.getrawtransaction(rbfid, 1)
190-
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 19900})
179+
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 49900})
191180
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
192-
assert_equal(bumped_tx["fee"], Decimal("0.00020000"))
181+
assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
193182
assert_equal(len(fulltx["vout"]), 2)
194183
assert_equal(len(full_bumped_tx["vout"]), 1) #change output is eliminated
195184

196185

197186
def test_settxfee(rbf_node, dest_address):
198187
# check that bumpfee reacts correctly to the use of settxfee (paytxfee)
199-
# increase feerate by 2.5x, test that fee increased at least 2x
200-
rbf_node.settxfee(Decimal("0.00001000"))
201-
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
188+
rbfid = spend_one_input(rbf_node, dest_address)
202189
rbftx = rbf_node.gettransaction(rbfid)
203-
rbf_node.settxfee(Decimal("0.00002500"))
190+
requested_feerate = Decimal("0.00025000")
191+
rbf_node.settxfee(requested_feerate)
204192
bumped_tx = rbf_node.bumpfee(rbfid)
205-
assert bumped_tx["fee"] > 2 * abs(rbftx["fee"])
193+
actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["size"]
194+
# Assert that the difference between the requested feerate and the actual
195+
# feerate of the bumped transaction is small.
196+
assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate))
206197
rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee
207198

208199

209200
def test_rebumping(rbf_node, dest_address):
210201
# check that re-bumping the original tx fails, but bumping the bumper succeeds
211-
rbf_node.settxfee(Decimal("0.00001000"))
212-
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
213-
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 1000})
214-
assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000})
215-
rbf_node.bumpfee(bumped["txid"], {"totalFee": 2000})
202+
rbfid = spend_one_input(rbf_node, dest_address)
203+
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 2000})
204+
assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 3000})
205+
rbf_node.bumpfee(bumped["txid"], {"totalFee": 3000})
216206

217207

218208
def test_rebumping_not_replaceable(rbf_node, dest_address):
219209
# check that re-bumping a non-replaceable bump tx fails
220-
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
210+
rbfid = spend_one_input(rbf_node, dest_address)
221211
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
222212
assert_raises_jsonrpc(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
223213
{"totalFee": 20000})
224214

225215

226216
def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
227217
# check that unconfirmed outputs from bumped transactions are not spendable
228-
rbfid = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00090000})
218+
rbfid = spend_one_input(rbf_node, rbf_node_address)
229219
rbftx = rbf_node.gettransaction(rbfid)["hex"]
230220
assert rbfid in rbf_node.getrawmempool()
231221
bumpid = rbf_node.bumpfee(rbfid)["txid"]
@@ -260,31 +250,26 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
260250

261251

262252
def test_bumpfee_metadata(rbf_node, dest_address):
263-
rbfid = rbf_node.sendtoaddress(dest_address, 0.00090000, "comment value", "to value")
253+
rbfid = rbf_node.sendtoaddress(dest_address, Decimal("0.00100000"), "comment value", "to value")
264254
bumped_tx = rbf_node.bumpfee(rbfid)
265255
bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
266256
assert_equal(bumped_wtx["comment"], "comment value")
267257
assert_equal(bumped_wtx["to"], "to value")
268258

269259

270260
def test_locked_wallet_fails(rbf_node, dest_address):
271-
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
261+
rbfid = spend_one_input(rbf_node, dest_address)
272262
rbf_node.walletlock()
273263
assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first.",
274264
rbf_node.bumpfee, rbfid)
275265

276266

277-
def create_fund_sign_send(node, outputs):
278-
rawtx = node.createrawtransaction([], outputs)
279-
fundtx = node.fundrawtransaction(rawtx)
280-
signedtx = node.signrawtransaction(fundtx["hex"])
281-
txid = node.sendrawtransaction(signedtx["hex"])
282-
return txid
283-
284-
285-
def spend_one_input(node, input_amount, outputs):
286-
input = dict(sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == input_amount))
287-
rawtx = node.createrawtransaction([input], outputs)
267+
def spend_one_input(node, dest_address):
268+
input = dict(
269+
sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
270+
rawtx = node.createrawtransaction(
271+
[input], {dest_address: Decimal("0.00050000"),
272+
node.getrawchangeaddress(): Decimal("0.00049000")})
288273
signedtx = node.signrawtransaction(rawtx)
289274
txid = node.sendrawtransaction(signedtx["hex"])
290275
return txid

0 commit comments

Comments
 (0)