mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-06 18:53:21 +01:00
Merge #11415: [RPC] Disallow using addresses in createmultisig
1df206f Disallow using addresses in createmultisig (Andrew Chow)
Pull request description:
This PR should be the last part of #7965.
This PR makes createmultisig only accept public keys and marks the old functionality of accepting addresses as deprecated.
It also splits `_createmultisig_redeemscript` into two functions, `_createmultisig_getpubkeys` and `_createmultisig_getaddr_pubkeys`. `_createmultisig_getpubkeys` retrieves public keys from the RPC parameters and `_createmultisig_getaddr_pubkeys` retrieves addresses' public keys from the wallet. `_createmultisig_getaddr_pubkeys` requires the wallet and is only used by `addwitnessaddress` (except when `createmultisig` is used in deprecated mode).
`addwitnessaddress`'s API is also changed. Instead of returning just an address, it now returns the same thing as `createmultisig`: a JSON object with two fields, address and redeemscript.
Tree-SHA512: a5796e41935ad5e47d8165ff996a8b20d5112b5fc1a06a6d3c7f5513c13e7628a4fd37ec30fde05d8b15abfed51bc250710140f6834b13f64d0a0e47a3817969
This commit is contained in:
109
src/rpc/misc.cpp
109
src/rpc/misc.cpp
@@ -15,6 +15,7 @@
|
||||
#include <netbase.h>
|
||||
#include <rpc/blockchain.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/util.h>
|
||||
#include <timedata.h>
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
@@ -254,88 +255,21 @@ UniValue validateaddress(const JSONRPCRequest& request)
|
||||
// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
|
||||
class CWallet;
|
||||
|
||||
/**
|
||||
* Used by addmultisigaddress / createmultisig:
|
||||
*/
|
||||
CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
|
||||
{
|
||||
int nRequired = params[0].get_int();
|
||||
const UniValue& keys = params[1].get_array();
|
||||
|
||||
// Gather public keys
|
||||
if (nRequired < 1)
|
||||
throw std::runtime_error("a multisignature address must require at least one key to redeem");
|
||||
if ((int)keys.size() < nRequired)
|
||||
throw std::runtime_error(
|
||||
strprintf("not enough keys supplied "
|
||||
"(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
|
||||
if (keys.size() > 16)
|
||||
throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
|
||||
std::vector<CPubKey> pubkeys;
|
||||
pubkeys.resize(keys.size());
|
||||
for (unsigned int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
const std::string& ks = keys[i].get_str();
|
||||
#ifdef ENABLE_WALLET
|
||||
// Case 1: Bitcoin address and we have full public key:
|
||||
CTxDestination dest = DecodeDestination(ks);
|
||||
if (pwallet && IsValidDestination(dest)) {
|
||||
CKeyID key = GetKeyForDestination(*pwallet, dest);
|
||||
if (key.IsNull()) {
|
||||
throw std::runtime_error(strprintf("%s does not refer to a key", ks));
|
||||
}
|
||||
CPubKey vchPubKey;
|
||||
if (!pwallet->GetPubKey(key, vchPubKey)) {
|
||||
throw std::runtime_error(strprintf("no full public key for address %s", ks));
|
||||
}
|
||||
if (!vchPubKey.IsFullyValid())
|
||||
throw std::runtime_error(" Invalid public key: "+ks);
|
||||
pubkeys[i] = vchPubKey;
|
||||
}
|
||||
|
||||
// Case 2: hex public key
|
||||
else
|
||||
#endif
|
||||
if (IsHex(ks))
|
||||
{
|
||||
CPubKey vchPubKey(ParseHex(ks));
|
||||
if (!vchPubKey.IsFullyValid())
|
||||
throw std::runtime_error(" Invalid public key: "+ks);
|
||||
pubkeys[i] = vchPubKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(" Invalid public key: "+ks);
|
||||
}
|
||||
}
|
||||
CScript result = GetScriptForMultisig(nRequired, pubkeys);
|
||||
|
||||
if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
throw std::runtime_error(
|
||||
strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue createmultisig(const JSONRPCRequest& request)
|
||||
{
|
||||
#ifdef ENABLE_WALLET
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
#else
|
||||
CWallet * const pwallet = nullptr;
|
||||
#endif
|
||||
|
||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
|
||||
{
|
||||
std::string msg = "createmultisig nrequired [\"key\",...]\n"
|
||||
"\nCreates a multi-signature address with n signature of m keys required.\n"
|
||||
"It returns a json object with the address and redeemScript.\n"
|
||||
|
||||
"DEPRECATION WARNING: Using addresses with createmultisig is deprecated. Clients must\n"
|
||||
"transition to using addmultisigaddress to create multisig addresses with addresses known\n"
|
||||
"to the wallet before upgrading to v0.17. To use the deprecated functionality, start bitcoind with -deprecatedrpc=createmultisig\n"
|
||||
"\nArguments:\n"
|
||||
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
||||
"2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
|
||||
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
||||
"2. \"keys\" (string, required) A json array of hex-encoded public keys\n"
|
||||
" [\n"
|
||||
" \"key\" (string) bitcoin address or hex-encoded public key\n"
|
||||
" \"key\" (string) The hex-encoded public key\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
|
||||
@@ -346,16 +280,37 @@ UniValue createmultisig(const JSONRPCRequest& request)
|
||||
"}\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
"\nCreate a multisig address from 2 addresses\n"
|
||||
+ HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
|
||||
"\nCreate a multisig address from 2 public keys\n"
|
||||
+ HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
|
||||
"\nAs a json rpc call\n"
|
||||
+ HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
|
||||
+ HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"")
|
||||
;
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
int required = request.params[0].get_int();
|
||||
|
||||
// Get the public keys
|
||||
const UniValue& keys = request.params[1].get_array();
|
||||
std::vector<CPubKey> pubkeys;
|
||||
for (unsigned int i = 0; i < keys.size(); ++i) {
|
||||
if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
|
||||
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
|
||||
} else {
|
||||
#ifdef ENABLE_WALLET
|
||||
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (IsDeprecatedRPCEnabled("createmultisig") && EnsureWalletIsAvailable(pwallet, false)) {
|
||||
pubkeys.push_back(AddrToPubKey(pwallet, keys[i].get_str()));
|
||||
} else
|
||||
#endif
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\nNote that from v0.16, createmultisig no longer accepts addresses."
|
||||
" Clients must transition to using addmultisigaddress to create multisig addresses with addresses known to the wallet before upgrading to v0.17."
|
||||
" To use the deprecated functionality, start bitcoind with -deprecatedrpc=createmultisig", keys[i].get_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct using pay-to-script-hash:
|
||||
CScript inner = _createmultisig_redeemScript(pwallet, request.params);
|
||||
CScript inner = CreateMultisigRedeemscript(required, pubkeys);
|
||||
CScriptID innerID(inner);
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
|
||||
Reference in New Issue
Block a user