]> Git Repo - VerusCoin.git/blame - src/rpcmisc.cpp
Bitcore port
[VerusCoin.git] / src / rpcmisc.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
652e1569
WL
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "base58.h"
71697f97 7#include "clientversion.h"
652e1569
WL
8#include "init.h"
9#include "main.h"
10#include "net.h"
11#include "netbase.h"
c037531d 12#include "rpcserver.h"
14f888ca 13#include "timedata.h"
8b78a819 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 **/
945f015d 44
b487a8fe 45int32_t Jumblr_depositaddradd(char *depositaddr);
eeaaf554 46int32_t Jumblr_secretaddradd(char *secretaddr);
da16b12e 47uint64_t komodo_interestsum();
f595c2e0 48int32_t komodo_longestchain();
c75c18fc 49int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp);
58033467 50int32_t komodo_whoami(char *pubkeystr,int32_t height);
eea03b7b 51extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE;
b000fa04 52extern char ASSETCHAINS_SYMBOL[];
0cb025c1 53int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
eeaaf554 54#define KOMODO_VERSION "0.1.1"
09e3cf94 55
d014114d 56UniValue getinfo(const UniValue& params, bool fHelp)
16bc9aaf 57{
7ea5a371 58 uint256 notarized_hash,notarized_desttxid; int32_t notarized_height,longestchain,kmdnotarized_height,txid_height;
16bc9aaf
WL
59 if (fHelp || params.size() != 0)
60 throw runtime_error(
61 "getinfo\n"
62 "Returns an object containing various state info.\n"
63 "\nResult:\n"
64 "{\n"
65 " \"version\": xxxxx, (numeric) the server version\n"
66 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
67 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
68 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
69 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
70 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
71 " \"connections\": xxxxx, (numeric) the number of connections\n"
72 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
73 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
74 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
75 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
76 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
16bc9aaf 77 " \"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"
1294cdc4
GM
78 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
79 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
16bc9aaf
WL
80 " \"errors\": \"...\" (string) any error messages\n"
81 "}\n"
82 "\nExamples:\n"
83 + HelpExampleCli("getinfo", "")
84 + HelpExampleRpc("getinfo", "")
85 );
86
4401b2d7
EL
87#ifdef ENABLE_WALLET
88 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
89#else
90 LOCK(cs_main);
91#endif
92
16bc9aaf
WL
93 proxyType proxy;
94 GetProxy(NET_IPV4, proxy);
c75c18fc 95 notarized_height = komodo_notarized_height(&notarized_hash,&notarized_desttxid);
16bc9aaf 96
38fc4b70 97 UniValue obj(UniValue::VOBJ);
faadbe17
PK
98 obj.push_back(Pair("version", CLIENT_VERSION));
99 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
b000fa04 100 obj.push_back(Pair("KMDversion", KOMODO_VERSION));
c75c18fc 101 obj.push_back(Pair("notarized", notarized_height));
102 obj.push_back(Pair("notarizedhash", notarized_hash.ToString()));
103 obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString()));
7ea5a371 104 txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height);
70d83934 105 if ( txid_height > 0 )
106 obj.push_back(Pair("notarizedtxid_height", txid_height));
107 else obj.push_back(Pair("notarizedtxid_height", "mempool"));
57dd4ada 108 if ( ASSETCHAINS_SYMBOL[0] != 0 )
109 obj.push_back(Pair("KMDnotarized_height", kmdnotarized_height));
110 obj.push_back(Pair("notarized_confirms", txid_height < kmdnotarized_height ? (kmdnotarized_height - txid_height + 1) : 0));
16bc9aaf
WL
111#ifdef ENABLE_WALLET
112 if (pwalletMain) {
113 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
114 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
9e1bde7e 115 if ( ASSETCHAINS_SYMBOL[0] == 0 )
b000fa04 116 obj.push_back(Pair("interest", ValueFromAmount(komodo_interestsum())));
16bc9aaf
WL
117 }
118#endif
119 obj.push_back(Pair("blocks", (int)chainActive.Height()));
a19b28ce 120 if ( (longestchain= komodo_longestchain()) != 0 && chainActive.Height() > longestchain )
121 longestchain = chainActive.Height();
122 obj.push_back(Pair("longestchain", longestchain));
d56e30ca 123 obj.push_back(Pair("timeoffset", GetTimeOffset()));
98d166cf 124 if ( chainActive.Tip() != 0 )
49c9db6a 125 obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime));
16bc9aaf 126 obj.push_back(Pair("connections", (int)vNodes.size()));
67a79493 127 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
16bc9aaf 128 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
cc972107 129 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
16bc9aaf
WL
130#ifdef ENABLE_WALLET
131 if (pwalletMain) {
d56e30ca 132 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
16bc9aaf
WL
133 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
134 }
16bc9aaf 135 if (pwalletMain && pwalletMain->IsCrypted())
d56e30ca 136 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
c6cb21d1 137 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
16bc9aaf 138#endif
13fc83c7 139 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
16bc9aaf 140 obj.push_back(Pair("errors", GetWarnings("statusbar")));
58033467 141 {
142 char pubkeystr[65]; int32_t notaryid;
1e2a41f6 143 if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight)) >= 0 )
144 {
145 obj.push_back(Pair("notaryid", notaryid));
146 obj.push_back(Pair("pubkey", pubkeystr));
147 if ( KOMODO_LASTMINED != 0 )
148 obj.push_back(Pair("lastmined", KOMODO_LASTMINED));
149 }
58033467 150 }
16bc9aaf
WL
151 return obj;
152}
153
452955f5 154#ifdef ENABLE_WALLET
d014114d 155class DescribeAddressVisitor : public boost::static_visitor<UniValue>
452955f5
WL
156{
157public:
d014114d 158 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
452955f5 159
851f58f9 160 UniValue operator()(const CKeyID &keyID) const {
38fc4b70 161 UniValue obj(UniValue::VOBJ);
452955f5 162 CPubKey vchPubKey;
452955f5 163 obj.push_back(Pair("isscript", false));
56215c77 164 if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
c8988460
PW
165 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
166 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
167 }
452955f5
WL
168 return obj;
169 }
170
851f58f9 171 UniValue operator()(const CScriptID &scriptID) const {
38fc4b70 172 UniValue obj(UniValue::VOBJ);
9c7167d1 173 CScript subscript;
452955f5 174 obj.push_back(Pair("isscript", true));
56215c77 175 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
c8988460
PW
176 std::vector<CTxDestination> addresses;
177 txnouttype whichType;
178 int nRequired;
179 ExtractDestinations(subscript, whichType, addresses, nRequired);
180 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
181 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
38fc4b70 182 UniValue a(UniValue::VARR);
c8988460
PW
183 BOOST_FOREACH(const CTxDestination& addr, addresses)
184 a.push_back(CBitcoinAddress(addr).ToString());
185 obj.push_back(Pair("addresses", a));
186 if (whichType == TX_MULTISIG)
187 obj.push_back(Pair("sigsrequired", nRequired));
188 }
452955f5
WL
189 return obj;
190 }
191};
192#endif
193
eeaaf554 194UniValue jumblr_deposit(const UniValue& params, bool fHelp)
195{
b487a8fe 196 int32_t retval; UniValue result(UniValue::VOBJ);
eeaaf554 197 if (fHelp || params.size() != 1)
198 throw runtime_error("jumblr_deposit \"depositaddress\"\n");
199 CBitcoinAddress address(params[0].get_str());
200 bool isValid = address.IsValid();
201 if ( isValid != 0 )
202 {
203 string addr = params[0].get_str();
b487a8fe 204 if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 )
190dbe6d 205 result.push_back(Pair("result", retval));
b487a8fe 206 else result.push_back(Pair("error", retval));
eeaaf554 207 } else result.push_back(Pair("error", "invalid address"));
208 return(result);
209}
210
211UniValue jumblr_secret(const UniValue& params, bool fHelp)
212{
213 int32_t retval; UniValue result(UniValue::VOBJ);
214 if (fHelp || params.size() != 1)
215 throw runtime_error("jumblr_secret \"secretaddress\"\n");
216 CBitcoinAddress address(params[0].get_str());
217 bool isValid = address.IsValid();
218 if ( isValid != 0 )
219 {
220 string addr = params[0].get_str();
bc035879 221 retval = Jumblr_secretaddradd((char *)addr.c_str());
eeaaf554 222 result.push_back(Pair("result", "success"));
223 result.push_back(Pair("num", retval));
224 } else result.push_back(Pair("error", "invalid address"));
225 return(result);
226}
227
eea03b7b 228UniValue jumblr_pause(const UniValue& params, bool fHelp)
229{
230 int32_t retval; UniValue result(UniValue::VOBJ);
231 if (fHelp )
232 throw runtime_error("jumblr_pause\n");
233 JUMBLR_PAUSE = 1;
234 result.push_back(Pair("result", "paused"));
235 return(result);
236}
237
238UniValue jumblr_resume(const UniValue& params, bool fHelp)
239{
240 int32_t retval; UniValue result(UniValue::VOBJ);
241 if (fHelp )
242 throw runtime_error("jumblr_resume\n");
243 JUMBLR_PAUSE = 0;
244 result.push_back(Pair("result", "resumed"));
245 return(result);
246}
247
d014114d 248UniValue validateaddress(const UniValue& params, bool fHelp)
452955f5
WL
249{
250 if (fHelp || params.size() != 1)
251 throw runtime_error(
252 "validateaddress \"bitcoinaddress\"\n"
253 "\nReturn information about the given bitcoin address.\n"
254 "\nArguments:\n"
255 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
256 "\nResult:\n"
257 "{\n"
258 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
259 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
426a74ed 260 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
452955f5
WL
261 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
262 " \"isscript\" : true|false, (boolean) If the key is a script\n"
263 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
264 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
7b782f5b 265 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
452955f5
WL
266 "}\n"
267 "\nExamples:\n"
268 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
269 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
270 );
271
4401b2d7
EL
272#ifdef ENABLE_WALLET
273 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
274#else
275 LOCK(cs_main);
276#endif
277
452955f5
WL
278 CBitcoinAddress address(params[0].get_str());
279 bool isValid = address.IsValid();
280
38fc4b70 281 UniValue ret(UniValue::VOBJ);
452955f5
WL
282 ret.push_back(Pair("isvalid", isValid));
283 if (isValid)
284 {
285 CTxDestination dest = address.Get();
286 string currentAddress = address.ToString();
287 ret.push_back(Pair("address", currentAddress));
426a74ed
PT
288
289 CScript scriptPubKey = GetScriptForDestination(dest);
290 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
291
452955f5 292#ifdef ENABLE_WALLET
a3e192a3
J
293 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
294 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
9c7167d1 295 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
296 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
297 ret.pushKVs(detail);
452955f5
WL
298 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
299 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
300#endif
301 }
302 return ret;
303}
304
4e16a724 305
0d37ae3a 306UniValue z_validateaddress(const UniValue& params, bool fHelp)
4e16a724
S
307{
308 if (fHelp || params.size() != 1)
309 throw runtime_error(
310 "z_validateaddress \"zaddr\"\n"
311 "\nReturn information about the given z address.\n"
312 "\nArguments:\n"
313 "1. \"zaddr\" (string, required) The z address to validate\n"
314 "\nResult:\n"
315 "{\n"
316 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
317 " \"address\" : \"zaddr\", (string) The z address validated\n"
318 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
319 " \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n"
320 " \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n"
321
322 "}\n"
323 "\nExamples:\n"
324 + HelpExampleCli("validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
325 );
326
327
328#ifdef ENABLE_WALLET
329 LOCK2(cs_main, pwalletMain->cs_wallet);
330#else
331 LOCK(cs_main);
332#endif
333
334 bool isValid = false;
335 bool isMine = false;
336 std::string payingKey, transmissionKey;
337
338 string strAddress = params[0].get_str();
339 try {
340 CZCPaymentAddress address(strAddress);
341 libzcash::PaymentAddress addr = address.Get();
342
343#ifdef ENABLE_WALLET
344 isMine = pwalletMain->HaveSpendingKey(addr);
345#endif
346 payingKey = addr.a_pk.GetHex();
347 transmissionKey = addr.pk_enc.GetHex();
348 isValid = true;
349 } catch (std::runtime_error e) {
350 // address is invalid, nop here as isValid is false.
351 }
352
0d37ae3a 353 UniValue ret(UniValue::VOBJ);
4e16a724
S
354 ret.push_back(Pair("isvalid", isValid));
355 if (isValid)
356 {
357 ret.push_back(Pair("address", strAddress));
358 ret.push_back(Pair("payingkey", payingKey));
359 ret.push_back(Pair("transmissionkey", transmissionKey));
360#ifdef ENABLE_WALLET
361 ret.push_back(Pair("ismine", isMine));
362#endif
363 }
364 return ret;
365}
366
367
72fb3d29
MF
368/**
369 * Used by addmultisigaddress / createmultisig:
370 */
d014114d 371CScript _createmultisig_redeemScript(const UniValue& params)
723a03d2
WL
372{
373 int nRequired = params[0].get_int();
d014114d 374 const UniValue& keys = params[1].get_array();
723a03d2
WL
375
376 // Gather public keys
377 if (nRequired < 1)
378 throw runtime_error("a multisignature address must require at least one key to redeem");
379 if ((int)keys.size() < nRequired)
380 throw runtime_error(
381 strprintf("not enough keys supplied "
783b182c 382 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
e5d9d77d 383 if (keys.size() > 16)
384 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
723a03d2
WL
385 std::vector<CPubKey> pubkeys;
386 pubkeys.resize(keys.size());
387 for (unsigned int i = 0; i < keys.size(); i++)
388 {
389 const std::string& ks = keys[i].get_str();
390#ifdef ENABLE_WALLET
391 // Case 1: Bitcoin address and we have full public key:
392 CBitcoinAddress address(ks);
393 if (pwalletMain && address.IsValid())
394 {
395 CKeyID keyID;
396 if (!address.GetKeyID(keyID))
397 throw runtime_error(
7d9d134b 398 strprintf("%s does not refer to a key",ks));
723a03d2
WL
399 CPubKey vchPubKey;
400 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
401 throw runtime_error(
7d9d134b 402 strprintf("no full public key for address %s",ks));
723a03d2
WL
403 if (!vchPubKey.IsFullyValid())
404 throw runtime_error(" Invalid public key: "+ks);
405 pubkeys[i] = vchPubKey;
406 }
407
408 // Case 2: hex public key
409 else
410#endif
411 if (IsHex(ks))
412 {
413 CPubKey vchPubKey(ParseHex(ks));
414 if (!vchPubKey.IsFullyValid())
415 throw runtime_error(" Invalid public key: "+ks);
416 pubkeys[i] = vchPubKey;
417 }
418 else
419 {
420 throw runtime_error(" Invalid public key: "+ks);
421 }
422 }
0be990ba 423 CScript result = GetScriptForMultisig(nRequired, pubkeys);
787ee0c9
PT
424
425 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
426 throw runtime_error(
427 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
428
723a03d2
WL
429 return result;
430}
431
d014114d 432UniValue createmultisig(const UniValue& params, bool fHelp)
723a03d2
WL
433{
434 if (fHelp || params.size() < 2 || params.size() > 2)
435 {
436 string msg = "createmultisig nrequired [\"key\",...]\n"
437 "\nCreates a multi-signature address with n signature of m keys required.\n"
438 "It returns a json object with the address and redeemScript.\n"
439
440 "\nArguments:\n"
441 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
442 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
443 " [\n"
444 " \"key\" (string) bitcoin address or hex-encoded public key\n"
445 " ,...\n"
446 " ]\n"
447
448 "\nResult:\n"
449 "{\n"
450 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
451 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
452 "}\n"
453
454 "\nExamples:\n"
455 "\nCreate a multisig address from 2 addresses\n"
456 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
457 "\nAs a json rpc call\n"
e3e3728f 458 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
723a03d2
WL
459 ;
460 throw runtime_error(msg);
461 }
462
463 // Construct using pay-to-script-hash:
787ee0c9 464 CScript inner = _createmultisig_redeemScript(params);
066e2a14 465 CScriptID innerID(inner);
723a03d2
WL
466 CBitcoinAddress address(innerID);
467
b47f3aea 468 UniValue result(UniValue::VOBJ);
723a03d2
WL
469 result.push_back(Pair("address", address.ToString()));
470 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
471
472 return result;
473}
474
d014114d 475UniValue verifymessage(const UniValue& params, bool fHelp)
c3a7f516
WL
476{
477 if (fHelp || params.size() != 3)
478 throw runtime_error(
479 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
480 "\nVerify a signed message\n"
481 "\nArguments:\n"
482 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
483 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
484 "3. \"message\" (string, required) The message that was signed.\n"
485 "\nResult:\n"
486 "true|false (boolean) If the signature is verified or not.\n"
487 "\nExamples:\n"
488 "\nUnlock the wallet for 30 seconds\n"
489 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
490 "\nCreate the signature\n"
491 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
492 "\nVerify the signature\n"
493 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
494 "\nAs json rpc\n"
495 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
496 );
497
4401b2d7
EL
498 LOCK(cs_main);
499
c3a7f516
WL
500 string strAddress = params[0].get_str();
501 string strSign = params[1].get_str();
502 string strMessage = params[2].get_str();
503
504 CBitcoinAddress addr(strAddress);
505 if (!addr.IsValid())
506 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
507
508 CKeyID keyID;
509 if (!addr.GetKeyID(keyID))
510 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
511
512 bool fInvalid = false;
513 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
514
515 if (fInvalid)
516 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
517
518 CHashWriter ss(SER_GETHASH, 0);
519 ss << strMessageMagic;
520 ss << strMessage;
521
522 CPubKey pubkey;
523 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
524 return false;
525
526 return (pubkey.GetID() == keyID);
527}
a8b2ce55 528
d014114d 529UniValue setmocktime(const UniValue& params, bool fHelp)
a8b2ce55
GA
530{
531 if (fHelp || params.size() != 1)
532 throw runtime_error(
533 "setmocktime timestamp\n"
534 "\nSet the local time to given timestamp (-regtest only)\n"
535 "\nArguments:\n"
536 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
537 " Pass 0 to go back to using the system time."
538 );
539
540 if (!Params().MineBlocksOnDemand())
541 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
542
abb0e8cc
GA
543 // cs_vNodes is locked and node send/receive times are updated
544 // atomically with the time change to prevent peers from being
545 // disconnected because we think we haven't communicated with them
546 // in a long time.
547 LOCK2(cs_main, cs_vNodes);
4401b2d7 548
9756b7bd 549 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
a8b2ce55
GA
550 SetMockTime(params[0].get_int64());
551
abb0e8cc
GA
552 uint64_t t = GetTime();
553 BOOST_FOREACH(CNode* pnode, vNodes) {
554 pnode->nLastSend = pnode->nLastRecv = t;
555 }
556
9756b7bd 557 return NullUniValue;
a8b2ce55 558}
8b78a819
T
559
560bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address)
561{
562 if (type == 2) {
563 address = CBitcoinAddress(CScriptID(hash)).ToString();
564 } else if (type == 1) {
565 address = CBitcoinAddress(CKeyID(hash)).ToString();
566 } else {
567 return false;
568 }
569 return true;
570}
571
572bool getAddressesFromParams(const UniValue& params, std::vector<std::pair<uint160, int> > &addresses)
573{
574 if (params[0].isStr()) {
575 CBitcoinAddress address(params[0].get_str());
576 uint160 hashBytes;
577 int type = 0;
578 if (!address.GetIndexKey(hashBytes, type)) {
579 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
580 }
581 addresses.push_back(std::make_pair(hashBytes, type));
582 } else if (params[0].isObject()) {
583
584 UniValue addressValues = find_value(params[0].get_obj(), "addresses");
585 if (!addressValues.isArray()) {
586 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Addresses is expected to be an array");
587 }
588
589 std::vector<UniValue> values = addressValues.getValues();
590
591 for (std::vector<UniValue>::iterator it = values.begin(); it != values.end(); ++it) {
592
593 CBitcoinAddress address(it->get_str());
594 uint160 hashBytes;
595 int type = 0;
596 if (!address.GetIndexKey(hashBytes, type)) {
597 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
598 }
599 addresses.push_back(std::make_pair(hashBytes, type));
600 }
601 } else {
602 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
603 }
604
605 return true;
606}
607
608bool heightSort(std::pair<CAddressUnspentKey, CAddressUnspentValue> a,
609 std::pair<CAddressUnspentKey, CAddressUnspentValue> b) {
610 return a.second.blockHeight < b.second.blockHeight;
611}
612
613bool timestampSort(std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> a,
614 std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> b) {
615 return a.second.time < b.second.time;
616}
617
618UniValue getaddressmempool(const UniValue& params, bool fHelp)
619{
620 if (fHelp || params.size() != 1)
621 throw runtime_error(
622 "getaddressmempool\n"
623 "\nReturns all mempool deltas for an address (requires addressindex to be enabled).\n"
624 "\nArguments:\n"
625 "{\n"
626 " \"addresses\"\n"
627 " [\n"
628 " \"address\" (string) The base58check encoded address\n"
629 " ,...\n"
630 " ]\n"
631 "}\n"
632 "\nResult:\n"
633 "[\n"
634 " {\n"
635 " \"address\" (string) The base58check encoded address\n"
636 " \"txid\" (string) The related txid\n"
637 " \"index\" (number) The related input or output index\n"
638 " \"satoshis\" (number) The difference of satoshis\n"
639 " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n"
640 " \"prevtxid\" (string) The previous txid (if spending)\n"
641 " \"prevout\" (string) The previous transaction output index (if spending)\n"
642 " }\n"
643 "]\n"
644 "\nExamples:\n"
645 + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
646 + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
647 );
648
649 std::vector<std::pair<uint160, int> > addresses;
650
651 if (!getAddressesFromParams(params, addresses)) {
652 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
653 }
654
655 std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > indexes;
656
657 if (!mempool.getAddressIndex(addresses, indexes)) {
658 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
659 }
660
661 std::sort(indexes.begin(), indexes.end(), timestampSort);
662
663 UniValue result(UniValue::VARR);
664
665 for (std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> >::iterator it = indexes.begin();
666 it != indexes.end(); it++) {
667
668 std::string address;
669 if (!getAddressFromIndex(it->first.type, it->first.addressBytes, address)) {
670 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
671 }
672
673 UniValue delta(UniValue::VOBJ);
674 delta.push_back(Pair("address", address));
675 delta.push_back(Pair("txid", it->first.txhash.GetHex()));
676 delta.push_back(Pair("index", (int)it->first.index));
677 delta.push_back(Pair("satoshis", it->second.amount));
678 delta.push_back(Pair("timestamp", it->second.time));
679 if (it->second.amount < 0) {
680 delta.push_back(Pair("prevtxid", it->second.prevhash.GetHex()));
681 delta.push_back(Pair("prevout", (int)it->second.prevout));
682 }
683 result.push_back(delta);
684 }
685
686 return result;
687}
688
689UniValue getaddressutxos(const UniValue& params, bool fHelp)
690{
691 if (fHelp || params.size() != 1)
692 throw runtime_error(
693 "getaddressutxos\n"
694 "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n"
695 "\nArguments:\n"
696 "{\n"
697 " \"addresses\"\n"
698 " [\n"
699 " \"address\" (string) The base58check encoded address\n"
700 " ,...\n"
701 " ],\n"
702 " \"chainInfo\" (boolean) Include chain info with results\n"
703 "}\n"
704 "\nResult\n"
705 "[\n"
706 " {\n"
707 " \"address\" (string) The address base58check encoded\n"
708 " \"txid\" (string) The output txid\n"
709 " \"height\" (number) The block height\n"
710 " \"outputIndex\" (number) The output index\n"
711 " \"script\" (strin) The script hex encoded\n"
712 " \"satoshis\" (number) The number of satoshis of the output\n"
713 " }\n"
714 "]\n"
715 "\nExamples:\n"
716 + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
717 + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
718 );
719
720 bool includeChainInfo = false;
721 if (params[0].isObject()) {
722 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
723 if (chainInfo.isBool()) {
724 includeChainInfo = chainInfo.get_bool();
725 }
726 }
727
728 std::vector<std::pair<uint160, int> > addresses;
729
730 if (!getAddressesFromParams(params, addresses)) {
731 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
732 }
733
734 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
735
736 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
737 if (!GetAddressUnspent((*it).first, (*it).second, unspentOutputs)) {
738 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
739 }
740 }
741
742 std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort);
743
744 UniValue utxos(UniValue::VARR);
745
746 for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) {
747 UniValue output(UniValue::VOBJ);
748 std::string address;
749 if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) {
750 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
751 }
752
753 output.push_back(Pair("address", address));
754 output.push_back(Pair("txid", it->first.txhash.GetHex()));
755 output.push_back(Pair("outputIndex", (int)it->first.index));
756 output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end())));
757 output.push_back(Pair("satoshis", it->second.satoshis));
758 output.push_back(Pair("height", it->second.blockHeight));
759 utxos.push_back(output);
760 }
761
762 if (includeChainInfo) {
763 UniValue result(UniValue::VOBJ);
764 result.push_back(Pair("utxos", utxos));
765
766 LOCK(cs_main);
767 result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex()));
768 result.push_back(Pair("height", (int)chainActive.Height()));
769 return result;
770 } else {
771 return utxos;
772 }
773}
774
775UniValue getaddressdeltas(const UniValue& params, bool fHelp)
776{
777 if (fHelp || params.size() != 1 || !params[0].isObject())
778 throw runtime_error(
779 "getaddressdeltas\n"
780 "\nReturns all changes for an address (requires addressindex to be enabled).\n"
781 "\nArguments:\n"
782 "{\n"
783 " \"addresses\"\n"
784 " [\n"
785 " \"address\" (string) The base58check encoded address\n"
786 " ,...\n"
787 " ]\n"
788 " \"start\" (number) The start block height\n"
789 " \"end\" (number) The end block height\n"
790 " \"chainInfo\" (boolean) Include chain info in results, only applies if start and end specified\n"
791 "}\n"
792 "\nResult:\n"
793 "[\n"
794 " {\n"
795 " \"satoshis\" (number) The difference of satoshis\n"
796 " \"txid\" (string) The related txid\n"
797 " \"index\" (number) The related input or output index\n"
798 " \"height\" (number) The block height\n"
799 " \"address\" (string) The base58check encoded address\n"
800 " }\n"
801 "]\n"
802 "\nExamples:\n"
803 + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
804 + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
805 );
806
807
808 UniValue startValue = find_value(params[0].get_obj(), "start");
809 UniValue endValue = find_value(params[0].get_obj(), "end");
810
811 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
812 bool includeChainInfo = false;
813 if (chainInfo.isBool()) {
814 includeChainInfo = chainInfo.get_bool();
815 }
816
817 int start = 0;
818 int end = 0;
819
820 if (startValue.isNum() && endValue.isNum()) {
821 start = startValue.get_int();
822 end = endValue.get_int();
823 if (start <= 0 || end <= 0) {
824 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start and end is expected to be greater than zero");
825 }
826 if (end < start) {
827 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "End value is expected to be greater than start");
828 }
829 }
830
831 std::vector<std::pair<uint160, int> > addresses;
832
833 if (!getAddressesFromParams(params, addresses)) {
834 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
835 }
836
837 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
838
839 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
840 if (start > 0 && end > 0) {
841 if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) {
842 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
843 }
844 } else {
845 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
846 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
847 }
848 }
849 }
850
851 UniValue deltas(UniValue::VARR);
852
853 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
854 std::string address;
855 if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) {
856 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
857 }
858
859 UniValue delta(UniValue::VOBJ);
860 delta.push_back(Pair("satoshis", it->second));
861 delta.push_back(Pair("txid", it->first.txhash.GetHex()));
862 delta.push_back(Pair("index", (int)it->first.index));
863 delta.push_back(Pair("blockindex", (int)it->first.txindex));
864 delta.push_back(Pair("height", it->first.blockHeight));
865 delta.push_back(Pair("address", address));
866 deltas.push_back(delta);
867 }
868
869 UniValue result(UniValue::VOBJ);
870
871 if (includeChainInfo && start > 0 && end > 0) {
872 LOCK(cs_main);
873
874 if (start > chainActive.Height() || end > chainActive.Height()) {
875 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range");
876 }
877
878 CBlockIndex* startIndex = chainActive[start];
879 CBlockIndex* endIndex = chainActive[end];
880
881 UniValue startInfo(UniValue::VOBJ);
882 UniValue endInfo(UniValue::VOBJ);
883
884 startInfo.push_back(Pair("hash", startIndex->GetBlockHash().GetHex()));
885 startInfo.push_back(Pair("height", start));
886
887 endInfo.push_back(Pair("hash", endIndex->GetBlockHash().GetHex()));
888 endInfo.push_back(Pair("height", end));
889
890 result.push_back(Pair("deltas", deltas));
891 result.push_back(Pair("start", startInfo));
892 result.push_back(Pair("end", endInfo));
893
894 return result;
895 } else {
896 return deltas;
897 }
898}
899
900UniValue getaddressbalance(const UniValue& params, bool fHelp)
901{
902 if (fHelp || params.size() != 1)
903 throw runtime_error(
904 "getaddressbalance\n"
905 "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n"
906 "\nArguments:\n"
907 "{\n"
908 " \"addresses\"\n"
909 " [\n"
910 " \"address\" (string) The base58check encoded address\n"
911 " ,...\n"
912 " ]\n"
913 "}\n"
914 "\nResult:\n"
915 "{\n"
916 " \"balance\" (string) The current balance in satoshis\n"
917 " \"received\" (string) The total number of satoshis received (including change)\n"
918 "}\n"
919 "\nExamples:\n"
920 + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
921 + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
922 );
923
924 std::vector<std::pair<uint160, int> > addresses;
925
926 if (!getAddressesFromParams(params, addresses)) {
927 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
928 }
929
930 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
931
932 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
933 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
934 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
935 }
936 }
937
938 CAmount balance = 0;
939 CAmount received = 0;
940
941 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
942 if (it->second > 0) {
943 received += it->second;
944 }
945 balance += it->second;
946 }
947
948 UniValue result(UniValue::VOBJ);
949 result.push_back(Pair("balance", balance));
950 result.push_back(Pair("received", received));
951
952 return result;
953
954}
955
956UniValue getaddresstxids(const UniValue& params, bool fHelp)
957{
958 if (fHelp || params.size() != 1)
959 throw runtime_error(
960 "getaddresstxids\n"
961 "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n"
962 "\nArguments:\n"
963 "{\n"
964 " \"addresses\"\n"
965 " [\n"
966 " \"address\" (string) The base58check encoded address\n"
967 " ,...\n"
968 " ]\n"
969 " \"start\" (number) The start block height\n"
970 " \"end\" (number) The end block height\n"
971 "}\n"
972 "\nResult:\n"
973 "[\n"
974 " \"transactionid\" (string) The transaction id\n"
975 " ,...\n"
976 "]\n"
977 "\nExamples:\n"
978 + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
979 + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
980 );
981
982 std::vector<std::pair<uint160, int> > addresses;
983
984 if (!getAddressesFromParams(params, addresses)) {
985 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
986 }
987
988 int start = 0;
989 int end = 0;
990 if (params[0].isObject()) {
991 UniValue startValue = find_value(params[0].get_obj(), "start");
992 UniValue endValue = find_value(params[0].get_obj(), "end");
993 if (startValue.isNum() && endValue.isNum()) {
994 start = startValue.get_int();
995 end = endValue.get_int();
996 }
997 }
998
999 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
1000
1001 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
1002 if (start > 0 && end > 0) {
1003 if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) {
1004 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
1005 }
1006 } else {
1007 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
1008 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
1009 }
1010 }
1011 }
1012
1013 std::set<std::pair<int, std::string> > txids;
1014 UniValue result(UniValue::VARR);
1015
1016 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
1017 int height = it->first.blockHeight;
1018 std::string txid = it->first.txhash.GetHex();
1019
1020 if (addresses.size() > 1) {
1021 txids.insert(std::make_pair(height, txid));
1022 } else {
1023 if (txids.insert(std::make_pair(height, txid)).second) {
1024 result.push_back(txid);
1025 }
1026 }
1027 }
1028
1029 if (addresses.size() > 1) {
1030 for (std::set<std::pair<int, std::string> >::const_iterator it=txids.begin(); it!=txids.end(); it++) {
1031 result.push_back(it->second);
1032 }
1033 }
1034
1035 return result;
1036
1037}
1038
1039UniValue getspentinfo(const UniValue& params, bool fHelp)
1040{
1041
1042 if (fHelp || params.size() != 1 || !params[0].isObject())
1043 throw runtime_error(
1044 "getspentinfo\n"
1045 "\nReturns the txid and index where an output is spent.\n"
1046 "\nArguments:\n"
1047 "{\n"
1048 " \"txid\" (string) The hex string of the txid\n"
1049 " \"index\" (number) The start block height\n"
1050 "}\n"
1051 "\nResult:\n"
1052 "{\n"
1053 " \"txid\" (string) The transaction id\n"
1054 " \"index\" (number) The spending input index\n"
1055 " ,...\n"
1056 "}\n"
1057 "\nExamples:\n"
1058 + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'")
1059 + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}")
1060 );
1061
1062 UniValue txidValue = find_value(params[0].get_obj(), "txid");
1063 UniValue indexValue = find_value(params[0].get_obj(), "index");
1064
1065 if (!txidValue.isStr() || !indexValue.isNum()) {
1066 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid or index");
1067 }
1068
1069 uint256 txid = ParseHashV(txidValue, "txid");
1070 int outputIndex = indexValue.get_int();
1071
1072 CSpentIndexKey key(txid, outputIndex);
1073 CSpentIndexValue value;
1074
1075 if (!GetSpentIndex(key, value)) {
1076 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info");
1077 }
1078
1079 UniValue obj(UniValue::VOBJ);
1080 obj.push_back(Pair("txid", value.txid.GetHex()));
1081 obj.push_back(Pair("index", (int)value.inputIndex));
1082 obj.push_back(Pair("height", value.blockHeight));
1083
1084 return obj;
1085}
This page took 0.427639 seconds and 4 git commands to generate.