]> Git Repo - VerusCoin.git/blame - src/rpcmisc.cpp
c++
[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();
69d23911 49int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp);
e34a9d43 50uint32_t komodo_chainactive_timestamp();
8683bd8d 51int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp);
94d3d09d 52extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
6bb74a02 53extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN;
9edf27ec 54extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
acbc7a94 55uint32_t komodo_segid32(char *coinaddr);
0cb025c1 56int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
eeaaf554 57#define KOMODO_VERSION "0.1.1"
05c2ba63 58extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
dbc80050 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;
09e3cf94 62
d014114d 63UniValue getinfo(const UniValue& params, bool fHelp)
16bc9aaf 64{
69d23911 65 uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,longestchain,kmdnotarized_height,txid_height;
16bc9aaf
WL
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"
a7322d77 75 " \"balance\": xxxxxxx, (numeric) the total Komodo balance of the wallet\n"
16bc9aaf
WL
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"
16bc9aaf 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"
091b2116
RN
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"
16bc9aaf
WL
87 " \"errors\": \"...\" (string) any error messages\n"
88 "}\n"
89 "\nExamples:\n"
90 + HelpExampleCli("getinfo", "")
91 + HelpExampleRpc("getinfo", "")
92 );
247428bd 93//#ifdef ENABLE_WALLET
94// LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
95//#else
4add33cf 96 LOCK(cs_main);
247428bd 97//#endif
4401b2d7 98
16bc9aaf
WL
99 proxyType proxy;
100 GetProxy(NET_IPV4, proxy);
69d23911 101 notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
6f1de985 102 //fprintf(stderr,"after notarized_height %u\n",(uint32_t)time(NULL));
16bc9aaf 103
38fc4b70 104 UniValue obj(UniValue::VOBJ);
faadbe17
PK
105 obj.push_back(Pair("version", CLIENT_VERSION));
106 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
b000fa04 107 obj.push_back(Pair("KMDversion", KOMODO_VERSION));
c75c18fc 108 obj.push_back(Pair("notarized", notarized_height));
69d23911 109 obj.push_back(Pair("prevMoMheight", prevMoMheight));
c75c18fc 110 obj.push_back(Pair("notarizedhash", notarized_hash.ToString()));
111 obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString()));
6f1de985 112 txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height);
70d83934 113 if ( txid_height > 0 )
114 obj.push_back(Pair("notarizedtxid_height", txid_height));
6f1de985 115 else obj.push_back(Pair("notarizedtxid_height", "mempool"));
57dd4ada 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));
6f1de985 119 //fprintf(stderr,"after notarized_confirms %u\n",(uint32_t)time(NULL));
16bc9aaf
WL
120#ifdef ENABLE_WALLET
121 if (pwalletMain) {
122 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
247428bd 123 obj.push_back(Pair("balance", ValueFromAmount(KOMODO_WALLETBALANCE))); //pwalletMain->GetBalance()
9e1bde7e 124 if ( ASSETCHAINS_SYMBOL[0] == 0 )
247428bd 125 obj.push_back(Pair("interest", ValueFromAmount(KOMODO_INTERESTSUM))); //komodo_interestsum()
16bc9aaf
WL
126 }
127#endif
6f1de985 128 //fprintf(stderr,"after wallet %u\n",(uint32_t)time(NULL));
16bc9aaf 129 obj.push_back(Pair("blocks", (int)chainActive.Height()));
daf214b1 130 if ( (longestchain= KOMODO_LONGESTCHAIN) != 0 && chainActive.Height() > longestchain )
a19b28ce 131 longestchain = chainActive.Height();
6f1de985 132 //fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL));
a19b28ce 133 obj.push_back(Pair("longestchain", longestchain));
d56e30ca 134 obj.push_back(Pair("timeoffset", GetTimeOffset()));
98d166cf 135 if ( chainActive.Tip() != 0 )
49c9db6a 136 obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime));
16bc9aaf 137 obj.push_back(Pair("connections", (int)vNodes.size()));
67a79493 138 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
16bc9aaf 139 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
cc972107 140 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
16bc9aaf
WL
141#ifdef ENABLE_WALLET
142 if (pwalletMain) {
d56e30ca 143 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
16bc9aaf
WL
144 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
145 }
16bc9aaf 146 if (pwalletMain && pwalletMain->IsCrypted())
d56e30ca 147 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
c6cb21d1 148 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
16bc9aaf 149#endif
13fc83c7 150 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
16bc9aaf 151 obj.push_back(Pair("errors", GetWarnings("statusbar")));
58033467 152 {
153 char pubkeystr[65]; int32_t notaryid;
e34a9d43 154 if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight,komodo_chainactive_timestamp())) >= 0 )
1e2a41f6 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 }
58033467 161 }
dbc80050 162 if ( ASSETCHAINS_CC != 0 )
91e76e0c 163 obj.push_back(Pair("CCid", (int)ASSETCHAINS_CC));
9edf27ec 164 obj.push_back(Pair("name", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL));
dbc80050 165 if ( ASSETCHAINS_SYMBOL[0] != 0 )
166 {
9edf27ec 167 //obj.push_back(Pair("name", ASSETCHAINS_SYMBOL));
05c2ba63 168 obj.push_back(Pair("p2pport", ASSETCHAINS_P2PPORT));
169 obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT));
91e76e0c 170 obj.push_back(Pair("magic", (int)ASSETCHAINS_MAGIC));
dbc80050 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 }
16bc9aaf
WL
186 return obj;
187}
188
452955f5 189#ifdef ENABLE_WALLET
d014114d 190class DescribeAddressVisitor : public boost::static_visitor<UniValue>
452955f5
WL
191{
192public:
d014114d 193 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
452955f5 194
851f58f9 195 UniValue operator()(const CKeyID &keyID) const {
38fc4b70 196 UniValue obj(UniValue::VOBJ);
452955f5 197 CPubKey vchPubKey;
452955f5 198 obj.push_back(Pair("isscript", false));
56215c77 199 if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
c8988460
PW
200 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
201 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
202 }
452955f5
WL
203 return obj;
204 }
205
851f58f9 206 UniValue operator()(const CScriptID &scriptID) const {
38fc4b70 207 UniValue obj(UniValue::VOBJ);
9c7167d1 208 CScript subscript;
452955f5 209 obj.push_back(Pair("isscript", true));
56215c77 210 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
c8988460
PW
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())));
38fc4b70 217 UniValue a(UniValue::VARR);
c8988460
PW
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 }
452955f5
WL
224 return obj;
225 }
226};
227#endif
228
eeaaf554 229UniValue jumblr_deposit(const UniValue& params, bool fHelp)
230{
b487a8fe 231 int32_t retval; UniValue result(UniValue::VOBJ);
eeaaf554 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();
b487a8fe 239 if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 )
e21c70e9 240 {
190dbe6d 241 result.push_back(Pair("result", retval));
e21c70e9 242 JUMBLR_PAUSE = 0;
243 }
b487a8fe 244 else result.push_back(Pair("error", retval));
eeaaf554 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();
bc035879 259 retval = Jumblr_secretaddradd((char *)addr.c_str());
eeaaf554 260 result.push_back(Pair("result", "success"));
261 result.push_back(Pair("num", retval));
e8fa58ec 262 JUMBLR_PAUSE = 0;
eeaaf554 263 } else result.push_back(Pair("error", "invalid address"));
264 return(result);
265}
266
eea03b7b 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
d014114d 287UniValue validateaddress(const UniValue& params, bool fHelp)
452955f5
WL
288{
289 if (fHelp || params.size() != 1)
290 throw runtime_error(
a7322d77 291 "validateaddress \"komodoaddress\"\n"
292 "\nReturn information about the given Komodo address.\n"
452955f5 293 "\nArguments:\n"
a7322d77 294 "1. \"komodoaddress\" (string, required) The Komodo address to validate\n"
452955f5
WL
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"
a7322d77 298 " \"address\" : \"komodoaddress\", (string) The Komodo address validated\n"
426a74ed 299 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
452955f5
WL
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"
7b782f5b 304 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
452955f5
WL
305 "}\n"
306 "\nExamples:\n"
a7322d77 307 + HelpExampleCli("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"")
308 + HelpExampleRpc("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"")
452955f5
WL
309 );
310
4401b2d7
EL
311#ifdef ENABLE_WALLET
312 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
313#else
314 LOCK(cs_main);
315#endif
316
452955f5
WL
317 CBitcoinAddress address(params[0].get_str());
318 bool isValid = address.IsValid();
319
38fc4b70 320 UniValue ret(UniValue::VOBJ);
452955f5
WL
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));
426a74ed
PT
327
328 CScript scriptPubKey = GetScriptForDestination(dest);
329 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
1eb7f616 330 ret.push_back(Pair("segid", (int32_t)komodo_segid32(params[0].get_str().c_str()) & 0x3f));
452955f5 331#ifdef ENABLE_WALLET
a3e192a3
J
332 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
333 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
9c7167d1 334 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
335 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
336 ret.pushKVs(detail);
452955f5
WL
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
4e16a724 344
0d37ae3a 345UniValue z_validateaddress(const UniValue& params, bool fHelp)
4e16a724
S
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"
337a99a2
JG
363 + HelpExampleCli("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
364 + HelpExampleRpc("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
4e16a724
S
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
0d37ae3a 393 UniValue ret(UniValue::VOBJ);
4e16a724
S
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
72fb3d29
MF
408/**
409 * Used by addmultisigaddress / createmultisig:
410 */
d014114d 411CScript _createmultisig_redeemScript(const UniValue& params)
723a03d2
WL
412{
413 int nRequired = params[0].get_int();
d014114d 414 const UniValue& keys = params[1].get_array();
723a03d2
WL
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 "
783b182c 422 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
e5d9d77d 423 if (keys.size() > 16)
424 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
723a03d2
WL
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(
7d9d134b 438 strprintf("%s does not refer to a key",ks));
723a03d2
WL
439 CPubKey vchPubKey;
440 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
441 throw runtime_error(
7d9d134b 442 strprintf("no full public key for address %s",ks));
723a03d2
WL
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 }
0be990ba 463 CScript result = GetScriptForMultisig(nRequired, pubkeys);
787ee0c9
PT
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
723a03d2
WL
469 return result;
470}
471
d014114d 472UniValue createmultisig(const UniValue& params, bool fHelp)
723a03d2
WL
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"
a7322d77 482 "2. \"keys\" (string, required) A json array of keys which are Komodo addresses or hex-encoded public keys\n"
723a03d2 483 " [\n"
a7322d77 484 " \"key\" (string) Komodo address or hex-encoded public key\n"
723a03d2
WL
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"
a7322d77 496 + HelpExampleCli("createmultisig", "2 \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"") +
723a03d2 497 "\nAs a json rpc call\n"
a7322d77 498 + HelpExampleRpc("createmultisig", "2, \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"")
723a03d2
WL
499 ;
500 throw runtime_error(msg);
501 }
502
503 // Construct using pay-to-script-hash:
787ee0c9 504 CScript inner = _createmultisig_redeemScript(params);
066e2a14 505 CScriptID innerID(inner);
723a03d2
WL
506 CBitcoinAddress address(innerID);
507
b47f3aea 508 UniValue result(UniValue::VOBJ);
723a03d2
WL
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
d014114d 515UniValue verifymessage(const UniValue& params, bool fHelp)
c3a7f516
WL
516{
517 if (fHelp || params.size() != 3)
518 throw runtime_error(
a7322d77 519 "verifymessage \"komodoaddress\" \"signature\" \"message\"\n"
c3a7f516
WL
520 "\nVerify a signed message\n"
521 "\nArguments:\n"
a7322d77 522 "1. \"komodoaddress\" (string, required) The Komodo address to use for the signature.\n"
c3a7f516
WL
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"
a7322d77 531 + HelpExampleCli("signmessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"my message\"") +
c3a7f516 532 "\nVerify the signature\n"
a7322d77 533 + HelpExampleCli("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"signature\" \"my message\"") +
c3a7f516 534 "\nAs json rpc\n"
a7322d77 535 + HelpExampleRpc("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\", \"signature\", \"my message\"")
c3a7f516
WL
536 );
537
4401b2d7
EL
538 LOCK(cs_main);
539
c3a7f516
WL
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}
a8b2ce55 568
d014114d 569UniValue setmocktime(const UniValue& params, bool fHelp)
a8b2ce55
GA
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
abb0e8cc
GA
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);
4401b2d7 588
9756b7bd 589 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
a8b2ce55
GA
590 SetMockTime(params[0].get_int64());
591
abb0e8cc
GA
592 uint64_t t = GetTime();
593 BOOST_FOREACH(CNode* pnode, vNodes) {
594 pnode->nLastSend = pnode->nLastRecv = t;
595 }
596
9756b7bd 597 return NullUniValue;
a8b2ce55 598}
8b78a819
T
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 } else {
607 return false;
608 }
609 return true;
610}
611
612bool getAddressesFromParams(const UniValue& params, std::vector<std::pair<uint160, int> > &addresses)
613{
614 if (params[0].isStr()) {
615 CBitcoinAddress address(params[0].get_str());
616 uint160 hashBytes;
617 int type = 0;
618 if (!address.GetIndexKey(hashBytes, type)) {
619 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
620 }
621 addresses.push_back(std::make_pair(hashBytes, type));
622 } else if (params[0].isObject()) {
623
624 UniValue addressValues = find_value(params[0].get_obj(), "addresses");
625 if (!addressValues.isArray()) {
626 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Addresses is expected to be an array");
627 }
628
629 std::vector<UniValue> values = addressValues.getValues();
630
631 for (std::vector<UniValue>::iterator it = values.begin(); it != values.end(); ++it) {
632
633 CBitcoinAddress address(it->get_str());
634 uint160 hashBytes;
635 int type = 0;
636 if (!address.GetIndexKey(hashBytes, type)) {
637 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
638 }
639 addresses.push_back(std::make_pair(hashBytes, type));
640 }
641 } else {
642 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
643 }
644
645 return true;
646}
647
648bool heightSort(std::pair<CAddressUnspentKey, CAddressUnspentValue> a,
649 std::pair<CAddressUnspentKey, CAddressUnspentValue> b) {
650 return a.second.blockHeight < b.second.blockHeight;
651}
652
653bool timestampSort(std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> a,
654 std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> b) {
655 return a.second.time < b.second.time;
656}
657
658UniValue getaddressmempool(const UniValue& params, bool fHelp)
659{
660 if (fHelp || params.size() != 1)
661 throw runtime_error(
662 "getaddressmempool\n"
663 "\nReturns all mempool deltas for an address (requires addressindex to be enabled).\n"
664 "\nArguments:\n"
665 "{\n"
666 " \"addresses\"\n"
667 " [\n"
668 " \"address\" (string) The base58check encoded address\n"
669 " ,...\n"
670 " ]\n"
671 "}\n"
672 "\nResult:\n"
673 "[\n"
674 " {\n"
675 " \"address\" (string) The base58check encoded address\n"
676 " \"txid\" (string) The related txid\n"
677 " \"index\" (number) The related input or output index\n"
678 " \"satoshis\" (number) The difference of satoshis\n"
679 " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n"
680 " \"prevtxid\" (string) The previous txid (if spending)\n"
681 " \"prevout\" (string) The previous transaction output index (if spending)\n"
682 " }\n"
683 "]\n"
684 "\nExamples:\n"
685 + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
686 + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
687 );
688
689 std::vector<std::pair<uint160, int> > addresses;
690
691 if (!getAddressesFromParams(params, addresses)) {
692 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
693 }
694
695 std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > indexes;
696
697 if (!mempool.getAddressIndex(addresses, indexes)) {
698 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
699 }
700
701 std::sort(indexes.begin(), indexes.end(), timestampSort);
702
703 UniValue result(UniValue::VARR);
704
705 for (std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> >::iterator it = indexes.begin();
706 it != indexes.end(); it++) {
707
708 std::string address;
709 if (!getAddressFromIndex(it->first.type, it->first.addressBytes, address)) {
710 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
711 }
712
713 UniValue delta(UniValue::VOBJ);
714 delta.push_back(Pair("address", address));
715 delta.push_back(Pair("txid", it->first.txhash.GetHex()));
716 delta.push_back(Pair("index", (int)it->first.index));
717 delta.push_back(Pair("satoshis", it->second.amount));
718 delta.push_back(Pair("timestamp", it->second.time));
719 if (it->second.amount < 0) {
720 delta.push_back(Pair("prevtxid", it->second.prevhash.GetHex()));
721 delta.push_back(Pair("prevout", (int)it->second.prevout));
722 }
723 result.push_back(delta);
724 }
725
726 return result;
727}
728
729UniValue getaddressutxos(const UniValue& params, bool fHelp)
730{
731 if (fHelp || params.size() != 1)
732 throw runtime_error(
733 "getaddressutxos\n"
734 "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n"
735 "\nArguments:\n"
736 "{\n"
737 " \"addresses\"\n"
738 " [\n"
739 " \"address\" (string) The base58check encoded address\n"
740 " ,...\n"
741 " ],\n"
742 " \"chainInfo\" (boolean) Include chain info with results\n"
743 "}\n"
744 "\nResult\n"
745 "[\n"
746 " {\n"
747 " \"address\" (string) The address base58check encoded\n"
748 " \"txid\" (string) The output txid\n"
749 " \"height\" (number) The block height\n"
750 " \"outputIndex\" (number) The output index\n"
751 " \"script\" (strin) The script hex encoded\n"
752 " \"satoshis\" (number) The number of satoshis of the output\n"
753 " }\n"
754 "]\n"
755 "\nExamples:\n"
756 + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
757 + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
758 );
759
760 bool includeChainInfo = false;
761 if (params[0].isObject()) {
762 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
763 if (chainInfo.isBool()) {
764 includeChainInfo = chainInfo.get_bool();
765 }
766 }
767
768 std::vector<std::pair<uint160, int> > addresses;
769
770 if (!getAddressesFromParams(params, addresses)) {
771 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
772 }
773
774 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
775
776 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
777 if (!GetAddressUnspent((*it).first, (*it).second, unspentOutputs)) {
778 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
779 }
780 }
781
782 std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort);
783
784 UniValue utxos(UniValue::VARR);
785
786 for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) {
787 UniValue output(UniValue::VOBJ);
788 std::string address;
789 if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) {
790 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
791 }
792
793 output.push_back(Pair("address", address));
794 output.push_back(Pair("txid", it->first.txhash.GetHex()));
795 output.push_back(Pair("outputIndex", (int)it->first.index));
796 output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end())));
797 output.push_back(Pair("satoshis", it->second.satoshis));
798 output.push_back(Pair("height", it->second.blockHeight));
799 utxos.push_back(output);
800 }
801
802 if (includeChainInfo) {
803 UniValue result(UniValue::VOBJ);
804 result.push_back(Pair("utxos", utxos));
805
806 LOCK(cs_main);
807 result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex()));
808 result.push_back(Pair("height", (int)chainActive.Height()));
809 return result;
810 } else {
811 return utxos;
812 }
813}
814
815UniValue getaddressdeltas(const UniValue& params, bool fHelp)
816{
817 if (fHelp || params.size() != 1 || !params[0].isObject())
818 throw runtime_error(
819 "getaddressdeltas\n"
820 "\nReturns all changes for an address (requires addressindex to be enabled).\n"
821 "\nArguments:\n"
822 "{\n"
823 " \"addresses\"\n"
824 " [\n"
825 " \"address\" (string) The base58check encoded address\n"
826 " ,...\n"
827 " ]\n"
828 " \"start\" (number) The start block height\n"
829 " \"end\" (number) The end block height\n"
830 " \"chainInfo\" (boolean) Include chain info in results, only applies if start and end specified\n"
831 "}\n"
832 "\nResult:\n"
833 "[\n"
834 " {\n"
835 " \"satoshis\" (number) The difference of satoshis\n"
836 " \"txid\" (string) The related txid\n"
837 " \"index\" (number) The related input or output index\n"
838 " \"height\" (number) The block height\n"
839 " \"address\" (string) The base58check encoded address\n"
840 " }\n"
841 "]\n"
842 "\nExamples:\n"
843 + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
844 + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
845 );
846
847
848 UniValue startValue = find_value(params[0].get_obj(), "start");
849 UniValue endValue = find_value(params[0].get_obj(), "end");
850
851 UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
852 bool includeChainInfo = false;
853 if (chainInfo.isBool()) {
854 includeChainInfo = chainInfo.get_bool();
855 }
856
857 int start = 0;
858 int end = 0;
859
860 if (startValue.isNum() && endValue.isNum()) {
861 start = startValue.get_int();
862 end = endValue.get_int();
863 if (start <= 0 || end <= 0) {
864 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start and end is expected to be greater than zero");
865 }
866 if (end < start) {
867 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "End value is expected to be greater than start");
868 }
869 }
870
871 std::vector<std::pair<uint160, int> > addresses;
872
873 if (!getAddressesFromParams(params, addresses)) {
874 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
875 }
876
877 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
878
879 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
880 if (start > 0 && end > 0) {
881 if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) {
882 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
883 }
884 } else {
885 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
886 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
887 }
888 }
889 }
890
891 UniValue deltas(UniValue::VARR);
892
893 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
894 std::string address;
895 if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) {
896 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type");
897 }
898
899 UniValue delta(UniValue::VOBJ);
900 delta.push_back(Pair("satoshis", it->second));
901 delta.push_back(Pair("txid", it->first.txhash.GetHex()));
902 delta.push_back(Pair("index", (int)it->first.index));
903 delta.push_back(Pair("blockindex", (int)it->first.txindex));
904 delta.push_back(Pair("height", it->first.blockHeight));
905 delta.push_back(Pair("address", address));
906 deltas.push_back(delta);
907 }
908
909 UniValue result(UniValue::VOBJ);
910
911 if (includeChainInfo && start > 0 && end > 0) {
912 LOCK(cs_main);
913
914 if (start > chainActive.Height() || end > chainActive.Height()) {
915 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range");
916 }
917
918 CBlockIndex* startIndex = chainActive[start];
919 CBlockIndex* endIndex = chainActive[end];
920
921 UniValue startInfo(UniValue::VOBJ);
922 UniValue endInfo(UniValue::VOBJ);
923
924 startInfo.push_back(Pair("hash", startIndex->GetBlockHash().GetHex()));
925 startInfo.push_back(Pair("height", start));
926
927 endInfo.push_back(Pair("hash", endIndex->GetBlockHash().GetHex()));
928 endInfo.push_back(Pair("height", end));
929
930 result.push_back(Pair("deltas", deltas));
931 result.push_back(Pair("start", startInfo));
932 result.push_back(Pair("end", endInfo));
933
934 return result;
935 } else {
936 return deltas;
937 }
938}
939
940UniValue getaddressbalance(const UniValue& params, bool fHelp)
941{
942 if (fHelp || params.size() != 1)
943 throw runtime_error(
944 "getaddressbalance\n"
945 "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n"
946 "\nArguments:\n"
947 "{\n"
948 " \"addresses\"\n"
949 " [\n"
950 " \"address\" (string) The base58check encoded address\n"
951 " ,...\n"
952 " ]\n"
953 "}\n"
954 "\nResult:\n"
955 "{\n"
956 " \"balance\" (string) The current balance in satoshis\n"
957 " \"received\" (string) The total number of satoshis received (including change)\n"
958 "}\n"
959 "\nExamples:\n"
960 + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
961 + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
962 );
963
964 std::vector<std::pair<uint160, int> > addresses;
965
966 if (!getAddressesFromParams(params, addresses)) {
967 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
968 }
969
970 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
971
972 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
973 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
974 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
975 }
976 }
977
978 CAmount balance = 0;
979 CAmount received = 0;
980
981 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
982 if (it->second > 0) {
983 received += it->second;
984 }
985 balance += it->second;
986 }
987
988 UniValue result(UniValue::VOBJ);
989 result.push_back(Pair("balance", balance));
990 result.push_back(Pair("received", received));
991
992 return result;
993
994}
995
996UniValue getaddresstxids(const UniValue& params, bool fHelp)
997{
998 if (fHelp || params.size() != 1)
999 throw runtime_error(
1000 "getaddresstxids\n"
1001 "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n"
1002 "\nArguments:\n"
1003 "{\n"
1004 " \"addresses\"\n"
1005 " [\n"
1006 " \"address\" (string) The base58check encoded address\n"
1007 " ,...\n"
1008 " ]\n"
1009 " \"start\" (number) The start block height\n"
1010 " \"end\" (number) The end block height\n"
1011 "}\n"
1012 "\nResult:\n"
1013 "[\n"
1014 " \"transactionid\" (string) The transaction id\n"
1015 " ,...\n"
1016 "]\n"
1017 "\nExamples:\n"
1018 + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
1019 + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
1020 );
1021
1022 std::vector<std::pair<uint160, int> > addresses;
1023
1024 if (!getAddressesFromParams(params, addresses)) {
1025 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
1026 }
1027
1028 int start = 0;
1029 int end = 0;
1030 if (params[0].isObject()) {
1031 UniValue startValue = find_value(params[0].get_obj(), "start");
1032 UniValue endValue = find_value(params[0].get_obj(), "end");
1033 if (startValue.isNum() && endValue.isNum()) {
1034 start = startValue.get_int();
1035 end = endValue.get_int();
1036 }
1037 }
1038
1039 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
1040
1041 for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) {
1042 if (start > 0 && end > 0) {
1043 if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) {
1044 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
1045 }
1046 } else {
1047 if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) {
1048 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
1049 }
1050 }
1051 }
1052
1053 std::set<std::pair<int, std::string> > txids;
1054 UniValue result(UniValue::VARR);
1055
1056 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
1057 int height = it->first.blockHeight;
1058 std::string txid = it->first.txhash.GetHex();
1059
1060 if (addresses.size() > 1) {
1061 txids.insert(std::make_pair(height, txid));
1062 } else {
1063 if (txids.insert(std::make_pair(height, txid)).second) {
1064 result.push_back(txid);
1065 }
1066 }
1067 }
1068
1069 if (addresses.size() > 1) {
1070 for (std::set<std::pair<int, std::string> >::const_iterator it=txids.begin(); it!=txids.end(); it++) {
1071 result.push_back(it->second);
1072 }
1073 }
1074
1075 return result;
1076
1077}
1078
1079UniValue getspentinfo(const UniValue& params, bool fHelp)
1080{
1081
1082 if (fHelp || params.size() != 1 || !params[0].isObject())
1083 throw runtime_error(
1084 "getspentinfo\n"
1085 "\nReturns the txid and index where an output is spent.\n"
1086 "\nArguments:\n"
1087 "{\n"
1088 " \"txid\" (string) The hex string of the txid\n"
1089 " \"index\" (number) The start block height\n"
1090 "}\n"
1091 "\nResult:\n"
1092 "{\n"
1093 " \"txid\" (string) The transaction id\n"
1094 " \"index\" (number) The spending input index\n"
1095 " ,...\n"
1096 "}\n"
1097 "\nExamples:\n"
1098 + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'")
1099 + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}")
1100 );
1101
1102 UniValue txidValue = find_value(params[0].get_obj(), "txid");
1103 UniValue indexValue = find_value(params[0].get_obj(), "index");
1104
1105 if (!txidValue.isStr() || !indexValue.isNum()) {
1106 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid or index");
1107 }
1108
1109 uint256 txid = ParseHashV(txidValue, "txid");
1110 int outputIndex = indexValue.get_int();
1111
1112 CSpentIndexKey key(txid, outputIndex);
1113 CSpentIndexValue value;
1114
1115 if (!GetSpentIndex(key, value)) {
1116 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info");
1117 }
1118
1119 UniValue obj(UniValue::VOBJ);
1120 obj.push_back(Pair("txid", value.txid.GetHex()));
1121 obj.push_back(Pair("index", (int)value.inputIndex));
1122 obj.push_back(Pair("height", value.blockHeight));
1123
1124 return obj;
e8fa58ec 1125}
This page took 0.444928 seconds and 4 git commands to generate.