Skip to content

Commit 8a98dfe

Browse files
committed
Merge #10583: [RPC] Split part of validateaddress into getaddressinfo
b22cce0 scripted-diff: validateaddress to getaddressinfo in tests (Andrew Chow) b98bfc5 Create getaddressinfo RPC and deprecate parts of validateaddress (Andrew Chow) 1598f32 [rpc] Move DescribeAddressVisitor to rpc/util (John Newbery) 39633ec [rpc] split wallet and non-wallet parts of DescribeAddressVisitor (John Newbery) Pull request description: This PR makes a new RPC command called `getaddressinfo` which relies on the wallet. It contains all of `validateaddress`'s address info stuff. Those parts in `validateaddress` have been marked as deprecated. The tests have been updated to use `getaddressinfo` except the `disablewallet` test which is the only test that actually uses `validateaddress` to validate an address. Tree-SHA512: ce00ed0f2416200b8de1e0a75e8517c024be0b6153457d302c3879b3491cce28191e7c29aed08ec7d2eeeadc62918f5c43a7cb79cd2e4b6d9291bd83ec31c852
2 parents 294a766 + b22cce0 commit 8a98dfe

23 files changed

+427
-302
lines changed

src/Makefile.am

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ BITCOIN_CORE_H = \
135135
rpc/register.h \
136136
rpc/util.h \
137137
scheduler.h \
138+
script/ismine.h \
138139
script/sigcache.h \
139140
script/sign.h \
140141
script/standard.h \
141-
script/ismine.h \
142142
streams.h \
143143
support/allocators/secure.h \
144144
support/allocators/zeroafterfree.h \
@@ -216,7 +216,6 @@ libbitcoin_server_a_SOURCES = \
216216
rpc/safemode.cpp \
217217
rpc/server.cpp \
218218
script/sigcache.cpp \
219-
script/ismine.cpp \
220219
timedata.cpp \
221220
torcontrol.cpp \
222221
txdb.cpp \
@@ -333,6 +332,7 @@ libbitcoin_common_a_SOURCES = \
333332
policy/feerate.cpp \
334333
protocol.cpp \
335334
scheduler.cpp \
335+
script/ismine.cpp \
336336
script/sign.cpp \
337337
script/standard.cpp \
338338
warnings.cpp \
@@ -389,10 +389,10 @@ endif
389389

390390
bitcoind_LDADD = \
391391
$(LIBBITCOIN_SERVER) \
392+
$(LIBBITCOIN_WALLET) \
392393
$(LIBBITCOIN_COMMON) \
393394
$(LIBUNIVALUE) \
394395
$(LIBBITCOIN_UTIL) \
395-
$(LIBBITCOIN_WALLET) \
396396
$(LIBBITCOIN_ZMQ) \
397397
$(LIBBITCOIN_CONSENSUS) \
398398
$(LIBBITCOIN_CRYPTO) \

src/Makefile.bench.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS
3535
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
3636
bench_bench_bitcoin_LDADD = \
3737
$(LIBBITCOIN_SERVER) \
38+
$(LIBBITCOIN_WALLET) \
3839
$(LIBBITCOIN_COMMON) \
3940
$(LIBBITCOIN_UTIL) \
4041
$(LIBBITCOIN_CONSENSUS) \
@@ -51,7 +52,6 @@ endif
5152

5253
if ENABLE_WALLET
5354
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
54-
bench_bench_bitcoin_LDADD += $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CRYPTO)
5555
endif
5656

5757
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)

src/rpc/misc.cpp

Lines changed: 21 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -33,221 +33,56 @@
3333

3434
#include <univalue.h>
3535

36-
#ifdef ENABLE_WALLET
37-
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
38-
{
39-
public:
40-
CWallet * const pwallet;
41-
42-
explicit DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {}
43-
44-
void ProcessSubScript(const CScript& subscript, UniValue& obj, bool include_addresses = false) const
45-
{
46-
// Always present: script type and redeemscript
47-
txnouttype which_type;
48-
std::vector<std::vector<unsigned char>> solutions_data;
49-
Solver(subscript, which_type, solutions_data);
50-
obj.pushKV("script", GetTxnOutputType(which_type));
51-
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
52-
53-
CTxDestination embedded;
54-
UniValue a(UniValue::VARR);
55-
if (ExtractDestination(subscript, embedded)) {
56-
// Only when the script corresponds to an address.
57-
UniValue subobj = boost::apply_visitor(*this, embedded);
58-
subobj.pushKV("address", EncodeDestination(embedded));
59-
subobj.pushKV("scriptPubKey", HexStr(subscript.begin(), subscript.end()));
60-
// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
61-
if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
62-
obj.pushKV("embedded", std::move(subobj));
63-
if (include_addresses) a.push_back(EncodeDestination(embedded));
64-
} else if (which_type == TX_MULTISIG) {
65-
// Also report some information on multisig scripts (which do not have a corresponding address).
66-
// TODO: abstract out the common functionality between this logic and ExtractDestinations.
67-
obj.pushKV("sigsrequired", solutions_data[0][0]);
68-
UniValue pubkeys(UniValue::VARR);
69-
for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
70-
CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
71-
if (include_addresses) a.push_back(EncodeDestination(key.GetID()));
72-
pubkeys.push_back(HexStr(key.begin(), key.end()));
73-
}
74-
obj.pushKV("pubkeys", std::move(pubkeys));
75-
}
76-
77-
// The "addresses" field is confusing because it refers to public keys using their P2PKH address.
78-
// For that reason, only add the 'addresses' field when needed for backward compatibility. New applications
79-
// can use the 'embedded'->'address' field for P2SH or P2WSH wrapped addresses, and 'pubkeys' for
80-
// inspecting multisig participants.
81-
if (include_addresses) obj.pushKV("addresses", std::move(a));
82-
}
83-
84-
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
85-
86-
UniValue operator()(const CKeyID &keyID) const {
87-
UniValue obj(UniValue::VOBJ);
88-
CPubKey vchPubKey;
89-
obj.pushKV("isscript", false);
90-
obj.pushKV("iswitness", false);
91-
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
92-
obj.pushKV("pubkey", HexStr(vchPubKey));
93-
obj.pushKV("iscompressed", vchPubKey.IsCompressed());
94-
}
95-
return obj;
96-
}
97-
98-
UniValue operator()(const CScriptID &scriptID) const {
99-
UniValue obj(UniValue::VOBJ);
100-
CScript subscript;
101-
obj.pushKV("isscript", true);
102-
obj.pushKV("iswitness", false);
103-
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
104-
ProcessSubScript(subscript, obj, true);
105-
}
106-
return obj;
107-
}
108-
109-
UniValue operator()(const WitnessV0KeyHash& id) const
110-
{
111-
UniValue obj(UniValue::VOBJ);
112-
CPubKey pubkey;
113-
obj.pushKV("isscript", false);
114-
obj.pushKV("iswitness", true);
115-
obj.pushKV("witness_version", 0);
116-
obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
117-
if (pwallet && pwallet->GetPubKey(CKeyID(id), pubkey)) {
118-
obj.pushKV("pubkey", HexStr(pubkey));
119-
}
120-
return obj;
121-
}
122-
123-
UniValue operator()(const WitnessV0ScriptHash& id) const
124-
{
125-
UniValue obj(UniValue::VOBJ);
126-
CScript subscript;
127-
obj.pushKV("isscript", true);
128-
obj.pushKV("iswitness", true);
129-
obj.pushKV("witness_version", 0);
130-
obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
131-
CRIPEMD160 hasher;
132-
uint160 hash;
133-
hasher.Write(id.begin(), 32).Finalize(hash.begin());
134-
if (pwallet && pwallet->GetCScript(CScriptID(hash), subscript)) {
135-
ProcessSubScript(subscript, obj);
136-
}
137-
return obj;
138-
}
139-
140-
UniValue operator()(const WitnessUnknown& id) const
141-
{
142-
UniValue obj(UniValue::VOBJ);
143-
CScript subscript;
144-
obj.pushKV("iswitness", true);
145-
obj.pushKV("witness_version", (int)id.version);
146-
obj.pushKV("witness_program", HexStr(id.program, id.program + id.length));
147-
return obj;
148-
}
149-
};
150-
#endif
151-
15236
UniValue validateaddress(const JSONRPCRequest& request)
15337
{
15438
if (request.fHelp || request.params.size() != 1)
15539
throw std::runtime_error(
15640
"validateaddress \"address\"\n"
15741
"\nReturn information about the given bitcoin address.\n"
42+
"DEPRECATION WARNING: Parts of this command have been deprecated and moved to getaddressinfo. Clients must\n"
43+
"transition to using getaddressinfo to access this information before upgrading to v0.18. The following deprecated\n"
44+
"fields have moved to getaddressinfo and will only be shown here with -deprecatedrpc=validateaddress: ismine, iswatchonly,\n"
45+
"script, hex, pubkeys, sigsrequired, pubkey, addresses, embedded, iscompressed, account, timestamp, hdkeypath, kdmasterkeyid.\n"
15846
"\nArguments:\n"
159-
"1. \"address\" (string, required) The bitcoin address to validate\n"
47+
"1. \"address\" (string, required) The bitcoin address to validate\n"
16048
"\nResult:\n"
16149
"{\n"
16250
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
16351
" \"address\" : \"address\", (string) The bitcoin address validated\n"
16452
" \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
165-
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
166-
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
167-
" \"isscript\" : true|false, (boolean, optional) If the address is P2SH or P2WSH. Not included for unknown witness types.\n"
168-
" \"iswitness\" : true|false, (boolean) If the address is P2WPKH, P2WSH, or an unknown witness version\n"
169-
" \"witness_version\" : version (number, optional) For all witness output types, gives the version number.\n"
170-
" \"witness_program\" : \"hex\" (string, optional) For all witness output types, gives the script or key hash present in the address.\n"
171-
" \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash, witness_unknown\n"
172-
" \"hex\" : \"hex\", (string, optional) The redeemscript for the P2SH or P2WSH address\n"
173-
" \"addresses\" (string, optional) Array of addresses associated with the known redeemscript (only if \"iswitness\" is false). This field is superseded by the \"pubkeys\" field and the address inside \"embedded\".\n"
174-
" [\n"
175-
" \"address\"\n"
176-
" ,...\n"
177-
" ]\n"
178-
" \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n"
179-
" [\n"
180-
" \"pubkey\"\n"
181-
" ,...\n"
182-
" ]\n"
183-
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
184-
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n"
185-
" \"embedded\" : {...}, (object, optional) information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all validateaddress output fields for the embedded address, excluding \"isvalid\", metadata (\"timestamp\", \"hdkeypath\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n"
186-
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
187-
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
188-
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
189-
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
190-
" \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
53+
" \"isscript\" : true|false, (boolean) If the key is a script\n"
54+
" \"iswitness\" : true|false, (boolean) If the address is a witness address\n"
55+
" \"witness_version\" : version (numeric, optional) The version number of the witness program\n"
56+
" \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n"
19157
"}\n"
19258
"\nExamples:\n"
19359
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
19460
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
19561
);
19662

197-
#ifdef ENABLE_WALLET
198-
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
199-
200-
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
201-
#else
202-
LOCK(cs_main);
203-
#endif
204-
20563
CTxDestination dest = DecodeDestination(request.params[0].get_str());
20664
bool isValid = IsValidDestination(dest);
20765

20866
UniValue ret(UniValue::VOBJ);
20967
ret.pushKV("isvalid", isValid);
21068
if (isValid)
21169
{
212-
std::string currentAddress = EncodeDestination(dest);
213-
ret.pushKV("address", currentAddress);
214-
215-
CScript scriptPubKey = GetScriptForDestination(dest);
216-
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
21770

21871
#ifdef ENABLE_WALLET
219-
isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
220-
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
221-
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
222-
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest);
223-
ret.pushKVs(detail);
224-
if (pwallet && pwallet->mapAddressBook.count(dest)) {
225-
ret.pushKV("account", pwallet->mapAddressBook[dest].name);
226-
}
227-
if (pwallet) {
228-
const CKeyMetadata* meta = nullptr;
229-
CKeyID key_id = GetKeyForDestination(*pwallet, dest);
230-
if (!key_id.IsNull()) {
231-
auto it = pwallet->mapKeyMetadata.find(key_id);
232-
if (it != pwallet->mapKeyMetadata.end()) {
233-
meta = &it->second;
234-
}
235-
}
236-
if (!meta) {
237-
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
238-
if (it != pwallet->m_script_metadata.end()) {
239-
meta = &it->second;
240-
}
241-
}
242-
if (meta) {
243-
ret.pushKV("timestamp", meta->nCreateTime);
244-
if (!meta->hdKeypath.empty()) {
245-
ret.pushKV("hdkeypath", meta->hdKeypath);
246-
ret.pushKV("hdmasterkeyid", meta->hdMasterKeyID.GetHex());
247-
}
248-
}
72+
if (!::vpwallets.empty() && IsDeprecatedRPCEnabled("validateaddress")) {
73+
ret.pushKVs(getaddressinfo(request));
24974
}
25075
#endif
76+
if (ret["address"].isNull()) {
77+
std::string currentAddress = EncodeDestination(dest);
78+
ret.pushKV("address", currentAddress);
79+
80+
CScript scriptPubKey = GetScriptForDestination(dest);
81+
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));;
82+
83+
UniValue detail = DescribeAddress(dest);
84+
ret.pushKVs(detail);
85+
}
25186
}
25287
return ret;
25388
}

src/rpc/util.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,64 @@ CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey
6666

6767
return result;
6868
}
69+
70+
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
71+
{
72+
public:
73+
explicit DescribeAddressVisitor() {}
74+
75+
UniValue operator()(const CNoDestination& dest) const
76+
{
77+
return UniValue(UniValue::VOBJ);
78+
}
79+
80+
UniValue operator()(const CKeyID& keyID) const
81+
{
82+
UniValue obj(UniValue::VOBJ);
83+
obj.pushKV("isscript", false);
84+
obj.pushKV("iswitness", false);
85+
return obj;
86+
}
87+
88+
UniValue operator()(const CScriptID& scriptID) const
89+
{
90+
UniValue obj(UniValue::VOBJ);
91+
obj.pushKV("isscript", true);
92+
obj.pushKV("iswitness", false);
93+
return obj;
94+
}
95+
96+
UniValue operator()(const WitnessV0KeyHash& id) const
97+
{
98+
UniValue obj(UniValue::VOBJ);
99+
obj.pushKV("isscript", false);
100+
obj.pushKV("iswitness", true);
101+
obj.pushKV("witness_version", 0);
102+
obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
103+
return obj;
104+
}
105+
106+
UniValue operator()(const WitnessV0ScriptHash& id) const
107+
{
108+
UniValue obj(UniValue::VOBJ);
109+
obj.pushKV("isscript", true);
110+
obj.pushKV("iswitness", true);
111+
obj.pushKV("witness_version", 0);
112+
obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
113+
return obj;
114+
}
115+
116+
UniValue operator()(const WitnessUnknown& id) const
117+
{
118+
UniValue obj(UniValue::VOBJ);
119+
obj.pushKV("iswitness", true);
120+
obj.pushKV("witness_version", (int)id.version);
121+
obj.pushKV("witness_program", HexStr(id.program, id.program + id.length));
122+
return obj;
123+
}
124+
};
125+
126+
UniValue DescribeAddress(const CTxDestination& dest)
127+
{
128+
return boost::apply_visitor(DescribeAddressVisitor(), dest);
129+
}

src/rpc/util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
#ifndef BITCOIN_RPC_UTIL_H
66
#define BITCOIN_RPC_UTIL_H
77

8+
#include <pubkey.h>
9+
#include <script/standard.h>
10+
#include <univalue.h>
11+
#include <utilstrencodings.h>
12+
13+
#include <boost/variant/static_visitor.hpp>
14+
815
#include <string>
916
#include <vector>
1017

@@ -16,4 +23,6 @@ CPubKey HexToPubKey(const std::string& hex_in);
1623
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
1724
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
1825

26+
UniValue DescribeAddress(const CTxDestination& dest);
27+
1928
#endif // BITCOIN_RPC_UTIL_H

0 commit comments

Comments
 (0)