Skip to content

Commit 100e8a7

Browse files
committed
rpc: check and throw specific pubkey parsing errors in HexToPubKey
In the helper `HexToPubKey`, check for three different causes of legacy public key parsing errors (in this order): - pubkey is not a hex string - pubkey doesn't have a valid length (33 or 65 bytes) [NEW] - pubkey is cryptographically invalid, i.e. not on curve (`IsFullyValid` check) and throw a specific error message for each one. Note that the error code is identical for all of them (-5), so this doesn't break RPC API compatibility. The helper is currently used for the RPCs `createmultisig` and `addmultisigaddress`. The length checks can be removed from the call-sites and error message checks in the functional tests are adapted.
1 parent b2b2b1e commit 100e8a7

File tree

3 files changed

+8
-9
lines changed

3 files changed

+8
-9
lines changed

src/rpc/output_script.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,7 @@ static RPCHelpMan createmultisig()
124124
const UniValue& keys = request.params[1].get_array();
125125
std::vector<CPubKey> pubkeys;
126126
for (unsigned int i = 0; i < keys.size(); ++i) {
127-
if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
128-
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
129-
} else {
130-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str()));
131-
}
127+
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
132128
}
133129

134130
// Get the output type

src/rpc/util.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,14 @@ std::string HelpExampleRpcNamed(const std::string& methodname, const RPCArgList&
180180
CPubKey HexToPubKey(const std::string& hex_in)
181181
{
182182
if (!IsHex(hex_in)) {
183-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
183+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be a hex string");
184+
}
185+
if (hex_in.length() != 66 && hex_in.length() != 130) {
186+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must have a length of either 33 or 65 bytes");
184187
}
185188
CPubKey vchPubKey(ParseHex(hex_in));
186189
if (!vchPubKey.IsFullyValid()) {
187-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
190+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be cryptographically valid.");
188191
}
189192
return vchPubKey;
190193
}

test/functional/rpc_rawtransaction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,11 @@ def raw_multisig_transaction_legacy_tests(self):
491491
addr2Obj = self.nodes[2].getaddressinfo(addr2)
492492

493493
# Tests for createmultisig and addmultisigaddress
494-
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
494+
assert_raises_rpc_error(-5, 'Pubkey "01020304" must have a length of either 33 or 65 bytes', self.nodes[0].createmultisig, 1, ["01020304"])
495495
# createmultisig can only take public keys
496496
self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
497497
# addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here
498-
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1])
498+
assert_raises_rpc_error(-5, f'Pubkey "{addr1}" must be a hex string', self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1])
499499

500500
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
501501

0 commit comments

Comments
 (0)