Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/misc.cpp
Show All 9 Lines | |||||
#include "config.h" | #include "config.h" | ||||
#include "dstencode.h" | #include "dstencode.h" | ||||
#include "init.h" | #include "init.h" | ||||
#include "net.h" | #include "net.h" | ||||
#include "netbase.h" | #include "netbase.h" | ||||
#include "rpc/blockchain.h" | #include "rpc/blockchain.h" | ||||
#include "rpc/server.h" | #include "rpc/server.h" | ||||
#include "timedata.h" | #include "timedata.h" | ||||
#include "util.h" | #include "util.h" | ||||
Fabien: Can you use `rpc/util.h` here to avoid confusion ? | |||||
#include "utilstrencodings.h" | #include "utilstrencodings.h" | ||||
#include "validation.h" | #include "validation.h" | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
#include "wallet/rpcwallet.h" | #include "wallet/rpcwallet.h" | ||||
#include "wallet/wallet.h" | #include "wallet/wallet.h" | ||||
#include "wallet/walletdb.h" | #include "wallet/walletdb.h" | ||||
#endif | #endif | ||||
#include "warnings.h" | #include "warnings.h" | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around | // Needed even with !ENABLE_WALLET, to pass (ignored) pointers around | ||||
class CWallet; | class CWallet; | ||||
/** | UniValue createmultisig(const Config &config, const JSONRPCRequest &request) { | ||||
* Used by addmultisigaddress / createmultisig: | |||||
*/ | |||||
CScript createmultisig_redeemScript(CWallet *const pwallet, | |||||
const UniValue ¶ms) { | |||||
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 (size_t 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: | |||||
if (pwallet) { | |||||
CTxDestination dest = DecodeDestination(ks, pwallet->chainParams); | |||||
if (IsValidDestination(dest)) { | |||||
const CKeyID *keyID = boost::get<CKeyID>(&dest); | |||||
if (!keyID) { | |||||
throw std::runtime_error( | |||||
strprintf("%s does not refer to a key", ks)); | |||||
} | |||||
CPubKey vchPubKey; | |||||
if (!pwallet->GetPubKey(*keyID, 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; | |||||
continue; | |||||
} | |||||
} | |||||
#endif | |||||
// Case 2: hex public key | |||||
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; | |||||
} | |||||
static UniValue createmultisig(const Config &config, | |||||
const JSONRPCRequest &request) { | |||||
#ifdef ENABLE_WALLET | |||||
CWallet *const pwallet = GetWalletForJSONRPCRequest(request); | |||||
#else | |||||
CWallet *const pwallet = nullptr; | |||||
#endif | |||||
if (request.fHelp || request.params.size() < 2 || | if (request.fHelp || request.params.size() < 2 || | ||||
request.params.size() > 2) { | request.params.size() > 2) { | ||||
std::string msg = | std::string msg = | ||||
"createmultisig nrequired [\"key\",...]\n" | "createmultisig nrequired [\"key\",...]\n" | ||||
"\nCreates a multi-signature address with n signature of m keys " | "\nCreates a multi-signature address with n signature of m keys " | ||||
"required.\n" | "required.\n" | ||||
"It returns a json object with the address and redeemScript.\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.20. To use the deprecated " | |||||
"functionality, start bitcoind with -deprecatedrpc=createmultisig\n" | |||||
"\nArguments:\n" | "\nArguments:\n" | ||||
"1. nrequired (numeric, required) The number of required " | "1. nrequired (numeric, required) The number of required " | ||||
"signatures out of the n keys or addresses.\n" | "signatures out of the n keys or addresses.\n" | ||||
"2. \"keys\" (string, required) A json array of keys which " | "2. \"keys\" (string, required) A json array of keys which " | ||||
"are bitcoin addresses or hex-encoded public keys\n" | "are bitcoin addresses or hex-encoded public keys\n" | ||||
FabienUnsubmitted Not Done Inline ActionsThe removal of the addresses mention in the help is missing from the PR Fabien: The removal of the addresses mention in the help is missing from the PR | |||||
" [\n" | " [\n" | ||||
" \"key\" (string) bitcoin address or hex-encoded public " | " \"key\" (string) bitcoin address or hex-encoded public " | ||||
"key\n" | "key\n" | ||||
" ,...\n" | " ,...\n" | ||||
" ]\n" | " ]\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"{\n" | "{\n" | ||||
Show All 12 Lines | if (request.fHelp || request.params.size() < 2 || | ||||
"\nAs a json rpc call\n" + | "\nAs a json rpc call\n" + | ||||
HelpExampleRpc("createmultisig", | HelpExampleRpc("createmultisig", | ||||
"2, " | "2, " | ||||
"\"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\"," | "\"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\"," | ||||
"\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\""); | "\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\""); | ||||
throw std::runtime_error(msg); | 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(gArgs, "createmultisig") && | |||||
EnsureWalletIsAvailable(pwallet, false)) { | |||||
pubkeys.push_back(AddrToPubKey(config.GetChainParams(), pwallet, | |||||
keys[i].get_str())); | |||||
} else | |||||
#endif | |||||
throw JSONRPCError( | |||||
FabienUnsubmitted Not Done Inline ActionsShould braces be added for the else above in this case ? Fabien: Should braces be added for the else above in this case ? | |||||
RPC_INVALID_ADDRESS_OR_KEY, | |||||
strprintf("Invalid public key: %s\nNote that from v0.19.4, " | |||||
"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.20." | |||||
" To use the deprecated functionality, start " | |||||
"bitcoind with -deprecatedrpc=createmultisig", | |||||
keys[i].get_str())); | |||||
} | |||||
} | |||||
// Construct using pay-to-script-hash: | // Construct using pay-to-script-hash: | ||||
CScript inner = createmultisig_redeemScript(pwallet, request.params); | CScript inner = CreateMultisigRedeemscript(required, pubkeys); | ||||
CScriptID innerID(inner); | CScriptID innerID(inner); | ||||
UniValue result(UniValue::VOBJ); | UniValue result(UniValue::VOBJ); | ||||
result.pushKV("address", EncodeDestination(innerID)); | result.pushKV("address", EncodeDestination(innerID)); | ||||
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); | result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); | ||||
return result; | return result; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 279 Lines • Show Last 20 Lines |
Can you use rpc/util.h here to avoid confusion ?