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:
commit
69ec021969
15 changed files with 204 additions and 126 deletions
|
@ -133,6 +133,7 @@ BITCOIN_CORE_H = \
|
|||
rpc/safemode.h \
|
||||
rpc/server.h \
|
||||
rpc/register.h \
|
||||
rpc/util.h \
|
||||
scheduler.h \
|
||||
script/sigcache.h \
|
||||
script/sign.h \
|
||||
|
@ -352,6 +353,7 @@ libbitcoin_util_a_SOURCES = \
|
|||
fs.cpp \
|
||||
random.cpp \
|
||||
rpc/protocol.cpp \
|
||||
rpc/util.cpp \
|
||||
support/cleanse.cpp \
|
||||
sync.cpp \
|
||||
threadinterrupt.cpp \
|
||||
|
|
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);
|
||||
|
|
68
src/rpc/util.cpp
Normal file
68
src/rpc/util.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <base58.h>
|
||||
#include <keystore.h>
|
||||
#include <pubkey.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/util.h>
|
||||
#include <tinyformat.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
// Converts a hex string to a public key if possible
|
||||
CPubKey HexToPubKey(const std::string& hex_in)
|
||||
{
|
||||
if (!IsHex(hex_in)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
|
||||
}
|
||||
CPubKey vchPubKey(ParseHex(hex_in));
|
||||
if (!vchPubKey.IsFullyValid()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
|
||||
}
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
// Retrieves a public key for an address from the given CKeyStore
|
||||
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in)
|
||||
{
|
||||
CTxDestination dest = DecodeDestination(addr_in);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in);
|
||||
}
|
||||
CKeyID key = GetKeyForDestination(*keystore, dest);
|
||||
if (key.IsNull()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
|
||||
}
|
||||
CPubKey vchPubKey;
|
||||
if (!keystore->GetPubKey(key, vchPubKey)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
|
||||
}
|
||||
if (!vchPubKey.IsFullyValid()) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key");
|
||||
}
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
// Creates a multisig redeemscript from a given list of public keys and number required.
|
||||
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys)
|
||||
{
|
||||
// Gather public keys
|
||||
if (required < 1) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem");
|
||||
}
|
||||
if ((int)pubkeys.size() < required) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", pubkeys.size(), required));
|
||||
}
|
||||
if (pubkeys.size() > 16) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Number of keys involved in the multisignature address creation > 16\nReduce the number");
|
||||
}
|
||||
|
||||
CScript result = GetScriptForMultisig(required, pubkeys);
|
||||
|
||||
if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
19
src/rpc/util.h
Normal file
19
src/rpc/util.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_RPC_UTIL_H
|
||||
#define BITCOIN_RPC_UTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CKeyStore;
|
||||
class CPubKey;
|
||||
class CScript;
|
||||
|
||||
CPubKey HexToPubKey(const std::string& hex_in);
|
||||
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
|
||||
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
|
||||
|
||||
#endif // BITCOIN_RPC_UTIL_H
|
|
@ -18,6 +18,7 @@
|
|||
#include <rpc/mining.h>
|
||||
#include <rpc/safemode.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/util.h>
|
||||
#include <script/sign.h>
|
||||
#include <timedata.h>
|
||||
#include <util.h>
|
||||
|
@ -1161,9 +1162,6 @@ UniValue sendmany(const JSONRPCRequest& request)
|
|||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
||||
// Defined in rpc/misc.cpp
|
||||
extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params);
|
||||
|
||||
UniValue addmultisigaddress(const JSONRPCRequest& request)
|
||||
{
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
|
@ -1181,16 +1179,22 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
"If 'account' is specified (DEPRECATED), assign address to that account.\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 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 bitcoin addresses or hex-encoded public keys\n"
|
||||
" [\n"
|
||||
" \"address\" (string) bitcoin address or hex-encoded public key\n"
|
||||
" \"address\" (string) bitcoin address or hex-encoded public key\n"
|
||||
" ...,\n"
|
||||
" ]\n"
|
||||
"3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
|
||||
"3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
|
||||
|
||||
"\nResult:\n"
|
||||
"\"address\" (string) A bitcoin address associated with the keys.\n"
|
||||
"{\n"
|
||||
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
|
||||
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
|
||||
"}\n"
|
||||
"\nResult (DEPRECATED. To see this result in v0.16 instead, please start bitcoind with -deprecatedrpc=addmultisigaddress).\n"
|
||||
" clients should transition to the new output api before upgrading to v0.17.\n"
|
||||
"\"address\" (string) A bitcoin address associated with the keys.\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
"\nAdd a multisig address from 2 addresses\n"
|
||||
|
@ -1207,14 +1211,34 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
if (!request.params[2].isNull())
|
||||
strAccount = AccountFromValue(request.params[2]);
|
||||
|
||||
int required = request.params[0].get_int();
|
||||
|
||||
// Get the public keys
|
||||
const UniValue& keys_or_addrs = request.params[1].get_array();
|
||||
std::vector<CPubKey> pubkeys;
|
||||
for (unsigned int i = 0; i < keys_or_addrs.size(); ++i) {
|
||||
if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) {
|
||||
pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
|
||||
} else {
|
||||
pubkeys.push_back(AddrToPubKey(pwallet, keys_or_addrs[i].get_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct using pay-to-script-hash:
|
||||
CScript inner = _createmultisig_redeemScript(pwallet, request.params);
|
||||
CScript inner = CreateMultisigRedeemscript(required, pubkeys);
|
||||
pwallet->AddCScript(inner);
|
||||
|
||||
CTxDestination dest = pwallet->AddAndGetDestinationForScript(inner, g_address_type);
|
||||
|
||||
pwallet->SetAddressBook(dest, strAccount, "send");
|
||||
return EncodeDestination(dest);
|
||||
|
||||
// Return old style interface
|
||||
if (IsDeprecatedRPCEnabled("addmultisigaddress")) {
|
||||
return EncodeDestination(dest);
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("address", EncodeDestination(dest));
|
||||
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
class Witnessifier : public boost::static_visitor<bool>
|
||||
|
|
|
@ -117,14 +117,14 @@ class AddressTypeTest(BitcoinTestFramework):
|
|||
|
||||
# addmultisigaddress with at least 1 uncompressed key should return a legacy address.
|
||||
for node in range(4):
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2]), True, 'legacy')
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2]), True, 'legacy')
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2]), True, 'legacy')
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
|
||||
self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
|
||||
# addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours).
|
||||
self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'legacy')
|
||||
self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit')
|
||||
self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit')
|
||||
self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'bech32')
|
||||
self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy')
|
||||
self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
|
||||
self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
|
||||
self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32')
|
||||
|
||||
for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)):
|
||||
address_type = None
|
||||
|
@ -155,7 +155,7 @@ class AddressTypeTest(BitcoinTestFramework):
|
|||
else:
|
||||
addr1 = self.nodes[to_node].getnewaddress()
|
||||
addr2 = self.nodes[to_node].getnewaddress()
|
||||
address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])
|
||||
address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address']
|
||||
|
||||
# Do some sanity checking on the created address
|
||||
if address_type is not None:
|
||||
|
|
|
@ -10,7 +10,7 @@ class DeprecatedRpcTest(BitcoinTestFramework):
|
|||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
self.extra_args = [[], ["-deprecatedrpc=estimatefee"]]
|
||||
self.extra_args = [[], ["-deprecatedrpc=estimatefee", "-deprecatedrpc=createmultisig"]]
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("estimatefee: Shows deprecated message")
|
||||
|
@ -19,5 +19,9 @@ class DeprecatedRpcTest(BitcoinTestFramework):
|
|||
self.log.info("Using -deprecatedrpc=estimatefee bypasses the error")
|
||||
self.nodes[1].estimatefee(1)
|
||||
|
||||
self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses")
|
||||
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()])
|
||||
self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
|
||||
|
||||
if __name__ == '__main__':
|
||||
DeprecatedRpcTest().main()
|
||||
|
|
|
@ -358,7 +358,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr1Obj = self.nodes[1].validateaddress(addr1)
|
||||
addr2Obj = self.nodes[1].validateaddress(addr2)
|
||||
|
||||
mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
|
||||
mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
|
||||
inputs = []
|
||||
outputs = {mSigObj:1.1}
|
||||
|
@ -391,7 +391,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr4Obj = self.nodes[1].validateaddress(addr4)
|
||||
addr5Obj = self.nodes[1].validateaddress(addr5)
|
||||
|
||||
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])
|
||||
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']
|
||||
|
||||
inputs = []
|
||||
outputs = {mSigObj:1.1}
|
||||
|
@ -418,7 +418,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr1Obj = self.nodes[2].validateaddress(addr1)
|
||||
addr2Obj = self.nodes[2].validateaddress(addr2)
|
||||
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
|
||||
|
||||
# send 1.2 BTC to msig addr
|
||||
|
|
|
@ -228,7 +228,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
|||
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
||||
self.nodes[1].generate(100)
|
||||
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
||||
self.nodes[1].generate(1)
|
||||
|
@ -255,7 +255,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
|||
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
||||
self.nodes[1].generate(100)
|
||||
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
||||
self.nodes[1].generate(1)
|
||||
|
@ -282,7 +282,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
|||
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
||||
self.nodes[1].generate(100)
|
||||
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
||||
self.nodes[1].generate(1)
|
||||
|
@ -309,7 +309,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
|||
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
|
||||
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
||||
self.nodes[1].generate(100)
|
||||
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
||||
self.nodes[1].generate(1)
|
||||
|
|
|
@ -81,7 +81,8 @@ class ListTransactionsTest(BitcoinTestFramework):
|
|||
{"category":"receive","amount":Decimal("0.44")},
|
||||
{"txid":txid, "account" : "toself"} )
|
||||
|
||||
multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
|
||||
pubkey = self.nodes[1].validateaddress(self.nodes[1].getnewaddress())['pubkey']
|
||||
multisig = self.nodes[1].createmultisig(1, [pubkey])
|
||||
self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
|
||||
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
|
||||
self.nodes[1].generate(1)
|
||||
|
|
|
@ -46,7 +46,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
|||
|
||||
def run_test(self):
|
||||
self.address = self.nodes[0].getnewaddress()
|
||||
self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])
|
||||
self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])['address']
|
||||
self.wit_address = self.nodes[0].addwitnessaddress(self.address)
|
||||
self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address)
|
||||
|
||||
|
|
|
@ -145,7 +145,12 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr1Obj = self.nodes[2].validateaddress(addr1)
|
||||
addr2Obj = self.nodes[2].validateaddress(addr2)
|
||||
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
|
||||
# Tests for createmultisig and addmultisigaddress
|
||||
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
|
||||
self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
|
||||
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
|
||||
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
|
||||
|
||||
#use balance deltas instead of absolute values
|
||||
bal = self.nodes[2].getbalance()
|
||||
|
@ -168,7 +173,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr2Obj = self.nodes[2].validateaddress(addr2)
|
||||
addr3Obj = self.nodes[2].validateaddress(addr3)
|
||||
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
|
||||
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
|
||||
decTx = self.nodes[0].gettransaction(txId)
|
||||
|
@ -213,8 +218,8 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
addr1Obj = self.nodes[1].validateaddress(addr1)
|
||||
addr2Obj = self.nodes[2].validateaddress(addr2)
|
||||
|
||||
self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
|
||||
self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
mSigObjValid = self.nodes[2].validateaddress(mSigObj)
|
||||
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
|
||||
|
|
|
@ -95,7 +95,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
for i in range(3):
|
||||
newaddress = self.nodes[i].getnewaddress()
|
||||
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
|
||||
multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
|
||||
multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])['address']
|
||||
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
|
||||
p2sh_addr = self.nodes[i].addwitnessaddress(newaddress)
|
||||
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
|
||||
|
@ -290,19 +290,19 @@ class SegWitTest(BitcoinTestFramework):
|
|||
solvable_anytime = [] # These outputs should be solvable after importpubkey
|
||||
unseen_anytime = [] # These outputs should never be seen
|
||||
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]]))
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]]))
|
||||
compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]]))
|
||||
uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]]))
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]]))
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]]))
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address'])
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address'])
|
||||
compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address'])
|
||||
uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address'])
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address'])
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address'])
|
||||
unknown_address = ["mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx"]
|
||||
|
||||
# Test multisig_without_privkey
|
||||
# We have 2 public keys without private keys, use addmultisigaddress to add to wallet.
|
||||
# Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address.
|
||||
|
||||
multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])
|
||||
multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address']
|
||||
script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG])
|
||||
solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL]))
|
||||
|
||||
|
@ -463,11 +463,11 @@ class SegWitTest(BitcoinTestFramework):
|
|||
solvable_anytime = [] # These outputs should be solvable after importpubkey
|
||||
unseen_anytime = [] # These outputs should never be seen
|
||||
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]]))
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]]))
|
||||
compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]]))
|
||||
uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]]))
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]]))
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address'])
|
||||
uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address'])
|
||||
compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address'])
|
||||
uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])['address'])
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address'])
|
||||
|
||||
premature_witaddress = []
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ class WalletAccountsTest(BitcoinTestFramework):
|
|||
addresses = []
|
||||
for x in range(10):
|
||||
addresses.append(node.getnewaddress())
|
||||
multisig_address = node.addmultisigaddress(5, addresses, account.name)
|
||||
multisig_address = node.addmultisigaddress(5, addresses, account.name)['address']
|
||||
account.add_address(multisig_address)
|
||||
account.verify(node)
|
||||
node.sendfrom("", multisig_address, 50)
|
||||
|
|
|
@ -94,7 +94,7 @@ class WalletDumpTest(BitcoinTestFramework):
|
|||
|
||||
# Test scripts dump by adding a P2SH witness and a 1-of-1 multisig address
|
||||
witness_addr = self.nodes[0].addwitnessaddress(addrs[0]["address"], True)
|
||||
multisig_addr = self.nodes[0].addmultisigaddress(1, [addrs[1]["address"]])
|
||||
multisig_addr = self.nodes[0].addmultisigaddress(1, [addrs[1]["address"]])["address"]
|
||||
script_addrs = [witness_addr, multisig_addr]
|
||||
|
||||
# dump unencrypted wallet
|
||||
|
|
Loading…
Reference in a new issue