From 122078b9ec587733a9c0074b71d58e7c0c19d6c4 Mon Sep 17 00:00:00 2001 From: dustinface <35775977+xdustinface@users.noreply.github.com> Date: Thu, 17 Dec 2020 13:46:20 +0100 Subject: [PATCH] backport: bitcoin#10583 - [RPC] Split part of validateaddress into getaddressinfo (#3880) * [rpc] split wallet and non-wallet parts of DescribeAddressVisitor * [rpc] Move DescribeAddressVisitor to rpc/util * Create getaddressinfo RPC and deprecate parts of validateaddress Moves the parts of validateaddress which require the wallet into getaddressinfo which is part of the wallet RPCs. Mark those parts of validateaddress which require the wallet as deprecated. Validateaddress will call getaddressinfo for the data that both share for right now. Moves IsMine functions to libbitcoin_common and then links libbitcoin_wallet before libbitcoin_common in order to prevent linker errors since IsMine is no longer used in libbitcoin_server. * scripted-diff: validateaddress to getaddressinfo in tests Change all instances of validateaddress to getaddressinfo since it seems that no test actually uses validateaddress for actually validating addresses. -BEGIN VERIFY SCRIPT- find ./test/functional -path '*py' -not -path ./test/functional/wallet_disable.py -not -path ./test/functional/rpc_deprecated.py -not -path ./test/functional/wallet_address_types.py -exec sed -i'' -e 's/validateaddress/getaddressinfo/g' {} \; -END VERIFY SCRIPT- * wallet: Add missing description of "hdchainid" * Update src/wallet/rpcwallet.cpp Co-authored-by: UdjinM6 Co-authored-by: John Newbery Co-authored-by: Andrew Chow Co-authored-by: UdjinM6 --- src/Makefile.am | 6 +- src/Makefile.bench.include | 2 +- src/rpc/misc.cpp | 124 +++------------ src/rpc/util.cpp | 26 ++++ src/rpc/util.h | 9 ++ src/wallet/rpcwallet.cpp | 144 ++++++++++++++++++ src/wallet/rpcwallet.h | 1 + .../feature_dip3_deterministicmns.py | 4 +- test/functional/rpc_deprecated.py | 13 +- test/functional/rpc_fundrawtransaction.py | 20 +-- test/functional/rpc_fundrawtransaction_hd.py | 20 +-- test/functional/rpc_listtransactions.py | 2 +- test/functional/rpc_rawtransaction.py | 16 +- test/functional/wallet_basic.py | 11 +- test/functional/wallet_dump.py | 6 +- test/functional/wallet_hd.py | 10 +- test/functional/wallet_import_rescan.py | 2 +- test/functional/wallet_importmulti.py | 102 ++++++------- test/functional/wallet_importprunedfunds.py | 14 +- test/functional/wallet_keypool_hd.py | 4 +- test/functional/wallet_keypool_topup.py | 2 +- 21 files changed, 320 insertions(+), 218 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4764960539..43182965be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -229,10 +229,10 @@ BITCOIN_CORE_H = \ rpc/util.h \ saltedhasher.h \ scheduler.h \ + script/ismine.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ - script/ismine.h \ spork.h \ stacktraces.h \ streams.h \ @@ -360,7 +360,6 @@ libdash_server_a_SOURCES = \ rpc/privatesend.cpp \ rpc/util.cpp \ script/sigcache.cpp \ - script/ismine.cpp \ spork.cpp \ statsd_client.cpp \ timedata.cpp \ @@ -537,6 +536,7 @@ libdash_common_a_SOURCES = \ protocol.cpp \ saltedhasher.cpp \ scheduler.cpp \ + script/ismine.cpp \ script/sign.cpp \ script/standard.cpp \ warnings.cpp \ @@ -602,10 +602,10 @@ endif dashd_LDADD = \ $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_COMMON) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 6ee2fa314f..86d76f8f49 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -43,6 +43,7 @@ bench_bench_dash_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $ bench_bench_dash_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bench_bench_dash_LDADD = \ $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ @@ -59,7 +60,6 @@ endif if ENABLE_WALLET bench_bench_dash_SOURCES += bench/coin_selection.cpp -bench_bench_dash_LDADD += $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CRYPTO) endif bench_bench_dash_LDADD += $(BACKTRACE_LIB) $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 95cbd48ce7..b94bbe15aa 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -114,51 +114,6 @@ UniValue mnsync(const JSONRPCRequest& request) return "failure"; } -#ifdef ENABLE_WALLET -class DescribeAddressVisitor : public boost::static_visitor -{ -public: - CWallet * const pwallet; - - explicit DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {} - - UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } - - UniValue operator()(const CKeyID &keyID) const { - UniValue obj(UniValue::VOBJ); - CPubKey vchPubKey; - obj.pushKV("isscript", false); - if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) { - obj.pushKV("pubkey", HexStr(vchPubKey)); - obj.pushKV("iscompressed", vchPubKey.IsCompressed()); - } - return obj; - } - - UniValue operator()(const CScriptID &scriptID) const { - UniValue obj(UniValue::VOBJ); - CScript subscript; - obj.pushKV("isscript", true); - if (pwallet && pwallet->GetCScript(scriptID, subscript)) { - std::vector addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.pushKV("script", GetTxnOutputType(whichType)); - obj.pushKV("hex", HexStr(subscript.begin(), subscript.end())); - UniValue a(UniValue::VARR); - for (const CTxDestination& addr : addresses) { - a.push_back(EncodeDestination(addr)); - } - obj.pushKV("addresses", a); - if (whichType == TX_MULTISIG) - obj.pushKV("sigsrequired", nRequired); - } - return obj; - } -}; -#endif - /* Used for updating/reading spork settings on the network */ @@ -241,44 +196,24 @@ UniValue validateaddress(const JSONRPCRequest& request) throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given dash address.\n" + "DEPRECATION WARNING: Parts of this command have been deprecated and moved to getaddressinfo. Clients must\n" + "transition to using getaddressinfo to access this information before upgrading to v0.18. The following deprecated\n" + "fields have moved to getaddressinfo and will only be shown here with -deprecatedrpc=validateaddress: ismine, iswatchonly,\n" + "script, hex, pubkeys, sigsrequired, pubkey, addresses, embedded, iscompressed, account, timestamp, hdkeypath.\n" "\nArguments:\n" - "1. \"address\" (string, required) The dash address to validate\n" + "1. \"address\" (string, required) The dash address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The dash address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" - " \"ismine\" : true|false, (boolean) If the address is yours or not\n" - " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata\n" - " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" - " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" - " [\n" - " \"address\"\n" - " ,...\n" - " ]\n" - " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" - " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" - " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" - " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" - " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" - " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" - " \"hdchainid\" : \"\" (string, optional) The ID of the HD chain\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") + HelpExampleRpc("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") ); -#ifdef ENABLE_WALLET - CWallet * const pwallet = GetWalletForJSONRPCRequest(request); - - LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr); -#else - LOCK(cs_main); -#endif - CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); @@ -286,47 +221,22 @@ UniValue validateaddress(const JSONRPCRequest& request) ret.pushKV("isvalid", isValid); if (isValid) { - std::string currentAddress = EncodeDestination(dest); - ret.pushKV("address", currentAddress); - - CScript scriptPubKey = GetScriptForDestination(dest); - ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); #ifdef ENABLE_WALLET - isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; - ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); - ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); - UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); - ret.pushKVs(detail); - if (pwallet && pwallet->mapAddressBook.count(dest)) { - ret.pushKV("account", pwallet->mapAddressBook[dest].name); - } - if (pwallet) { - const CKeyMetadata* meta = nullptr; - const CKeyID *keyID = boost::get(&dest); - if (const CKeyID* key_id = boost::get(&dest)) { - auto it = pwallet->mapKeyMetadata.find(*key_id); - if (it != pwallet->mapKeyMetadata.end()) { - meta = &it->second; - } - } - if (!meta) { - auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); - if (it != pwallet->m_script_metadata.end()) { - meta = &it->second; - } - } - if (meta) { - ret.pushKV("timestamp", meta->nCreateTime); - } - - CHDChain hdChainCurrent; - if (keyID && pwallet->mapHdPubKeys.count(*keyID) && pwallet->GetHDChain(hdChainCurrent)) { - ret.pushKV("hdkeypath", pwallet->mapHdPubKeys[*keyID].GetKeyPath()); - ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex()); - } + if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) { + ret.pushKVs(getaddressinfo(request)); } #endif + if (ret["address"].isNull()) { + std::string currentAddress = EncodeDestination(dest); + ret.pushKV("address", currentAddress); + + CScript scriptPubKey = GetScriptForDestination(dest); + ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));; + + UniValue detail = DescribeAddress(dest); + ret.pushKVs(detail); + } } return ret; } diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 50e332f9a8..7093cc7ec5 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -66,3 +66,29 @@ CScript CreateMultisigRedeemscript(const int required, const std::vector +{ +public: + + explicit DescribeAddressVisitor() {} + + UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } + + UniValue operator()(const CKeyID &keyID) const { + UniValue obj(UniValue::VOBJ); + obj.pushKV("isscript", false); + return obj; + } + + UniValue operator()(const CScriptID &scriptID) const { + UniValue obj(UniValue::VOBJ); + obj.pushKV("isscript", true); + return obj; + } +}; + +UniValue DescribeAddress(const CTxDestination& dest) +{ + return boost::apply_visitor(DescribeAddressVisitor(), dest); +} diff --git a/src/rpc/util.h b/src/rpc/util.h index 568a4260ba..5380d45a83 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -5,6 +5,13 @@ #ifndef BITCOIN_RPC_UTIL_H #define BITCOIN_RPC_UTIL_H +#include +#include