]> Git Repo - VerusCoin.git/blob - src/wallet/rpcwallet.cpp
Scan 10 minute window
[VerusCoin.git] / src / wallet / rpcwallet.cpp
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 "amount.h"
7 #include "base58.h"
8 #include "consensus/upgrades.h"
9 #include "core_io.h"
10 #include "init.h"
11 #include "main.h"
12 #include "net.h"
13 #include "netbase.h"
14 #include "rpcserver.h"
15 #include "timedata.h"
16 #include "util.h"
17 #include "utilmoneystr.h"
18 #include "wallet.h"
19 #include "walletdb.h"
20 #include "primitives/transaction.h"
21 #include "zcbenchmarks.h"
22 #include "script/interpreter.h"
23
24 #include "utiltime.h"
25 #include "asyncrpcoperation.h"
26 #include "asyncrpcqueue.h"
27 #include "wallet/asyncrpcoperation_mergetoaddress.h"
28 #include "wallet/asyncrpcoperation_sendmany.h"
29 #include "wallet/asyncrpcoperation_shieldcoinbase.h"
30
31 #include "sodium.h"
32
33 #include <stdint.h>
34
35 #include <boost/assign/list_of.hpp>
36
37 #include <univalue.h>
38
39 #include <numeric>
40
41 using namespace std;
42
43 using namespace libzcash;
44
45 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
46 extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
47 extern uint8_t ASSETCHAINS_PRIVATE;
48 uint32_t komodo_segid32(char *coinaddr);
49
50 int64_t nWalletUnlockTime;
51 static CCriticalSection cs_nWalletUnlockTime;
52
53 // Private method:
54 UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
55
56 std::string HelpRequiringPassphrase()
57 {
58     return pwalletMain && pwalletMain->IsCrypted()
59         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
60         : "";
61 }
62
63 bool EnsureWalletIsAvailable(bool avoidException)
64 {
65     if (!pwalletMain)
66     {
67         if (!avoidException)
68             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
69         else
70             return false;
71     }
72     return true;
73 }
74
75 void EnsureWalletIsUnlocked()
76 {
77     if (pwalletMain->IsLocked())
78         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
79 }
80
81 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
82
83 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
84 {
85     //int32_t i,n,txheight; uint32_t locktime; uint64_t interest = 0;
86     int confirms = wtx.GetDepthInMainChain();
87     entry.push_back(Pair("confirmations", confirms));
88     if (wtx.IsCoinBase())
89         entry.push_back(Pair("generated", true));
90     if (confirms > 0)
91     {
92         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
93         entry.push_back(Pair("blockindex", wtx.nIndex));
94         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
95         entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
96     }
97     uint256 hash = wtx.GetHash();
98     entry.push_back(Pair("txid", hash.GetHex()));
99     UniValue conflicts(UniValue::VARR);
100     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
101         conflicts.push_back(conflict.GetHex());
102     entry.push_back(Pair("walletconflicts", conflicts));
103     entry.push_back(Pair("time", wtx.GetTxTime()));
104     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
105     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
106         entry.push_back(Pair(item.first, item.second));
107
108     entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx)));
109 }
110
111 string AccountFromValue(const UniValue& value)
112 {
113     string strAccount = value.get_str();
114     //if (strAccount != "")
115     //    throw JSONRPCError(RPC_WALLET_ACCOUNTS_UNSUPPORTED, "Accounts are unsupported");
116     return strAccount;
117 }
118
119 char *komodo_chainname() 
120
121      return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL); 
122 }
123
124 UniValue getnewaddress(const UniValue& params, bool fHelp)
125 {
126     if (!EnsureWalletIsAvailable(fHelp))
127         return NullUniValue;
128
129     if (fHelp || params.size() > 1)
130         throw runtime_error(
131             "getnewaddress ( \"account\" )\n"
132             "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address for receiving payments.\n"
133             "\nArguments:\n"
134             "1. \"account\"        (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
135             "\nResult:\n"
136             "\"" + strprintf("%s",komodo_chainname()) + "_address\"    (string) The new " + strprintf("%s",komodo_chainname()) + " address\n"
137             "\nExamples:\n"
138             + HelpExampleCli("getnewaddress", "")
139             + HelpExampleRpc("getnewaddress", "")
140         );
141
142     LOCK2(cs_main, pwalletMain->cs_wallet);
143
144     // Parse the account first so we don't generate a key if there's an error
145     string strAccount;
146     if (params.size() > 0)
147         strAccount = AccountFromValue(params[0]);
148
149     if (!pwalletMain->IsLocked())
150         pwalletMain->TopUpKeyPool();
151
152     // Generate a new key that is added to wallet
153     CPubKey newKey;
154     if (!pwalletMain->GetKeyFromPool(newKey))
155         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
156     CKeyID keyID = newKey.GetID();
157
158     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
159
160     return CBitcoinAddress(keyID).ToString();
161 }
162
163
164 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
165 {
166     CWalletDB walletdb(pwalletMain->strWalletFile);
167
168     CAccount account;
169     walletdb.ReadAccount(strAccount, account);
170
171     bool bKeyUsed = false;
172
173     // Check if the current key has been used
174     if (account.vchPubKey.IsValid())
175     {
176         CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
177         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
178              it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
179              ++it)
180         {
181             const CWalletTx& wtx = (*it).second;
182             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
183                 if (txout.scriptPubKey == scriptPubKey)
184                     bKeyUsed = true;
185         }
186     }
187
188     // Generate a new key
189     if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
190     {
191         if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
192             throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
193
194         pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
195         walletdb.WriteAccount(strAccount, account);
196     }
197
198     return CBitcoinAddress(account.vchPubKey.GetID());
199 }
200
201 UniValue getaccountaddress(const UniValue& params, bool fHelp)
202 {
203     if (!EnsureWalletIsAvailable(fHelp))
204         return NullUniValue;
205
206     if (fHelp || params.size() != 1)
207         throw runtime_error(
208             "getaccountaddress \"account\"\n"
209             "\nDEPRECATED. Returns the current " + strprintf("%s",komodo_chainname()) + " address for receiving payments to this account.\n"
210             "\nArguments:\n"
211             "1. \"account\"       (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
212             "\nResult:\n"
213             "\"" + strprintf("%s",komodo_chainname()) + "_address\"   (string) The account " + strprintf("%s",komodo_chainname()) + " address\n"
214             "\nExamples:\n"
215             + HelpExampleCli("getaccountaddress", "")
216             + HelpExampleCli("getaccountaddress", "\"\"")
217             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
218             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
219         );
220
221     LOCK2(cs_main, pwalletMain->cs_wallet);
222
223     // Parse the account first so we don't generate a key if there's an error
224     string strAccount = AccountFromValue(params[0]);
225
226     UniValue ret(UniValue::VSTR);
227
228     ret = GetAccountAddress(strAccount).ToString();
229     return ret;
230 }
231
232
233 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
234 {
235     if (!EnsureWalletIsAvailable(fHelp))
236         return NullUniValue;
237
238     if (fHelp || params.size() > 1)
239         throw runtime_error(
240             "getrawchangeaddress\n"
241             "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address, for receiving change.\n"
242             "This is for use with raw transactions, NOT normal use.\n"
243             "\nResult:\n"
244             "\"address\"    (string) The address\n"
245             "\nExamples:\n"
246             + HelpExampleCli("getrawchangeaddress", "")
247             + HelpExampleRpc("getrawchangeaddress", "")
248        );
249
250     LOCK2(cs_main, pwalletMain->cs_wallet);
251
252     if (!pwalletMain->IsLocked())
253         pwalletMain->TopUpKeyPool();
254
255     CReserveKey reservekey(pwalletMain);
256     CPubKey vchPubKey;
257     if (!reservekey.GetReservedKey(vchPubKey))
258         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
259
260     reservekey.KeepKey();
261
262     CKeyID keyID = vchPubKey.GetID();
263
264     return CBitcoinAddress(keyID).ToString();
265 }
266
267
268 UniValue setaccount(const UniValue& params, bool fHelp)
269 {
270     if (!EnsureWalletIsAvailable(fHelp))
271         return NullUniValue;
272
273     if (fHelp || params.size() < 1 || params.size() > 2)
274         throw runtime_error(
275             "setaccount \"" + strprintf("%s",komodo_chainname()) + "_address\" \"account\"\n"
276             "\nDEPRECATED. Sets the account associated with the given address.\n"
277             "\nArguments:\n"
278             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to be associated with an account.\n"
279             "2. \"account\"         (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
280             "\nExamples:\n"
281             + HelpExampleCli("setaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"tabby\"")
282             + HelpExampleRpc("setaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"tabby\"")
283         );
284
285     LOCK2(cs_main, pwalletMain->cs_wallet);
286
287     CBitcoinAddress address(params[0].get_str());
288     if (!address.IsValid())
289         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
290
291     string strAccount;
292     if (params.size() > 1)
293         strAccount = AccountFromValue(params[1]);
294
295     // Only add the account if the address is yours.
296     if (IsMine(*pwalletMain, address.Get()))
297     {
298         // Detect when changing the account of an address that is the 'unused current key' of another account:
299         if (pwalletMain->mapAddressBook.count(address.Get()))
300         {
301             string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
302             if (address == GetAccountAddress(strOldAccount))
303                 GetAccountAddress(strOldAccount, true);
304         }
305         pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
306     }
307     else
308         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
309
310     return NullUniValue;
311 }
312
313
314 UniValue getaccount(const UniValue& params, bool fHelp)
315 {
316     if (!EnsureWalletIsAvailable(fHelp))
317         return NullUniValue;
318
319     if (fHelp || params.size() != 1)
320         throw runtime_error(
321             "getaccount \"" + strprintf("%s",komodo_chainname()) + "_address\"\n"
322             "\nDEPRECATED. Returns the account associated with the given address.\n"
323             "\nArguments:\n"
324             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address for account lookup.\n"
325             "\nResult:\n"
326             "\"accountname\"        (string) the account address\n"
327             "\nExamples:\n"
328             + HelpExampleCli("getaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"")
329             + HelpExampleRpc("getaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"")
330         );
331
332     LOCK2(cs_main, pwalletMain->cs_wallet);
333
334     CBitcoinAddress address(params[0].get_str());
335     if (!address.IsValid())
336         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
337
338     string strAccount;
339     map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
340     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
341         strAccount = (*mi).second.name;
342     return strAccount;
343 }
344
345
346 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
347 {
348     if (!EnsureWalletIsAvailable(fHelp))
349         return NullUniValue;
350
351     if (fHelp || params.size() != 1)
352         throw runtime_error(
353             "getaddressesbyaccount \"account\"\n"
354             "\nDEPRECATED. Returns the list of addresses for the given account.\n"
355             "\nArguments:\n"
356             "1. \"account\"  (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
357             "\nResult:\n"
358             "[                     (json array of string)\n"
359             "  \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string) a " + strprintf("%s",komodo_chainname()) + " address associated with the given account\n"
360             "  ,...\n"
361             "]\n"
362             "\nExamples:\n"
363             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
364             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
365         );
366
367     LOCK2(cs_main, pwalletMain->cs_wallet);
368
369     string strAccount = AccountFromValue(params[0]);
370
371     // Find all addresses that have the given account
372     UniValue ret(UniValue::VARR);
373     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
374     {
375         const CBitcoinAddress& address = item.first;
376         const string& strName = item.second.name;
377         if (strName == strAccount)
378             ret.push_back(address.ToString());
379     }
380     return ret;
381 }
382
383 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew,uint8_t *opretbuf,int32_t opretlen,long int opretValue)
384 {
385     CAmount curBalance = pwalletMain->GetBalance();
386
387     // Check amount
388     if (nValue <= 0)
389         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
390
391     if (nValue > curBalance)
392         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
393
394     // Parse Zcash address
395     CScript scriptPubKey = GetScriptForDestination(address);
396
397     // Create and send the transaction
398     CReserveKey reservekey(pwalletMain);
399     CAmount nFeeRequired;
400     std::string strError;
401     vector<CRecipient> vecSend;
402     int nChangePosRet = -1;
403     CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
404     vecSend.push_back(recipient);
405     if ( opretlen > 0 && opretbuf != 0 )
406     {
407         CScript opretpubkey; int32_t i; uint8_t *ptr;
408         opretpubkey.resize(opretlen);
409         ptr = (uint8_t *)opretpubkey.data();
410         for (i=0; i<opretlen; i++)
411         {
412             ptr[i] = opretbuf[i];
413             //printf("%02x",ptr[i]);
414         }
415         //printf(" opretbuf[%d]\n",opretlen);
416         CRecipient opret = { opretpubkey, opretValue, false };
417         vecSend.push_back(opret);
418     }
419     if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
420         if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
421             strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
422         throw JSONRPCError(RPC_WALLET_ERROR, strError);
423     }
424     if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
425         throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
426 }
427
428 UniValue sendtoaddress(const UniValue& params, bool fHelp)
429 {
430     if (!EnsureWalletIsAvailable(fHelp))
431         return NullUniValue;
432
433     if (fHelp || params.size() < 2 || params.size() > 5)
434         throw runtime_error(
435             "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
436             "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
437             + HelpRequiringPassphrase() +
438             "\nArguments:\n"
439             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send to.\n"
440             "2. \"amount\"      (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " to send. eg 0.1\n"
441             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
442             "                             This is not part of the transaction, just kept in your wallet.\n"
443             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
444             "                             to which you're sending the transaction. This is not part of the \n"
445             "                             transaction, just kept in your wallet.\n"
446             "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
447             "                             The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n"
448             "\nResult:\n"
449             "\"transactionid\"  (string) The transaction id.\n"
450             "\nExamples:\n"
451             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1")
452             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\"")
453             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"\" \"\" true")
454             + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"")
455         );
456
457     if ( ASSETCHAINS_PRIVATE != 0 && AmountFromValue(params[1]) > 0 )
458         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
459
460     LOCK2(cs_main, pwalletMain->cs_wallet);
461
462     CBitcoinAddress address(params[0].get_str());
463     if (!address.IsValid())
464         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
465
466     // Amount
467     CAmount nAmount = AmountFromValue(params[1]);
468     if (nAmount <= 0)
469         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
470
471     // Wallet comments
472     CWalletTx wtx;
473     if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
474         wtx.mapValue["comment"] = params[2].get_str();
475     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
476         wtx.mapValue["to"]      = params[3].get_str();
477
478     bool fSubtractFeeFromAmount = false;
479     if (params.size() > 4)
480         fSubtractFeeFromAmount = params[4].get_bool();
481
482     EnsureWalletIsUnlocked();
483
484     SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx,0,0,0);
485
486     return wtx.GetHash().GetHex();
487 }
488 #include "komodo_defs.h"
489
490 #define KOMODO_KVPROTECTED 1
491 #define KOMODO_KVBINARY 2
492 #define KOMODO_KVDURATION 1440
493 #define IGUANA_MAXSCRIPTSIZE 10001
494 uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis);
495 int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen);
496 #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
497 extern int32_t KOMODO_PAX;
498 extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
499 int32_t komodo_is_issuer();
500 int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp);
501 int32_t komodo_isrealtime(int32_t *kmdheightp);
502 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
503 int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen);
504 int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize);
505 uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen);
506 uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey);
507 int32_t komodo_kvduration(uint32_t flags);
508 uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase);
509 int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig);
510
511 UniValue kvupdate(const UniValue& params, bool fHelp)
512 {
513     static uint256 zeroes;
514     CWalletTx wtx; UniValue ret(UniValue::VOBJ);
515     uint8_t keyvalue[IGUANA_MAXSCRIPTSIZE],opretbuf[IGUANA_MAXSCRIPTSIZE]; int32_t i,coresize,haveprivkey,duration,opretlen,height; uint16_t keylen=0,valuesize=0,refvaluesize=0; uint8_t *key,*value=0; uint32_t flags,tmpflags,n; struct komodo_kv *ptr; uint64_t fee; uint256 privkey,pubkey,refpubkey,sig;
516     if (fHelp || params.size() < 3 )
517         throw runtime_error(
518             "kvupdate key \"value\" days passphrase\n"
519             "\nStore a key value. This feature is only available for asset chains.\n"
520             "\nArguments:\n"
521             "1. key                      (string, required) key\n"
522             "2. \"value\"                (string, required) value\n"
523             "3. days                     (numeric, required) amount of days(1440 blocks/day) before the key expires. Minimum 1 day\n"
524             "4. passphrase               (string, optional) passphrase required to update this key\n"
525             "\nResult:\n"
526             "{\n"
527             "  \"coin\": \"xxxxx\",          (string) chain the key is stored on\n"
528             "  \"height\": xxxxx,            (numeric) height the key was stored at\n"
529             "  \"expiration\": xxxxx,        (numeric) height the key will expire\n"
530             "  \"flags\": x,                 (string) amount of days the key will be stored \n"
531             "  \"key\": \"xxxxx\",           (numeric) stored key\n"
532             "  \"keylen\": xxxxx,            (numeric) length of the key\n"
533             "  \"value\": \"xxxxx\"          (numeric) stored value\n"
534             "  \"valuesize\": xxxxx,         (string) length of the stored value\n"
535             "  \"fee\": xxxxx                (string) transaction fee paid to store the key\n"
536             "  \"txid\": \"xxxxx\"           (string) transaction id\n"
537             "}\n"
538             "\nExamples:\n"
539             + HelpExampleCli("kvupdate", "examplekey \"examplevalue\" 2 examplepassphrase")
540             + HelpExampleRpc("kvupdate", "examplekey \"examplevalue\" 2 examplepassphrase")
541         );
542     if (!EnsureWalletIsAvailable(fHelp))
543         return 0;
544     if ( ASSETCHAINS_SYMBOL[0] == 0 )
545         return(0);
546     haveprivkey = 0;
547     memset(&sig,0,sizeof(sig));
548     memset(&privkey,0,sizeof(privkey));
549     memset(&refpubkey,0,sizeof(refpubkey));
550     memset(&pubkey,0,sizeof(pubkey));
551     if ( (n= (int32_t)params.size()) >= 3 )
552     {
553         flags = atoi(params[2].get_str().c_str());
554         //printf("flags.%d (%s) n.%d\n",flags,params[2].get_str().c_str(),n);
555     } else flags = 0;
556     if ( n >= 4 )
557         privkey = komodo_kvprivkey(&pubkey,(char *)(n >= 4 ? params[3].get_str().c_str() : "password"));
558     haveprivkey = 1;
559     flags |= 1;
560     /*for (i=0; i<32; i++)
561         printf("%02x",((uint8_t *)&privkey)[i]);
562     printf(" priv, ");
563     for (i=0; i<32; i++)
564         printf("%02x",((uint8_t *)&pubkey)[i]);
565     printf(" pubkey, privkey derived from (%s)\n",(char *)params[3].get_str().c_str());
566     */
567     LOCK2(cs_main, pwalletMain->cs_wallet);
568     if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
569     {
570         key = (uint8_t *)params[0].get_str().c_str();
571         if ( n >= 2 && params[1].get_str().c_str() != 0 )
572         {
573             value = (uint8_t *)params[1].get_str().c_str();
574             valuesize = (int32_t)strlen(params[1].get_str().c_str());
575         }
576         memcpy(keyvalue,key,keylen);
577         if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 )
578         {
579             if ( (tmpflags & KOMODO_KVPROTECTED) != 0 )
580             {
581                 if ( memcmp(&refpubkey,&pubkey,sizeof(refpubkey)) != 0 )
582                 {
583                     ret.push_back(Pair("error",(char *)"cant modify write once key without passphrase"));
584                     return ret;
585                 }
586             }
587             if ( keylen+refvaluesize <= sizeof(keyvalue) )
588             {
589                 sig = komodo_kvsig(keyvalue,keylen+refvaluesize,privkey);
590                 if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 )
591                 {
592                     ret.push_back(Pair("error",(char *)"error verifying sig, passphrase is probably wrong"));
593                     printf("VERIFY ERROR\n");
594                     return ret;
595                 } // else printf("verified immediately\n");
596             }
597         }
598         //for (i=0; i<32; i++)
599         //    printf("%02x",((uint8_t *)&sig)[i]);
600         //printf(" sig for keylen.%d + valuesize.%d\n",keylen,refvaluesize);
601         ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
602         height = chainActive.LastTip()->nHeight;
603         if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
604             ret.push_back(Pair("owner",refpubkey.GetHex()));
605         ret.push_back(Pair("height", (int64_t)height));
606         duration = komodo_kvduration(flags); //((flags >> 2) + 1) * KOMODO_KVDURATION;
607         ret.push_back(Pair("expiration", (int64_t)(height+duration)));
608         ret.push_back(Pair("flags",(int64_t)flags));
609         ret.push_back(Pair("key",params[0].get_str()));
610         ret.push_back(Pair("keylen",(int64_t)keylen));
611         if ( n >= 2 && params[1].get_str().c_str() != 0 )
612         {
613             ret.push_back(Pair("value",params[1].get_str()));
614             ret.push_back(Pair("valuesize",valuesize));
615         }
616         iguana_rwnum(1,&keyvalue[0],sizeof(keylen),&keylen);
617         iguana_rwnum(1,&keyvalue[2],sizeof(valuesize),&valuesize);
618         iguana_rwnum(1,&keyvalue[4],sizeof(height),&height);
619         iguana_rwnum(1,&keyvalue[8],sizeof(flags),&flags);
620         memcpy(&keyvalue[12],key,keylen);
621         if ( value != 0 )
622             memcpy(&keyvalue[12 + keylen],value,valuesize);
623         coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(uint16_t)*2+keylen+valuesize);
624         if ( haveprivkey != 0 )
625         {
626             for (i=0; i<32; i++)
627                 keyvalue[12 + keylen + valuesize + i] = ((uint8_t *)&pubkey)[i];
628             coresize += 32;
629             if ( refvaluesize >=0 )
630             {
631                 for (i=0; i<32; i++)
632                     keyvalue[12 + keylen + valuesize + 32 + i] = ((uint8_t *)&sig)[i];
633                 coresize += 32;
634             }
635         }
636         if ( (opretlen= komodo_opreturnscript(opretbuf,'K',keyvalue,coresize)) == 40 )
637             opretlen++;
638         //for (i=0; i<opretlen; i++)
639         //    printf("%02x",opretbuf[i]);
640         //printf(" opretbuf keylen.%d valuesize.%d height.%d (%02x %02x %02x)\n",*(uint16_t *)&keyvalue[0],*(uint16_t *)&keyvalue[2],*(uint32_t *)&keyvalue[4],keyvalue[8],keyvalue[9],keyvalue[10]);
641         EnsureWalletIsUnlocked();
642         fee = komodo_kvfee(flags,opretlen,keylen);
643         ret.push_back(Pair("fee",(double)fee/COIN));
644         CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
645         if (!destaddress.IsValid())
646             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
647         SendMoney(destaddress.Get(),10000,false,wtx,opretbuf,opretlen,fee);
648         ret.push_back(Pair("txid",wtx.GetHash().GetHex()));
649     } else ret.push_back(Pair("error",(char *)"null key"));
650     return ret;
651 }
652
653 UniValue paxdeposit(const UniValue& params, bool fHelp)
654 {
655     uint64_t available,deposited,issued,withdrawn,approved,redeemed,seed,komodoshis = 0; int32_t height; char destaddr[64]; uint8_t i,pubkey37[33];
656     bool fSubtractFeeFromAmount = false;
657     if ( KOMODO_PAX == 0 )
658     {
659         throw runtime_error("paxdeposit disabled without -pax");
660     }
661     if ( komodo_is_issuer() != 0 )
662         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "paxdeposit only from KMD");
663     if (!EnsureWalletIsAvailable(fHelp))
664         throw runtime_error("paxdeposit needs wallet"); //return Value::null;
665     if (fHelp || params.size() != 3)
666         throw runtime_error("paxdeposit address fiatoshis base");
667     LOCK2(cs_main, pwalletMain->cs_wallet);
668     CBitcoinAddress address(params[0].get_str());
669     if (!address.IsValid())
670         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
671     int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
672     std::string base = params[2].get_str();
673     std::string dest;
674     height = chainActive.LastTip()->nHeight;
675     if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,(char *)base.c_str()) != 0 || available < fiatoshis )
676     {
677         fprintf(stderr,"available %llu vs fiatoshis %llu\n",(long long)available,(long long)fiatoshis);
678         throw runtime_error("paxdeposit not enough available inventory");
679     }
680     komodoshis = PAX_fiatdest(&seed,0,destaddr,pubkey37,(char *)params[0].get_str().c_str(),height,(char *)base.c_str(),fiatoshis);
681     dest.append(destaddr);
682     CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
683     if (!destaddress.IsValid())
684         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
685     for (i=0; i<33; i++)
686         fprintf(stderr,"%02x",pubkey37[i]);
687     fprintf(stderr," ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",height,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed);
688     EnsureWalletIsUnlocked();
689     CWalletTx wtx;
690     uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000;
691     if ( fee < 10000 )
692         fee = 10000;
693     iguana_rwnum(1,&pubkey37[33],sizeof(height),&height);
694     opretlen = komodo_opreturnscript(opretbuf,'D',pubkey37,37);
695     SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis);
696     return wtx.GetHash().GetHex();
697 }
698
699 UniValue paxwithdraw(const UniValue& params, bool fHelp)
700 {
701     CWalletTx wtx; std::string dest; int32_t kmdheight; uint64_t seed,komodoshis = 0; char destaddr[64]; uint8_t i,pubkey37[37]; bool fSubtractFeeFromAmount = false;
702     if ( ASSETCHAINS_SYMBOL[0] == 0 )
703         return(0);
704     if (!EnsureWalletIsAvailable(fHelp))
705         return 0;
706     throw runtime_error("paxwithdraw deprecated");
707     if (fHelp || params.size() != 2)
708         throw runtime_error("paxwithdraw address fiatamount");
709     if ( komodo_isrealtime(&kmdheight) == 0 )
710         return(0);
711     LOCK2(cs_main, pwalletMain->cs_wallet);
712     CBitcoinAddress address(params[0].get_str());
713     if (!address.IsValid())
714         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
715     int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
716     komodoshis = PAX_fiatdest(&seed,1,destaddr,pubkey37,(char *)params[0].get_str().c_str(),kmdheight,ASSETCHAINS_SYMBOL,fiatoshis);
717     dest.append(destaddr);
718     CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
719     if (!destaddress.IsValid())
720         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
721     for (i=0; i<33; i++)
722         printf("%02x",pubkey37[i]);
723     printf(" kmdheight.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",kmdheight,(char *)params[0].get_str().c_str(),ASSETCHAINS_SYMBOL,(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed);
724     EnsureWalletIsUnlocked();
725     uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = fiatoshis / 1000;
726     if ( fee < 10000 )
727         fee = 10000;
728     iguana_rwnum(1,&pubkey37[33],sizeof(kmdheight),&kmdheight);
729     opretlen = komodo_opreturnscript(opretbuf,'W',pubkey37,37);
730     SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,fiatoshis);
731     return wtx.GetHash().GetHex();
732 }
733
734 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
735 {
736     if (!EnsureWalletIsAvailable(fHelp))
737         return NullUniValue;
738
739     if (fHelp)
740         throw runtime_error(
741             "listaddressgroupings\n"
742             "\nLists groups of addresses which have had their common ownership\n"
743             "made public by common use as inputs or as the resulting change\n"
744             "in past transactions\n"
745             "\nResult:\n"
746             "[\n"
747             "  [\n"
748             "    [\n"
749             "      \"" + strprintf("%s",komodo_chainname()) + " address\",     (string) The " + strprintf("%s",komodo_chainname()) + " address\n"
750             "      amount,                 (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n"
751             "      \"account\"             (string, optional) The account (DEPRECATED)\n"
752             "    ]\n"
753             "    ,...\n"
754             "  ]\n"
755             "  ,...\n"
756             "]\n"
757             "\nExamples:\n"
758             + HelpExampleCli("listaddressgroupings", "")
759             + HelpExampleRpc("listaddressgroupings", "")
760         );
761
762     LOCK2(cs_main, pwalletMain->cs_wallet);
763
764     UniValue jsonGroupings(UniValue::VARR);
765     map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
766     BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
767     {
768         UniValue jsonGrouping(UniValue::VARR);
769         BOOST_FOREACH(CTxDestination address, grouping)
770         {
771             UniValue addressInfo(UniValue::VARR);
772             addressInfo.push_back(CBitcoinAddress(address).ToString());
773             addressInfo.push_back(ValueFromAmount(balances[address]));
774             {
775                 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
776                     addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
777             }
778             jsonGrouping.push_back(addressInfo);
779         }
780         jsonGroupings.push_back(jsonGrouping);
781     }
782     return jsonGroupings;
783 }
784
785 UniValue signmessage(const UniValue& params, bool fHelp)
786 {
787     if (!EnsureWalletIsAvailable(fHelp))
788         return NullUniValue;
789
790     if (fHelp || params.size() != 2)
791         throw runtime_error(
792             "signmessage \"" + strprintf("%s",komodo_chainname()) + " address\" \"message\"\n"
793             "\nSign a message with the private key of an address"
794             + HelpRequiringPassphrase() + "\n"
795             "\nArguments:\n"
796             "1. \"" + strprintf("%s",komodo_chainname()) + " address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to use for the private key.\n"
797             "2. \"message\"         (string, required) The message to create a signature of.\n"
798             "\nResult:\n"
799             "\"signature\"          (string) The signature of the message encoded in base 64\n"
800             "\nExamples:\n"
801             "\nUnlock the wallet for 30 seconds\n"
802             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
803             "\nCreate the signature\n"
804             + HelpExampleCli("signmessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"my message\"") +
805             "\nVerify the signature\n"
806             + HelpExampleCli("verifymessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"signature\" \"my message\"") +
807             "\nAs json rpc\n"
808             + HelpExampleRpc("signmessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"my message\"")
809         );
810
811     LOCK2(cs_main, pwalletMain->cs_wallet);
812
813     EnsureWalletIsUnlocked();
814
815     string strAddress = params[0].get_str();
816     string strMessage = params[1].get_str();
817
818     CBitcoinAddress addr(strAddress);
819     if (!addr.IsValid())
820         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
821
822     CKeyID keyID;
823     if (!addr.GetKeyID(keyID))
824         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
825
826     CKey key;
827     if (!pwalletMain->GetKey(keyID, key))
828         throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
829
830     CHashWriter ss(SER_GETHASH, 0);
831     ss << strMessageMagic;
832     ss << strMessage;
833
834     vector<unsigned char> vchSig;
835     if (!key.SignCompact(ss.GetHash(), vchSig))
836         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
837
838     return EncodeBase64(&vchSig[0], vchSig.size());
839 }
840
841 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
842 {
843     if (!EnsureWalletIsAvailable(fHelp))
844         return NullUniValue;
845
846     if (fHelp || params.size() < 1 || params.size() > 2)
847         throw runtime_error(
848             "getreceivedbyaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" ( minconf )\n"
849             "\nReturns the total amount received by the given " + strprintf("%s",komodo_chainname()) + " address in transactions with at least minconf confirmations.\n"
850             "\nArguments:\n"
851             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address for transactions.\n"
852             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
853             "\nResult:\n"
854             "amount   (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received at this address.\n"
855             "\nExamples:\n"
856             "\nThe amount from transactions with at least 1 confirmation\n"
857             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"") +
858             "\nThe amount including unconfirmed transactions, zero confirmations\n"
859             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0") +
860             "\nThe amount with at least 6 confirmations, very safe\n"
861             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 6") +
862             "\nAs a json rpc call\n"
863             + HelpExampleRpc("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 6")
864        );
865
866     LOCK2(cs_main, pwalletMain->cs_wallet);
867
868     // Bitcoin address
869     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
870     if (!address.IsValid())
871         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
872     CScript scriptPubKey = GetScriptForDestination(address.Get());
873     if (!IsMine(*pwalletMain,scriptPubKey))
874         return (double)0.0;
875
876     // Minimum confirmations
877     int nMinDepth = 1;
878     if (params.size() > 1)
879         nMinDepth = params[1].get_int();
880
881     // Tally
882     CAmount nAmount = 0;
883     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
884     {
885         const CWalletTx& wtx = (*it).second;
886         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
887             continue;
888
889         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
890             if (txout.scriptPubKey == scriptPubKey)
891                 if (wtx.GetDepthInMainChain() >= nMinDepth)
892                     nAmount += txout.nValue; // komodo_interest?
893     }
894
895     return  ValueFromAmount(nAmount);
896 }
897
898
899 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
900 {
901     if (!EnsureWalletIsAvailable(fHelp))
902         return NullUniValue;
903
904     if (fHelp || params.size() < 1 || params.size() > 2)
905         throw runtime_error(
906             "getreceivedbyaccount \"account\" ( minconf )\n"
907             "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
908             "\nArguments:\n"
909             "1. \"account\"      (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
910             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
911             "\nResult:\n"
912             "amount              (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n"
913             "\nExamples:\n"
914             "\nAmount received by the default account with at least 1 confirmation\n"
915             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
916             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
917             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
918             "\nThe amount with at least 6 confirmation, very safe\n"
919             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
920             "\nAs a json rpc call\n"
921             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
922         );
923
924     LOCK2(cs_main, pwalletMain->cs_wallet);
925
926     // Minimum confirmations
927     int nMinDepth = 1;
928     if (params.size() > 1)
929         nMinDepth = params[1].get_int();
930
931     // Get the set of pub keys assigned to account
932     string strAccount = AccountFromValue(params[0]);
933     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
934
935     // Tally
936     CAmount nAmount = 0;
937     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
938     {
939         const CWalletTx& wtx = (*it).second;
940         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
941             continue;
942
943         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
944         {
945             CTxDestination address;
946             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
947                 if (wtx.GetDepthInMainChain() >= nMinDepth)
948                     nAmount += txout.nValue; // komodo_interest?
949         }
950     }
951
952     return (double)nAmount / (double)COIN;
953 }
954
955
956 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
957 {
958     CAmount nBalance = 0;
959
960     // Tally wallet transactions
961     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
962     {
963         const CWalletTx& wtx = (*it).second;
964         if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
965             continue;
966
967         CAmount nReceived, nSent, nFee;
968         wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
969
970         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
971             nBalance += nReceived;
972         nBalance -= nSent + nFee;
973     }
974
975     // Tally internal accounting entries
976     nBalance += walletdb.GetAccountCreditDebit(strAccount);
977
978     return nBalance;
979 }
980
981 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
982 {
983     CWalletDB walletdb(pwalletMain->strWalletFile);
984     return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
985 }
986
987
988 UniValue getbalance(const UniValue& params, bool fHelp)
989 {
990     if (!EnsureWalletIsAvailable(fHelp))
991         return NullUniValue;
992
993     if (fHelp || params.size() > 3)
994         throw runtime_error(
995             "getbalance ( \"account\" minconf includeWatchonly )\n"
996             "\nReturns the server's total available balance.\n"
997             "\nArguments:\n"
998             "1. \"account\"      (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" or to the string \"*\", either of which will give the total available balance. Passing any other string will result in an error.\n"
999             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
1000             "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
1001             "\nResult:\n"
1002             "amount              (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n"
1003             "\nExamples:\n"
1004             "\nThe total amount in the wallet\n"
1005             + HelpExampleCli("getbalance", "") +
1006             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
1007             + HelpExampleCli("getbalance", "\"*\" 6") +
1008             "\nAs a json rpc call\n"
1009             + HelpExampleRpc("getbalance", "\"*\", 6")
1010         );
1011
1012     LOCK2(cs_main, pwalletMain->cs_wallet);
1013
1014     if (params.size() == 0)
1015         return  ValueFromAmount(pwalletMain->GetBalance());
1016
1017     int nMinDepth = 1;
1018     if (params.size() > 1)
1019         nMinDepth = params[1].get_int();
1020     isminefilter filter = ISMINE_SPENDABLE;
1021     if(params.size() > 2)
1022         if(params[2].get_bool())
1023             filter = filter | ISMINE_WATCH_ONLY;
1024
1025     if (params[0].get_str() == "*") {
1026         // Calculate total balance a different way from GetBalance()
1027         // (GetBalance() sums up all unspent TxOuts)
1028         // getbalance and "getbalance * 1 true" should return the same number
1029         CAmount nBalance = 0;
1030         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1031         {
1032             const CWalletTx& wtx = (*it).second;
1033             if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
1034                 continue;
1035
1036             CAmount allFee;
1037             string strSentAccount;
1038             list<COutputEntry> listReceived;
1039             list<COutputEntry> listSent;
1040             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
1041             if (wtx.GetDepthInMainChain() >= nMinDepth)
1042             {
1043                 BOOST_FOREACH(const COutputEntry& r, listReceived)
1044                     nBalance += r.amount;
1045             }
1046             BOOST_FOREACH(const COutputEntry& s, listSent)
1047                 nBalance -= s.amount;
1048             nBalance -= allFee;
1049         }
1050         return  ValueFromAmount(nBalance);
1051     }
1052
1053     string strAccount = AccountFromValue(params[0]);
1054
1055     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
1056
1057     return ValueFromAmount(nBalance);
1058 }
1059
1060 UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
1061 {
1062     if (!EnsureWalletIsAvailable(fHelp))
1063         return NullUniValue;
1064
1065     if (fHelp || params.size() > 0)
1066         throw runtime_error(
1067                 "getunconfirmedbalance\n"
1068                 "Returns the server's total unconfirmed balance\n");
1069
1070     LOCK2(cs_main, pwalletMain->cs_wallet);
1071
1072     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
1073 }
1074
1075
1076 UniValue movecmd(const UniValue& params, bool fHelp)
1077 {
1078     if (!EnsureWalletIsAvailable(fHelp))
1079         return NullUniValue;
1080
1081     if (fHelp || params.size() < 3 || params.size() > 5)
1082         throw runtime_error(
1083             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
1084             "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
1085             "\nArguments:\n"
1086             "1. \"fromaccount\"   (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
1087             "2. \"toaccount\"     (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
1088             "3. amount            (numeric) Quantity of " + strprintf("%s",komodo_chainname()) + " to move between accounts.\n"
1089             "4. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
1090             "5. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
1091             "\nResult:\n"
1092             "true|false           (boolean) true if successful.\n"
1093             "\nExamples:\n"
1094             "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the account named tabby\n"
1095             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
1096             "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " timotei to akiko with a comment and funds have 6 confirmations\n"
1097             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
1098             "\nAs a json rpc call\n"
1099             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
1100         );
1101     if ( ASSETCHAINS_PRIVATE != 0 )
1102         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1103
1104     LOCK2(cs_main, pwalletMain->cs_wallet);
1105
1106     string strFrom = AccountFromValue(params[0]);
1107     string strTo = AccountFromValue(params[1]);
1108     CAmount nAmount = AmountFromValue(params[2]);
1109     if (nAmount <= 0)
1110         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1111     if (params.size() > 3)
1112         // unused parameter, used to be nMinDepth, keep type-checking it though
1113         (void)params[3].get_int();
1114     string strComment;
1115     if (params.size() > 4)
1116         strComment = params[4].get_str();
1117
1118     CWalletDB walletdb(pwalletMain->strWalletFile);
1119     if (!walletdb.TxnBegin())
1120         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
1121
1122     int64_t nNow = GetAdjustedTime();
1123
1124     // Debit
1125     CAccountingEntry debit;
1126     debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
1127     debit.strAccount = strFrom;
1128     debit.nCreditDebit = -nAmount;
1129     debit.nTime = nNow;
1130     debit.strOtherAccount = strTo;
1131     debit.strComment = strComment;
1132     walletdb.WriteAccountingEntry(debit);
1133
1134     // Credit
1135     CAccountingEntry credit;
1136     credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
1137     credit.strAccount = strTo;
1138     credit.nCreditDebit = nAmount;
1139     credit.nTime = nNow;
1140     credit.strOtherAccount = strFrom;
1141     credit.strComment = strComment;
1142     walletdb.WriteAccountingEntry(credit);
1143
1144     if (!walletdb.TxnCommit())
1145         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
1146
1147     return true;
1148 }
1149
1150
1151 UniValue sendfrom(const UniValue& params, bool fHelp)
1152 {
1153     if (!EnsureWalletIsAvailable(fHelp))
1154         return NullUniValue;
1155
1156     if (fHelp || params.size() < 3 || params.size() > 6)
1157         throw runtime_error(
1158             "sendfrom \"fromaccount\" \"to" + strprintf("%s",komodo_chainname()) + "address\" amount ( minconf \"comment\" \"comment-to\" )\n"
1159             "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a " + strprintf("%s",komodo_chainname()) + " address.\n"
1160             "The amount is a real and is rounded to the nearest 0.00000001."
1161             + HelpRequiringPassphrase() + "\n"
1162             "\nArguments:\n"
1163             "1. \"fromaccount\"       (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
1164             "2. \"to" + strprintf("%s",komodo_chainname()) + "address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send funds to.\n"
1165             "3. amount                (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " (transaction fee is added on top).\n"
1166             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
1167             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
1168             "                                     This is not part of the transaction, just kept in your wallet.\n"
1169             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
1170             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
1171             "                                     it is just kept in your wallet.\n"
1172             "\nResult:\n"
1173             "\"transactionid\"        (string) The transaction id.\n"
1174             "\nExamples:\n"
1175             "\nSend 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the address, must have at least 1 confirmation\n"
1176             + HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") +
1177             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
1178             + HelpExampleCli("sendfrom", "\"tabby\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01 6 \"donation\" \"seans outpost\"") +
1179             "\nAs a json rpc call\n"
1180             + HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"seans outpost\"")
1181         );
1182     if ( ASSETCHAINS_PRIVATE != 0 )
1183         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1184
1185     LOCK2(cs_main, pwalletMain->cs_wallet);
1186
1187     string strAccount = AccountFromValue(params[0]);
1188     CBitcoinAddress address(params[1].get_str());
1189     if (!address.IsValid())
1190         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
1191     CAmount nAmount = AmountFromValue(params[2]);
1192     if (nAmount <= 0)
1193         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1194     int nMinDepth = 1;
1195     if (params.size() > 3)
1196         nMinDepth = params[3].get_int();
1197
1198     CWalletTx wtx;
1199     wtx.strFromAccount = strAccount;
1200     if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
1201         wtx.mapValue["comment"] = params[4].get_str();
1202     if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
1203         wtx.mapValue["to"]      = params[5].get_str();
1204
1205     EnsureWalletIsUnlocked();
1206
1207     // Check funds
1208     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1209     if (nAmount > nBalance)
1210         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1211
1212     SendMoney(address.Get(), nAmount, false, wtx,0,0,0);
1213
1214     return wtx.GetHash().GetHex();
1215 }
1216
1217
1218 UniValue sendmany(const UniValue& params, bool fHelp)
1219 {
1220     if (!EnsureWalletIsAvailable(fHelp))
1221         return NullUniValue;
1222
1223     if (fHelp || params.size() < 2 || params.size() > 5)
1224         throw runtime_error(
1225             "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
1226             "\nSend multiple times. Amounts are double-precision floating point numbers."
1227             + HelpRequiringPassphrase() + "\n"
1228             "\nArguments:\n"
1229             "1. \"fromaccount\"         (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
1230             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
1231             "    {\n"
1232             "      \"address\":amount   (numeric) The " + strprintf("%s",komodo_chainname()) + " address is the key, the numeric amount in " + strprintf("%s",komodo_chainname()) + " is the value\n"
1233             "      ,...\n"
1234             "    }\n"
1235             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
1236             "4. \"comment\"             (string, optional) A comment\n"
1237             "5. subtractfeefromamount   (string, optional) A json array with addresses.\n"
1238             "                           The fee will be equally deducted from the amount of each selected address.\n"
1239             "                           Those recipients will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in their corresponding amount field.\n"
1240             "                           If no addresses are specified here, the sender pays the fee.\n"
1241             "    [\n"
1242             "      \"address\"            (string) Subtract fee from this address\n"
1243             "      ,...\n"
1244             "    ]\n"
1245             "\nResult:\n"
1246             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
1247             "                                    the number of addresses.\n"
1248             "\nExamples:\n"
1249             "\nSend two amounts to two different addresses:\n"
1250             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\"") +
1251             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
1252             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\" 6 \"testing\"") +
1253             "\nSend two amounts to two different addresses, subtract fee from amount:\n"
1254             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\" 1 \"\" \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"") +
1255             "\nAs a json rpc call\n"
1256             + HelpExampleRpc("sendmany", "\"\", \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\", 6, \"testing\"")
1257         );
1258     if ( ASSETCHAINS_PRIVATE != 0 )
1259         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1260
1261     LOCK2(cs_main, pwalletMain->cs_wallet);
1262
1263     string strAccount = AccountFromValue(params[0]);
1264     UniValue sendTo = params[1].get_obj();
1265     int nMinDepth = 1;
1266     if (params.size() > 2)
1267         nMinDepth = params[2].get_int();
1268
1269     CWalletTx wtx;
1270     wtx.strFromAccount = strAccount;
1271     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
1272         wtx.mapValue["comment"] = params[3].get_str();
1273
1274     UniValue subtractFeeFromAmount(UniValue::VARR);
1275     if (params.size() > 4)
1276         subtractFeeFromAmount = params[4].get_array();
1277
1278     set<CBitcoinAddress> setAddress;
1279     vector<CRecipient> vecSend;
1280
1281     CAmount totalAmount = 0;
1282     vector<string> keys = sendTo.getKeys();
1283     BOOST_FOREACH(const string& name_, keys)
1284     {
1285         CBitcoinAddress address(name_);
1286         if (!address.IsValid())
1287             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid " + strprintf("%s",komodo_chainname()) + " address: ")+name_);
1288
1289         //if (setAddress.count(address))
1290         //    throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
1291         setAddress.insert(address);
1292
1293         CScript scriptPubKey = GetScriptForDestination(address.Get());
1294         CAmount nAmount = AmountFromValue(sendTo[name_]);
1295         if (nAmount <= 0)
1296             throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1297         totalAmount += nAmount;
1298
1299         bool fSubtractFeeFromAmount = false;
1300         for (size_t idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1301             const UniValue& addr = subtractFeeFromAmount[idx];
1302             if (addr.get_str() == name_)
1303                 fSubtractFeeFromAmount = true;
1304         }
1305
1306         CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1307         vecSend.push_back(recipient);
1308     }
1309
1310     EnsureWalletIsUnlocked();
1311
1312     // Check funds
1313     CAmount nBalance = pwalletMain->GetBalance();
1314     //CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1315     if (totalAmount > nBalance)
1316         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1317
1318     // Send
1319     CReserveKey keyChange(pwalletMain);
1320     CAmount nFeeRequired = 0;
1321     int nChangePosRet = -1;
1322     string strFailReason;
1323     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1324     if (!fCreated)
1325         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1326     if (!pwalletMain->CommitTransaction(wtx, keyChange))
1327         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
1328
1329     return wtx.GetHash().GetHex();
1330 }
1331
1332 // Defined in rpcmisc.cpp
1333 extern CScript _createmultisig_redeemScript(const UniValue& params);
1334
1335 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
1336 {
1337     if (!EnsureWalletIsAvailable(fHelp))
1338         return NullUniValue;
1339
1340     if (fHelp || params.size() < 2 || params.size() > 3)
1341     {
1342         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1343             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1344             "Each key is a " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key.\n"
1345             "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1346
1347             "\nArguments:\n"
1348             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1349             "2. \"keysobject\"   (string, required) A json array of " + strprintf("%s",komodo_chainname()) + " addresses or hex-encoded public keys\n"
1350             "     [\n"
1351             "       \"address\"  (string) " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key\n"
1352             "       ...,\n"
1353             "     ]\n"
1354             "3. \"account\"      (string, optional) DEPRECATED. If provided, MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
1355
1356             "\nResult:\n"
1357             "\"" + strprintf("%s",komodo_chainname()) + "_address\"  (string) A " + strprintf("%s",komodo_chainname()) + " address associated with the keys.\n"
1358
1359             "\nExamples:\n"
1360             "\nAdd a multisig address from 2 addresses\n"
1361             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"") +
1362             "\nAs json rpc call\n"
1363             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
1364         ;
1365         throw runtime_error(msg);
1366     }
1367
1368     LOCK2(cs_main, pwalletMain->cs_wallet);
1369
1370     string strAccount;
1371     if (params.size() > 2)
1372         strAccount = AccountFromValue(params[2]);
1373
1374     // Construct using pay-to-script-hash:
1375     CScript inner = _createmultisig_redeemScript(params);
1376     CScriptID innerID(inner);
1377     pwalletMain->AddCScript(inner);
1378
1379     pwalletMain->SetAddressBook(innerID, strAccount, "send");
1380     return CBitcoinAddress(innerID).ToString();
1381 }
1382
1383
1384 struct tallyitem
1385 {
1386     CAmount nAmount;
1387     int nConf;
1388     vector<uint256> txids;
1389     bool fIsWatchonly;
1390     tallyitem()
1391     {
1392         nAmount = 0;
1393         nConf = std::numeric_limits<int>::max();
1394         fIsWatchonly = false;
1395     }
1396 };
1397
1398 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1399 {
1400     // Minimum confirmations
1401     int nMinDepth = 1;
1402     if (params.size() > 0)
1403         nMinDepth = params[0].get_int();
1404
1405     // Whether to include empty accounts
1406     bool fIncludeEmpty = false;
1407     if (params.size() > 1)
1408         fIncludeEmpty = params[1].get_bool();
1409
1410     isminefilter filter = ISMINE_SPENDABLE;
1411     if(params.size() > 2)
1412         if(params[2].get_bool())
1413             filter = filter | ISMINE_WATCH_ONLY;
1414
1415     // Tally
1416     map<CBitcoinAddress, tallyitem> mapTally;
1417     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1418     {
1419         const CWalletTx& wtx = (*it).second;
1420
1421         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1422             continue;
1423
1424         int nDepth = wtx.GetDepthInMainChain();
1425         if (nDepth < nMinDepth)
1426             continue;
1427
1428         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1429         {
1430             CTxDestination address;
1431             if (!ExtractDestination(txout.scriptPubKey, address))
1432                 continue;
1433
1434             isminefilter mine = IsMine(*pwalletMain, address);
1435             if(!(mine & filter))
1436                 continue;
1437
1438             tallyitem& item = mapTally[address];
1439             item.nAmount += txout.nValue; // komodo_interest?
1440             item.nConf = min(item.nConf, nDepth);
1441             item.txids.push_back(wtx.GetHash());
1442             if (mine & ISMINE_WATCH_ONLY)
1443                 item.fIsWatchonly = true;
1444         }
1445     }
1446
1447     // Reply
1448     UniValue ret(UniValue::VARR);
1449     map<string, tallyitem> mapAccountTally;
1450     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1451     {
1452         const CBitcoinAddress& address = item.first;
1453         const string& strAccount = item.second.name;
1454         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1455         if (it == mapTally.end() && !fIncludeEmpty)
1456             continue;
1457
1458         CAmount nAmount = 0;
1459         int nConf = std::numeric_limits<int>::max();
1460         bool fIsWatchonly = false;
1461         if (it != mapTally.end())
1462         {
1463             nAmount = (*it).second.nAmount;
1464             nConf = (*it).second.nConf;
1465             fIsWatchonly = (*it).second.fIsWatchonly;
1466         }
1467
1468         if (fByAccounts)
1469         {
1470             tallyitem& item = mapAccountTally[strAccount];
1471             item.nAmount += nAmount;
1472             item.nConf = min(item.nConf, nConf);
1473             item.fIsWatchonly = fIsWatchonly;
1474         }
1475         else
1476         {
1477             UniValue obj(UniValue::VOBJ);
1478             if(fIsWatchonly)
1479                 obj.push_back(Pair("involvesWatchonly", true));
1480             obj.push_back(Pair("address",       address.ToString()));
1481             obj.push_back(Pair("account",       strAccount));
1482             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1483             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1484             UniValue transactions(UniValue::VARR);
1485             if (it != mapTally.end())
1486             {
1487                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1488                 {
1489                     transactions.push_back(item.GetHex());
1490                 }
1491             }
1492             obj.push_back(Pair("txids", transactions));
1493             ret.push_back(obj);
1494         }
1495     }
1496
1497     if (fByAccounts)
1498     {
1499         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1500         {
1501             CAmount nAmount = (*it).second.nAmount;
1502             int nConf = (*it).second.nConf;
1503             UniValue obj(UniValue::VOBJ);
1504             if((*it).second.fIsWatchonly)
1505                 obj.push_back(Pair("involvesWatchonly", true));
1506             obj.push_back(Pair("account",       (*it).first));
1507             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1508             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1509             ret.push_back(obj);
1510         }
1511     }
1512
1513     return ret;
1514 }
1515
1516 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1517 {
1518     if (!EnsureWalletIsAvailable(fHelp))
1519         return NullUniValue;
1520
1521     if (fHelp || params.size() > 3)
1522         throw runtime_error(
1523             "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1524             "\nList balances by receiving address.\n"
1525             "\nArguments:\n"
1526             "1. minconf       (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1527             "2. includeempty  (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1528             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1529
1530             "\nResult:\n"
1531             "[\n"
1532             "  {\n"
1533             "    \"involvesWatchonly\" : true,        (bool) Only returned if imported addresses were involved in transaction\n"
1534             "    \"address\" : \"receivingaddress\",  (string) The receiving address\n"
1535             "    \"account\" : \"accountname\",       (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1536             "    \"amount\" : x.xxx,                  (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received by the address\n"
1537             "    \"confirmations\" : n                (numeric) The number of confirmations of the most recent transaction included\n"
1538             "  }\n"
1539             "  ,...\n"
1540             "]\n"
1541
1542             "\nExamples:\n"
1543             + HelpExampleCli("listreceivedbyaddress", "")
1544             + HelpExampleCli("listreceivedbyaddress", "6 true")
1545             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1546         );
1547
1548     LOCK2(cs_main, pwalletMain->cs_wallet);
1549
1550     return ListReceived(params, false);
1551 }
1552
1553 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
1554 {
1555     if (!EnsureWalletIsAvailable(fHelp))
1556         return NullUniValue;
1557
1558     if (fHelp || params.size() > 3)
1559         throw runtime_error(
1560             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1561             "\nDEPRECATED. List balances by account.\n"
1562             "\nArguments:\n"
1563             "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1564             "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1565             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1566
1567             "\nResult:\n"
1568             "[\n"
1569             "  {\n"
1570             "    \"involvesWatchonly\" : true,   (bool) Only returned if imported addresses were involved in transaction\n"
1571             "    \"account\" : \"accountname\",  (string) The account name of the receiving account\n"
1572             "    \"amount\" : x.xxx,             (numeric) The total amount received by addresses with this account\n"
1573             "    \"confirmations\" : n           (numeric) The number of confirmations of the most recent transaction included\n"
1574             "  }\n"
1575             "  ,...\n"
1576             "]\n"
1577
1578             "\nExamples:\n"
1579             + HelpExampleCli("listreceivedbyaccount", "")
1580             + HelpExampleCli("listreceivedbyaccount", "6 true")
1581             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1582         );
1583
1584     LOCK2(cs_main, pwalletMain->cs_wallet);
1585
1586     return ListReceived(params, true);
1587 }
1588
1589 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1590 {
1591     CBitcoinAddress addr;
1592     if (addr.Set(dest))
1593         entry.push_back(Pair("address", addr.ToString()));
1594 }
1595
1596 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1597 {
1598     CAmount nFee;
1599     string strSentAccount;
1600     list<COutputEntry> listReceived;
1601     list<COutputEntry> listSent;
1602
1603     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1604
1605     bool fAllAccounts = (strAccount == string("*"));
1606     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1607
1608     // Sent
1609     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1610     {
1611         BOOST_FOREACH(const COutputEntry& s, listSent)
1612         {
1613             UniValue entry(UniValue::VOBJ);
1614             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1615                 entry.push_back(Pair("involvesWatchonly", true));
1616             entry.push_back(Pair("account", strSentAccount));
1617             MaybePushAddress(entry, s.destination);
1618             entry.push_back(Pair("category", "send"));
1619             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1620             entry.push_back(Pair("vout", s.vout));
1621             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1622             if (fLong)
1623                 WalletTxToJSON(wtx, entry);
1624             #ifdef __APPLE__
1625             entry.push_back(Pair("size", (uint64_t)static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
1626             #else
1627             entry.push_back(Pair("size", static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
1628             #endif
1629             ret.push_back(entry);
1630         }
1631     }
1632
1633     // Received
1634     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1635     {
1636         BOOST_FOREACH(const COutputEntry& r, listReceived)
1637         {
1638             string account;
1639             if (pwalletMain->mapAddressBook.count(r.destination))
1640                 account = pwalletMain->mapAddressBook[r.destination].name;
1641             if (fAllAccounts || (account == strAccount))
1642             {
1643                 UniValue entry(UniValue::VOBJ);
1644                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1645                     entry.push_back(Pair("involvesWatchonly", true));
1646                 entry.push_back(Pair("account", account));
1647                 MaybePushAddress(entry, r.destination);
1648                 if (wtx.IsCoinBase())
1649                 {
1650                     if (wtx.GetDepthInMainChain() < 1)
1651                         entry.push_back(Pair("category", "orphan"));
1652                     else if (wtx.GetBlocksToMaturity() > 0)
1653                         entry.push_back(Pair("category", "immature"));
1654                     else
1655                         entry.push_back(Pair("category", "generate"));
1656                 }
1657                 else
1658                 {
1659                     entry.push_back(Pair("category", "receive"));
1660                 }
1661                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1662                 entry.push_back(Pair("vout", r.vout));
1663                 if (fLong)
1664                     WalletTxToJSON(wtx, entry);
1665                     #ifdef __APPLE__
1666                     entry.push_back(Pair("size", (uint64_t)static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
1667                     #else
1668                     entry.push_back(Pair("size", static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
1669                     #endif
1670                 ret.push_back(entry);
1671             }
1672         }
1673     }
1674 }
1675
1676 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1677 {
1678     bool fAllAccounts = (strAccount == string("*"));
1679
1680     if (fAllAccounts || acentry.strAccount == strAccount)
1681     {
1682         UniValue entry(UniValue::VOBJ);
1683         entry.push_back(Pair("account", acentry.strAccount));
1684         entry.push_back(Pair("category", "move"));
1685         entry.push_back(Pair("time", acentry.nTime));
1686         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1687         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1688         entry.push_back(Pair("comment", acentry.strComment));
1689         ret.push_back(entry);
1690     }
1691 }
1692
1693 UniValue listtransactions(const UniValue& params, bool fHelp)
1694 {
1695     if (!EnsureWalletIsAvailable(fHelp))
1696         return NullUniValue;
1697
1698     if (fHelp || params.size() > 4)
1699         throw runtime_error(
1700             "listtransactions ( \"account\" count from includeWatchonly)\n"
1701             "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1702             "\nArguments:\n"
1703             "1. \"account\"    (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1704             "2. count          (numeric, optional, default=10) The number of transactions to return\n"
1705             "3. from           (numeric, optional, default=0) The number of transactions to skip\n"
1706             "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1707             "\nResult:\n"
1708             "[\n"
1709             "  {\n"
1710             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. \n"
1711             "                                                It will be \"\" for the default account.\n"
1712             "    \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\",    (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for \n"
1713             "                                                move transactions (category = move).\n"
1714             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1715             "                                                transaction between accounts, and not associated with an address,\n"
1716             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
1717             "                                                associated with an address, transaction id and block details\n"
1718             "    \"amount\": x.xxx,          (numeric) The amount in " + strprintf("%s",komodo_chainname()) + ". This is negative for the 'send' category, and for the\n"
1719             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
1720             "                                         and for the 'move' category for inbound funds.\n"
1721             "    \"vout\" : n,               (numeric) the vout value\n"
1722             "    \"fee\": x.xxx,             (numeric) The amount of the fee in " + strprintf("%s",komodo_chainname()) + ". This is negative and only available for the \n"
1723             "                                         'send' category of transactions.\n"
1724             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1725             "                                         'receive' category of transactions.\n"
1726             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1727             "                                          category of transactions.\n"
1728             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1729             "                                          category of transactions.\n"
1730             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1731             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1732             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1733             "                                          for 'send' and 'receive' category of transactions.\n"
1734             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1735             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
1736             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1737             "                                          negative amounts).\n"
1738             "    \"size\": n,                (numeric) Transaction size in bytes\n"
1739             "  }\n"
1740             "]\n"
1741
1742             "\nExamples:\n"
1743             "\nList the most recent 10 transactions in the systems\n"
1744             + HelpExampleCli("listtransactions", "") +
1745             "\nList transactions 100 to 120\n"
1746             + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1747             "\nAs a json rpc call\n"
1748             + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1749         );
1750
1751     LOCK2(cs_main, pwalletMain->cs_wallet);
1752
1753     string strAccount = "*";
1754     if (params.size() > 0)
1755         strAccount = params[0].get_str();
1756     int nCount = 10;
1757     if (params.size() > 1)
1758         nCount = params[1].get_int();
1759     int nFrom = 0;
1760     if (params.size() > 2)
1761         nFrom = params[2].get_int();
1762     isminefilter filter = ISMINE_SPENDABLE;
1763     if(params.size() > 3)
1764         if(params[3].get_bool())
1765             filter = filter | ISMINE_WATCH_ONLY;
1766
1767     if (nCount < 0)
1768         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1769     if (nFrom < 0)
1770         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1771
1772     UniValue ret(UniValue::VARR);
1773
1774     std::list<CAccountingEntry> acentries;
1775     CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1776
1777     // iterate backwards until we have nCount items to return:
1778     for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1779     {
1780         CWalletTx *const pwtx = (*it).second.first;
1781         if (pwtx != 0)
1782             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1783         CAccountingEntry *const pacentry = (*it).second.second;
1784         if (pacentry != 0)
1785             AcentryToJSON(*pacentry, strAccount, ret);
1786
1787         if ((int)ret.size() >= (nCount+nFrom)) break;
1788     }
1789     // ret is newest to oldest
1790
1791     if (nFrom > (int)ret.size())
1792         nFrom = ret.size();
1793     if ((nFrom + nCount) > (int)ret.size())
1794         nCount = ret.size() - nFrom;
1795
1796     vector<UniValue> arrTmp = ret.getValues();
1797
1798     vector<UniValue>::iterator first = arrTmp.begin();
1799     std::advance(first, nFrom);
1800     vector<UniValue>::iterator last = arrTmp.begin();
1801     std::advance(last, nFrom+nCount);
1802
1803     if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1804     if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1805
1806     std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1807
1808     ret.clear();
1809     ret.setArray();
1810     ret.push_backV(arrTmp);
1811
1812     return ret;
1813 }
1814
1815 UniValue listaccounts(const UniValue& params, bool fHelp)
1816 {
1817     if (!EnsureWalletIsAvailable(fHelp))
1818         return NullUniValue;
1819
1820     if (fHelp || params.size() > 2)
1821         throw runtime_error(
1822             "listaccounts ( minconf includeWatchonly)\n"
1823             "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1824             "\nArguments:\n"
1825             "1. minconf          (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1826             "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1827             "\nResult:\n"
1828             "{                      (json object where keys are account names, and values are numeric balances\n"
1829             "  \"account\": x.xxx,  (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1830             "  ...\n"
1831             "}\n"
1832             "\nExamples:\n"
1833             "\nList account balances where there at least 1 confirmation\n"
1834             + HelpExampleCli("listaccounts", "") +
1835             "\nList account balances including zero confirmation transactions\n"
1836             + HelpExampleCli("listaccounts", "0") +
1837             "\nList account balances for 6 or more confirmations\n"
1838             + HelpExampleCli("listaccounts", "6") +
1839             "\nAs json rpc call\n"
1840             + HelpExampleRpc("listaccounts", "6")
1841         );
1842
1843     LOCK2(cs_main, pwalletMain->cs_wallet);
1844
1845     int nMinDepth = 1;
1846     if (params.size() > 0)
1847         nMinDepth = params[0].get_int();
1848     isminefilter includeWatchonly = ISMINE_SPENDABLE;
1849     if(params.size() > 1)
1850         if(params[1].get_bool())
1851             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1852
1853     map<string, CAmount> mapAccountBalances;
1854     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1855         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1856             mapAccountBalances[entry.second.name] = 0;
1857     }
1858
1859     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1860     {
1861         const CWalletTx& wtx = (*it).second;
1862         CAmount nFee;
1863         string strSentAccount;
1864         list<COutputEntry> listReceived;
1865         list<COutputEntry> listSent;
1866         int nDepth = wtx.GetDepthInMainChain();
1867         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1868             continue;
1869         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1870         mapAccountBalances[strSentAccount] -= nFee;
1871         BOOST_FOREACH(const COutputEntry& s, listSent)
1872             mapAccountBalances[strSentAccount] -= s.amount;
1873         if (nDepth >= nMinDepth)
1874         {
1875             BOOST_FOREACH(const COutputEntry& r, listReceived)
1876                 if (pwalletMain->mapAddressBook.count(r.destination))
1877                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1878                 else
1879                     mapAccountBalances[""] += r.amount;
1880         }
1881     }
1882
1883     list<CAccountingEntry> acentries;
1884     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1885     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1886         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1887
1888     UniValue ret(UniValue::VOBJ);
1889     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1890         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1891     }
1892     return ret;
1893 }
1894
1895 UniValue listsinceblock(const UniValue& params, bool fHelp)
1896 {
1897     if (!EnsureWalletIsAvailable(fHelp))
1898         return NullUniValue;
1899
1900     if (fHelp)
1901         throw runtime_error(
1902             "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1903             "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1904             "\nArguments:\n"
1905             "1. \"blockhash\"   (string, optional) The block hash to list transactions since\n"
1906             "2. target-confirmations:    (numeric, optional) The confirmations required, must be 1 or more\n"
1907             "3. includeWatchonly:        (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1908             "\nResult:\n"
1909             "{\n"
1910             "  \"transactions\": [\n"
1911             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1912             "    \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\",    (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for move transactions (category = move).\n"
1913             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1914             "    \"amount\": x.xxx,          (numeric) The amount in " + strprintf("%s",komodo_chainname()) + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1915             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1916             "    \"vout\" : n,               (numeric) the vout value\n"
1917             "    \"fee\": x.xxx,             (numeric) The amount of the fee in " + strprintf("%s",komodo_chainname()) + ". This is negative and only available for the 'send' category of transactions.\n"
1918             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1919             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1920             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1921             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1922             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1923             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1924             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1925             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1926             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
1927              "  ],\n"
1928             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
1929             "}\n"
1930             "\nExamples:\n"
1931             + HelpExampleCli("listsinceblock", "")
1932             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1933             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1934         );
1935
1936     LOCK2(cs_main, pwalletMain->cs_wallet);
1937
1938     CBlockIndex *pindex = NULL;
1939     int target_confirms = 1;
1940     isminefilter filter = ISMINE_SPENDABLE;
1941
1942     if (params.size() > 0)
1943     {
1944         uint256 blockId;
1945
1946         blockId.SetHex(params[0].get_str());
1947         BlockMap::iterator it = mapBlockIndex.find(blockId);
1948         if (it != mapBlockIndex.end())
1949             pindex = it->second;
1950     }
1951
1952     if (params.size() > 1)
1953     {
1954         target_confirms = params[1].get_int();
1955
1956         if (target_confirms < 1)
1957             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1958     }
1959
1960     if(params.size() > 2)
1961         if(params[2].get_bool())
1962             filter = filter | ISMINE_WATCH_ONLY;
1963
1964     int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1965
1966     UniValue transactions(UniValue::VARR);
1967
1968     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1969     {
1970         CWalletTx tx = (*it).second;
1971
1972         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1973             ListTransactions(tx, "*", 0, true, transactions, filter);
1974     }
1975
1976     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1977     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1978
1979     UniValue ret(UniValue::VOBJ);
1980     ret.push_back(Pair("transactions", transactions));
1981     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1982
1983     return ret;
1984 }
1985
1986 UniValue gettransaction(const UniValue& params, bool fHelp)
1987 {
1988     if (!EnsureWalletIsAvailable(fHelp))
1989         return NullUniValue;
1990
1991     if (fHelp || params.size() < 1 || params.size() > 2)
1992         throw runtime_error(
1993             "gettransaction \"txid\" ( includeWatchonly )\n"
1994             "\nGet detailed information about in-wallet transaction <txid>\n"
1995             "\nArguments:\n"
1996             "1. \"txid\"    (string, required) The transaction id\n"
1997             "2. \"includeWatchonly\"    (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1998             "\nResult:\n"
1999             "{\n"
2000             "  \"amount\" : x.xxx,        (numeric) The transaction amount in " + strprintf("%s",komodo_chainname()) + "\n"
2001             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
2002             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
2003             "  \"blockindex\" : xx,       (numeric) The block index\n"
2004             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
2005             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
2006             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
2007             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
2008             "  \"details\" : [\n"
2009             "    {\n"
2010             "      \"account\" : \"accountname\",  (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
2011             "      \"address\" : \"" + strprintf("%s",komodo_chainname()) + "_address\",   (string) The " + strprintf("%s",komodo_chainname()) + " address involved in the transaction\n"
2012             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
2013             "      \"amount\" : x.xxx                  (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n"
2014             "      \"vout\" : n,                       (numeric) the vout value\n"
2015             "    }\n"
2016             "    ,...\n"
2017             "  ],\n"
2018             "  \"vjoinsplit\" : [\n"
2019             "    {\n"
2020             "      \"anchor\" : \"treestateref\",          (string) Merkle root of note commitment tree\n"
2021             "      \"nullifiers\" : [ string, ... ]      (string) Nullifiers of input notes\n"
2022             "      \"commitments\" : [ string, ... ]     (string) Note commitments for note outputs\n"
2023             "      \"macs\" : [ string, ... ]            (string) Message authentication tags\n"
2024             "      \"vpub_old\" : x.xxx                  (numeric) The amount removed from the transparent value pool\n"
2025             "      \"vpub_new\" : x.xxx,                 (numeric) The amount added to the transparent value pool\n"
2026             "    }\n"
2027             "    ,...\n"
2028             "  ],\n"
2029             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
2030             "}\n"
2031
2032             "\nExamples:\n"
2033             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2034             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
2035             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2036         );
2037
2038     LOCK2(cs_main, pwalletMain->cs_wallet);
2039
2040     uint256 hash;
2041     hash.SetHex(params[0].get_str());
2042
2043     isminefilter filter = ISMINE_SPENDABLE;
2044     if(params.size() > 1)
2045         if(params[1].get_bool())
2046             filter = filter | ISMINE_WATCH_ONLY;
2047
2048     UniValue entry(UniValue::VOBJ);
2049     if (!pwalletMain->mapWallet.count(hash))
2050         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2051     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
2052
2053     CAmount nCredit = wtx.GetCredit(filter);
2054     CAmount nDebit = wtx.GetDebit(filter);
2055     CAmount nNet = nCredit - nDebit;
2056     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
2057
2058     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
2059     if (wtx.IsFromMe(filter))
2060         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
2061
2062     WalletTxToJSON(wtx, entry);
2063
2064     UniValue details(UniValue::VARR);
2065     ListTransactions(wtx, "*", 0, false, details, filter);
2066     entry.push_back(Pair("details", details));
2067
2068     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
2069     entry.push_back(Pair("hex", strHex));
2070
2071     return entry;
2072 }
2073
2074
2075 UniValue backupwallet(const UniValue& params, bool fHelp)
2076 {
2077     if (!EnsureWalletIsAvailable(fHelp))
2078         return NullUniValue;
2079
2080     if (fHelp || params.size() != 1)
2081         throw runtime_error(
2082             "backupwallet \"destination\"\n"
2083             "\nSafely copies wallet.dat to destination filename\n"
2084             "\nArguments:\n"
2085             "1. \"destination\"   (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
2086             "\nResult:\n"
2087             "\"path\"             (string) The full path of the destination file\n"
2088             "\nExamples:\n"
2089             + HelpExampleCli("backupwallet", "\"backupdata\"")
2090             + HelpExampleRpc("backupwallet", "\"backupdata\"")
2091         );
2092
2093     LOCK2(cs_main, pwalletMain->cs_wallet);
2094
2095     boost::filesystem::path exportdir;
2096     try {
2097         exportdir = GetExportDir();
2098     } catch (const std::runtime_error& e) {
2099         throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
2100     }
2101     if (exportdir.empty()) {
2102         throw JSONRPCError(RPC_WALLET_ERROR, "Cannot backup wallet until the -exportdir option has been set");
2103     }
2104     std::string unclean = params[0].get_str();
2105     std::string clean = SanitizeFilename(unclean);
2106     if (clean.compare(unclean) != 0) {
2107         throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Filename is invalid as only alphanumeric characters are allowed.  Try '%s' instead.", clean));
2108     }
2109     boost::filesystem::path exportfilepath = exportdir / clean;
2110
2111     if (!BackupWallet(*pwalletMain, exportfilepath.string()))
2112         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
2113
2114     return exportfilepath.string();
2115 }
2116
2117
2118 UniValue keypoolrefill(const UniValue& params, bool fHelp)
2119 {
2120     if (!EnsureWalletIsAvailable(fHelp))
2121         return NullUniValue;
2122
2123     if (fHelp || params.size() > 1)
2124         throw runtime_error(
2125             "keypoolrefill ( newsize )\n"
2126             "\nFills the keypool."
2127             + HelpRequiringPassphrase() + "\n"
2128             "\nArguments\n"
2129             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
2130             "\nExamples:\n"
2131             + HelpExampleCli("keypoolrefill", "")
2132             + HelpExampleRpc("keypoolrefill", "")
2133         );
2134
2135     LOCK2(cs_main, pwalletMain->cs_wallet);
2136
2137     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
2138     unsigned int kpSize = 0;
2139     if (params.size() > 0) {
2140         if (params[0].get_int() < 0)
2141             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
2142         kpSize = (unsigned int)params[0].get_int();
2143     }
2144
2145     EnsureWalletIsUnlocked();
2146     pwalletMain->TopUpKeyPool(kpSize);
2147
2148     if (pwalletMain->GetKeyPoolSize() < kpSize)
2149         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
2150
2151     return NullUniValue;
2152 }
2153
2154
2155 static void LockWallet(CWallet* pWallet)
2156 {
2157     LOCK(cs_nWalletUnlockTime);
2158     nWalletUnlockTime = 0;
2159     pWallet->Lock();
2160 }
2161
2162 UniValue walletpassphrase(const UniValue& params, bool fHelp)
2163 {
2164     if (!EnsureWalletIsAvailable(fHelp))
2165         return NullUniValue;
2166
2167     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
2168         throw runtime_error(
2169             "walletpassphrase \"passphrase\" timeout\n"
2170             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
2171             "This is needed prior to performing transactions related to private keys such as sending " + strprintf("%s",komodo_chainname()) + "\n"
2172             "\nArguments:\n"
2173             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
2174             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
2175             "\nNote:\n"
2176             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
2177             "time that overrides the old one.\n"
2178             "\nExamples:\n"
2179             "\nunlock the wallet for 60 seconds\n"
2180             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
2181             "\nLock the wallet again (before 60 seconds)\n"
2182             + HelpExampleCli("walletlock", "") +
2183             "\nAs json rpc call\n"
2184             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
2185         );
2186
2187     LOCK2(cs_main, pwalletMain->cs_wallet);
2188
2189     if (fHelp)
2190         return true;
2191     if (!pwalletMain->IsCrypted())
2192         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
2193
2194     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
2195     SecureString strWalletPass;
2196     strWalletPass.reserve(100);
2197     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2198     // Alternately, find a way to make params[0] mlock()'d to begin with.
2199     strWalletPass = params[0].get_str().c_str();
2200
2201     if (strWalletPass.length() > 0)
2202     {
2203         if (!pwalletMain->Unlock(strWalletPass))
2204             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2205     }
2206     else
2207         throw runtime_error(
2208             "walletpassphrase <passphrase> <timeout>\n"
2209             "Stores the wallet decryption key in memory for <timeout> seconds.");
2210
2211     // No need to check return values, because the wallet was unlocked above
2212     pwalletMain->UpdateNullifierNoteMap();
2213     pwalletMain->TopUpKeyPool();
2214
2215     int64_t nSleepTime = params[1].get_int64();
2216     LOCK(cs_nWalletUnlockTime);
2217     nWalletUnlockTime = GetTime() + nSleepTime;
2218     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
2219
2220     return NullUniValue;
2221 }
2222
2223
2224 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
2225 {
2226     if (!EnsureWalletIsAvailable(fHelp))
2227         return NullUniValue;
2228
2229     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
2230         throw runtime_error(
2231             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
2232             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
2233             "\nArguments:\n"
2234             "1. \"oldpassphrase\"      (string) The current passphrase\n"
2235             "2. \"newpassphrase\"      (string) The new passphrase\n"
2236             "\nExamples:\n"
2237             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
2238             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
2239         );
2240
2241     LOCK2(cs_main, pwalletMain->cs_wallet);
2242
2243     if (fHelp)
2244         return true;
2245     if (!pwalletMain->IsCrypted())
2246         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
2247
2248     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
2249     // Alternately, find a way to make params[0] mlock()'d to begin with.
2250     SecureString strOldWalletPass;
2251     strOldWalletPass.reserve(100);
2252     strOldWalletPass = params[0].get_str().c_str();
2253
2254     SecureString strNewWalletPass;
2255     strNewWalletPass.reserve(100);
2256     strNewWalletPass = params[1].get_str().c_str();
2257
2258     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
2259         throw runtime_error(
2260             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
2261             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
2262
2263     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
2264         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2265
2266     return NullUniValue;
2267 }
2268
2269
2270 UniValue walletlock(const UniValue& params, bool fHelp)
2271 {
2272     if (!EnsureWalletIsAvailable(fHelp))
2273         return NullUniValue;
2274
2275     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
2276         throw runtime_error(
2277             "walletlock\n"
2278             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2279             "After calling this method, you will need to call walletpassphrase again\n"
2280             "before being able to call any methods which require the wallet to be unlocked.\n"
2281             "\nExamples:\n"
2282             "\nSet the passphrase for 2 minutes to perform a transaction\n"
2283             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2284             "\nPerform a send (requires passphrase set)\n"
2285             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 1.0") +
2286             "\nClear the passphrase since we are done before 2 minutes is up\n"
2287             + HelpExampleCli("walletlock", "") +
2288             "\nAs json rpc call\n"
2289             + HelpExampleRpc("walletlock", "")
2290         );
2291
2292     LOCK2(cs_main, pwalletMain->cs_wallet);
2293
2294     if (fHelp)
2295         return true;
2296     if (!pwalletMain->IsCrypted())
2297         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2298
2299     {
2300         LOCK(cs_nWalletUnlockTime);
2301         pwalletMain->Lock();
2302         nWalletUnlockTime = 0;
2303     }
2304
2305     return NullUniValue;
2306 }
2307
2308
2309 UniValue encryptwallet(const UniValue& params, bool fHelp)
2310 {
2311     if (!EnsureWalletIsAvailable(fHelp))
2312         return NullUniValue;
2313
2314     auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-developerencryptwallet", false);
2315
2316     std::string strWalletEncryptionDisabledMsg = "";
2317     if (!fEnableWalletEncryption) {
2318         strWalletEncryptionDisabledMsg = "\nWARNING: Wallet encryption is DISABLED. This call always fails.\n";
2319     }
2320
2321     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2322         throw runtime_error(
2323             "encryptwallet \"passphrase\"\n"
2324             + strWalletEncryptionDisabledMsg +
2325             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2326             "After this, any calls that interact with private keys such as sending or signing \n"
2327             "will require the passphrase to be set prior the making these calls.\n"
2328             "Use the walletpassphrase call for this, and then walletlock call.\n"
2329             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2330             "Note that this will shutdown the server.\n"
2331             "\nArguments:\n"
2332             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2333             "\nExamples:\n"
2334             "\nEncrypt you wallet\n"
2335             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2336             "\nNow set the passphrase to use the wallet, such as for signing or sending " + strprintf("%s",komodo_chainname()) + "\n"
2337             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2338             "\nNow we can so something like sign\n"
2339             + HelpExampleCli("signmessage", "\"" + strprintf("%s",komodo_chainname()) + "_address\" \"test message\"") +
2340             "\nNow lock the wallet again by removing the passphrase\n"
2341             + HelpExampleCli("walletlock", "") +
2342             "\nAs a json rpc call\n"
2343             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2344         );
2345
2346     LOCK2(cs_main, pwalletMain->cs_wallet);
2347
2348     if (fHelp)
2349         return true;
2350     if (!fEnableWalletEncryption) {
2351         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
2352     }
2353     if (pwalletMain->IsCrypted())
2354         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2355
2356     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2357     // Alternately, find a way to make params[0] mlock()'d to begin with.
2358     SecureString strWalletPass;
2359     strWalletPass.reserve(100);
2360     strWalletPass = params[0].get_str().c_str();
2361
2362     if (strWalletPass.length() < 1)
2363         throw runtime_error(
2364             "encryptwallet <passphrase>\n"
2365             "Encrypts the wallet with <passphrase>.");
2366
2367     if (!pwalletMain->EncryptWallet(strWalletPass))
2368         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2369
2370     // BDB seems to have a bad habit of writing old data into
2371     // slack space in .dat files; that is bad if the old data is
2372     // unencrypted private keys. So:
2373     StartShutdown();
2374     return "wallet encrypted; Komodo server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
2375 }
2376
2377 UniValue lockunspent(const UniValue& params, bool fHelp)
2378 {
2379     if (!EnsureWalletIsAvailable(fHelp))
2380         return NullUniValue;
2381
2382     if (fHelp || params.size() < 1 || params.size() > 2)
2383         throw runtime_error(
2384             "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2385             "\nUpdates list of temporarily unspendable outputs.\n"
2386             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2387             "A locked transaction output will not be chosen by automatic coin selection, when spending " + strprintf("%s",komodo_chainname()) + ".\n"
2388             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2389             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2390             "Also see the listunspent call\n"
2391             "\nArguments:\n"
2392             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2393             "2. \"transactions\"  (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2394             "     [           (json array of json objects)\n"
2395             "       {\n"
2396             "         \"txid\":\"id\",    (string) The transaction id\n"
2397             "         \"vout\": n         (numeric) The output number\n"
2398             "       }\n"
2399             "       ,...\n"
2400             "     ]\n"
2401
2402             "\nResult:\n"
2403             "true|false    (boolean) Whether the command was successful or not\n"
2404
2405             "\nExamples:\n"
2406             "\nList the unspent transactions\n"
2407             + HelpExampleCli("listunspent", "") +
2408             "\nLock an unspent transaction\n"
2409             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2410             "\nList the locked transactions\n"
2411             + HelpExampleCli("listlockunspent", "") +
2412             "\nUnlock the transaction again\n"
2413             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2414             "\nAs a json rpc call\n"
2415             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2416         );
2417
2418     LOCK2(cs_main, pwalletMain->cs_wallet);
2419
2420     if (params.size() == 1)
2421         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2422     else
2423         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2424
2425     bool fUnlock = params[0].get_bool();
2426
2427     if (params.size() == 1) {
2428         if (fUnlock)
2429             pwalletMain->UnlockAllCoins();
2430         return true;
2431     }
2432
2433     UniValue outputs = params[1].get_array();
2434     for (size_t idx = 0; idx < outputs.size(); idx++) {
2435         const UniValue& output = outputs[idx];
2436         if (!output.isObject())
2437             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2438         const UniValue& o = output.get_obj();
2439
2440         RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
2441
2442         string txid = find_value(o, "txid").get_str();
2443         if (!IsHex(txid))
2444             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2445
2446         int nOutput = find_value(o, "vout").get_int();
2447         if (nOutput < 0)
2448             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2449
2450         COutPoint outpt(uint256S(txid), nOutput);
2451
2452         if (fUnlock)
2453             pwalletMain->UnlockCoin(outpt);
2454         else
2455             pwalletMain->LockCoin(outpt);
2456     }
2457
2458     return true;
2459 }
2460
2461 UniValue listlockunspent(const UniValue& params, bool fHelp)
2462 {
2463     if (!EnsureWalletIsAvailable(fHelp))
2464         return NullUniValue;
2465
2466     if (fHelp || params.size() > 0)
2467         throw runtime_error(
2468             "listlockunspent\n"
2469             "\nReturns list of temporarily unspendable outputs.\n"
2470             "See the lockunspent call to lock and unlock transactions for spending.\n"
2471             "\nResult:\n"
2472             "[\n"
2473             "  {\n"
2474             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
2475             "    \"vout\" : n                      (numeric) The vout value\n"
2476             "  }\n"
2477             "  ,...\n"
2478             "]\n"
2479             "\nExamples:\n"
2480             "\nList the unspent transactions\n"
2481             + HelpExampleCli("listunspent", "") +
2482             "\nLock an unspent transaction\n"
2483             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2484             "\nList the locked transactions\n"
2485             + HelpExampleCli("listlockunspent", "") +
2486             "\nUnlock the transaction again\n"
2487             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2488             "\nAs a json rpc call\n"
2489             + HelpExampleRpc("listlockunspent", "")
2490         );
2491
2492     LOCK2(cs_main, pwalletMain->cs_wallet);
2493
2494     vector<COutPoint> vOutpts;
2495     pwalletMain->ListLockedCoins(vOutpts);
2496
2497     UniValue ret(UniValue::VARR);
2498
2499     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2500         UniValue o(UniValue::VOBJ);
2501
2502         o.push_back(Pair("txid", outpt.hash.GetHex()));
2503         o.push_back(Pair("vout", (int)outpt.n));
2504         ret.push_back(o);
2505     }
2506
2507     return ret;
2508 }
2509
2510 UniValue settxfee(const UniValue& params, bool fHelp)
2511 {
2512     if (!EnsureWalletIsAvailable(fHelp))
2513         return NullUniValue;
2514
2515     if (fHelp || params.size() < 1 || params.size() > 1)
2516         throw runtime_error(
2517             "settxfee amount\n"
2518             "\nSet the transaction fee per kB.\n"
2519             "\nArguments:\n"
2520             "1. amount         (numeric, required) The transaction fee in " + strprintf("%s",komodo_chainname()) + "/kB rounded to the nearest 0.00000001\n"
2521             "\nResult\n"
2522             "true|false        (boolean) Returns true if successful\n"
2523             "\nExamples:\n"
2524             + HelpExampleCli("settxfee", "0.00001")
2525             + HelpExampleRpc("settxfee", "0.00001")
2526         );
2527
2528     LOCK2(cs_main, pwalletMain->cs_wallet);
2529
2530     // Amount
2531     CAmount nAmount = AmountFromValue(params[0]);
2532
2533     payTxFee = CFeeRate(nAmount, 1000);
2534     return true;
2535 }
2536
2537 UniValue getwalletinfo(const UniValue& params, bool fHelp)
2538 {
2539     if (!EnsureWalletIsAvailable(fHelp))
2540         return NullUniValue;
2541
2542     if (fHelp || params.size() != 0)
2543         throw runtime_error(
2544             "getwalletinfo\n"
2545             "Returns an object containing various wallet state info.\n"
2546             "\nResult:\n"
2547             "{\n"
2548             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
2549             "  \"balance\": xxxxxxx,         (numeric) the total confirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
2550             "  \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
2551             "  \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
2552             "  \"txcount\": xxxxxxx,         (numeric) the total number of transactions in the wallet\n"
2553             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
2554             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
2555             "  \"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"
2556             "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee configuration, set in KMD/KB\n"
2557             "}\n"
2558             "\nExamples:\n"
2559             + HelpExampleCli("getwalletinfo", "")
2560             + HelpExampleRpc("getwalletinfo", "")
2561         );
2562
2563     LOCK2(cs_main, pwalletMain->cs_wallet);
2564
2565     UniValue obj(UniValue::VOBJ);
2566     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2567     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
2568     obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2569     obj.push_back(Pair("immature_balance",    ValueFromAmount(pwalletMain->GetImmatureBalance())));
2570     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
2571     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2572     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
2573     if (pwalletMain->IsCrypted())
2574         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2575     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
2576     return obj;
2577 }
2578
2579 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
2580 {
2581     if (!EnsureWalletIsAvailable(fHelp))
2582         return NullUniValue;
2583
2584     if (fHelp || params.size() != 0)
2585         throw runtime_error(
2586             "resendwallettransactions\n"
2587             "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2588             "Intended only for testing; the wallet code periodically re-broadcasts\n"
2589             "automatically.\n"
2590             "Returns array of transaction ids that were re-broadcast.\n"
2591             );
2592
2593     LOCK2(cs_main, pwalletMain->cs_wallet);
2594
2595     std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2596     UniValue result(UniValue::VARR);
2597     BOOST_FOREACH(const uint256& txid, txids)
2598     {
2599         result.push_back(txid.ToString());
2600     }
2601     return result;
2602 }
2603
2604 UniValue listunspent(const UniValue& params, bool fHelp)
2605 {
2606     if (!EnsureWalletIsAvailable(fHelp))
2607         return NullUniValue;
2608
2609     if (fHelp || params.size() > 3)
2610         throw runtime_error(
2611             "listunspent ( minconf maxconf  [\"address\",...] )\n"
2612             "\nReturns array of unspent transaction outputs\n"
2613             "with between minconf and maxconf (inclusive) confirmations.\n"
2614             "Optionally filter to only include txouts paid to specified addresses.\n"
2615             "Results are an array of Objects, each of which has:\n"
2616             "{txid, vout, scriptPubKey, amount, confirmations}\n"
2617             "\nArguments:\n"
2618             "1. minconf          (numeric, optional, default=1) The minimum confirmations to filter\n"
2619             "2. maxconf          (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2620             "3. \"addresses\"    (string) A json array of " + strprintf("%s",komodo_chainname()) + " addresses to filter\n"
2621             "    [\n"
2622             "      \"address\"   (string) " + strprintf("%s",komodo_chainname()) + " address\n"
2623             "      ,...\n"
2624             "    ]\n"
2625             "\nResult\n"
2626             "[                   (array of json object)\n"
2627             "  {\n"
2628             "    \"txid\" : \"txid\",        (string) the transaction id \n"
2629             "    \"vout\" : n,               (numeric) the vout value\n"
2630             "    \"generated\" : true|false  (boolean) true if txout is a coinbase transaction output\n"
2631             "    \"address\" : \"address\",  (string) the " + strprintf("%s",komodo_chainname()) + " address\n"
2632             "    \"account\" : \"account\",  (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2633             "    \"scriptPubKey\" : \"key\", (string) the script key\n"
2634             "    \"amount\" : x.xxx,         (numeric) the transaction amount in " + strprintf("%s",komodo_chainname()) + "\n"
2635             "    \"confirmations\" : n       (numeric) The number of confirmations\n"
2636             "  }\n"
2637             "  ,...\n"
2638             "]\n"
2639
2640             "\nExamples\n"
2641             + HelpExampleCli("listunspent", "")
2642             + HelpExampleCli("listunspent", "6 9999999 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
2643             + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
2644         );
2645
2646     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
2647
2648     int nMinDepth = 1;
2649     if (params.size() > 0)
2650         nMinDepth = params[0].get_int();
2651
2652     int nMaxDepth = 9999999;
2653     if (params.size() > 1)
2654         nMaxDepth = params[1].get_int();
2655
2656     set<CBitcoinAddress> setAddress;
2657     if (params.size() > 2) {
2658         UniValue inputs = params[2].get_array();
2659         for (size_t idx = 0; idx < inputs.size(); idx++) {
2660             const UniValue& input = inputs[idx];
2661             CBitcoinAddress address(input.get_str());
2662             if (!address.IsValid())
2663                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid " + strprintf("%s",komodo_chainname()) + " address: ")+input.get_str());
2664             if (setAddress.count(address))
2665                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
2666            setAddress.insert(address);
2667         }
2668     }
2669
2670     UniValue results(UniValue::VARR);
2671     vector<COutput> vecOutputs;
2672     assert(pwalletMain != NULL);
2673     LOCK2(cs_main, pwalletMain->cs_wallet);
2674     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2675     BOOST_FOREACH(const COutput& out, vecOutputs) {
2676         if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2677             continue;
2678
2679         if (setAddress.size()) {
2680             CTxDestination address;
2681             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
2682                 continue;
2683
2684             if (!setAddress.count(address))
2685                 continue;
2686         }
2687
2688         CAmount nValue = out.tx->vout[out.i].nValue;
2689         const CScript& pk = out.tx->vout[out.i].scriptPubKey;
2690         UniValue entry(UniValue::VOBJ);
2691         entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2692         entry.push_back(Pair("vout", out.i));
2693         entry.push_back(Pair("generated", out.tx->IsCoinBase()));
2694         CTxDestination address;
2695         if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
2696             entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
2697             if (pwalletMain->mapAddressBook.count(address))
2698                 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2699         }
2700         entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
2701         if (pk.IsPayToScriptHash()) {
2702             CTxDestination address;
2703             if (ExtractDestination(pk, address)) {
2704                 const CScriptID& hash = boost::get<CScriptID>(address);
2705                 CScript redeemScript;
2706                 if (pwalletMain->GetCScript(hash, redeemScript))
2707                     entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2708             }
2709         }
2710         entry.push_back(Pair("amount",ValueFromAmount(nValue)));
2711         if ( out.tx->nLockTime != 0 )
2712         {
2713             BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
2714             CBlockIndex *tipindex,*pindex = it->second;
2715             uint64_t interest; uint32_t locktime; int32_t txheight;
2716             if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
2717             {
2718                 interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight);
2719                 //interest = komodo_interest(txheight,nValue,out.tx->nLockTime,tipindex->nTime);
2720                 entry.push_back(Pair("interest",ValueFromAmount(interest)));
2721             }
2722             //fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.LastTip(),locktime,txheight,pindex->nHeight);
2723         }
2724         entry.push_back(Pair("confirmations",out.nDepth));
2725         entry.push_back(Pair("spendable", out.fSpendable));
2726         results.push_back(entry);
2727     }
2728
2729     return results;
2730 }
2731
2732 uint64_t komodo_interestsum()
2733 {
2734 #ifdef ENABLE_WALLET
2735     if ( GetBoolArg("-disablewallet", false) == 0 )
2736     {
2737         uint64_t interest,sum = 0; int32_t txheight; uint32_t locktime;
2738         vector<COutput> vecOutputs;
2739         assert(pwalletMain != NULL);
2740         LOCK2(cs_main, pwalletMain->cs_wallet);
2741         pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2742         BOOST_FOREACH(const COutput& out,vecOutputs)
2743         {
2744             CAmount nValue = out.tx->vout[out.i].nValue;
2745             if ( out.tx->nLockTime != 0 && out.fSpendable != 0 )
2746             {
2747                 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
2748                 CBlockIndex *tipindex,*pindex = it->second;
2749                 if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
2750                 {
2751                     interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight);
2752                     //interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime);
2753                     sum += interest;
2754                 }
2755             }
2756         }
2757         KOMODO_INTERESTSUM = sum;
2758         KOMODO_WALLETBALANCE = pwalletMain->GetBalance();
2759         return(sum);
2760     }
2761 #endif
2762     return(0);
2763 }
2764
2765 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
2766 {
2767     if (!EnsureWalletIsAvailable(fHelp))
2768         return NullUniValue;
2769
2770     if (fHelp || params.size() != 1)
2771         throw runtime_error(
2772                             "fundrawtransaction \"hexstring\"\n"
2773                             "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2774                             "This will not modify existing inputs, and will add one change output to the outputs.\n"
2775                             "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2776                             "The inputs added will not be signed, use signrawtransaction for that.\n"
2777                             "\nArguments:\n"
2778                             "1. \"hexstring\"    (string, required) The hex string of the raw transaction\n"
2779                             "\nResult:\n"
2780                             "{\n"
2781                             "  \"hex\":       \"value\", (string)  The resulting raw transaction (hex-encoded string)\n"
2782                             "  \"fee\":       n,         (numeric) The fee added to the transaction\n"
2783                             "  \"changepos\": n          (numeric) The position of the added change output, or -1\n"
2784                             "}\n"
2785                             "\"hex\"             \n"
2786                             "\nExamples:\n"
2787                             "\nCreate a transaction with no inputs\n"
2788                             + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2789                             "\nAdd sufficient unsigned inputs to meet the output value\n"
2790                             + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2791                             "\nSign the transaction\n"
2792                             + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2793                             "\nSend the transaction\n"
2794                             + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2795                             );
2796
2797     RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
2798
2799     // parse hex string from parameter
2800     CTransaction origTx;
2801     if (!DecodeHexTx(origTx, params[0].get_str()))
2802         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2803
2804     CMutableTransaction tx(origTx);
2805     CAmount nFee;
2806     string strFailReason;
2807     int nChangePos = -1;
2808     if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason))
2809         throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2810
2811     UniValue result(UniValue::VOBJ);
2812     result.push_back(Pair("hex", EncodeHexTx(tx)));
2813     result.push_back(Pair("changepos", nChangePos));
2814     result.push_back(Pair("fee", ValueFromAmount(nFee)));
2815
2816     return result;
2817 }
2818
2819 UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
2820 {
2821     if (fHelp) {
2822         throw runtime_error(
2823             "zcsamplejoinsplit\n"
2824             "\n"
2825             "Perform a joinsplit and return the JSDescription.\n"
2826             );
2827     }
2828
2829     LOCK(cs_main);
2830
2831     uint256 pubKeyHash;
2832     uint256 anchor = ZCIncrementalMerkleTree().root();
2833     JSDescription samplejoinsplit(*pzcashParams,
2834                                   pubKeyHash,
2835                                   anchor,
2836                                   {JSInput(), JSInput()},
2837                                   {JSOutput(), JSOutput()},
2838                                   0,
2839                                   0);
2840
2841     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2842     ss << samplejoinsplit;
2843
2844     return HexStr(ss.begin(), ss.end());
2845 }
2846
2847 UniValue zc_benchmark(const UniValue& params, bool fHelp)
2848 {
2849     if (!EnsureWalletIsAvailable(fHelp)) {
2850         return NullUniValue;
2851     }
2852
2853     if (fHelp || params.size() < 2) {
2854         throw runtime_error(
2855             "zcbenchmark benchmarktype samplecount\n"
2856             "\n"
2857             "Runs a benchmark of the selected type samplecount times,\n"
2858             "returning the running times of each sample.\n"
2859             "\n"
2860             "Output: [\n"
2861             "  {\n"
2862             "    \"runningtime\": runningtime\n"
2863             "  },\n"
2864             "  {\n"
2865             "    \"runningtime\": runningtime\n"
2866             "  }\n"
2867             "  ...\n"
2868             "]\n"
2869             );
2870     }
2871
2872     LOCK(cs_main);
2873
2874     std::string benchmarktype = params[0].get_str();
2875     int samplecount = params[1].get_int();
2876
2877     if (samplecount <= 0) {
2878         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid samplecount");
2879     }
2880
2881     std::vector<double> sample_times;
2882
2883     JSDescription samplejoinsplit;
2884
2885     if (benchmarktype == "verifyjoinsplit") {
2886         CDataStream ss(ParseHexV(params[2].get_str(), "js"), SER_NETWORK, PROTOCOL_VERSION);
2887         ss >> samplejoinsplit;
2888     }
2889
2890     for (int i = 0; i < samplecount; i++) {
2891         if (benchmarktype == "sleep") {
2892             sample_times.push_back(benchmark_sleep());
2893         } else if (benchmarktype == "parameterloading") {
2894             sample_times.push_back(benchmark_parameter_loading());
2895         } else if (benchmarktype == "createjoinsplit") {
2896             if (params.size() < 3) {
2897                 sample_times.push_back(benchmark_create_joinsplit());
2898             } else {
2899                 int nThreads = params[2].get_int();
2900                 std::vector<double> vals = benchmark_create_joinsplit_threaded(nThreads);
2901                 // Divide by nThreads^2 to get average seconds per JoinSplit because
2902                 // we are running one JoinSplit per thread.
2903                 sample_times.push_back(std::accumulate(vals.begin(), vals.end(), 0.0) / (nThreads*nThreads));
2904             }
2905         } else if (benchmarktype == "verifyjoinsplit") {
2906             sample_times.push_back(benchmark_verify_joinsplit(samplejoinsplit));
2907 #ifdef ENABLE_MINING
2908         } else if (benchmarktype == "solveequihash") {
2909             if (params.size() < 3) {
2910                 sample_times.push_back(benchmark_solve_equihash());
2911             } else {
2912                 int nThreads = params[2].get_int();
2913                 std::vector<double> vals = benchmark_solve_equihash_threaded(nThreads);
2914                 sample_times.insert(sample_times.end(), vals.begin(), vals.end());
2915             }
2916 #endif
2917         } else if (benchmarktype == "verifyequihash") {
2918             sample_times.push_back(benchmark_verify_equihash());
2919         } else if (benchmarktype == "validatelargetx") {
2920             // Number of inputs in the spending transaction that we will simulate
2921             int nInputs = 555;
2922             if (params.size() >= 3) {
2923                 nInputs = params[2].get_int();
2924             }
2925             sample_times.push_back(benchmark_large_tx(nInputs));
2926         } else if (benchmarktype == "trydecryptnotes") {
2927             int nAddrs = params[2].get_int();
2928             sample_times.push_back(benchmark_try_decrypt_notes(nAddrs));
2929         } else if (benchmarktype == "incnotewitnesses") {
2930             int nTxs = params[2].get_int();
2931             sample_times.push_back(benchmark_increment_note_witnesses(nTxs));
2932         } else if (benchmarktype == "connectblockslow") {
2933             if (Params().NetworkIDString() != "regtest") {
2934                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2935             }
2936             sample_times.push_back(benchmark_connectblock_slow());
2937         } else if (benchmarktype == "sendtoaddress") {
2938             if (Params().NetworkIDString() != "regtest") {
2939                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2940             }
2941             auto amount = AmountFromValue(params[2]);
2942             sample_times.push_back(benchmark_sendtoaddress(amount));
2943         } else if (benchmarktype == "loadwallet") {
2944             if (Params().NetworkIDString() != "regtest") {
2945                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2946             }
2947             sample_times.push_back(benchmark_loadwallet());
2948         } else if (benchmarktype == "listunspent") {
2949             sample_times.push_back(benchmark_listunspent());
2950         } else {
2951             throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
2952         }
2953     }
2954
2955     UniValue results(UniValue::VARR);
2956     for (auto time : sample_times) {
2957         UniValue result(UniValue::VOBJ);
2958         result.push_back(Pair("runningtime", time));
2959         results.push_back(result);
2960     }
2961
2962     return results;
2963 }
2964
2965 UniValue zc_raw_receive(const UniValue& params, bool fHelp)
2966 {
2967     if (!EnsureWalletIsAvailable(fHelp)) {
2968         return NullUniValue;
2969     }
2970
2971     if (fHelp || params.size() != 2) {
2972         throw runtime_error(
2973             "zcrawreceive zcsecretkey encryptednote\n"
2974             "\n"
2975             "DEPRECATED. Decrypts encryptednote and checks if the coin commitments\n"
2976             "are in the blockchain as indicated by the \"exists\" result.\n"
2977             "\n"
2978             "Output: {\n"
2979             "  \"amount\": value,\n"
2980             "  \"note\": noteplaintext,\n"
2981             "  \"exists\": exists\n"
2982             "}\n"
2983             );
2984     }
2985
2986     RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR));
2987
2988     LOCK(cs_main);
2989
2990     CZCSpendingKey spendingkey(params[0].get_str());
2991     SpendingKey k = spendingkey.Get();
2992
2993     uint256 epk;
2994     unsigned char nonce;
2995     ZCNoteEncryption::Ciphertext ct;
2996     uint256 h_sig;
2997
2998     {
2999         CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
3000         try {
3001             ssData >> nonce;
3002             ssData >> epk;
3003             ssData >> ct;
3004             ssData >> h_sig;
3005         } catch(const std::exception &) {
3006             throw runtime_error(
3007                 "encrypted_note could not be decoded"
3008             );
3009         }
3010     }
3011
3012     ZCNoteDecryption decryptor(k.receiving_key());
3013
3014     NotePlaintext npt = NotePlaintext::decrypt(
3015         decryptor,
3016         ct,
3017         epk,
3018         h_sig,
3019         nonce
3020     );
3021     PaymentAddress payment_addr = k.address();
3022     Note decrypted_note = npt.note(payment_addr);
3023
3024     assert(pwalletMain != NULL);
3025     std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
3026     uint256 anchor;
3027     uint256 commitment = decrypted_note.cm();
3028     pwalletMain->WitnessNoteCommitment(
3029         {commitment},
3030         witnesses,
3031         anchor
3032     );
3033
3034     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3035     ss << npt;
3036
3037     UniValue result(UniValue::VOBJ);
3038     result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value)));
3039     result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
3040     result.push_back(Pair("exists", (bool) witnesses[0]));
3041     return result;
3042 }
3043
3044
3045
3046 UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
3047 {
3048     if (!EnsureWalletIsAvailable(fHelp)) {
3049         return NullUniValue;
3050     }
3051
3052     if (fHelp || params.size() != 5) {
3053         throw runtime_error(
3054             "zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
3055             "  inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
3056             "  outputs: a JSON object mapping {zcaddr: value, ...}\n"
3057             "\n"
3058             "DEPRECATED. Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
3059             "Outputs are confidential between sender/receiver. The vpub_old and\n"
3060             "vpub_new values are globally public and move transparent value into\n"
3061             "or out of the confidential value store, respectively.\n"
3062             "\n"
3063             "Note: The caller is responsible for delivering the output enc1 and\n"
3064             "enc2 to the appropriate recipients, as well as signing rawtxout and\n"
3065             "ensuring it is mined. (A future RPC call will deliver the confidential\n"
3066             "payments in-band on the blockchain.)\n"
3067             "\n"
3068             "Output: {\n"
3069             "  \"encryptednote1\": enc1,\n"
3070             "  \"encryptednote2\": enc2,\n"
3071             "  \"rawtxn\": rawtxout\n"
3072             "}\n"
3073             );
3074     }
3075
3076     LOCK(cs_main);
3077
3078     CTransaction tx;
3079     if (!DecodeHexTx(tx, params[0].get_str()))
3080         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3081
3082     UniValue inputs = params[1].get_obj();
3083     UniValue outputs = params[2].get_obj();
3084
3085     CAmount vpub_old(0);
3086     CAmount vpub_new(0);
3087
3088     if (params[3].get_real() != 0.0)
3089         vpub_old = AmountFromValue(params[3]);
3090
3091     if (params[4].get_real() != 0.0)
3092         vpub_new = AmountFromValue(params[4]);
3093
3094     std::vector<JSInput> vjsin;
3095     std::vector<JSOutput> vjsout;
3096     std::vector<Note> notes;
3097     std::vector<SpendingKey> keys;
3098     std::vector<uint256> commitments;
3099
3100     for (const string& name_ : inputs.getKeys()) {
3101         CZCSpendingKey spendingkey(inputs[name_].get_str());
3102         SpendingKey k = spendingkey.Get();
3103
3104         keys.push_back(k);
3105
3106         NotePlaintext npt;
3107
3108         {
3109             CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
3110             ssData >> npt;
3111         }
3112
3113         PaymentAddress addr = k.address();
3114         Note note = npt.note(addr);
3115         notes.push_back(note);
3116         commitments.push_back(note.cm());
3117     }
3118
3119     uint256 anchor;
3120     std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
3121     pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
3122
3123     assert(witnesses.size() == notes.size());
3124     assert(notes.size() == keys.size());
3125
3126     {
3127         for (size_t i = 0; i < witnesses.size(); i++) {
3128             if (!witnesses[i]) {
3129                 throw runtime_error(
3130                     "joinsplit input could not be found in tree"
3131                 );
3132             }
3133
3134             vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
3135         }
3136     }
3137
3138     while (vjsin.size() < ZC_NUM_JS_INPUTS) {
3139         vjsin.push_back(JSInput());
3140     }
3141
3142     for (const string& name_ : outputs.getKeys()) {
3143         CZCPaymentAddress pubaddr(name_);
3144         PaymentAddress addrTo = pubaddr.Get();
3145         CAmount nAmount = AmountFromValue(outputs[name_]);
3146
3147         vjsout.push_back(JSOutput(addrTo, nAmount));
3148     }
3149
3150     while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
3151         vjsout.push_back(JSOutput());
3152     }
3153
3154     // TODO
3155     if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
3156         throw runtime_error("unsupported joinsplit input/output counts");
3157     }
3158
3159     uint256 joinSplitPubKey;
3160     unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
3161     crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
3162
3163     CMutableTransaction mtx(tx);
3164     mtx.nVersion = 2;
3165     mtx.joinSplitPubKey = joinSplitPubKey;
3166
3167     JSDescription jsdesc(*pzcashParams,
3168                          joinSplitPubKey,
3169                          anchor,
3170                          {vjsin[0], vjsin[1]},
3171                          {vjsout[0], vjsout[1]},
3172                          vpub_old,
3173                          vpub_new);
3174
3175     {
3176         auto verifier = libzcash::ProofVerifier::Strict();
3177         assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
3178     }
3179
3180     mtx.vjoinsplit.push_back(jsdesc);
3181
3182     // Empty output script.
3183     CScript scriptCode;
3184     CTransaction signTx(mtx);
3185     auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
3186     uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
3187
3188     // Add the signature
3189     assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
3190                          dataToBeSigned.begin(), 32,
3191                          joinSplitPrivKey
3192                         ) == 0);
3193
3194     // Sanity check
3195     assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
3196                                        dataToBeSigned.begin(), 32,
3197                                        mtx.joinSplitPubKey.begin()
3198                                       ) == 0);
3199
3200     CTransaction rawTx(mtx);
3201
3202     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3203     ss << rawTx;
3204
3205     std::string encryptedNote1;
3206     std::string encryptedNote2;
3207     {
3208         CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3209         ss2 << ((unsigned char) 0x00);
3210         ss2 << jsdesc.ephemeralKey;
3211         ss2 << jsdesc.ciphertexts[0];
3212         ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3213
3214         encryptedNote1 = HexStr(ss2.begin(), ss2.end());
3215     }
3216     {
3217         CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3218         ss2 << ((unsigned char) 0x01);
3219         ss2 << jsdesc.ephemeralKey;
3220         ss2 << jsdesc.ciphertexts[1];
3221         ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3222
3223         encryptedNote2 = HexStr(ss2.begin(), ss2.end());
3224     }
3225
3226     UniValue result(UniValue::VOBJ);
3227     result.push_back(Pair("encryptednote1", encryptedNote1));
3228     result.push_back(Pair("encryptednote2", encryptedNote2));
3229     result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
3230     return result;
3231 }
3232
3233 UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
3234 {
3235     if (!EnsureWalletIsAvailable(fHelp)) {
3236         return NullUniValue;
3237     }
3238
3239     if (fHelp || params.size() != 0) {
3240         throw runtime_error(
3241             "zcrawkeygen\n"
3242             "\n"
3243             "DEPRECATED. Generate a zcaddr which can send and receive confidential values.\n"
3244             "\n"
3245             "Output: {\n"
3246             "  \"zcaddress\": zcaddr,\n"
3247             "  \"zcsecretkey\": zcsecretkey,\n"
3248             "  \"zcviewingkey\": zcviewingkey,\n"
3249             "}\n"
3250             );
3251     }
3252
3253     auto k = SpendingKey::random();
3254     auto addr = k.address();
3255     auto viewing_key = k.viewing_key();
3256
3257     CZCPaymentAddress pubaddr(addr);
3258     CZCSpendingKey spendingkey(k);
3259     CZCViewingKey viewingkey(viewing_key);
3260
3261     UniValue result(UniValue::VOBJ);
3262     result.push_back(Pair("zcaddress", pubaddr.ToString()));
3263     result.push_back(Pair("zcsecretkey", spendingkey.ToString()));
3264     result.push_back(Pair("zcviewingkey", viewingkey.ToString()));
3265     return result;
3266 }
3267
3268
3269 UniValue z_getnewaddress(const UniValue& params, bool fHelp)
3270 {
3271     if (!EnsureWalletIsAvailable(fHelp))
3272         return NullUniValue;
3273
3274     if (fHelp || params.size() > 0)
3275         throw runtime_error(
3276             "z_getnewaddress\n"
3277             "\nReturns a new zaddr for receiving payments.\n"
3278             "\nArguments:\n"
3279             "\nResult:\n"
3280             "\"" + strprintf("%s",komodo_chainname()) + "_address\"    (string) The new zaddr\n"
3281             "\nExamples:\n"
3282             + HelpExampleCli("z_getnewaddress", "")
3283             + HelpExampleRpc("z_getnewaddress", "")
3284         );
3285
3286     LOCK2(cs_main, pwalletMain->cs_wallet);
3287
3288     EnsureWalletIsUnlocked();
3289
3290     CZCPaymentAddress pubaddr = pwalletMain->GenerateNewZKey();
3291     std::string result = pubaddr.ToString();
3292     return result;
3293 }
3294
3295
3296 UniValue z_listaddresses(const UniValue& params, bool fHelp)
3297 {
3298     if (!EnsureWalletIsAvailable(fHelp))
3299         return NullUniValue;
3300
3301     if (fHelp || params.size() > 1)
3302         throw runtime_error(
3303             "z_listaddresses ( includeWatchonly )\n"
3304             "\nReturns the list of zaddr belonging to the wallet.\n"
3305             "\nArguments:\n"
3306             "1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
3307             "\nResult:\n"
3308             "[                     (json array of string)\n"
3309             "  \"zaddr\"           (string) a zaddr belonging to the wallet\n"
3310             "  ,...\n"
3311             "]\n"
3312             "\nExamples:\n"
3313             + HelpExampleCli("z_listaddresses", "")
3314             + HelpExampleRpc("z_listaddresses", "")
3315         );
3316
3317     LOCK2(cs_main, pwalletMain->cs_wallet);
3318
3319     bool fIncludeWatchonly = false;
3320     if (params.size() > 0) {
3321         fIncludeWatchonly = params[0].get_bool();
3322     }
3323
3324     UniValue ret(UniValue::VARR);
3325     std::set<libzcash::PaymentAddress> addresses;
3326     pwalletMain->GetPaymentAddresses(addresses);
3327     for (auto addr : addresses ) {
3328         if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
3329             ret.push_back(CZCPaymentAddress(addr).ToString());
3330         }
3331     }
3332     return ret;
3333 }
3334
3335 CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
3336     set<CBitcoinAddress> setAddress;
3337     vector<COutput> vecOutputs;
3338     CAmount balance = 0;
3339
3340     if (transparentAddress.length() > 0) {
3341         CBitcoinAddress taddr = CBitcoinAddress(transparentAddress);
3342         if (!taddr.IsValid()) {
3343             throw std::runtime_error("invalid transparent address");
3344         }
3345         setAddress.insert(taddr);
3346     }
3347
3348     LOCK2(cs_main, pwalletMain->cs_wallet);
3349
3350     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
3351
3352     BOOST_FOREACH(const COutput& out, vecOutputs) {
3353         if (out.nDepth < minDepth) {
3354             continue;
3355         }
3356
3357         if (ignoreUnspendable && !out.fSpendable) {
3358             continue;
3359         }
3360
3361         if (setAddress.size()) {
3362             CTxDestination address;
3363             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
3364                 continue;
3365             }
3366
3367             if (!setAddress.count(address)) {
3368                 continue;
3369             }
3370         }
3371
3372         CAmount nValue = out.tx->vout[out.i].nValue; // komodo_interest
3373         balance += nValue;
3374     }
3375     return balance;
3376 }
3377
3378 CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
3379     CAmount balance = 0;
3380     std::vector<CNotePlaintextEntry> entries;
3381     LOCK2(cs_main, pwalletMain->cs_wallet);
3382     pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
3383     for (auto & entry : entries) {
3384         balance += CAmount(entry.plaintext.value);
3385     }
3386     return balance;
3387 }
3388
3389
3390 UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
3391 {
3392     if (!EnsureWalletIsAvailable(fHelp))
3393         return NullUniValue;
3394
3395     if (fHelp || params.size()==0 || params.size() >2)
3396         throw runtime_error(
3397             "z_listreceivedbyaddress \"address\" ( minconf )\n"
3398             "\nReturn a list of amounts received by a zaddr belonging to the node’s wallet.\n"
3399             "\nArguments:\n"
3400             "1. \"address\"      (string) The private address.\n"
3401             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3402             "\nResult:\n"
3403             "{\n"
3404             "  \"txid\": xxxxx,     (string) the transaction id\n"
3405             "  \"amount\": xxxxx,   (numeric) the amount of value in the note\n"
3406             "  \"memo\": xxxxx,     (string) hexademical string representation of memo field\n"
3407             "}\n"
3408             "\nExamples:\n"
3409             + HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3410             + HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3411         );
3412
3413     LOCK2(cs_main, pwalletMain->cs_wallet);
3414
3415     int nMinDepth = 1;
3416     if (params.size() > 1) {
3417         nMinDepth = params[1].get_int();
3418     }
3419     if (nMinDepth < 0) {
3420         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3421     }
3422
3423     // Check that the from address is valid.
3424     auto fromaddress = params[0].get_str();
3425
3426     libzcash::PaymentAddress zaddr;
3427     CZCPaymentAddress address(fromaddress);
3428     try {
3429         zaddr = address.Get();
3430     } catch (const std::runtime_error&) {
3431         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
3432     }
3433
3434     if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
3435         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
3436     }
3437
3438
3439     UniValue result(UniValue::VARR);
3440     std::vector<CNotePlaintextEntry> entries;
3441     pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
3442     for (CNotePlaintextEntry & entry : entries) {
3443         UniValue obj(UniValue::VOBJ);
3444         obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
3445         obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));
3446         std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
3447         obj.push_back(Pair("memo", HexStr(data)));
3448         result.push_back(obj);
3449     }
3450     return result;
3451 }
3452
3453
3454 UniValue z_getbalance(const UniValue& params, bool fHelp)
3455 {
3456     if (!EnsureWalletIsAvailable(fHelp))
3457         return NullUniValue;
3458
3459     if (fHelp || params.size()==0 || params.size() >2)
3460         throw runtime_error(
3461             "z_getbalance \"address\" ( minconf )\n"
3462             "\nReturns the balance of a taddr or zaddr belonging to the node’s wallet.\n"
3463             "\nCAUTION: If address is a watch-only zaddr, the returned balance may be larger than the actual balance,"
3464             "\nbecause spends cannot be detected with incoming viewing keys.\n"
3465             "\nArguments:\n"
3466             "1. \"address\"      (string) The selected address. It may be a transparent or private address.\n"
3467             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3468             "\nResult:\n"
3469             "amount              (numeric) The total amount in KMD received for this address.\n"
3470             "\nExamples:\n"
3471             "\nThe total amount received by address \"myaddress\"\n"
3472             + HelpExampleCli("z_getbalance", "\"myaddress\"") +
3473             "\nThe total amount received by address \"myaddress\" at least 5 blocks confirmed\n"
3474             + HelpExampleCli("z_getbalance", "\"myaddress\" 5") +
3475             "\nAs a json rpc call\n"
3476             + HelpExampleRpc("z_getbalance", "\"myaddress\", 5")
3477         );
3478
3479     LOCK2(cs_main, pwalletMain->cs_wallet);
3480
3481     int nMinDepth = 1;
3482     if (params.size() > 1) {
3483         nMinDepth = params[1].get_int();
3484     }
3485     if (nMinDepth < 0) {
3486         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3487     }
3488
3489     // Check that the from address is valid.
3490     auto fromaddress = params[0].get_str();
3491     bool fromTaddr = false;
3492     CBitcoinAddress taddr(fromaddress);
3493     fromTaddr = taddr.IsValid();
3494     libzcash::PaymentAddress zaddr;
3495     if (!fromTaddr) {
3496         CZCPaymentAddress address(fromaddress);
3497         try {
3498             zaddr = address.Get();
3499         } catch (const std::runtime_error&) {
3500             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3501         }
3502         if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
3503              throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
3504         }
3505     }
3506
3507     CAmount nBalance = 0;
3508     if (fromTaddr) {
3509         nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
3510     } else {
3511         nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
3512     }
3513
3514     return ValueFromAmount(nBalance);
3515 }
3516
3517
3518 UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
3519 {
3520     if (!EnsureWalletIsAvailable(fHelp))
3521         return NullUniValue;
3522
3523     if (fHelp || params.size() > 2)
3524         throw runtime_error(
3525             "z_gettotalbalance ( minconf includeWatchonly )\n"
3526             "\nReturn the total value of funds stored in the node’s wallet.\n"
3527             "\nCAUTION: If the wallet contains watch-only zaddrs, the returned private balance may be larger than the actual balance,"
3528             "\nbecause spends cannot be detected with incoming viewing keys.\n"
3529             "\nArguments:\n"
3530             "1. minconf          (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
3531             "2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
3532             "\nResult:\n"
3533             "{\n"
3534             "  \"transparent\": xxxxx,     (numeric) the total balance of transparent funds\n"
3535             "  \"private\": xxxxx,         (numeric) the total balance of private funds\n"
3536             "  \"total\": xxxxx,           (numeric) the total balance of both transparent and private funds\n"
3537             "}\n"
3538             "\nExamples:\n"
3539             "\nThe total amount in the wallet\n"
3540             + HelpExampleCli("z_gettotalbalance", "") +
3541             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
3542             + HelpExampleCli("z_gettotalbalance", "5") +
3543             "\nAs a json rpc call\n"
3544             + HelpExampleRpc("z_gettotalbalance", "5")
3545         );
3546
3547     LOCK2(cs_main, pwalletMain->cs_wallet);
3548
3549     int nMinDepth = 1;
3550     if (params.size() > 0) {
3551         nMinDepth = params[0].get_int();
3552     }
3553     if (nMinDepth < 0) {
3554         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3555     }
3556
3557     bool fIncludeWatchonly = false;
3558     if (params.size() > 1) {
3559         fIncludeWatchonly = params[1].get_bool();
3560     }
3561
3562     // getbalance and "getbalance * 1 true" should return the same number
3563     // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
3564     // pwalletMain->GetBalance() does not accept min depth parameter
3565     // so we use our own method to get balance of utxos.
3566     CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
3567     CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
3568     uint64_t interest = komodo_interestsum();
3569     CAmount nTotalBalance = nBalance + nPrivateBalance;
3570     UniValue result(UniValue::VOBJ);
3571     result.push_back(Pair("transparent", FormatMoney(nBalance)));
3572     result.push_back(Pair("interest", FormatMoney(interest)));
3573     result.push_back(Pair("private", FormatMoney(nPrivateBalance)));
3574     result.push_back(Pair("total", FormatMoney(nTotalBalance)));
3575     return result;
3576 }
3577
3578 UniValue z_getoperationresult(const UniValue& params, bool fHelp)
3579 {
3580     if (!EnsureWalletIsAvailable(fHelp))
3581         return NullUniValue;
3582
3583     if (fHelp || params.size() > 1)
3584         throw runtime_error(
3585             "z_getoperationresult ([\"operationid\", ... ]) \n"
3586             "\nRetrieve the result and status of an operation which has finished, and then remove the operation from memory."
3587             + HelpRequiringPassphrase() + "\n"
3588             "\nArguments:\n"
3589             "1. \"operationid\"         (array, optional) A list of operation ids we are interested in.  If not provided, examine all operations known to the node.\n"
3590             "\nResult:\n"
3591             "\"    [object, ...]\"      (array) A list of JSON objects\n"
3592             "\nExamples:\n"
3593             + HelpExampleCli("z_getoperationresult", "'[\"operationid\", ... ]'")
3594             + HelpExampleRpc("z_getoperationresult", "'[\"operationid\", ... ]'")
3595         );
3596
3597     // This call will remove finished operations
3598     return z_getoperationstatus_IMPL(params, true);
3599 }
3600
3601 UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
3602 {
3603    if (!EnsureWalletIsAvailable(fHelp))
3604         return NullUniValue;
3605
3606     if (fHelp || params.size() > 1)
3607         throw runtime_error(
3608             "z_getoperationstatus ([\"operationid\", ... ]) \n"
3609             "\nGet operation status and any associated result or error data.  The operation will remain in memory."
3610             + HelpRequiringPassphrase() + "\n"
3611             "\nArguments:\n"
3612             "1. \"operationid\"         (array, optional) A list of operation ids we are interested in.  If not provided, examine all operations known to the node.\n"
3613             "\nResult:\n"
3614             "\"    [object, ...]\"      (array) A list of JSON objects\n"
3615             "\nExamples:\n"
3616             + HelpExampleCli("z_getoperationstatus", "'[\"operationid\", ... ]'")
3617             + HelpExampleRpc("z_getoperationstatus", "'[\"operationid\", ... ]'")
3618         );
3619
3620    // This call is idempotent so we don't want to remove finished operations
3621    return z_getoperationstatus_IMPL(params, false);
3622 }
3623
3624 UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedOperations=false)
3625 {
3626     LOCK2(cs_main, pwalletMain->cs_wallet);
3627
3628     std::set<AsyncRPCOperationId> filter;
3629     if (params.size()==1) {
3630         UniValue ids = params[0].get_array();
3631         for (const UniValue & v : ids.getValues()) {
3632             filter.insert(v.get_str());
3633         }
3634     }
3635     bool useFilter = (filter.size()>0);
3636
3637     UniValue ret(UniValue::VARR);
3638     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3639     std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
3640
3641     for (auto id : ids) {
3642         if (useFilter && !filter.count(id))
3643             continue;
3644
3645         std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
3646         if (!operation) {
3647             continue;
3648             // It's possible that the operation was removed from the internal queue and map during this loop
3649             // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id.");
3650         }
3651
3652         UniValue obj = operation->getStatus();
3653         std::string s = obj["status"].get_str();
3654         if (fRemoveFinishedOperations) {
3655             // Caller is only interested in retrieving finished results
3656             if ("success"==s || "failed"==s || "cancelled"==s) {
3657                 ret.push_back(obj);
3658                 q->popOperationForId(id);
3659             }
3660         } else {
3661             ret.push_back(obj);
3662         }
3663     }
3664
3665     std::vector<UniValue> arrTmp = ret.getValues();
3666
3667     // sort results chronologically by creation_time
3668     std::sort(arrTmp.begin(), arrTmp.end(), [](UniValue a, UniValue b) -> bool {
3669         const int64_t t1 = find_value(a.get_obj(), "creation_time").get_int64();
3670         const int64_t t2 = find_value(b.get_obj(), "creation_time").get_int64();
3671         return t1 < t2;
3672     });
3673
3674     ret.clear();
3675     ret.setArray();
3676     ret.push_backV(arrTmp);
3677
3678     return ret;
3679 }
3680
3681
3682 // Here we define the maximum number of zaddr outputs that can be included in a transaction.
3683 // If input notes are small, we might actually require more than one joinsplit per zaddr output.
3684 // For now though, we assume we use one joinsplit per zaddr output (and the second output note is change).
3685 // We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data.
3686 #define Z_SENDMANY_MAX_ZADDR_OUTPUTS    ((MAX_TX_SIZE / JSDescription().GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)) - 1)
3687
3688 // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes
3689 #define CTXIN_SPEND_DUST_SIZE   148
3690 #define CTXOUT_REGULAR_SIZE     34
3691
3692 UniValue z_sendmany(const UniValue& params, bool fHelp)
3693 {
3694     if (!EnsureWalletIsAvailable(fHelp))
3695         return NullUniValue;
3696
3697     if (fHelp || params.size() < 2 || params.size() > 4)
3698         throw runtime_error(
3699             "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
3700             "\nSend multiple times. Amounts are double-precision floating point numbers."
3701             "\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself."
3702             "\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
3703             + strprintf("\nCurrently, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS)
3704             + HelpRequiringPassphrase() + "\n"
3705             "\nArguments:\n"
3706             "1. \"fromaddress\"         (string, required) The taddr or zaddr to send the funds from.\n"
3707             "2. \"amounts\"             (array, required) An array of json objects representing the amounts to send.\n"
3708             "    [{\n"
3709             "      \"address\":address  (string, required) The address is a taddr or zaddr\n"
3710             "      \"amount\":amount    (numeric, required) The numeric amount in KMD is the value\n"
3711             "      \"memo\":memo        (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
3712             "    }, ... ]\n"
3713             "3. minconf               (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
3714             "4. fee                   (numeric, optional, default="
3715             + strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
3716             "\nResult:\n"
3717             "\"operationid\"          (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
3718             "\nExamples:\n"
3719             + HelpExampleCli("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
3720             + HelpExampleRpc("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
3721         );
3722
3723     LOCK2(cs_main, pwalletMain->cs_wallet);
3724
3725     // Check that the from address is valid.
3726     auto fromaddress = params[0].get_str();
3727     bool fromTaddr = false;
3728     CBitcoinAddress taddr(fromaddress);
3729     fromTaddr = taddr.IsValid();
3730     libzcash::PaymentAddress zaddr;
3731     if (!fromTaddr) {
3732         CZCPaymentAddress address(fromaddress);
3733         try {
3734             zaddr = address.Get();
3735         } catch (const std::runtime_error&) {
3736             // invalid
3737             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3738         }
3739     }
3740
3741     // Check that we have the spending key
3742     if (!fromTaddr) {
3743         if (!pwalletMain->HaveSpendingKey(zaddr)) {
3744              throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
3745         }
3746     }
3747
3748     UniValue outputs = params[1].get_array();
3749
3750     if (outputs.size()==0)
3751         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty.");
3752
3753     // Keep track of addresses to spot duplicates
3754     set<std::string> setAddress;
3755
3756     // Recipients
3757     std::vector<SendManyRecipient> taddrRecipients;
3758     std::vector<SendManyRecipient> zaddrRecipients;
3759     CAmount nTotalOut = 0;
3760
3761     for (const UniValue& o : outputs.getValues()) {
3762         if (!o.isObject())
3763             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
3764
3765         // sanity check, report error if unknown key-value pairs
3766         for (const string& name_ : o.getKeys()) {
3767             std::string s = name_;
3768             if (s != "address" && s != "amount" && s!="memo")
3769                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown key: ")+s);
3770         }
3771
3772         string address = find_value(o, "address").get_str();
3773         bool isZaddr = false;
3774         CBitcoinAddress taddr(address);
3775         if (!taddr.IsValid())
3776         {
3777             try {
3778                 CZCPaymentAddress zaddr(address);
3779                 zaddr.Get();
3780                 isZaddr = true;
3781             } catch (const std::runtime_error&) {
3782                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
3783             }
3784         }
3785         else if ( ASSETCHAINS_PRIVATE != 0 )
3786             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
3787
3788         if (setAddress.count(address))
3789             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address);
3790         setAddress.insert(address);
3791
3792         UniValue memoValue = find_value(o, "memo");
3793         string memo;
3794         if (!memoValue.isNull()) {
3795             memo = memoValue.get_str();
3796             if (!isZaddr) {
3797                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo cannot be used with a taddr.  It can only be used with a zaddr.");
3798             } else if (!IsHex(memo)) {
3799                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
3800             }
3801             if (memo.length() > ZC_MEMO_SIZE*2) {
3802                 throw JSONRPCError(RPC_INVALID_PARAMETER,  strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
3803             }
3804         }
3805
3806         UniValue av = find_value(o, "amount");
3807         CAmount nAmount = AmountFromValue( av );
3808         if (nAmount < 0)
3809             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");
3810
3811         if (isZaddr) {
3812             zaddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3813         } else {
3814             taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3815         }
3816
3817         nTotalOut += nAmount;
3818     }
3819
3820     // Check the number of zaddr outputs does not exceed the limit.
3821     if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS)  {
3822         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs");
3823     }
3824
3825     // As a sanity check, estimate and verify that the size of the transaction will be valid.
3826     // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
3827     size_t txsize = 0;
3828     CMutableTransaction mtx;
3829     mtx.nVersion = 2;
3830     for (int i = 0; i < zaddrRecipients.size(); i++) {
3831         mtx.vjoinsplit.push_back(JSDescription());
3832     }
3833     CTransaction tx(mtx);
3834     txsize += tx.GetSerializeSize(SER_NETWORK, tx.nVersion);
3835     if (fromTaddr) {
3836         txsize += CTXIN_SPEND_DUST_SIZE;
3837         txsize += CTXOUT_REGULAR_SIZE;      // There will probably be taddr change
3838     }
3839     txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size();
3840     if (txsize > MAX_TX_SIZE) {
3841         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", MAX_TX_SIZE ));
3842     }
3843
3844     // Minimum confirmations
3845     int nMinDepth = 1;
3846     if (params.size() > 2) {
3847         nMinDepth = params[2].get_int();
3848     }
3849     if (nMinDepth < 0) {
3850         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3851     }
3852
3853     // Fee in Zatoshis, not currency format)
3854     CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
3855     if (params.size() > 3) {
3856         if (params[3].get_real() == 0.0) {
3857             nFee = 0;
3858         } else {
3859             nFee = AmountFromValue( params[3] );
3860         }
3861
3862         // Check that the user specified fee is sane.
3863         if (nFee > nTotalOut) {
3864             throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s", FormatMoney(nFee), FormatMoney(nTotalOut)));
3865         }
3866     }
3867
3868     // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
3869     UniValue o(UniValue::VOBJ);
3870     o.push_back(Pair("fromaddress", params[0]));
3871     o.push_back(Pair("amounts", params[1]));
3872     o.push_back(Pair("minconf", nMinDepth));
3873     o.push_back(Pair("fee", std::stod(FormatMoney(nFee))));
3874     UniValue contextInfo = o;
3875
3876     // Contextual transaction we will build on
3877     int nextBlockHeight = chainActive.Height() + 1;
3878     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
3879     bool isShielded = !fromTaddr || zaddrRecipients.size() > 0;
3880     if (contextualTx.nVersion == 1 && isShielded) {
3881         contextualTx.nVersion = 2; // Tx format should support vjoinsplits
3882     }
3883     if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
3884         contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
3885     }
3886
3887     // Create operation and add to global queue
3888     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3889     std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
3890     q->addOperation(operation);
3891     AsyncRPCOperationId operationId = operation->getId();
3892     return operationId;
3893 }
3894
3895
3896 /**
3897 When estimating the number of coinbase utxos we can shield in a single transaction:
3898 1. Joinsplit description is 1802 bytes.
3899 2. Transaction overhead ~ 100 bytes
3900 3. Spending a typical P2PKH is >=148 bytes, as defined in CTXIN_SPEND_DUST_SIZE.
3901 4. Spending a multi-sig P2SH address can vary greatly:
3902    https://github.com/bitcoin/bitcoin/blob/c3ad56f4e0b587d8d763af03d743fdfc2d180c9b/src/main.cpp#L517
3903    In real-world coinbase utxos, we consider a 3-of-3 multisig, where the size is roughly:
3904     (3*(33+1))+3 = 105 byte redeem script
3905     105 + 1 + 3*(73+1) = 328 bytes of scriptSig, rounded up to 400 based on testnet experiments.
3906 */
3907 #define CTXIN_SPEND_P2SH_SIZE 400
3908
3909 #define SHIELD_COINBASE_DEFAULT_LIMIT 50
3910
3911 UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
3912 {
3913     if (!EnsureWalletIsAvailable(fHelp))
3914         return NullUniValue;
3915
3916     if (fHelp || params.size() < 2 || params.size() > 4)
3917         throw runtime_error(
3918             "z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n"
3919             "\nShield transparent coinbase funds by sending to a shielded zaddr.  This is an asynchronous operation and utxos"
3920             "\nselected for shielding will be locked.  If there is an error, they are unlocked.  The RPC call `listlockunspent`"
3921             "\ncan be used to return a list of locked utxos.  The number of coinbase utxos selected for shielding can be limited"
3922             "\nby the caller.  If the limit parameter is set to zero, the -mempooltxinputlimit option will determine the number"
3923             "\nof uxtos.  Any limit is constrained by the consensus rule defining a maximum transaction size of "
3924             + strprintf("%d bytes.", MAX_TX_SIZE)
3925             + HelpRequiringPassphrase() + "\n"
3926             "\nArguments:\n"
3927             "1. \"fromaddress\"         (string, required) The address is a taddr or \"*\" for all taddrs belonging to the wallet.\n"
3928             "2. \"toaddress\"           (string, required) The address is a zaddr.\n"
3929             "3. fee                   (numeric, optional, default="
3930             + strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
3931             "4. limit                 (numeric, optional, default="
3932             + strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield.  Set to 0 to use node option -mempooltxinputlimit.\n"
3933             "\nResult:\n"
3934             "{\n"
3935             "  \"remainingUTXOs\": xxx       (numeric) Number of coinbase utxos still available for shielding.\n"
3936             "  \"remainingValue\": xxx       (numeric) Value of coinbase utxos still available for shielding.\n"
3937             "  \"shieldingUTXOs\": xxx        (numeric) Number of coinbase utxos being shielded.\n"
3938             "  \"shieldingValue\": xxx        (numeric) Value of coinbase utxos being shielded.\n"
3939             "  \"opid\": xxx          (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
3940             "}\n"
3941             "\nExamples:\n"
3942             + HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3943             + HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3944         );
3945
3946     LOCK2(cs_main, pwalletMain->cs_wallet);
3947
3948     // Validate the from address
3949     auto fromaddress = params[0].get_str();
3950     bool isFromWildcard = fromaddress == "*";
3951     CBitcoinAddress taddr;
3952     if (!isFromWildcard) {
3953         taddr = CBitcoinAddress(fromaddress);
3954         if (!taddr.IsValid()) {
3955             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
3956         }
3957     }
3958
3959     // Validate the destination address
3960     auto destaddress = params[1].get_str();
3961     try {
3962         CZCPaymentAddress pa(destaddress);
3963         libzcash::PaymentAddress zaddr = pa.Get();
3964     } catch (const std::runtime_error&) {
3965         throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
3966     }
3967
3968     // Convert fee from currency format to zatoshis
3969     CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
3970     if (params.size() > 2) {
3971         if (params[2].get_real() == 0.0) {
3972             nFee = 0;
3973         } else {
3974             nFee = AmountFromValue( params[2] );
3975         }
3976     }
3977
3978     int nLimit = SHIELD_COINBASE_DEFAULT_LIMIT;
3979     if (params.size() > 3) {
3980         nLimit = params[3].get_int();
3981         if (nLimit < 0) {
3982             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of utxos cannot be negative");
3983         }
3984     }
3985
3986     // Prepare to get coinbase utxos
3987     std::vector<ShieldCoinbaseUTXO> inputs;
3988     CAmount shieldedValue = 0;
3989     CAmount remainingValue = 0;
3990     size_t estimatedTxSize = 2000;  // 1802 joinsplit description + tx overhead + wiggle room
3991
3992     #ifdef __LP64__
3993     uint64_t utxoCounter = 0;
3994     #else
3995     size_t utxoCounter = 0;
3996     #endif
3997
3998     bool maxedOutFlag = false;
3999     size_t mempoolLimit = (nLimit != 0) ? nLimit : (size_t)GetArg("-mempooltxinputlimit", 0);
4000
4001     // Set of addresses to filter utxos by
4002     set<CBitcoinAddress> setAddress = {};
4003     if (!isFromWildcard) {
4004         setAddress.insert(taddr);
4005     }
4006
4007     // Get available utxos
4008     vector<COutput> vecOutputs;
4009     pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true);
4010
4011     // Find unspent coinbase utxos and update estimated size
4012     BOOST_FOREACH(const COutput& out, vecOutputs) {
4013         if (!out.fSpendable) {
4014             continue;
4015         }
4016
4017         CTxDestination address;
4018         if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
4019             continue;
4020         }
4021         // If taddr is not wildcard "*", filter utxos
4022         if (setAddress.size()>0 && !setAddress.count(address)) {
4023             continue;
4024         }
4025
4026         if (!out.tx->IsCoinBase()) {
4027             continue;
4028         }
4029
4030         utxoCounter++;
4031         CAmount nValue = out.tx->vout[out.i].nValue;
4032
4033         if (!maxedOutFlag) {
4034             CBitcoinAddress ba(address);
4035             size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
4036             if (estimatedTxSize + increase >= MAX_TX_SIZE ||
4037                 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
4038             {
4039                 maxedOutFlag = true;
4040             } else {
4041                 estimatedTxSize += increase;
4042                 ShieldCoinbaseUTXO utxo = {out.tx->GetHash(), out.i, nValue};
4043                 inputs.push_back(utxo);
4044                 shieldedValue += nValue;
4045             }
4046         }
4047
4048         if (maxedOutFlag) {
4049             remainingValue += nValue;
4050         }
4051     }
4052
4053     #ifdef __LP64__
4054     uint64_t numUtxos = inputs.size();
4055     #else
4056     size_t numUtxos = inputs.size();
4057     #endif
4058
4059     if (numUtxos == 0) {
4060         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase funds to shield.");
4061     }
4062
4063     if (shieldedValue < nFee) {
4064         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
4065             strprintf("Insufficient coinbase funds, have %s, which is less than miners fee %s",
4066             FormatMoney(shieldedValue), FormatMoney(nFee)));
4067     }
4068
4069     // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
4070     CAmount netAmount = shieldedValue - nFee;
4071     if (nFee > netAmount) {
4072         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
4073     }
4074
4075     // Keep record of parameters in context object
4076     UniValue contextInfo(UniValue::VOBJ);
4077     contextInfo.push_back(Pair("fromaddress", params[0]));
4078     contextInfo.push_back(Pair("toaddress", params[1]));
4079     contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
4080
4081     // Contextual transaction we will build on
4082     int nextBlockHeight = chainActive.Height() + 1;
4083     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
4084         Params().GetConsensus(), nextBlockHeight);
4085     if (contextualTx.nVersion == 1) {
4086         contextualTx.nVersion = 2; // Tx format should support vjoinsplits
4087     }
4088     if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
4089         contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
4090     }
4091
4092     // Create operation and add to global queue
4093     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4094     std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(contextualTx, inputs, destaddress, nFee, contextInfo) );
4095     q->addOperation(operation);
4096     AsyncRPCOperationId operationId = operation->getId();
4097
4098     // Return continuation information
4099     UniValue o(UniValue::VOBJ);
4100     o.push_back(Pair("remainingUTXOs", utxoCounter - numUtxos));
4101     o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue)));
4102     o.push_back(Pair("shieldingUTXOs", numUtxos));
4103     o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
4104     o.push_back(Pair("opid", operationId));
4105     return o;
4106 }
4107
4108
4109 #define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
4110 #define MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT 10
4111
4112 #define JOINSPLIT_SIZE JSDescription().GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)
4113
4114 UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
4115 {
4116     if (!EnsureWalletIsAvailable(fHelp))
4117         return NullUniValue;
4118
4119     auto fEnableMergeToAddress = true; //fExperimentalMode && GetBoolArg("-zmergetoaddress", false);
4120     std::string strDisabledMsg = "";
4121     if (!fEnableMergeToAddress) {
4122         strDisabledMsg = "\nWARNING: z_mergetoaddress is DISABLED but can be enabled as an experimental feature.\n";
4123     }
4124
4125     if (fHelp || params.size() < 2 || params.size() > 6)
4126         throw runtime_error(
4127             "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
4128             + strDisabledMsg +
4129             "\nMerge multiple UTXOs and notes into a single UTXO or note.  Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
4130             "\nto combine those into a single note."
4131             "\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked.  If there is an error, they"
4132             "\nare unlocked.  The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
4133             "\n\nThe number of UTXOs and notes selected for merging can be limited by the caller.  If the transparent limit"
4134             "\nparameter is set to zero, the -mempooltxinputlimit option will determine the number of UTXOs.  Any limit is"
4135             "\nconstrained by the consensus rule defining a maximum transaction size of "
4136             + strprintf("%d bytes.", MAX_TX_SIZE)
4137             + HelpRequiringPassphrase() + "\n"
4138             "\nArguments:\n"
4139             "1. fromaddresses         (string, required) A JSON array with addresses.\n"
4140             "                         The following special strings are accepted inside the array:\n"
4141             "                             - \"*\": Merge both UTXOs and notes from all addresses belonging to the wallet.\n"
4142             "                             - \"ANY_TADDR\": Merge UTXOs from all t-addrs belonging to the wallet.\n"
4143             "                             - \"ANY_ZADDR\": Merge notes from all z-addrs belonging to the wallet.\n"
4144             "                         If a special string is given, any given addresses of that type will be ignored.\n"
4145             "    [\n"
4146             "      \"address\"          (string) Can be a t-addr or a z-addr\n"
4147             "      ,...\n"
4148             "    ]\n"
4149             "2. \"toaddress\"           (string, required) The t-addr or z-addr to send the funds to.\n"
4150             "3. fee                   (numeric, optional, default="
4151             + strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
4152             "4. transparent_limit     (numeric, optional, default="
4153             + strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge.  Set to 0 to use node option -mempooltxinputlimit.\n"
4154             "4. shielded_limit        (numeric, optional, default="
4155             + strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT) + ") Limit on the maximum number of notes to merge.  Set to 0 to merge as many as will fit in the transaction.\n"
4156             "5. \"memo\"                (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
4157             "\nResult:\n"
4158             "{\n"
4159             "  \"remainingUTXOs\": xxx               (numeric) Number of UTXOs still available for merging.\n"
4160             "  \"remainingTransparentValue\": xxx    (numeric) Value of UTXOs still available for merging.\n"
4161             "  \"remainingNotes\": xxx               (numeric) Number of notes still available for merging.\n"
4162             "  \"remainingShieldedValue\": xxx       (numeric) Value of notes still available for merging.\n"
4163             "  \"mergingUTXOs\": xxx                 (numeric) Number of UTXOs being merged.\n"
4164             "  \"mergingTransparentValue\": xxx      (numeric) Value of UTXOs being merged.\n"
4165             "  \"mergingNotes\": xxx                 (numeric) Number of notes being merged.\n"
4166             "  \"mergingShieldedValue\": xxx         (numeric) Value of notes being merged.\n"
4167             "  \"opid\": xxx          (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
4168             "}\n"
4169             "\nExamples:\n"
4170             + HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
4171             + HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4172         );
4173
4174     if (!fEnableMergeToAddress) {
4175         throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
4176     }
4177
4178     LOCK2(cs_main, pwalletMain->cs_wallet);
4179
4180     bool useAny = false;
4181     bool useAnyUTXO = false;
4182     bool useAnyNote = false;
4183     std::set<CBitcoinAddress> taddrs = {};
4184     std::set<libzcash::PaymentAddress> zaddrs = {};
4185
4186     UniValue addresses = params[0].get_array();
4187     if (addresses.size()==0)
4188         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
4189
4190     // Keep track of addresses to spot duplicates
4191     std::set<std::string> setAddress;
4192
4193     // Sources
4194     for (const UniValue& o : addresses.getValues()) {
4195         if (!o.isStr())
4196             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
4197
4198         std::string address = o.get_str();
4199         if (address == "*") {
4200             useAny = true;
4201         } else if (address == "ANY_TADDR") {
4202             useAnyUTXO = true;
4203         } else if (address == "ANY_ZADDR") {
4204             useAnyNote = true;
4205         } else {
4206             CBitcoinAddress taddr(address);
4207             if (taddr.IsValid()) {
4208                 // Ignore any listed t-addrs if we are using all of them
4209                 if (!(useAny || useAnyUTXO)) {
4210                     taddrs.insert(taddr);
4211                 }
4212             } else {
4213                 try {
4214                     CZCPaymentAddress zaddr(address);
4215                     // Ignore listed z-addrs if we are using all of them
4216                     if (!(useAny || useAnyNote)) {
4217                         zaddrs.insert(zaddr.Get());
4218                     }
4219                 } catch (const std::runtime_error&) {
4220                     throw JSONRPCError(
4221                         RPC_INVALID_PARAMETER,
4222                         string("Invalid parameter, unknown address format: ") + address);
4223                 }
4224             }
4225         }
4226
4227         if (setAddress.count(address))
4228             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
4229         setAddress.insert(address);
4230     }
4231
4232     // Validate the destination address
4233     auto destaddress = params[1].get_str();
4234     bool isToZaddr = false;
4235     CBitcoinAddress taddr(destaddress);
4236     if (!taddr.IsValid()) {
4237         try {
4238             CZCPaymentAddress zaddr(destaddress);
4239             zaddr.Get();
4240             isToZaddr = true;
4241         } catch (const std::runtime_error&) {
4242             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
4243         }
4244     }
4245     else if ( ASSETCHAINS_PRIVATE != 0 )
4246         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
4247
4248     // Convert fee from currency format to zatoshis
4249     CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
4250     if (params.size() > 2) {
4251         if (params[2].get_real() == 0.0) {
4252             nFee = 0;
4253         } else {
4254             nFee = AmountFromValue( params[2] );
4255         }
4256     }
4257
4258     int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
4259     if (params.size() > 3) {
4260         nUTXOLimit = params[3].get_int();
4261         if (nUTXOLimit < 0) {
4262             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
4263         }
4264     }
4265
4266     int nNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT;
4267     if (params.size() > 4) {
4268         nNoteLimit = params[4].get_int();
4269         if (nNoteLimit < 0) {
4270             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
4271         }
4272     }
4273
4274     std::string memo;
4275     if (params.size() > 5) {
4276         memo = params[5].get_str();
4277         if (!isToZaddr) {
4278             throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr.  It can only be used with a zaddr.");
4279         } else if (!IsHex(memo)) {
4280             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
4281         }
4282         if (memo.length() > ZC_MEMO_SIZE*2) {
4283             throw JSONRPCError(RPC_INVALID_PARAMETER,  strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
4284         }
4285     }
4286
4287     MergeToAddressRecipient recipient(destaddress, memo);
4288
4289     // Prepare to get UTXOs and notes
4290     std::vector<MergeToAddressInputUTXO> utxoInputs;
4291     std::vector<MergeToAddressInputNote> noteInputs;
4292     CAmount mergedUTXOValue = 0;
4293     CAmount mergedNoteValue = 0;
4294     CAmount remainingUTXOValue = 0;
4295     CAmount remainingNoteValue = 0;
4296     #ifdef __LP64__
4297     uint64_t utxoCounter = 0;
4298     uint64_t noteCounter = 0;
4299     #else
4300     size_t utxoCounter = 0;
4301     size_t noteCounter = 0;
4302     #endif
4303     bool maxedOutUTXOsFlag = false;
4304     bool maxedOutNotesFlag = false;
4305     size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (size_t)GetArg("-mempooltxinputlimit", 0);
4306
4307     size_t estimatedTxSize = 200;  // tx overhead + wiggle room
4308     if (isToZaddr) {
4309         estimatedTxSize += JOINSPLIT_SIZE;
4310     }
4311
4312     if (useAny || useAnyUTXO || taddrs.size() > 0) {
4313         // Get available utxos
4314         vector<COutput> vecOutputs;
4315         pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
4316
4317         // Find unspent utxos and update estimated size
4318         for (const COutput& out : vecOutputs) {
4319             if (!out.fSpendable) {
4320                 continue;
4321             }
4322
4323             CTxDestination address;
4324             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
4325                 continue;
4326             }
4327             // If taddr is not wildcard "*", filter utxos
4328             if (taddrs.size() > 0 && !taddrs.count(address)) {
4329                 continue;
4330             }
4331
4332             utxoCounter++;
4333             CAmount nValue = out.tx->vout[out.i].nValue;
4334
4335             if (!maxedOutUTXOsFlag) {
4336                 CBitcoinAddress ba(address);
4337                 size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
4338                 if (estimatedTxSize + increase >= MAX_TX_SIZE ||
4339                     (mempoolLimit > 0 && utxoCounter > mempoolLimit))
4340                 {
4341                     maxedOutUTXOsFlag = true;
4342                 } else {
4343                     estimatedTxSize += increase;
4344                     COutPoint utxo(out.tx->GetHash(), out.i);
4345                     utxoInputs.emplace_back(utxo, nValue);
4346                     mergedUTXOValue += nValue;
4347                 }
4348             }
4349
4350             if (maxedOutUTXOsFlag) {
4351                 remainingUTXOValue += nValue;
4352             }
4353         }
4354     }
4355
4356     if (useAny || useAnyNote || zaddrs.size() > 0) {
4357         // Get available notes
4358         std::vector<CNotePlaintextEntry> entries;
4359         pwalletMain->GetFilteredNotes(entries, zaddrs);
4360
4361         // Find unspent notes and update estimated size
4362         for (CNotePlaintextEntry& entry : entries) {
4363             noteCounter++;
4364             CAmount nValue = entry.plaintext.value;
4365
4366             if (!maxedOutNotesFlag) {
4367                 // If we haven't added any notes yet and the merge is to a
4368                 // z-address, we have already accounted for the first JoinSplit.
4369                 size_t increase = (noteInputs.empty() && !isToZaddr) || (noteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
4370                 if (estimatedTxSize + increase >= MAX_TX_SIZE ||
4371                     (nNoteLimit > 0 && noteCounter > nNoteLimit))
4372                 {
4373                     maxedOutNotesFlag = true;
4374                 } else {
4375                     estimatedTxSize += increase;
4376                     SpendingKey zkey;
4377                     pwalletMain->GetSpendingKey(entry.address, zkey);
4378                     noteInputs.emplace_back(entry.jsop, entry.plaintext.note(entry.address), nValue, zkey);
4379                     mergedNoteValue += nValue;
4380                 }
4381             }
4382
4383             if (maxedOutNotesFlag) {
4384                 remainingNoteValue += nValue;
4385             }
4386         }
4387     }
4388
4389     #ifdef __LP64__
4390     uint64_t numUtxos = utxoInputs.size(); //ca333
4391     uint64_t numNotes = noteInputs.size();
4392     #else
4393     size_t numUtxos = utxoInputs.size();
4394     size_t numNotes = noteInputs.size();
4395     #endif
4396
4397
4398     if (numUtxos == 0 && numNotes == 0) {
4399         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
4400     }
4401
4402     // Sanity check: Don't do anything if:
4403     // - We only have one from address
4404     // - It's equal to toaddress
4405     // - The address only contains a single UTXO or note
4406     if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
4407         throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
4408     }
4409
4410     CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
4411     if (mergedValue < nFee) {
4412         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
4413             strprintf("Insufficient funds, have %s, which is less than miners fee %s",
4414             FormatMoney(mergedValue), FormatMoney(nFee)));
4415     }
4416
4417     // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
4418     CAmount netAmount = mergedValue - nFee;
4419     if (nFee > netAmount) {
4420         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
4421     }
4422
4423     // Keep record of parameters in context object
4424     UniValue contextInfo(UniValue::VOBJ);
4425     contextInfo.push_back(Pair("fromaddresses", params[0]));
4426     contextInfo.push_back(Pair("toaddress", params[1]));
4427     contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
4428
4429     // Contextual transaction we will build on
4430     int nextBlockHeight = chainActive.Height() + 1;
4431     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
4432         Params().GetConsensus(),
4433         nextBlockHeight);
4434     bool isShielded = numNotes > 0 || isToZaddr;
4435     if (contextualTx.nVersion == 1 && isShielded) {
4436         contextualTx.nVersion = 2; // Tx format should support vjoinsplit
4437     }
4438     if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
4439         contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
4440     }
4441
4442     // Create operation and add to global queue
4443     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4444     std::shared_ptr<AsyncRPCOperation> operation(
4445         new AsyncRPCOperation_mergetoaddress(contextualTx, utxoInputs, noteInputs, recipient, nFee, contextInfo) );
4446     q->addOperation(operation);
4447     AsyncRPCOperationId operationId = operation->getId();
4448
4449     // Return continuation information
4450     UniValue o(UniValue::VOBJ);
4451     o.push_back(Pair("remainingUTXOs", utxoCounter - numUtxos));
4452     o.push_back(Pair("remainingTransparentValue", ValueFromAmount(remainingUTXOValue)));
4453     o.push_back(Pair("remainingNotes", noteCounter - numNotes));
4454     o.push_back(Pair("remainingShieldedValue", ValueFromAmount(remainingNoteValue)));
4455     o.push_back(Pair("mergingUTXOs", numUtxos));
4456     o.push_back(Pair("mergingTransparentValue", ValueFromAmount(mergedUTXOValue)));
4457     o.push_back(Pair("mergingNotes", numNotes));
4458     o.push_back(Pair("mergingShieldedValue", ValueFromAmount(mergedNoteValue)));
4459     o.push_back(Pair("opid", operationId));
4460     return o;
4461 }
4462
4463
4464 UniValue z_listoperationids(const UniValue& params, bool fHelp)
4465 {
4466     if (!EnsureWalletIsAvailable(fHelp))
4467         return NullUniValue;
4468
4469     if (fHelp || params.size() > 1)
4470         throw runtime_error(
4471             "z_listoperationids\n"
4472             "\nReturns the list of operation ids currently known to the wallet.\n"
4473             "\nArguments:\n"
4474             "1. \"status\"         (string, optional) Filter result by the operation's state e.g. \"success\".\n"
4475             "\nResult:\n"
4476             "[                     (json array of string)\n"
4477             "  \"operationid\"       (string) an operation id belonging to the wallet\n"
4478             "  ,...\n"
4479             "]\n"
4480             "\nExamples:\n"
4481             + HelpExampleCli("z_listoperationids", "")
4482             + HelpExampleRpc("z_listoperationids", "")
4483         );
4484
4485     LOCK2(cs_main, pwalletMain->cs_wallet);
4486
4487     std::string filter;
4488     bool useFilter = false;
4489     if (params.size()==1) {
4490         filter = params[0].get_str();
4491         useFilter = true;
4492     }
4493
4494     UniValue ret(UniValue::VARR);
4495     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4496     std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
4497     for (auto id : ids) {
4498         std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
4499         if (!operation) {
4500             continue;
4501         }
4502         std::string state = operation->getStateAsString();
4503         if (useFilter && filter.compare(state)!=0)
4504             continue;
4505         ret.push_back(id);
4506     }
4507
4508     return ret;
4509 }
4510
4511
4512 #include "script/sign.h"
4513 int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
4514 extern std::string NOTARY_PUBKEY;
4515 uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 hash,int32_t n,uint32_t blocktime,uint32_t prevtime,char *destaddr);
4516 int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout);
4517 int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n);
4518
4519 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
4520 {
4521     set<CBitcoinAddress> setAddress; uint8_t *script,utxosig[128]; uint256 utxotxid; uint64_t utxovalue; int32_t i,siglen=0,nMinDepth = 1,nMaxDepth = 9999999; vector<COutput> vecOutputs; uint32_t utxovout,eligible,earliest = 0; CScript best_scriptPubKey; bool fNegative,fOverflow;
4522     bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr;
4523     auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
4524     const CKeyStore& keystore = *pwalletMain;
4525     assert(pwalletMain != NULL);
4526     LOCK2(cs_main, pwalletMain->cs_wallet);
4527     utxovalue = 0;
4528     memset(&utxotxid,0,sizeof(utxotxid));
4529     memset(&utxovout,0,sizeof(utxovout));
4530     memset(utxosig,0,sizeof(utxosig));
4531     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
4532     BOOST_FOREACH(const COutput& out, vecOutputs)
4533     {
4534         if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
4535             continue;
4536         if ( setAddress.size() )
4537         {
4538             CTxDestination address;
4539             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
4540                 continue;
4541             if (!setAddress.count(address))
4542                 continue;
4543         }
4544         CAmount nValue = out.tx->vout[out.i].nValue;
4545         if ( nValue != 10000 )
4546             continue;
4547         const CScript& pk = out.tx->vout[out.i].scriptPubKey;
4548         CTxDestination address;
4549         if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
4550         {
4551             //entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
4552             //if (pwalletMain->mapAddressBook.count(address))
4553             //    entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
4554         }
4555         script = (uint8_t *)out.tx->vout[out.i].scriptPubKey.data();
4556         if ( out.tx->vout[out.i].scriptPubKey.size() != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(notarypub33,script+1,33) != 0 )
4557         {
4558             //fprintf(stderr,"scriptsize.%d [0] %02x\n",(int32_t)out.tx->vout[out.i].scriptPubKey.size(),script[0]);
4559             continue;
4560         }
4561         utxovalue = (uint64_t)nValue;
4562         //decode_hex((uint8_t *)&utxotxid,32,(char *)out.tx->GetHash().GetHex().c_str());
4563         utxotxid = out.tx->GetHash();
4564         utxovout = out.i;
4565         best_scriptPubKey = out.tx->vout[out.i].scriptPubKey;
4566         //fprintf(stderr,"check %s/v%d %llu\n",(char *)utxotxid.GetHex().c_str(),utxovout,(long long)utxovalue);
4567  
4568         txNew.vin.resize(1);
4569         txNew.vout.resize(1);
4570         txfee = utxovalue / 2;
4571         //for (i=0; i<32; i++)
4572         //    ((uint8_t *)&revtxid)[i] = ((uint8_t *)&utxotxid)[31 - i];
4573         txNew.vin[0].prevout.hash = utxotxid; //revtxid;
4574         txNew.vin[0].prevout.n = utxovout;
4575         txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG;
4576         txNew.vout[0].nValue = utxovalue - txfee;
4577         CTransaction txNewConst(txNew);
4578         signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, utxovalue, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
4579         if (!signSuccess)
4580             fprintf(stderr,"notaryvin failed to create signature\n");
4581         else
4582         {
4583             UpdateTransaction(txNew,0,sigdata);
4584             ptr = (uint8_t *)sigdata.scriptSig.data();
4585             siglen = sigdata.scriptSig.size();
4586             for (i=0; i<siglen; i++)
4587                 utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
4588             //fprintf(stderr," siglen.%d notaryvin %s/v%d\n",siglen,utxotxid.GetHex().c_str(),utxovout);
4589             break;
4590         }
4591     }
4592     return(siglen);
4593 }
4594
4595 struct komodo_staking
4596 {
4597     char address[64];
4598     uint256 txid;
4599     arith_uint256 hashval;
4600     uint64_t nValue;
4601     uint32_t segid32,txtime;
4602     int32_t vout;
4603     CScript scriptPubKey;
4604 };
4605
4606 struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk)
4607 {
4608     uint256 hash; uint32_t segid32; struct komodo_staking *kp;
4609     segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
4610     if ( *numkp >= *maxkp )
4611     {
4612         *maxkp += 1000;
4613         array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
4614     }
4615     kp = &array[(*numkp)++];
4616     memset(kp,0,sizeof(*kp));
4617     strcpy(kp->address,address);
4618     kp->txid = txid;
4619     kp->vout = vout;
4620     kp->hashval = UintToArith256(hash);
4621     kp->txtime = txtime;
4622     kp->segid32 = segid32;
4623     kp->nValue = nValue;
4624     kp->scriptPubKey = pk;
4625     return(array);
4626 }
4627
4628 arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime)
4629 {
4630     int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval;
4631     diff = (iter + blocktime - kp->txtime - minage);
4632     if ( diff < 0 )
4633         diff = 60;
4634     else if ( diff > 3600*24*30 )
4635         diff = 3600*24*30;
4636     if ( iter > 0 )
4637         diff += segid*2;
4638     coinage = ((uint64_t)kp->nValue/COIN * diff);
4639     if ( blocktime+iter+segid*2 > prevtime+480 )
4640         coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
4641     //if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
4642     //    coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
4643     coinage256 = arith_uint256(coinage+1);
4644     hashval = ratio * (kp->hashval / coinage256);
4645     //if ( nHeight >= 900 && nHeight < 916 )
4646     //    hashval = (hashval / coinage256);
4647     return(hashval);
4648 }
4649
4650 uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf)
4651 {
4652     int32_t maxiters = 600; uint256 hash;
4653     int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256;
4654     komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout);
4655     kp->hashval = UintToArith256(hash);
4656     segid = ((nHeight + kp->segid32) & 0x3f);
4657     hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime);
4658     //for (int i=32; i>=0; i--)
4659     //    fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
4660     //fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime);
4661     if ( hashval <= bnTarget )
4662     {
4663         for (iter=0; iter<maxiters; iter++)
4664         {
4665             if ( blocktime+iter+segid*2 < kp->txtime+minage )
4666                 continue;
4667             hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime);
4668             if ( hashval <= bnTarget )
4669             {
4670                 //fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid);
4671                 blocktime += iter;
4672                 blocktime += segid * 2;
4673                 return(blocktime);
4674             }
4675         }
4676     }
4677     return(0);
4678 }
4679
4680 int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig)
4681 {
4682     static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime;
4683     set<CBitcoinAddress> setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock;
4684     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
4685     mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
4686     ratio = (mindiff / bnTarget);
4687     assert(pwalletMain != NULL);
4688     LOCK2(cs_main, pwalletMain->cs_wallet);
4689     *utxovaluep = 0;
4690     memset(utxotxidp,0,sizeof(*utxotxidp));
4691     memset(utxovoutp,0,sizeof(*utxovoutp));
4692     memset(utxosig,0,72);
4693     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
4694     if ( (tipindex= chainActive.Tip()) == 0 )
4695         return(0);
4696     nHeight = tipindex->nHeight + 1;
4697     if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
4698         minage = 6000;
4699     komodo_segids(hashbuf,nHeight-101,100);
4700     if ( *blocktimep > tipindex->nTime+60 )
4701         *blocktimep = tipindex->nTime+60;
4702     //fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
4703     if ( time(NULL) > lasttime+600 )
4704     {
4705         if ( array != 0 )
4706         {
4707             free(array);
4708             array = 0;
4709             maxkp = numkp = 0;
4710             lasttime = 0;
4711         }
4712         BOOST_FOREACH(const COutput& out, vecOutputs)
4713         {
4714             if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight )
4715             {
4716                 fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
4717                 return(0);
4718             }
4719             counter++;
4720             if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
4721             {
4722                 //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
4723                 continue;
4724             }
4725             CAmount nValue = out.tx->vout[out.i].nValue;
4726             if ( nValue < COIN  || !out.fSpendable )
4727                 continue;
4728             const CScript& pk = out.tx->vout[out.i].scriptPubKey;
4729             if ( ExtractDestination(pk,address) != 0 )
4730             {
4731                 if ( IsMine(*pwalletMain,address) == 0 )
4732                     continue;
4733                 if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= mapBlockIndex[hashBlock]) != 0 )
4734                 {
4735                     array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk);
4736                 }
4737             }
4738         }
4739         lasttime = (uint32_t)time(NULL);
4740         //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
4741     }
4742     block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
4743     for (i=winners=0; i<numkp; i++)
4744     {
4745         if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight )
4746         {
4747             fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
4748             return(0);
4749         }
4750         kp = &array[i];
4751         if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
4752             continue;
4753         eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
4754         //fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
4755         if ( eligible > 0 )
4756         {
4757             besttime = m = 0;
4758             if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
4759             {
4760                 while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
4761                 {
4762                     besttime = eligible;
4763                     eligible--;
4764                     if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
4765                         break;
4766                     m++;
4767                     //fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
4768                 }
4769             }
4770             else
4771             {
4772                 fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
4773                 continue;
4774             }
4775             eligible = besttime;
4776             winners++;
4777             //fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
4778             if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
4779             {
4780                 earliest = eligible;
4781                 best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey;
4782                 *utxovaluep = (uint64_t)kp->nValue;
4783                 //decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str());
4784                 decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
4785                 *utxovoutp = kp->vout;
4786                 *txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime;
4787                 fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
4788             }
4789         } //else fprintf(stderr,"utxo not eligible\n");
4790     } //else fprintf(stderr,"no tipindex\n");
4791     if ( numkp < 10000 && array != 0 )
4792     {
4793         free(array);
4794         array = 0;
4795         maxkp = numkp = 0;
4796         lasttime = 0;
4797     }
4798     if ( earliest != 0 )
4799     {
4800         bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid;
4801         auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
4802         const CKeyStore& keystore = *pwalletMain;
4803         txNew.vin.resize(1);
4804         txNew.vout.resize(1);
4805         txfee = 0;
4806         for (i=0; i<32; i++)
4807             ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i];
4808         txNew.vin[0].prevout.hash = revtxid;
4809         txNew.vin[0].prevout.n = *utxovoutp;
4810         txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
4811         txNew.vout[0].nValue = *utxovaluep - txfee;
4812         txNew.nLockTime = earliest;
4813         CTransaction txNewConst(txNew);
4814         signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
4815         if (!signSuccess)
4816             fprintf(stderr,"failed to create signature\n");
4817         else
4818         {
4819             UpdateTransaction(txNew,0,sigdata);
4820             ptr = (uint8_t *)sigdata.scriptSig.data();
4821             siglen = sigdata.scriptSig.size();
4822             for (i=0; i<siglen; i++)
4823                 utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
4824             //fprintf(stderr," siglen.%d\n",siglen);
4825             //fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
4826             *blocktimep = earliest;
4827         }
4828     } //else fprintf(stderr,"no earliest utxo for staking\n");
4829     //fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners);
4830     return(siglen);
4831 }
4832
4833 UniValue getbalance64(const UniValue& params, bool fHelp)
4834 {
4835     set<CBitcoinAddress> setAddress; vector<COutput> vecOutputs;
4836     UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR),b(UniValue::VARR); CTxDestination address;
4837     const CKeyStore& keystore = *pwalletMain;
4838     CAmount nValues[64],nValues2[64],nValue,total,total2; int32_t i,segid;
4839     assert(pwalletMain != NULL);
4840     if (fHelp || params.size() > 0)
4841         throw runtime_error("getbalance64\n");
4842     total = total2 = 0;
4843     memset(nValues,0,sizeof(nValues));
4844     memset(nValues2,0,sizeof(nValues2));
4845     LOCK2(cs_main, pwalletMain->cs_wallet);
4846     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
4847     BOOST_FOREACH(const COutput& out, vecOutputs)
4848     {
4849         nValue = out.tx->vout[out.i].nValue;
4850         if ( ExtractDestination(out.tx->vout[out.i].scriptPubKey, address) )
4851         {
4852             segid = (komodo_segid32((char *)CBitcoinAddress(address).ToString().c_str()) & 0x3f);
4853             if ( out.nDepth < 100 )
4854                 nValues2[segid] += nValue, total2 += nValue;
4855             else nValues[segid] += nValue, total += nValue;
4856             //fprintf(stderr,"%s %.8f depth.%d segid.%d\n",(char *)CBitcoinAddress(address).ToString().c_str(),(double)nValue/COIN,(int32_t)out.nDepth,segid);
4857         } else fprintf(stderr,"no destination\n");
4858     }
4859     ret.push_back(Pair("mature",(double)total/COIN));
4860     ret.push_back(Pair("immature",(double)total2/COIN));
4861     for (i=0; i<64; i++)
4862     {
4863         a.push_back((uint64_t)nValues[i]);
4864         b.push_back((uint64_t)nValues2[i]);
4865     }
4866     ret.push_back(Pair("staking", a));
4867     ret.push_back(Pair("notstaking", b));
4868     return ret;
4869 }
This page took 0.305507 seconds and 4 git commands to generate.