Skip to content

Commit 96ddfa5

Browse files
achow101xdustinface
authored andcommitted
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.
1 parent 3bd6522 commit 96ddfa5

File tree

7 files changed

+181
-124
lines changed

7 files changed

+181
-124
lines changed

src/Makefile.am

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,10 @@ BITCOIN_CORE_H = \
229229
rpc/util.h \
230230
saltedhasher.h \
231231
scheduler.h \
232+
script/ismine.h \
232233
script/sigcache.h \
233234
script/sign.h \
234235
script/standard.h \
235-
script/ismine.h \
236236
spork.h \
237237
stacktraces.h \
238238
streams.h \
@@ -360,7 +360,6 @@ libdash_server_a_SOURCES = \
360360
rpc/privatesend.cpp \
361361
rpc/util.cpp \
362362
script/sigcache.cpp \
363-
script/ismine.cpp \
364363
spork.cpp \
365364
statsd_client.cpp \
366365
timedata.cpp \
@@ -537,6 +536,7 @@ libdash_common_a_SOURCES = \
537536
protocol.cpp \
538537
saltedhasher.cpp \
539538
scheduler.cpp \
539+
script/ismine.cpp \
540540
script/sign.cpp \
541541
script/standard.cpp \
542542
warnings.cpp \
@@ -602,10 +602,10 @@ endif
602602

603603
dashd_LDADD = \
604604
$(LIBBITCOIN_SERVER) \
605+
$(LIBBITCOIN_WALLET) \
605606
$(LIBBITCOIN_COMMON) \
606607
$(LIBUNIVALUE) \
607608
$(LIBBITCOIN_UTIL) \
608-
$(LIBBITCOIN_WALLET) \
609609
$(LIBBITCOIN_ZMQ) \
610610
$(LIBBITCOIN_CONSENSUS) \
611611
$(LIBBITCOIN_CRYPTO) \

src/Makefile.bench.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ bench_bench_dash_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $
4343
bench_bench_dash_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
4444
bench_bench_dash_LDADD = \
4545
$(LIBBITCOIN_SERVER) \
46+
$(LIBBITCOIN_WALLET) \
4647
$(LIBBITCOIN_COMMON) \
4748
$(LIBBITCOIN_UTIL) \
4849
$(LIBBITCOIN_CONSENSUS) \
@@ -59,7 +60,6 @@ endif
5960

6061
if ENABLE_WALLET
6162
bench_bench_dash_SOURCES += bench/coin_selection.cpp
62-
bench_bench_dash_LDADD += $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CRYPTO)
6363
endif
6464

6565
bench_bench_dash_LDADD += $(BACKTRACE_LIB) $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS)

src/rpc/misc.cpp

Lines changed: 16 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -114,58 +114,6 @@ UniValue mnsync(const JSONRPCRequest& request)
114114
return "failure";
115115
}
116116

117-
#ifdef ENABLE_WALLET
118-
class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
119-
{
120-
public:
121-
CWallet * const pwallet;
122-
123-
explicit DescribeWalletAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {}
124-
125-
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
126-
127-
UniValue operator()(const CKeyID &keyID) const {
128-
UniValue obj(UniValue::VOBJ);
129-
CPubKey vchPubKey;
130-
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
131-
obj.pushKV("pubkey", HexStr(vchPubKey));
132-
obj.pushKV("iscompressed", vchPubKey.IsCompressed());
133-
}
134-
return obj;
135-
}
136-
137-
UniValue operator()(const CScriptID &scriptID) const {
138-
UniValue obj(UniValue::VOBJ);
139-
CScript subscript;
140-
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
141-
std::vector<CTxDestination> addresses;
142-
txnouttype whichType;
143-
int nRequired;
144-
ExtractDestinations(subscript, whichType, addresses, nRequired);
145-
obj.pushKV("script", GetTxnOutputType(whichType));
146-
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
147-
UniValue a(UniValue::VARR);
148-
for (const CTxDestination& addr : addresses) {
149-
a.push_back(EncodeDestination(addr));
150-
}
151-
obj.pushKV("addresses", a);
152-
if (whichType == TX_MULTISIG)
153-
obj.pushKV("sigsrequired", nRequired);
154-
}
155-
return obj;
156-
}
157-
};
158-
159-
UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest)
160-
{
161-
UniValue ret(UniValue::VOBJ);
162-
UniValue detail = DescribeAddress(dest);
163-
ret.pushKVs(detail);
164-
ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(pwallet), dest));
165-
return ret;
166-
}
167-
#endif
168-
169117
/*
170118
Used for updating/reading spork settings on the network
171119
*/
@@ -248,94 +196,47 @@ UniValue validateaddress(const JSONRPCRequest& request)
248196
throw std::runtime_error(
249197
"validateaddress \"address\"\n"
250198
"\nReturn information about the given dash address.\n"
199+
"DEPRECATION WARNING: Parts of this command have been deprecated and moved to getaddressinfo. Clients must\n"
200+
"transition to using getaddressinfo to access this information before upgrading to v0.18. The following deprecated\n"
201+
"fields have moved to getaddressinfo and will only be shown here with -deprecatedrpc=validateaddress: ismine, iswatchonly,\n"
202+
"script, hex, pubkeys, sigsrequired, pubkey, addresses, embedded, iscompressed, account, timestamp, hdkeypath.\n"
251203
"\nArguments:\n"
252-
"1. \"address\" (string, required) The dash address to validate\n"
204+
"1. \"address\" (string, required) The dash address to validate\n"
253205
"\nResult:\n"
254206
"{\n"
255207
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
256208
" \"address\" : \"address\", (string) The dash address validated\n"
257209
" \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
258-
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
259-
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
260210
" \"isscript\" : true|false, (boolean) If the key is a script\n"
261-
" \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata\n"
262-
" \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n"
263-
" \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n"
264-
" [\n"
265-
" \"address\"\n"
266-
" ,...\n"
267-
" ]\n"
268-
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n"
269-
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
270-
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
271-
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
272-
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
273-
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
274-
" \"hdchainid\" : \"<hash>\" (string, optional) The ID of the HD chain\n"
275211
"}\n"
276212
"\nExamples:\n"
277213
+ HelpExampleCli("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"")
278214
+ HelpExampleRpc("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"")
279215
);
280216

281-
#ifdef ENABLE_WALLET
282-
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
283-
284-
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
285-
#else
286-
LOCK(cs_main);
287-
#endif
288-
289217
CTxDestination dest = DecodeDestination(request.params[0].get_str());
290218
bool isValid = IsValidDestination(dest);
291219

292220
UniValue ret(UniValue::VOBJ);
293221
ret.pushKV("isvalid", isValid);
294222
if (isValid)
295223
{
296-
std::string currentAddress = EncodeDestination(dest);
297-
ret.pushKV("address", currentAddress);
298-
299-
CScript scriptPubKey = GetScriptForDestination(dest);
300-
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
301224

302225
#ifdef ENABLE_WALLET
303-
isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
304-
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
305-
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
306-
UniValue detail = DescribeWalletAddress(pwallet, dest);
307-
ret.pushKVs(detail);
308-
if (pwallet && pwallet->mapAddressBook.count(dest)) {
309-
ret.pushKV("account", pwallet->mapAddressBook[dest].name);
226+
if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) {
227+
ret.pushKVs(getaddressinfo(request));
310228
}
311-
if (pwallet) {
312-
const CKeyMetadata* meta = nullptr;
313-
const CKeyID *keyID = boost::get<CKeyID>(&dest);
314-
if (const CKeyID* key_id = boost::get<CKeyID>(&dest)) {
315-
auto it = pwallet->mapKeyMetadata.find(*key_id);
316-
if (it != pwallet->mapKeyMetadata.end()) {
317-
meta = &it->second;
318-
}
319-
}
320-
if (!meta) {
321-
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
322-
if (it != pwallet->m_script_metadata.end()) {
323-
meta = &it->second;
324-
}
325-
}
326-
if (meta) {
327-
ret.pushKV("timestamp", meta->nCreateTime);
328-
}
229+
#endif
230+
if (ret["address"].isNull()) {
231+
std::string currentAddress = EncodeDestination(dest);
232+
ret.pushKV("address", currentAddress);
329233

330-
CHDChain hdChainCurrent;
331-
if (keyID && pwallet->mapHdPubKeys.count(*keyID) && pwallet->GetHDChain(hdChainCurrent)) {
332-
ret.pushKV("hdkeypath", pwallet->mapHdPubKeys[*keyID].GetKeyPath());
333-
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
334-
}
234+
CScript scriptPubKey = GetScriptForDestination(dest);
235+
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));;
236+
237+
UniValue detail = DescribeAddress(dest);
238+
ret.pushKVs(detail);
335239
}
336-
#else
337-
ret.pushKvs = DescribeAddress(dest);
338-
#endif
339240
}
340241
return ret;
341242
}

src/wallet/rpcwallet.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <utilmoneystr.h>
2626
#include <validation.h>
2727
#include <wallet/coincontrol.h>
28+
#include <wallet/rpcwallet.h>
2829
#include <wallet/wallet.h>
2930
#include <wallet/walletdb.h>
3031
#include <wallet/walletutil.h>
@@ -3569,6 +3570,147 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
35693570
return response;
35703571
}
35713572

3573+
class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
3574+
{
3575+
public:
3576+
CWallet * const pwallet;
3577+
3578+
explicit DescribeWalletAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {}
3579+
3580+
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
3581+
3582+
UniValue operator()(const CKeyID &keyID) const {
3583+
UniValue obj(UniValue::VOBJ);
3584+
CPubKey vchPubKey;
3585+
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
3586+
obj.pushKV("pubkey", HexStr(vchPubKey));
3587+
obj.pushKV("iscompressed", vchPubKey.IsCompressed());
3588+
}
3589+
return obj;
3590+
}
3591+
3592+
UniValue operator()(const CScriptID &scriptID) const {
3593+
UniValue obj(UniValue::VOBJ);
3594+
CScript subscript;
3595+
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
3596+
std::vector<CTxDestination> addresses;
3597+
txnouttype whichType;
3598+
int nRequired;
3599+
ExtractDestinations(subscript, whichType, addresses, nRequired);
3600+
obj.pushKV("script", GetTxnOutputType(whichType));
3601+
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
3602+
UniValue a(UniValue::VARR);
3603+
for (const CTxDestination& addr : addresses) {
3604+
a.push_back(EncodeDestination(addr));
3605+
}
3606+
obj.pushKV("addresses", a);
3607+
if (whichType == TX_MULTISIG)
3608+
obj.pushKV("sigsrequired", nRequired);
3609+
}
3610+
return obj;
3611+
}
3612+
};
3613+
3614+
UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest)
3615+
{
3616+
UniValue ret(UniValue::VOBJ);
3617+
UniValue detail = DescribeAddress(dest);
3618+
ret.pushKVs(detail);
3619+
ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(pwallet), dest));
3620+
return ret;
3621+
}
3622+
3623+
UniValue getaddressinfo(const JSONRPCRequest& request)
3624+
{
3625+
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3626+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3627+
return NullUniValue;
3628+
}
3629+
3630+
if (request.fHelp || request.params.size() != 1) {
3631+
throw std::runtime_error(
3632+
"getaddressinfo \"address\"\n"
3633+
"\nReturn information about the given dash address. Some information requires the address\n"
3634+
"to be in the wallet.\n"
3635+
"\nArguments:\n"
3636+
"1. \"address\" (string, required) The dash address to get the information of.\n"
3637+
"\nResult:\n"
3638+
"{\n"
3639+
" \"address\" : \"address\", (string) The dash address validated\n"
3640+
" \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
3641+
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
3642+
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
3643+
" \"isscript\" : true|false, (boolean) If the key is a script\n"
3644+
" \"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\n"
3645+
" \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n"
3646+
" \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n"
3647+
" [\n"
3648+
" \"pubkey\"\n"
3649+
" ,...\n"
3650+
" ]\n"
3651+
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
3652+
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH)\n"
3653+
" \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n"
3654+
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
3655+
" \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
3656+
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
3657+
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
3658+
"}\n"
3659+
"\nExamples:\n"
3660+
+ HelpExampleCli("getaddressinfo", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"")
3661+
+ HelpExampleRpc("getaddressinfo", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"")
3662+
);
3663+
}
3664+
3665+
LOCK(pwallet->cs_wallet);
3666+
3667+
UniValue ret(UniValue::VOBJ);
3668+
CTxDestination dest = DecodeDestination(request.params[0].get_str());
3669+
3670+
// Make sure the destination is valid
3671+
if (!IsValidDestination(dest)) {
3672+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
3673+
}
3674+
3675+
std::string currentAddress = EncodeDestination(dest);
3676+
ret.pushKV("address", currentAddress);
3677+
3678+
CScript scriptPubKey = GetScriptForDestination(dest);
3679+
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
3680+
3681+
isminetype mine = IsMine(*pwallet, dest);
3682+
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
3683+
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
3684+
UniValue detail = DescribeWalletAddress(pwallet, dest);
3685+
ret.pushKVs(detail);
3686+
if (pwallet->mapAddressBook.count(dest)) {
3687+
ret.pushKV("account", pwallet->mapAddressBook[dest].name);
3688+
}
3689+
const CKeyMetadata* meta = nullptr;
3690+
const CKeyID *key_id = boost::get<CKeyID>(&dest);
3691+
if (key_id != nullptr && !key_id->IsNull()) {
3692+
auto it = pwallet->mapKeyMetadata.find(*key_id);
3693+
if (it != pwallet->mapKeyMetadata.end()) {
3694+
meta = &it->second;
3695+
}
3696+
}
3697+
if (!meta) {
3698+
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
3699+
if (it != pwallet->m_script_metadata.end()) {
3700+
meta = &it->second;
3701+
}
3702+
}
3703+
if (meta) {
3704+
ret.pushKV("timestamp", meta->nCreateTime);
3705+
CHDChain hdChainCurrent;
3706+
if (key_id && pwallet->mapHdPubKeys.count(*key_id) && pwallet->GetHDChain(hdChainCurrent)) {
3707+
ret.pushKV("hdkeypath", pwallet->mapHdPubKeys[*key_id].GetKeyPath());
3708+
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
3709+
}
3710+
}
3711+
return ret;
3712+
}
3713+
35723714
extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
35733715
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
35743716
extern UniValue importprivkey(const JSONRPCRequest& request);
@@ -3599,6 +3741,7 @@ static const CRPCCommand commands[] =
35993741
{ "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
36003742
{ "wallet", "getaccount", &getaccount, {"address"} },
36013743
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
3744+
{ "wallet", "getaddressinfo", &getaddressinfo, {"address"} },
36023745
{ "wallet", "getbalance", &getbalance, {"account","minconf","addlocked","include_watchonly"} },
36033746
{ "wallet", "getnewaddress", &getnewaddress, {"account"} },
36043747
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, {} },

src/wallet/rpcwallet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ std::string HelpRequiringPassphrase(CWallet *);
2626
void EnsureWalletIsUnlocked(CWallet *);
2727
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
2828

29+
UniValue getaddressinfo(const JSONRPCRequest& request);
2930
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
3031
#endif //BITCOIN_WALLET_RPCWALLET_H

0 commit comments

Comments
 (0)