Skip to content

Commit c740b15

Browse files
committed
rpc: use HexToPubKey helper for all legacy pubkey-parsing RPCs
This deduplicates code and leads to more consistent and detailed error messages. Affected are legacy import RPCs (`importpubkey`, `importmulti`) and other ones where solving data can be provided (`fundrawtransaction`, `walletcreatefundedpsbt`, `send`, `sendall`).
1 parent 100e8a7 commit c740b15

File tree

4 files changed

+9
-29
lines changed

4 files changed

+9
-29
lines changed

src/wallet/rpc/backup.cpp

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,7 @@ RPCHelpMan importpubkey()
460460
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
461461
}
462462

463-
if (!IsHex(request.params[0].get_str()))
464-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
465-
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
466-
CPubKey pubKey(data);
467-
if (!pubKey.IsFullyValid())
468-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
463+
CPubKey pubKey = HexToPubKey(request.params[0].get_str());
469464

470465
{
471466
LOCK(pwallet->cs_wallet);
@@ -986,15 +981,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP
986981
import_data.witnessscript = std::make_unique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
987982
}
988983
for (size_t i = 0; i < pubKeys.size(); ++i) {
989-
const auto& str = pubKeys[i].get_str();
990-
if (!IsHex(str)) {
991-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string");
992-
}
993-
auto parsed_pubkey = ParseHex(str);
994-
CPubKey pubkey(parsed_pubkey);
995-
if (!pubkey.IsFullyValid()) {
996-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key");
997-
}
984+
CPubKey pubkey = HexToPubKey(pubKeys[i].get_str());
998985
pubkey_map.emplace(pubkey.GetID(), pubkey);
999986
ordered_pubkeys.push_back(pubkey.GetID());
1000987
}

src/wallet/rpc/spend.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -627,15 +627,7 @@ CreatedTransactionResult FundTransaction(CWallet& wallet, const CMutableTransact
627627
const UniValue solving_data = options["solving_data"].get_obj();
628628
if (solving_data.exists("pubkeys")) {
629629
for (const UniValue& pk_univ : solving_data["pubkeys"].get_array().getValues()) {
630-
const std::string& pk_str = pk_univ.get_str();
631-
if (!IsHex(pk_str)) {
632-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not hex", pk_str));
633-
}
634-
const std::vector<unsigned char> data(ParseHex(pk_str));
635-
const CPubKey pubkey(data.begin(), data.end());
636-
if (!pubkey.IsFullyValid()) {
637-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not a valid public key", pk_str));
638-
}
630+
const CPubKey pubkey = HexToPubKey(pk_univ.get_str());
639631
coinControl.m_external_provider.pubkeys.emplace(pubkey.GetID(), pubkey);
640632
// Add witness script for pubkeys
641633
const CScript wit_script = GetScriptForDestination(WitnessV0KeyHash(pubkey));

test/functional/wallet_basic.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,11 @@ def run_test(self):
459459
assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid")
460460

461461
# This will raise an exception for attempting to import a pubkey that isn't in hex
462-
assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")
462+
assert_raises_rpc_error(-5, 'Pubkey "not hex" must be a hex string', self.nodes[0].importpubkey, "not hex")
463463

464-
# This will raise an exception for importing an invalid pubkey
465-
assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")
464+
# This will raise an exception for importing a pubkey with invalid length
465+
too_short_pubkey = "5361746f736869204e616b616d6f746f"
466+
assert_raises_rpc_error(-5, f'Pubkey "{too_short_pubkey}" must have a length of either 33 or 65 bytes', self.nodes[0].importpubkey, too_short_pubkey)
466467

467468
# Bech32m addresses cannot be imported into a legacy wallet
468469
assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6")

test/functional/wallet_fundrawtransaction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,8 +1055,8 @@ def test_external_inputs(self):
10551055
assert_raises_rpc_error(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]), wallet.fundrawtransaction, raw_tx)
10561056

10571057
# Error conditions
1058-
assert_raises_rpc_error(-5, "'not a pubkey' is not hex", wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["not a pubkey"]})
1059-
assert_raises_rpc_error(-5, "'01234567890a0b0c0d0e0f' is not a valid public key", wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["01234567890a0b0c0d0e0f"]})
1058+
assert_raises_rpc_error(-5, 'Pubkey "not a pubkey" must be a hex string', wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["not a pubkey"]})
1059+
assert_raises_rpc_error(-5, 'Pubkey "01234567890a0b0c0d0e0f" must have a length of either 33 or 65 bytes', wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["01234567890a0b0c0d0e0f"]})
10601060
assert_raises_rpc_error(-5, "'not a script' is not hex", wallet.fundrawtransaction, raw_tx, solving_data={"scripts":["not a script"]})
10611061
assert_raises_rpc_error(-8, "Unable to parse descriptor 'not a descriptor'", wallet.fundrawtransaction, raw_tx, solving_data={"descriptors":["not a descriptor"]})
10621062
assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", wallet.fundrawtransaction, raw_tx, input_weights=[{"txid": ext_utxo["txid"]}])

0 commit comments

Comments
 (0)