mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-07 19:48:58 +02:00
Merge bitcoin/bitcoin#26344: wallet: Fix sendall with watchonly wallets and specified inputs
315fd4dbabb6b631b755811742a3bdf93e1241bf test: Test for out of bounds vout in sendall (Andrew Chow)
b132c85650afb2182f2e58e903f3d6f86fd3fb22 wallet: Check utxo prevout index out of bounds in sendall (Andrew Chow)
708b72b7151c855cb5dac2fb6a81e8f35153c46f test: Test that sendall works with watchonly spending specific utxos (Andrew Chow)
6bcd7e2a3b52f855db84cd23b5ee70d27be3434f 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:
commit
085f83940d
@ -1379,7 +1379,7 @@ RPCHelpMan sendall()
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
|
||||
}
|
||||
const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
|
||||
if (!tx || pwallet->IsMine(tx->tx->vout[input.prevout.n]) != (coin_control.fAllowWatchOnly ? ISMINE_ALL : ISMINE_SPENDABLE)) {
|
||||
if (!tx || input.prevout.n >= tx->tx->vout.size() || !(pwallet->IsMine(tx->tx->vout[input.prevout.n]) & (coin_control.fAllowWatchOnly ? ISMINE_ALL : ISMINE_SPENDABLE))) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
|
||||
}
|
||||
total_input_value += tx->tx->vout[input.prevout.n].nValue;
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user