Skip to content

Commit 603c005

Browse files
committed
wallet: add rpc send explicit fee rate coverage
1 parent dd341e6 commit 603c005

File tree

1 file changed

+58
-12
lines changed

1 file changed

+58
-12
lines changed

test/functional/wallet_send.py

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def test_send(self, from_wallet, to_wallet=None, amount=None, data=None,
9797
except AssertionError:
9898
# Provide debug info if the test fails
9999
self.log.error("Unexpected successful result:")
100+
self.log.error(arg_conf_target)
101+
self.log.error(arg_estimate_mode)
100102
self.log.error(options)
101103
res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options)
102104
self.log.error(res)
@@ -224,8 +226,10 @@ def run_test(self):
224226
assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"],
225227
self.nodes[1].decodepsbt(res2["psbt"])["fee"])
226228
# but not at the same time
227-
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical",
228-
conf_target=1, estimate_mode="economical", add_to_wallet=False, expect_error=(-8,"Use either conf_target and estimate_mode or the options dictionary to control fee rate"))
229+
for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]:
230+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical",
231+
conf_target=1, estimate_mode=mode, add_to_wallet=False,
232+
expect_error=(-8, "Use either conf_target and estimate_mode or the options dictionary to control fee rate"))
229233

230234
self.log.info("Create PSBT from watch-only wallet w3, sign with w2...")
231235
res = self.test_send(from_wallet=w3, to_wallet=w1, amount=1)
@@ -246,19 +250,61 @@ def run_test(self):
246250
res = w2.walletprocesspsbt(res["psbt"])
247251
assert res["complete"]
248252

249-
self.log.info("Set fee rate...")
253+
self.log.info("Test setting explicit fee rate")
254+
res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical", add_to_wallet=False)
255+
res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=1, estimate_mode="economical", add_to_wallet=False)
256+
assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"], self.nodes[1].decodepsbt(res2["psbt"])["fee"])
257+
258+
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.00007, estimate_mode="btc/kb", add_to_wallet=False)
259+
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
260+
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007"))
261+
250262
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=2, estimate_mode="sat/b", add_to_wallet=False)
251263
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
252264
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002"))
253-
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=-1, estimate_mode="sat/b",
254-
expect_error=(-3, "Amount out of range"))
255-
# Fee rate of 0.1 satoshi per byte should throw an error
256-
# TODO: error should use sat/b
257-
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b",
258-
expect_error=(-4, "Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
259-
260-
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.000001, estimate_mode="BTC/KB",
261-
expect_error=(-4, "Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
265+
266+
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.00004531, arg_estimate_mode="btc/kb", add_to_wallet=False)
267+
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
268+
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531"))
269+
270+
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=3, arg_estimate_mode="sat/b", add_to_wallet=False)
271+
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
272+
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003"))
273+
274+
# TODO: This test should pass with all modes, e.g. with the next line uncommented, for consistency with the other explicit feerate RPCs.
275+
# for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]:
276+
for mode in ["btc/kb", "sat/b"]:
277+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=-1, estimate_mode=mode,
278+
expect_error=(-3, "Amount out of range"))
279+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0, estimate_mode=mode,
280+
expect_error=(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
281+
282+
for mode in ["foo", Decimal("3.141592")]:
283+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode,
284+
expect_error=(-8, "Invalid estimate_mode parameter"))
285+
# TODO: these 2 equivalent sends with an invalid estimate_mode arg should both fail, but they do not...why?
286+
# self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode,
287+
# expect_error=(-8, "Invalid estimate_mode parameter"))
288+
# assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", lambda: w0.send({w1.getnewaddress(): 1}, 0.1, mode))
289+
290+
# TODO: These tests should pass for consistency with the other explicit feerate RPCs, but they do not.
291+
# for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]:
292+
# self.log.debug("{}".format(mode))
293+
# for k, v in {"string": "", "object": {"foo": "bar"}}.items():
294+
# self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode,
295+
# expect_error=(-3, "Expected type number for conf_target, got {}".format(k)))
296+
297+
# TODO: error should use sat/B instead of BTC/kB if sat/B is selected.
298+
# Test setting explicit fee rate just below the minimum.
299+
for unit, fee_rate in {"sat/B": 0.99999999, "BTC/kB": 0.00000999}.items():
300+
self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if conf_target {} and estimate_mode {} are passed".format(fee_rate, unit))
301+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=fee_rate, estimate_mode=unit,
302+
expect_error=(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
303+
304+
self.log.info("Explicit fee rate raises RPC error if estimate_mode is passed without a conf_target")
305+
for unit, fee_rate in {"sat/B": 100, "BTC/kB": 0.001}.items():
306+
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, estimate_mode=unit,
307+
expect_error=(-8, "Selected estimate_mode {} requires a fee rate to be specified in conf_target".format(unit)))
262308

263309
# TODO: Return hex if fee rate is below -maxmempool
264310
# res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False)

0 commit comments

Comments
 (0)