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