]> Git Repo - VerusCoin.git/blame - src/rpc/misc.cpp
add spentindex RPC for bitcore block explorer
[VerusCoin.git] / src / rpc / misc.cpp
CommitLineData
652e1569 1// Copyright (c) 2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
72fb3d29 3// Distributed under the MIT software license, see the accompanying
bc909a7a 4// file COPYING or https://www.opensource.org/licenses/mit-license.php .
652e1569 5
71697f97 6#include "clientversion.h"
652e1569 7#include "init.h"
3d31e09c 8#include "key_io.h"
652e1569
WL
9#include "main.h"
10#include "net.h"
11#include "netbase.h"
4519a766 12#include "rpc/server.h"
14f888ca 13#include "timedata.h"
68e174e2 14#include "txmempool.h"
652e1569
WL
15#include "util.h"
16#ifdef ENABLE_WALLET
50c72f23
JS
17#include "wallet/wallet.h"
18#include "wallet/walletdb.h"
652e1569
WL
19#endif
20
21#include <stdint.h>
22
23#include <boost/assign/list_of.hpp>
a10a6e2a
JS
24
25#include <univalue.h>
652e1569 26
4e16a724
S
27#include "zcash/Address.hpp"
28
40a158e1 29using namespace std;
652e1569 30
f9de17ec
WL
31/**
32 * @note Do not add or change anything in the information returned by this
72fb3d29 33 * method. `getinfo` exists for backwards-compatibility only. It combines
f9de17ec
WL
34 * information from wildly different sources in the program, which is a mess,
35 * and is thus planned to be deprecated eventually.
36 *
37 * Based on the source of the information, new information should be added to:
38 * - `getblockchaininfo`,
39 * - `getnetworkinfo` or
40 * - `getwalletinfo`
41 *
42 * Or alternatively, create a specific query method for the information.
43 **/
d014114d 44UniValue getinfo(const UniValue& params, bool fHelp)
16bc9aaf
WL
45{
46 if (fHelp || params.size() != 0)
47 throw runtime_error(
48 "getinfo\n"
49 "Returns an object containing various state info.\n"
50 "\nResult:\n"
51 "{\n"
52 " \"version\": xxxxx, (numeric) the server version\n"
53 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
54 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
c1652849 55 " \"balance\": xxxxxxx, (numeric) the total Zcash balance of the wallet\n"
16bc9aaf
WL
56 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
57 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
58 " \"connections\": xxxxx, (numeric) the number of connections\n"
59 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
60 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
61 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
62 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
63 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
16bc9aaf 64 " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
091b2116
RN
65 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
66 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
16bc9aaf
WL
67 " \"errors\": \"...\" (string) any error messages\n"
68 "}\n"
69 "\nExamples:\n"
70 + HelpExampleCli("getinfo", "")
71 + HelpExampleRpc("getinfo", "")
72 );
73
4401b2d7
EL
74#ifdef ENABLE_WALLET
75 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
76#else
77 LOCK(cs_main);
78#endif
79
16bc9aaf
WL
80 proxyType proxy;
81 GetProxy(NET_IPV4, proxy);
82
38fc4b70 83 UniValue obj(UniValue::VOBJ);
faadbe17
PK
84 obj.push_back(Pair("version", CLIENT_VERSION));
85 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
16bc9aaf
WL
86#ifdef ENABLE_WALLET
87 if (pwalletMain) {
88 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
89 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
90 }
91#endif
92 obj.push_back(Pair("blocks", (int)chainActive.Height()));
d56e30ca 93 obj.push_back(Pair("timeoffset", GetTimeOffset()));
16bc9aaf 94 obj.push_back(Pair("connections", (int)vNodes.size()));
67a79493 95 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
16bc9aaf 96 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
cc972107 97 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
16bc9aaf
WL
98#ifdef ENABLE_WALLET
99 if (pwalletMain) {
d56e30ca 100 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
16bc9aaf
WL
101 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
102 }
16bc9aaf 103 if (pwalletMain && pwalletMain->IsCrypted())
d56e30ca 104 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
c6cb21d1 105 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
16bc9aaf 106#endif
13fc83c7 107 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
16bc9aaf
WL
108 obj.push_back(Pair("errors", GetWarnings("statusbar")));
109 return obj;
110}
111
452955f5 112#ifdef ENABLE_WALLET
d014114d 113class DescribeAddressVisitor : public boost::static_visitor<UniValue>
452955f5
WL
114{
115public:
d014114d 116 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
452955f5 117
851f58f9 118 UniValue operator()(const CKeyID &keyID) const {
38fc4b70 119 UniValue obj(UniValue::VOBJ);
452955f5 120 CPubKey vchPubKey;
452955f5 121 obj.push_back(Pair("isscript", false));
56215c77 122 if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
c8988460
PW
123 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
124 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
125 }
452955f5
WL
126 return obj;
127 }
128
851f58f9 129 UniValue operator()(const CScriptID &scriptID) const {
38fc4b70 130 UniValue obj(UniValue::VOBJ);
9c7167d1 131 CScript subscript;
452955f5 132 obj.push_back(Pair("isscript", true));
56215c77 133 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
c8988460
PW
134 std::vector<CTxDestination> addresses;
135 txnouttype whichType;
136 int nRequired;
137 ExtractDestinations(subscript, whichType, addresses, nRequired);
138 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
139 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
38fc4b70 140 UniValue a(UniValue::VARR);
07444da1
PW
141 for (const CTxDestination& addr : addresses) {
142 a.push_back(EncodeDestination(addr));
143 }
c8988460
PW
144 obj.push_back(Pair("addresses", a));
145 if (whichType == TX_MULTISIG)
146 obj.push_back(Pair("sigsrequired", nRequired));
147 }
452955f5
WL
148 return obj;
149 }
150};
151#endif
152
d014114d 153UniValue validateaddress(const UniValue& params, bool fHelp)
452955f5
WL
154{
155 if (fHelp || params.size() != 1)
156 throw runtime_error(
d2c1e4a8 157 "validateaddress \"zcashaddress\"\n"
c1652849 158 "\nReturn information about the given Zcash address.\n"
452955f5 159 "\nArguments:\n"
c1652849 160 "1. \"zcashaddress\" (string, required) The Zcash address to validate\n"
452955f5
WL
161 "\nResult:\n"
162 "{\n"
163 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
c1652849 164 " \"address\" : \"zcashaddress\", (string) The Zcash address validated\n"
426a74ed 165 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
452955f5
WL
166 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
167 " \"isscript\" : true|false, (boolean) If the key is a script\n"
168 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
169 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
7b782f5b 170 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
452955f5
WL
171 "}\n"
172 "\nExamples:\n"
173 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
174 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
175 );
176
4401b2d7
EL
177#ifdef ENABLE_WALLET
178 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
179#else
180 LOCK(cs_main);
181#endif
182
07444da1
PW
183 CTxDestination dest = DecodeDestination(params[0].get_str());
184 bool isValid = IsValidDestination(dest);
452955f5 185
38fc4b70 186 UniValue ret(UniValue::VOBJ);
452955f5
WL
187 ret.push_back(Pair("isvalid", isValid));
188 if (isValid)
189 {
07444da1 190 std::string currentAddress = EncodeDestination(dest);
452955f5 191 ret.push_back(Pair("address", currentAddress));
426a74ed
PT
192
193 CScript scriptPubKey = GetScriptForDestination(dest);
194 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
195
452955f5 196#ifdef ENABLE_WALLET
a3e192a3
J
197 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
198 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
9c7167d1 199 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
200 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
201 ret.pushKVs(detail);
452955f5
WL
202 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
203 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
204#endif
205 }
206 return ret;
207}
208
4e16a724 209
bea87915
JG
210class DescribePaymentAddressVisitor : public boost::static_visitor<UniValue>
211{
212public:
213 UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); }
214
215 UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const {
216 UniValue obj(UniValue::VOBJ);
217 obj.push_back(Pair("type", "sprout"));
218 obj.push_back(Pair("payingkey", zaddr.a_pk.GetHex()));
219 obj.push_back(Pair("transmissionkey", zaddr.pk_enc.GetHex()));
220#ifdef ENABLE_WALLET
221 if (pwalletMain) {
25d5e80c 222 obj.push_back(Pair("ismine", pwalletMain->HaveSproutSpendingKey(zaddr)));
bea87915
JG
223 }
224#endif
225 return obj;
226 }
227
228 UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
229 UniValue obj(UniValue::VOBJ);
230 obj.push_back(Pair("type", "sapling"));
231 obj.push_back(Pair("diversifier", HexStr(zaddr.d)));
232 obj.push_back(Pair("diversifiedtransmissionkey", zaddr.pk_d.GetHex()));
233#ifdef ENABLE_WALLET
234 if (pwalletMain) {
235 libzcash::SaplingIncomingViewingKey ivk;
236 libzcash::SaplingFullViewingKey fvk;
237 bool isMine = pwalletMain->GetSaplingIncomingViewingKey(zaddr, ivk) &&
238 pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
239 pwalletMain->HaveSaplingSpendingKey(fvk);
240 obj.push_back(Pair("ismine", isMine));
241 }
242#endif
243 return obj;
244 }
245};
246
0d37ae3a 247UniValue z_validateaddress(const UniValue& params, bool fHelp)
4e16a724
S
248{
249 if (fHelp || params.size() != 1)
250 throw runtime_error(
251 "z_validateaddress \"zaddr\"\n"
252 "\nReturn information about the given z address.\n"
253 "\nArguments:\n"
254 "1. \"zaddr\" (string, required) The z address to validate\n"
255 "\nResult:\n"
256 "{\n"
257 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
258 " \"address\" : \"zaddr\", (string) The z address validated\n"
bea87915 259 " \"type\" : \"xxxx\", (string) \"sprout\" or \"sapling\"\n"
4e16a724 260 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
bea87915
JG
261 " \"payingkey\" : \"hex\", (string) [sprout] The hex value of the paying key, a_pk\n"
262 " \"transmissionkey\" : \"hex\", (string) [sprout] The hex value of the transmission key, pk_enc\n"
263 " \"diversifier\" : \"hex\", (string) [sapling] The hex value of the diversifier, d\n"
264 " \"diversifiedtransmissionkey\" : \"hex\", (string) [sapling] The hex value of pk_d\n"
4e16a724
S
265
266 "}\n"
267 "\nExamples:\n"
337a99a2
JG
268 + HelpExampleCli("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
269 + HelpExampleRpc("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
4e16a724
S
270 );
271
272
273#ifdef ENABLE_WALLET
274 LOCK2(cs_main, pwalletMain->cs_wallet);
275#else
276 LOCK(cs_main);
277#endif
278
4e16a724 279 string strAddress = params[0].get_str();
e5eab182
JG
280 auto address = DecodePaymentAddress(strAddress);
281 bool isValid = IsValidPaymentAddress(address);
4e16a724 282
0d37ae3a 283 UniValue ret(UniValue::VOBJ);
bea87915 284 ret.push_back(Pair("isvalid", isValid));
4e16a724
S
285 if (isValid)
286 {
287 ret.push_back(Pair("address", strAddress));
bea87915
JG
288 UniValue detail = boost::apply_visitor(DescribePaymentAddressVisitor(), address);
289 ret.pushKVs(detail);
4e16a724
S
290 }
291 return ret;
292}
293
294
72fb3d29
MF
295/**
296 * Used by addmultisigaddress / createmultisig:
297 */
d014114d 298CScript _createmultisig_redeemScript(const UniValue& params)
723a03d2
WL
299{
300 int nRequired = params[0].get_int();
d014114d 301 const UniValue& keys = params[1].get_array();
723a03d2
WL
302
303 // Gather public keys
304 if (nRequired < 1)
305 throw runtime_error("a multisignature address must require at least one key to redeem");
306 if ((int)keys.size() < nRequired)
307 throw runtime_error(
308 strprintf("not enough keys supplied "
783b182c 309 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
e5d9d77d 310 if (keys.size() > 16)
311 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
723a03d2
WL
312 std::vector<CPubKey> pubkeys;
313 pubkeys.resize(keys.size());
314 for (unsigned int i = 0; i < keys.size(); i++)
315 {
316 const std::string& ks = keys[i].get_str();
317#ifdef ENABLE_WALLET
318 // Case 1: Bitcoin address and we have full public key:
07444da1
PW
319 CTxDestination dest = DecodeDestination(ks);
320 if (pwalletMain && IsValidDestination(dest)) {
321 const CKeyID *keyID = boost::get<CKeyID>(&dest);
322 if (!keyID) {
323 throw std::runtime_error(strprintf("%s does not refer to a key", ks));
324 }
723a03d2 325 CPubKey vchPubKey;
07444da1
PW
326 if (!pwalletMain->GetPubKey(*keyID, vchPubKey)) {
327 throw std::runtime_error(strprintf("no full public key for address %s", ks));
328 }
723a03d2
WL
329 if (!vchPubKey.IsFullyValid())
330 throw runtime_error(" Invalid public key: "+ks);
331 pubkeys[i] = vchPubKey;
332 }
333
334 // Case 2: hex public key
335 else
336#endif
337 if (IsHex(ks))
338 {
339 CPubKey vchPubKey(ParseHex(ks));
340 if (!vchPubKey.IsFullyValid())
341 throw runtime_error(" Invalid public key: "+ks);
342 pubkeys[i] = vchPubKey;
343 }
344 else
345 {
346 throw runtime_error(" Invalid public key: "+ks);
347 }
348 }
0be990ba 349 CScript result = GetScriptForMultisig(nRequired, pubkeys);
787ee0c9
PT
350
351 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
352 throw runtime_error(
353 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
354
723a03d2
WL
355 return result;
356}
357
d014114d 358UniValue createmultisig(const UniValue& params, bool fHelp)
723a03d2
WL
359{
360 if (fHelp || params.size() < 2 || params.size() > 2)
361 {
362 string msg = "createmultisig nrequired [\"key\",...]\n"
363 "\nCreates a multi-signature address with n signature of m keys required.\n"
364 "It returns a json object with the address and redeemScript.\n"
365
366 "\nArguments:\n"
367 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
c1652849 368 "2. \"keys\" (string, required) A json array of keys which are Zcash addresses or hex-encoded public keys\n"
723a03d2 369 " [\n"
c1652849 370 " \"key\" (string) Zcash address or hex-encoded public key\n"
723a03d2
WL
371 " ,...\n"
372 " ]\n"
373
374 "\nResult:\n"
375 "{\n"
376 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
377 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
378 "}\n"
379
380 "\nExamples:\n"
381 "\nCreate a multisig address from 2 addresses\n"
70454796 382 + HelpExampleCli("createmultisig", "2 \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
723a03d2 383 "\nAs a json rpc call\n"
70454796 384 + HelpExampleRpc("createmultisig", "2, \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
723a03d2
WL
385 ;
386 throw runtime_error(msg);
387 }
388
389 // Construct using pay-to-script-hash:
787ee0c9 390 CScript inner = _createmultisig_redeemScript(params);
066e2a14 391 CScriptID innerID(inner);
723a03d2 392
b47f3aea 393 UniValue result(UniValue::VOBJ);
07444da1 394 result.push_back(Pair("address", EncodeDestination(innerID)));
723a03d2
WL
395 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
396
397 return result;
398}
399
d014114d 400UniValue verifymessage(const UniValue& params, bool fHelp)
c3a7f516
WL
401{
402 if (fHelp || params.size() != 3)
403 throw runtime_error(
d2c1e4a8 404 "verifymessage \"zcashaddress\" \"signature\" \"message\"\n"
c3a7f516
WL
405 "\nVerify a signed message\n"
406 "\nArguments:\n"
c1652849 407 "1. \"zcashaddress\" (string, required) The Zcash address to use for the signature.\n"
c3a7f516
WL
408 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
409 "3. \"message\" (string, required) The message that was signed.\n"
410 "\nResult:\n"
411 "true|false (boolean) If the signature is verified or not.\n"
412 "\nExamples:\n"
413 "\nUnlock the wallet for 30 seconds\n"
414 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
415 "\nCreate the signature\n"
70454796 416 + HelpExampleCli("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"my message\"") +
c3a7f516 417 "\nVerify the signature\n"
70454796 418 + HelpExampleCli("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"signature\" \"my message\"") +
c3a7f516 419 "\nAs json rpc\n"
70454796 420 + HelpExampleRpc("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"signature\", \"my message\"")
c3a7f516
WL
421 );
422
4401b2d7
EL
423 LOCK(cs_main);
424
c3a7f516
WL
425 string strAddress = params[0].get_str();
426 string strSign = params[1].get_str();
427 string strMessage = params[2].get_str();
428
07444da1
PW
429 CTxDestination destination = DecodeDestination(strAddress);
430 if (!IsValidDestination(destination)) {
c3a7f516 431 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
07444da1 432 }
c3a7f516 433
07444da1
PW
434 const CKeyID *keyID = boost::get<CKeyID>(&destination);
435 if (!keyID) {
c3a7f516 436 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
07444da1 437 }
c3a7f516
WL
438
439 bool fInvalid = false;
440 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
441
442 if (fInvalid)
443 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
444
445 CHashWriter ss(SER_GETHASH, 0);
446 ss << strMessageMagic;
447 ss << strMessage;
448
449 CPubKey pubkey;
450 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
451 return false;
452
07444da1 453 return (pubkey.GetID() == *keyID);
c3a7f516 454}
a8b2ce55 455
d014114d 456UniValue setmocktime(const UniValue& params, bool fHelp)
a8b2ce55
GA
457{
458 if (fHelp || params.size() != 1)
459 throw runtime_error(
460 "setmocktime timestamp\n"
461 "\nSet the local time to given timestamp (-regtest only)\n"
462 "\nArguments:\n"
463 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
464 " Pass 0 to go back to using the system time."
465 );
466
467 if (!Params().MineBlocksOnDemand())
468 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
469
abb0e8cc
GA
470 // cs_vNodes is locked and node send/receive times are updated
471 // atomically with the time change to prevent peers from being
472 // disconnected because we think we haven't communicated with them
473 // in a long time.
474 LOCK2(cs_main, cs_vNodes);
4401b2d7 475
9756b7bd 476 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
a8b2ce55
GA
477 SetMockTime(params[0].get_int64());
478
abb0e8cc
GA
479 uint64_t t = GetTime();
480 BOOST_FOREACH(CNode* pnode, vNodes) {
481 pnode->nLastSend = pnode->nLastRecv = t;
482 }
483
9756b7bd 484 return NullUniValue;
a8b2ce55 485}
a9496b08 486
86b23f37 487// insightexplorer
68e174e2
LR
488static bool getAddressFromIndex(
489 int type, const uint160 &hash, std::string &address)
490{
491 if (type == CScript::P2SH) {
492 address = EncodeDestination(CScriptID(hash));
493 } else if (type == CScript::P2PKH) {
494 address = EncodeDestination(CKeyID(hash));
495 } else {
496 return false;
497 }
498 return true;
499}
500
501// This function accepts an address and returns in the output parameters
502// the version and raw bytes for the RIPEMD-160 hash.
503static bool getIndexKey(
504 const CTxDestination& dest, uint160& hashBytes, int& type)
505{
506 if (!IsValidDestination(dest)) {
507 return false;
508 }
509 if (dest.type() == typeid(CKeyID)) {
510 auto x = boost::get<CKeyID>(&dest);
511 memcpy(&hashBytes, x->begin(), 20);
512 type = CScript::P2PKH;
513 return true;
514 }
515 if (dest.type() == typeid(CScriptID)) {
516 auto x = boost::get<CScriptID>(&dest);
517 memcpy(&hashBytes, x->begin(), 20);
518 type = CScript::P2SH;
519 return true;
520 }
521 return false;
522}
523
86b23f37 524// insightexplorer
68e174e2
LR
525static bool getAddressesFromParams(
526 const UniValue& params,
527 std::vector<std::pair<uint160, int>> &addresses)
528{
529 std::vector<std::string> param_addresses;
530 if (params[0].isStr()) {
531 param_addresses.push_back(params[0].get_str());
532 } else if (params[0].isObject()) {
533 UniValue addressValues = find_value(params[0].get_obj(), "addresses");
534 if (!addressValues.isArray()) {
535 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
536 "Addresses is expected to be an array");
537 }
538 for (const auto& it : addressValues.getValues()) {
539 param_addresses.push_back(it.get_str());
540 }
541
542 } else {
543 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
544 }
545 for (const auto& it : param_addresses) {
546 CTxDestination address = DecodeDestination(it);
547 uint160 hashBytes;
548 int type = 0;
549 if (!getIndexKey(address, hashBytes, type)) {
550 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
551 }
552 addresses.push_back(std::make_pair(hashBytes, type));
553 }
554 return true;
555}
556
86b23f37 557// insightexplorer
68e174e2
LR
558UniValue getaddressmempool(const UniValue& params, bool fHelp)
559{
560 std::string enableArg = "insightexplorer";
86b23f37 561 bool enabled = fExperimentalMode && fInsightExplorer;
68e174e2 562 std::string disabledMsg = "";
86b23f37 563 if (!enabled) {
68e174e2
LR
564 disabledMsg = experimentalDisabledHelpMsg("getaddressmempool", enableArg);
565 }
566 if (fHelp || params.size() != 1)
567 throw runtime_error(
568 "getaddressmempool {\"addresses\": [\"taddr\", ...]}\n"
569 "\nReturns all mempool deltas for an address.\n"
570 + disabledMsg +
571 "\nArguments:\n"
572 "{\n"
573 " \"addresses\":\n"
574 " [\n"
575 " \"address\" (string) The base58check encoded address\n"
576 " ,...\n"
577 " ]\n"
578 "}\n"
579 "(or)\n"
580 "\"address\" (string) The base58check encoded address\n"
581 "\nResult:\n"
582 "[\n"
583 " {\n"
584 " \"address\" (string) The base58check encoded address\n"
585 " \"txid\" (string) The related txid\n"
586 " \"index\" (number) The related input or output index\n"
587 " \"satoshis\" (number) The difference of zatoshis\n"
588 " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n"
589 " \"prevtxid\" (string) The previous txid (if spending)\n"
590 " \"prevout\" (string) The previous transaction output index (if spending)\n"
591 " }\n"
592 "]\n"
593 "\nExamples:\n"
594 + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}'")
595 + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}")
596 );
597
86b23f37 598 if (!enabled) {
68e174e2
LR
599 throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressmempool is disabled. "
600 "Run './zcash-cli help getaddressmempool' for instructions on how to enable this feature.");
601 }
602
603 std::vector<std::pair<uint160, int>> addresses;
604
605 if (!getAddressesFromParams(params, addresses)) {
606 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
607 }
608 std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta>> indexes;
609 mempool.getAddressIndex(addresses, indexes);
610 std::sort(indexes.begin(), indexes.end(),
611 [](const std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta>& a,
612 const std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta>& b) -> bool {
613 return a.second.time < b.second.time;
614 });
615
616 UniValue result(UniValue::VARR);
617
618 for (const auto& it : indexes) {
619 std::string address;
620 if (!getAddressFromIndex(it.first.type, it.first.addressBytes, address)) {
621 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
622 }
623 UniValue delta(UniValue::VOBJ);
624 delta.push_back(Pair("address", address));
625 delta.push_back(Pair("txid", it.first.txhash.GetHex()));
626 delta.push_back(Pair("index", (int)it.first.index));
627 delta.push_back(Pair("satoshis", it.second.amount));
628 delta.push_back(Pair("timestamp", it.second.time));
629 if (it.second.amount < 0) {
630 delta.push_back(Pair("prevtxid", it.second.prevhash.GetHex()));
631 delta.push_back(Pair("prevout", (int)it.second.prevout));
632 }
633 result.push_back(delta);
634 }
635 return result;
636}
637
86b23f37 638// insightexplorer
68e174e2
LR
639UniValue getaddressutxos(const UniValue& params, bool fHelp)
640{
641 std::string enableArg = "insightexplorer";
86b23f37 642 bool enabled = fExperimentalMode && fInsightExplorer;
68e174e2 643 std::string disabledMsg = "";
86b23f37 644 if (!enabled) {
68e174e2
LR
645 disabledMsg = experimentalDisabledHelpMsg("getaddressutxos", enableArg);
646 }
647 if (fHelp || params.size() != 1)
648 throw runtime_error(
649 "getaddressutxos {\"addresses\": [\"taddr\", ...], (\"chainInfo\": true|false)}\n"
650 "\nReturns all unspent outputs for an address.\n"
651 + disabledMsg +
652 "\nArguments:\n"
653 "{\n"
654 " \"addresses\":\n"
655 " [\n"
656 " \"address\" (string) The base58check encoded address\n"
657 " ,...\n"
658 " ],\n"
659 " \"chainInfo\" (boolean, optional, default=false) Include chain info with results\n"
660 "}\n"
661 "(or)\n"
662 "\"address\" (string) The base58check encoded address\n"
663 "\nResult\n"
664 "[\n"
665 " {\n"
666 " \"address\" (string) The address base58check encoded\n"
667 " \"txid\" (string) The output txid\n"
668 " \"height\" (number) The block height\n"
669 " \"outputIndex\" (number) The output index\n"
670 " \"script\" (string) The script hex encoded\n"
671 " \"satoshis\" (number) The number of zatoshis of the output\n"
672 " }, ...\n"
673 "]\n\n"
674 "(or, if chainInfo is true):\n\n"
675 "{\n"
676 " \"utxos\":\n"
677 " [\n"
678 " {\n"
679 " \"address\" (string) The address base58check encoded\n"
680 " \"txid\" (string) The output txid\n"
681 " \"height\" (number) The block height\n"
682 " \"outputIndex\" (number) The output index\n"
683 " \"script\" (string) The script hex encoded\n"
684 " \"satoshis\" (number) The number of zatoshis of the output\n"
685 " }, ...\n"
686 " ],\n"
687 " \"hash\" (string) The block hash\n"
688 " \"height\" (numeric) The block height\n"
689 "}\n"
690 "\nExamples:\n"
691 + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"chainInfo\": true}'")
692 + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"chainInfo\": true}")
693 );
694
86b23f37 695 if (!enabled) {
68e174e2
LR
696 throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressutxos is disabled. "
697 "Run './zcash-cli help getaddressutxos' for instructions on how to enable this feature.");
698 }
699
700 bool includeChainInfo = false;
701 if (params[0].isObject()) {
702 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
703 if (!chainInfo.isNull()) {
704 includeChainInfo = chainInfo.get_bool();
705 }
706 }
707 std::vector<std::pair<uint160, int>> addresses;
708 if (!getAddressesFromParams(params, addresses)) {
709 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
710 }
711 std::vector<CAddressUnspentDbEntry> unspentOutputs;
712 for (const auto& it : addresses) {
713 if (!GetAddressUnspent(it.first, it.second, unspentOutputs)) {
714 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
715 }
716 }
717 std::sort(unspentOutputs.begin(), unspentOutputs.end(),
718 [](const CAddressUnspentDbEntry& a, const CAddressUnspentDbEntry& b) -> bool {
719 return a.second.blockHeight < b.second.blockHeight;
720 });
721
722 UniValue utxos(UniValue::VARR);
723 for (const auto& it : unspentOutputs) {
724 UniValue output(UniValue::VOBJ);
725 std::string address;
726 if (!getAddressFromIndex(it.first.type, it.first.hashBytes, address)) {
727 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
728 }
729
730 output.push_back(Pair("address", address));
731 output.push_back(Pair("txid", it.first.txhash.GetHex()));
732 output.push_back(Pair("outputIndex", (int)it.first.index));
733 output.push_back(Pair("script", HexStr(it.second.script.begin(), it.second.script.end())));
734 output.push_back(Pair("satoshis", it.second.satoshis));
735 output.push_back(Pair("height", it.second.blockHeight));
736 utxos.push_back(output);
737 }
738
739 if (!includeChainInfo)
740 return utxos;
741
742 UniValue result(UniValue::VOBJ);
743 result.push_back(Pair("utxos", utxos));
744
745 LOCK(cs_main); // for chainActive
746 result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex()));
747 result.push_back(Pair("height", (int)chainActive.Height()));
748 return result;
749}
750
751static void getHeightRange(const UniValue& params, int& start, int& end)
752{
753 start = 0;
754 end = 0;
755 if (params[0].isObject()) {
756 UniValue startValue = find_value(params[0].get_obj(), "start");
757 UniValue endValue = find_value(params[0].get_obj(), "end");
758 // If either is not specified, the other is ignored.
759 if (!startValue.isNull() && !endValue.isNull()) {
760 start = startValue.get_int();
761 end = endValue.get_int();
762 if (start <= 0 || end <= 0) {
763 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
764 "Start and end are expected to be greater than zero");
765 }
766 if (end < start) {
767 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
768 "End value is expected to be greater than start");
769 }
770 }
771 }
772
773 LOCK(cs_main); // for chainActive
774 if (start > chainActive.Height() || end > chainActive.Height()) {
775 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range");
776 }
777}
778
779// Parse an address list then fetch the corresponding addressindex information.
780static void getAddressesInHeightRange(
781 const UniValue& params,
782 int start, int end,
783 std::vector<std::pair<uint160, int>>& addresses,
784 std::vector<std::pair<CAddressIndexKey, CAmount>> &addressIndex)
785{
786 if (!getAddressesFromParams(params, addresses)) {
787 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
788 }
789 for (const auto& it : addresses) {
790 if (!GetAddressIndex(it.first, it.second, addressIndex, start, end)) {
791 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
792 "No information available for address");
793 }
794 }
795}
796
86b23f37 797// insightexplorer
68e174e2
LR
798UniValue getaddressdeltas(const UniValue& params, bool fHelp)
799{
800 std::string enableArg = "insightexplorer";
86b23f37 801 bool enabled = fExperimentalMode && fInsightExplorer;
68e174e2 802 std::string disabledMsg = "";
86b23f37 803 if (!enabled) {
68e174e2
LR
804 disabledMsg = experimentalDisabledHelpMsg("getaddressdeltas", enableArg);
805 }
806 if (fHelp || params.size() != 1)
807 throw runtime_error(
808 "getaddressdeltas {\"addresses\": [\"taddr\", ...], (\"start\": n), (\"end\": n), (\"chainInfo\": true|false)}\n"
809 "\nReturns all changes for an address.\n"
810 "\nReturns information about all changes to the given transparent addresses within the given (inclusive)\n"
811 "\nblock height range, default is the full blockchain.\n"
812 + disabledMsg +
813 "\nArguments:\n"
814 "{\n"
815 " \"addresses\":\n"
816 " [\n"
817 " \"address\" (string) The base58check encoded address\n"
818 " ,...\n"
819 " ]\n"
820 " \"start\" (number, optional) The start block height\n"
821 " \"end\" (number, optional) The end block height\n"
822 " \"chainInfo\" (boolean, optional, default=false) Include chain info in results, only applies if start and end specified\n"
823 "}\n"
824 "(or)\n"
825 "\"address\" (string) The base58check encoded address\n"
826 "\nResult:\n"
827 "[\n"
828 " {\n"
829 " \"satoshis\" (number) The difference of zatoshis\n"
830 " \"txid\" (string) The related txid\n"
831 " \"index\" (number) The related input or output index\n"
832 " \"height\" (number) The block height\n"
833 " \"address\" (string) The base58check encoded address\n"
834 " }, ...\n"
835 "]\n\n"
836 "(or, if chainInfo is true):\n\n"
837 "{\n"
838 " \"deltas\":\n"
839 " [\n"
840 " {\n"
841 " \"satoshis\" (number) The difference of zatoshis\n"
842 " \"txid\" (string) The related txid\n"
843 " \"index\" (number) The related input or output index\n"
844 " \"height\" (number) The block height\n"
845 " \"address\" (string) The address base58check encoded\n"
846 " }, ...\n"
847 " ],\n"
848 " \"start\":\n"
849 " {\n"
850 " \"hash\" (string) The start block hash\n"
851 " \"height\" (numeric) The height of the start block\n"
852 " }\n"
853 " \"end\":\n"
854 " {\n"
855 " \"hash\" (string) The end block hash\n"
856 " \"height\" (numeric) The height of the end block\n"
857 " }\n"
858 "}\n"
859 "\nExamples:\n"
860 + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000, \"chainInfo\": true}'")
861 + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000, \"chainInfo\": true}")
862 );
863
86b23f37 864 if (!enabled) {
68e174e2
LR
865 throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressdeltas is disabled. "
866 "Run './zcash-cli help getaddressdeltas' for instructions on how to enable this feature.");
867 }
868
869 int start = 0;
870 int end = 0;
871 getHeightRange(params, start, end);
872
873 std::vector<std::pair<uint160, int>> addresses;
874 std::vector<std::pair<CAddressIndexKey, CAmount>> addressIndex;
875 getAddressesInHeightRange(params, start, end, addresses, addressIndex);
876
877 bool includeChainInfo = false;
878 if (params[0].isObject()) {
879 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
880 if (!chainInfo.isNull()) {
881 includeChainInfo = chainInfo.get_bool();
882 }
883 }
884
885 UniValue deltas(UniValue::VARR);
886 for (const auto& it : addressIndex) {
887 std::string address;
888 if (!getAddressFromIndex(it.first.type, it.first.hashBytes, address)) {
889 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
890 }
891
892 UniValue delta(UniValue::VOBJ);
893 delta.push_back(Pair("address", address));
894 delta.push_back(Pair("blockindex", (int)it.first.txindex));
895 delta.push_back(Pair("height", it.first.blockHeight));
896 delta.push_back(Pair("index", (int)it.first.index));
897 delta.push_back(Pair("satoshis", it.second));
898 delta.push_back(Pair("txid", it.first.txhash.GetHex()));
899 deltas.push_back(delta);
900 }
901
902 UniValue result(UniValue::VOBJ);
903
904 if (!(includeChainInfo && start > 0 && end > 0)) {
905 return deltas;
906 }
907
908 UniValue startInfo(UniValue::VOBJ);
909 UniValue endInfo(UniValue::VOBJ);
910 {
911 LOCK(cs_main); // for chainActive
912 if (start > chainActive.Height() || end > chainActive.Height()) {
913 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range");
914 }
915 startInfo.push_back(Pair("hash", chainActive[start]->GetBlockHash().GetHex()));
916 endInfo.push_back(Pair("hash", chainActive[end]->GetBlockHash().GetHex()));
917 }
918 startInfo.push_back(Pair("height", start));
919 endInfo.push_back(Pair("height", end));
920
921 result.push_back(Pair("deltas", deltas));
922 result.push_back(Pair("start", startInfo));
923 result.push_back(Pair("end", endInfo));
924
925 return result;
926}
927
86b23f37 928// insightexplorer
68e174e2
LR
929UniValue getaddressbalance(const UniValue& params, bool fHelp)
930{
931 std::string enableArg = "insightexplorer";
86b23f37 932 bool enabled = fExperimentalMode && fInsightExplorer;
68e174e2 933 std::string disabledMsg = "";
86b23f37 934 if (!enabled) {
68e174e2
LR
935 disabledMsg = experimentalDisabledHelpMsg("getaddressbalance", enableArg);
936 }
937 if (fHelp || params.size() != 1)
938 throw runtime_error(
939 "getaddressbalance {\"addresses\": [\"taddr\", ...]}\n"
940 "\nReturns the balance for addresses.\n"
941 + disabledMsg +
942 "\nArguments:\n"
943 "{\n"
944 " \"addresses:\"\n"
945 " [\n"
946 " \"address\" (string) The base58check encoded address\n"
947 " ,...\n"
948 " ]\n"
949 "}\n"
950 "(or)\n"
951 "\"address\" (string) The base58check encoded address\n"
952 "\nResult:\n"
953 "{\n"
954 " \"balance\" (string) The current balance in zatoshis\n"
955 " \"received\" (string) The total number of zatoshis received (including change)\n"
956 "}\n"
957 "\nExamples:\n"
958 + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}'")
959 + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}")
960 );
961
86b23f37 962 if (!enabled) {
68e174e2
LR
963 throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressbalance is disabled. "
964 "Run './zcash-cli help getaddressbalance' for instructions on how to enable this feature.");
965 }
966
967 std::vector<std::pair<uint160, int>> addresses;
968 std::vector<std::pair<CAddressIndexKey, CAmount>> addressIndex;
969 // this method doesn't take start and end block height params, so set
970 // to zero (full range, entire blockchain)
971 getAddressesInHeightRange(params, 0, 0, addresses, addressIndex);
972
973 CAmount balance = 0;
974 CAmount received = 0;
975 for (const auto& it : addressIndex) {
976 if (it.second > 0) {
977 received += it.second;
978 }
979 balance += it.second;
980 }
981 UniValue result(UniValue::VOBJ);
982 result.push_back(Pair("balance", balance));
983 result.push_back(Pair("received", received));
984 return result;
985}
986
86b23f37 987// insightexplorer
68e174e2
LR
988UniValue getaddresstxids(const UniValue& params, bool fHelp)
989{
990 std::string enableArg = "insightexplorer";
86b23f37 991 bool enabled = fExperimentalMode && fInsightExplorer;
68e174e2 992 std::string disabledMsg = "";
86b23f37 993 if (!enabled) {
68e174e2
LR
994 disabledMsg = experimentalDisabledHelpMsg("getaddresstxids", enableArg);
995 }
996 if (fHelp || params.size() != 1)
997 throw runtime_error(
998 "getaddresstxids {\"addresses\": [\"taddr\", ...], (\"start\": n), (\"end\": n)}\n"
999 "\nReturns the txids for given transparent addresses within the given (inclusive)\n"
1000 "\nblock height range, default is the full blockchain.\n"
1001 + disabledMsg +
1002 "\nArguments:\n"
1003 "{\n"
1004 " \"addresses\":\n"
1005 " [\n"
1006 " \"taddr\" (string) The base58check encoded address\n"
1007 " ,...\n"
1008 " ]\n"
1009 " \"start\" (number, optional) The start block height\n"
1010 " \"end\" (number, optional) The end block height\n"
1011 "}\n"
1012 "(or)\n"
1013 "\"address\" (string) The base58check encoded address\n"
1014 "\nResult:\n"
1015 "[\n"
1016 " \"transactionid\" (string) The transaction id\n"
1017 " ,...\n"
1018 "]\n"
1019 "\nExamples:\n"
1020 + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000}'")
1021 + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000}")
1022 );
1023
86b23f37 1024 if (!enabled) {
68e174e2
LR
1025 throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddresstxids is disabled. "
1026 "Run './zcash-cli help getaddresstxids' for instructions on how to enable this feature.");
1027 }
1028
1029 int start = 0;
1030 int end = 0;
1031 getHeightRange(params, start, end);
1032
1033 std::vector<std::pair<uint160, int>> addresses;
1034 std::vector<std::pair<CAddressIndexKey, CAmount>> addressIndex;
1035 getAddressesInHeightRange(params, start, end, addresses, addressIndex);
1036
1037 // This is an ordered set, sorted by height, so result also sorted by height.
1038 std::set<std::pair<int, std::string>> txids;
1039
1040 for (const auto& it : addressIndex) {
1041 const int height = it.first.blockHeight;
1042 const std::string txid = it.first.txhash.GetHex();
1043 // Duplicate entries (two addresses in same tx) are suppressed
1044 txids.insert(std::make_pair(height, txid));
1045 }
1046 UniValue result(UniValue::VARR);
1047 for (const auto& it : txids) {
1048 // only push the txid, not the height
1049 result.push_back(it.second);
1050 }
1051 return result;
1052}
1053
86b23f37
LR
1054// insightexplorer
1055UniValue getspentinfo(const UniValue& params, bool fHelp)
1056{
1057 std::string enableArg = "insightexplorer";
1058 bool enabled = fExperimentalMode && fInsightExplorer;
1059 std::string disabledMsg = "";
1060 if (!enabled) {
1061 disabledMsg = experimentalDisabledHelpMsg("getspentinfo", enableArg);
1062 }
1063 if (fHelp || params.size() != 1 || !params[0].isObject())
1064 throw runtime_error(
1065 "getspentinfo {\"txid\": \"txidhex\", \"index\": n}\n"
1066 "\nReturns the txid and index where an output is spent.\n"
1067 + disabledMsg +
1068 "\nArguments:\n"
1069 "{\n"
1070 " \"txid\" (string) The hex string of the txid\n"
1071 " \"index\" (number) The vout (output) index\n"
1072 "}\n"
1073 "\nResult:\n"
1074 "{\n"
1075 " \"txid\" (string) The transaction id\n"
1076 " \"index\" (number) The spending (vin, input) index\n"
1077 " ,...\n"
1078 "}\n"
1079 "\nExamples:\n"
1080 + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'")
1081 + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}")
1082 );
1083
1084 if (!enabled) {
1085 throw JSONRPCError(RPC_MISC_ERROR, "Error: getspentinfo is disabled. "
1086 "Run './zcash-cli help getspentinfo' for instructions on how to enable this feature.");
1087 }
1088
1089 UniValue txidValue = find_value(params[0].get_obj(), "txid");
1090 UniValue indexValue = find_value(params[0].get_obj(), "index");
1091
1092 if (!txidValue.isStr())
1093 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid, must be a string");
1094 if (!indexValue.isNum())
1095 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid index, must be an integer");
1096 uint256 txid = ParseHashV(txidValue, "txid");
1097 int outputIndex = indexValue.get_int();
1098
1099 CSpentIndexKey key(txid, outputIndex);
1100 CSpentIndexValue value;
1101
1102 if (!GetSpentIndex(key, value)) {
1103 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info");
1104 }
1105 UniValue obj(UniValue::VOBJ);
1106 obj.push_back(Pair("txid", value.txid.GetHex()));
1107 obj.push_back(Pair("index", (int)value.inputIndex));
1108 obj.push_back(Pair("height", value.blockHeight));
1109
1110 return obj;
1111}
68e174e2 1112
a9496b08
WL
1113static const CRPCCommand commands[] =
1114{ // category name actor (function) okSafeMode
1115 // --------------------- ------------------------ ----------------------- ----------
1116 { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
1117 { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
1118 { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */
1119 { "util", "createmultisig", &createmultisig, true },
1120 { "util", "verifymessage", &verifymessage, true },
1121
86b23f37 1122 // START insightexplorer
68e174e2
LR
1123 /* Address index */
1124 { "addressindex", "getaddresstxids", &getaddresstxids, false }, /* insight explorer */
1125 { "addressindex", "getaddressbalance", &getaddressbalance, false }, /* insight explorer */
1126 { "addressindex", "getaddressdeltas", &getaddressdeltas, false }, /* insight explorer */
1127 { "addressindex", "getaddressutxos", &getaddressutxos, false }, /* insight explorer */
1128 { "addressindex", "getaddressmempool", &getaddressmempool, true }, /* insight explorer */
86b23f37
LR
1129 { "blockchain", "getspentinfo", &getspentinfo, false }, /* insight explorer */
1130 // END insightexplorer
68e174e2 1131
a9496b08
WL
1132 /* Not shown in help */
1133 { "hidden", "setmocktime", &setmocktime, true },
1134};
1135
1136void RegisterMiscRPCCommands(CRPCTable &tableRPC)
1137{
1138 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1139 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1140}
This page took 0.316455 seconds and 4 git commands to generate.