Merge bitcoin/bitcoin#26344: wallet: Fix sendall with watchonly wallets and specified inputs

315fd4dbab test: Test for out of bounds vout in sendall (Andrew Chow)
b132c85650 wallet: Check utxo prevout index out of bounds in sendall (Andrew Chow)
708b72b715 test: Test that sendall works with watchonly spending specific utxos (Andrew Chow)
6bcd7e2a3b wallet: Correctly check ismine for sendall (Andrew Chow)

Pull request description:

  The `sendall` RPC would previously fail when used with a watchonly wallet and specified inputs. This failure was caused by checking isminetype equality with ISMINE_ALL rather than a bitwise AND as IsMine can never return ISMINE_ALL.

  Also added a test.

ACKs for top commit:
  w0xlt:
    ACK 315fd4dbab
  furszy:
    ACK 315fd4db

Tree-SHA512: fb55cf6524e789964770b803f401027319f0351433ea084ffa7c5e6f1797567a608c956b7f7c5bd542aa172c4b7b38b07d0976f5ec587569efead27266e8664c
This commit is contained in:
fanquake
2022-10-21 16:21:34 +08:00
2 changed files with 36 additions and 1 deletions

View File

@@ -221,6 +221,11 @@ class SendallTest(BitcoinTestFramework):
self.add_utxos([16, 5])
spent_utxo = self.wallet.listunspent()[0]
# fails on out of bounds vout
assert_raises_rpc_error(-8,
"Input not found. UTXO ({}:{}) is not part of wallet.".format(spent_utxo["txid"], 1000),
self.wallet.sendall, recipients=[self.remainder_target], options={"inputs": [{"txid": spent_utxo["txid"], "vout": 1000}]})
# fails on unconfirmed spent UTXO
self.wallet.sendall(recipients=[self.remainder_target])
assert_raises_rpc_error(-8,
@@ -276,6 +281,33 @@ class SendallTest(BitcoinTestFramework):
recipients=[self.remainder_target],
fee_rate=100000)
@cleanup
def sendall_watchonly_specific_inputs(self):
self.log.info("Test sendall with a subset of UTXO pool in a watchonly wallet")
self.add_utxos([17, 4])
utxo = self.wallet.listunspent()[0]
self.nodes[0].createwallet(wallet_name="watching", disable_private_keys=True)
watchonly = self.nodes[0].get_wallet_rpc("watching")
import_req = [{
"desc": utxo["desc"],
"timestamp": 0,
}]
if self.options.descriptors:
watchonly.importdescriptors(import_req)
else:
watchonly.importmulti(import_req)
sendall_tx_receipt = watchonly.sendall(recipients=[self.remainder_target], options={"inputs": [utxo]})
psbt = sendall_tx_receipt["psbt"]
decoded = self.nodes[0].decodepsbt(psbt)
assert_equal(len(decoded["inputs"]), 1)
assert_equal(len(decoded["outputs"]), 1)
assert_equal(decoded["tx"]["vin"][0]["txid"], utxo["txid"])
assert_equal(decoded["tx"]["vin"][0]["vout"], utxo["vout"])
assert_equal(decoded["tx"]["vout"][0]["scriptPubKey"]["address"], self.remainder_target)
# This tests needs to be the last one otherwise @cleanup will fail with "Transaction too large" error
def sendall_fails_with_transaction_too_large(self):
self.log.info("Test that sendall fails if resulting transaction is too large")
@@ -341,6 +373,9 @@ class SendallTest(BitcoinTestFramework):
# Sendall fails when providing a fee that is too high
self.sendall_fails_on_high_fee()
# Sendall succeeds with watchonly wallets spending specific UTXOs
self.sendall_watchonly_specific_inputs()
# Sendall fails when many inputs result to too large transaction
self.sendall_fails_with_transaction_too_large()