Merge bitcoin/bitcoin#21359: rpc: include_unsafe option for fundrawtransaction

11d6459b6e rpc: include_unsafe option for fundrawtransaction (t-bast)

Pull request description:

  Allow RPC users to opt-in to unsafe inputs when funding a raw transaction.

  Applications that need to manage a complex RBF flow (such as lightning nodes using anchor outputs) are very limited if they can only use safe inputs.

  I also added this option to `send` and `walletcreatefundedpsbt` who internally delegate to `fundrawtransaction`.

  Fixes #21299

ACKs for top commit:
  laanwj:
    Code review ACK 11d6459b6e

Tree-SHA512: 5e542a4febcfd6f41cf784678ff02ec9282eae2082c274983f72c5ea87b7ebbe1bd5fdc6a020d7a9d5996157754eb4966b8aeb6c1ceebf0b1519f735579b8bac
This commit is contained in:
W. J. van der Laan
2021-05-10 15:55:22 +02:00
8 changed files with 97 additions and 10 deletions

View File

@@ -33,12 +33,15 @@ class WalletSendTest(BitcoinTestFramework):
def test_send(self, from_wallet, to_wallet=None, amount=None, data=None,
arg_conf_target=None, arg_estimate_mode=None, arg_fee_rate=None,
conf_target=None, estimate_mode=None, fee_rate=None, add_to_wallet=None, psbt=None,
inputs=None, add_inputs=None, change_address=None, change_position=None, change_type=None,
inputs=None, add_inputs=None, include_unsafe=None, change_address=None, change_position=None, change_type=None,
include_watching=None, locktime=None, lock_unspents=None, replaceable=None, subtract_fee_from_outputs=None,
expect_error=None):
assert (amount is None) != (data is None)
from_balance_before = from_wallet.getbalance()
from_balance_before = from_wallet.getbalances()["mine"]["trusted"]
if include_unsafe:
from_balance_before += from_wallet.getbalances()["mine"]["untrusted_pending"]
if to_wallet is None:
assert amount is None
else:
@@ -71,6 +74,8 @@ class WalletSendTest(BitcoinTestFramework):
options["inputs"] = inputs
if add_inputs is not None:
options["add_inputs"] = add_inputs
if include_unsafe is not None:
options["include_unsafe"] = include_unsafe
if change_address is not None:
options["change_address"] = change_address
if change_position is not None:
@@ -133,6 +138,10 @@ class WalletSendTest(BitcoinTestFramework):
assert not "txid" in res
assert "psbt" in res
from_balance = from_wallet.getbalances()["mine"]["trusted"]
if include_unsafe:
from_balance += from_wallet.getbalances()["mine"]["untrusted_pending"]
if add_to_wallet and not include_watching:
# Ensure transaction exists in the wallet:
tx = from_wallet.gettransaction(res["txid"])
@@ -143,13 +152,13 @@ class WalletSendTest(BitcoinTestFramework):
assert tx
if amount:
if subtract_fee_from_outputs:
assert_equal(from_balance_before - from_wallet.getbalance(), amount)
assert_equal(from_balance_before - from_balance, amount)
else:
assert_greater_than(from_balance_before - from_wallet.getbalance(), amount)
assert_greater_than(from_balance_before - from_balance, amount)
else:
assert next((out for out in tx["vout"] if out["scriptPubKey"]["asm"] == "OP_RETURN 35"), None)
else:
assert_equal(from_balance_before, from_wallet.getbalance())
assert_equal(from_balance_before, from_balance)
if to_wallet:
self.sync_mempools()
@@ -459,6 +468,14 @@ class WalletSendTest(BitcoinTestFramework):
self.log.info("Subtract fee from output")
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, subtract_fee_from_outputs=[0])
self.log.info("Include unsafe inputs")
self.nodes[1].createwallet(wallet_name="w5")
w5 = self.nodes[1].get_wallet_rpc("w5")
self.test_send(from_wallet=w0, to_wallet=w5, amount=2)
self.test_send(from_wallet=w5, to_wallet=w0, amount=1, expect_error=(-4, "Insufficient funds"))
res = self.test_send(from_wallet=w5, to_wallet=w0, amount=1, include_unsafe=True)
assert res["complete"]
if __name__ == '__main__':
WalletSendTest().main()