Skip to content

Commit 3a2d5bf

Browse files
committed
Merge #21201: rpc: Disallow sendtoaddress and sendmany when private keys disabled
6bfbc97 test: disallow sendtoaddress/sendmany when private keys disabled (Jon Atack) 0997019 Disallow sendtoaddress and sendmany when private keys disabled (Andrew Chow) Pull request description: Since `sendtoaddress` and `sendmany` (which use the `SendMoney` function) create and commit a transaction, they should not do anything when the wallet does not have private keys. Otherwise a valid transaction cannot be made. Fixes #21104 ACKs for top commit: jonatack: ACK 6bfbc97 meshcollider: utACK 6bfbc97 kristapsk: ACK 6bfbc97. "Error: Private keys are disabled for this wallet" is definitely a better error message than "Insufficient funds" here. Hopefully change of error code from -6 to -4 doesn't break any software using Bitcoin JSON-RPC API. Tree-SHA512: f277d6b5252e43942d568614032596f2c0827f00cd0cb71e44ffcb9822bfb15a71730a3e3688f31e59ba4eb7d275250c4e65ad4b6b3e96be6314c56a672432fb
2 parents b805dbb + 6bfbc97 commit 3a2d5bf

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,12 @@ UniValue SendMoney(CWallet* const pwallet, const CCoinControl &coin_control, std
400400
{
401401
EnsureWalletIsUnlocked(pwallet);
402402

403+
// This function is only used by sendtoaddress and sendmany.
404+
// This should always try to sign, if we don't have private keys, don't try to do anything here.
405+
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
406+
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
407+
}
408+
403409
// Shuffle recipient list
404410
std::shuffle(recipients.begin(), recipients.end(), FastRandomContext());
405411

@@ -409,7 +415,7 @@ UniValue SendMoney(CWallet* const pwallet, const CCoinControl &coin_control, std
409415
bilingual_str error;
410416
CTransactionRef tx;
411417
FeeCalculation fee_calc_out;
412-
bool fCreated = pwallet->CreateTransaction(recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, fee_calc_out, !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
418+
const bool fCreated = pwallet->CreateTransaction(recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, fee_calc_out, true);
413419
if (!fCreated) {
414420
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original);
415421
}

test/functional/wallet_watchonly.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Copyright (c) 2018-2019 The Bitcoin Core developers
33
# Distributed under the MIT software license, see the accompanying
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5-
"""Test createwallet arguments.
5+
"""Test createwallet watchonly arguments.
66
"""
77

88
from test_framework.test_framework import BitcoinTestFramework
@@ -49,6 +49,11 @@ def run_test(self):
4949
assert_equal(len(wo_wallet.listtransactions()), 1)
5050
assert_equal(wo_wallet.getbalance(include_watchonly=False), 0)
5151

52+
self.log.info('Test sending from a watch-only wallet raises RPC error')
53+
msg = "Error: Private keys are disabled for this wallet"
54+
assert_raises_rpc_error(-4, msg, wo_wallet.sendtoaddress, a1, 0.1)
55+
assert_raises_rpc_error(-4, msg, wo_wallet.sendmany, amounts={a1: 0.1})
56+
5257
self.log.info('Testing listreceivedbyaddress watch-only defaults')
5358
result = wo_wallet.listreceivedbyaddress()
5459
assert_equal(len(result), 1)

0 commit comments

Comments
 (0)