]> Git Repo - VerusCoin.git/blob - src/wallet/rpcwallet.cpp
Currency transfer updates and debug outputs
[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 https://www.opensource.org/licenses/mit-license.php .
5
6 #include "amount.h"
7 #include "consensus/upgrades.h"
8 #include "core_io.h"
9 #include "init.h"
10 #include "key_io.h"
11 #include "main.h"
12 #include "pbaas/pbaas.h"
13 #include "net.h"
14 #include "netbase.h"
15 #include "rpc/server.h"
16 #include "timedata.h"
17 #include "transaction_builder.h"
18 #include "util.h"
19 #include "utilmoneystr.h"
20 #include "wallet.h"
21 #include "walletdb.h"
22 #include "primitives/transaction.h"
23 #include "zcbenchmarks.h"
24 #include "script/interpreter.h"
25 #include "zcash/zip32.h"
26
27 #include "utiltime.h"
28 #include "asyncrpcoperation.h"
29 #include "asyncrpcqueue.h"
30 #include "wallet/asyncrpcoperation_mergetoaddress.h"
31 #include "wallet/asyncrpcoperation_saplingmigration.h"
32 #include "wallet/asyncrpcoperation_sendmany.h"
33 #include "wallet/asyncrpcoperation_shieldcoinbase.h"
34
35 #include "consensus/upgrades.h"
36
37 #include "sodium.h"
38
39 #include <stdint.h>
40 #include <boost/assign/list_of.hpp>
41 #include <univalue.h>
42 #include <numeric>
43 #include <algorithm>
44
45 using namespace std;
46
47 using namespace libzcash;
48
49 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
50 extern int32_t VERUS_MIN_STAKEAGE;
51 const std::string ADDR_TYPE_SPROUT = "sprout";
52 const std::string ADDR_TYPE_SAPLING = "sapling";
53
54 extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
55 extern uint8_t ASSETCHAINS_PRIVATE;
56 uint32_t komodo_segid32(char *coinaddr);
57
58 int64_t nWalletUnlockTime;
59 static CCriticalSection cs_nWalletUnlockTime;
60 std::string CCerror;
61
62 // Private method:
63 UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
64
65 #define PLAN_NAME_MAX   8
66 #define VALID_PLAN_NAME(x)  (strlen(x) <= PLAN_NAME_MAX)
67
68 std::string HelpRequiringPassphrase()
69 {
70     return pwalletMain && pwalletMain->IsCrypted()
71         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
72         : "";
73 }
74
75 bool EnsureWalletIsAvailable(bool avoidException)
76 {
77     if (!pwalletMain)
78     {
79         if (!avoidException)
80             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
81         else
82             return false;
83     }
84     return true;
85 }
86
87 void EnsureWalletIsUnlocked()
88 {
89     if (pwalletMain->IsLocked())
90         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
91 }
92
93 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);
94
95 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
96 {
97     //int32_t i,n,txheight; uint32_t locktime; uint64_t interest = 0;
98     int confirms = wtx.GetDepthInMainChain();
99     entry.push_back(Pair("confirmations", confirms));
100     if (wtx.IsCoinBase())
101         entry.push_back(Pair("generated", true));
102     if (confirms > 0)
103     {
104         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
105         entry.push_back(Pair("blockindex", wtx.nIndex));
106         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
107         entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
108     }
109     uint256 hash = wtx.GetHash();
110     entry.push_back(Pair("txid", hash.GetHex()));
111     UniValue conflicts(UniValue::VARR);
112     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
113         conflicts.push_back(conflict.GetHex());
114     entry.push_back(Pair("walletconflicts", conflicts));
115     entry.push_back(Pair("time", wtx.GetTxTime()));
116     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
117     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
118         entry.push_back(Pair(item.first, item.second));
119
120     entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx)));
121 }
122
123 string AccountFromValue(const UniValue& value)
124 {
125     string strAccount = value.get_str();
126     //if (strAccount != "")
127     //    throw JSONRPCError(RPC_WALLET_ACCOUNTS_UNSUPPORTED, "Accounts are unsupported");
128     return strAccount;
129 }
130
131 char *komodo_chainname()
132 {
133      return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL);
134 }
135
136 UniValue getnewaddress(const UniValue& params, bool fHelp)
137 {
138     if (!EnsureWalletIsAvailable(fHelp))
139         return NullUniValue;
140
141     if (fHelp || params.size() > 1)
142         throw runtime_error(
143             "getnewaddress ( \"account\" )\n"
144             "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address for receiving payments.\n"
145             "\nArguments:\n"
146             "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"
147             "\nResult:\n"
148             "\"" + strprintf("%s",komodo_chainname()) + "_address\"    (string) The new " + strprintf("%s",komodo_chainname()) + " address\n"
149             "\nExamples:\n"
150             + HelpExampleCli("getnewaddress", "")
151             + HelpExampleRpc("getnewaddress", "")
152         );
153
154     LOCK2(cs_main, pwalletMain->cs_wallet);
155
156     // Parse the account first so we don't generate a key if there's an error
157     string strAccount;
158     if (params.size() > 0)
159         strAccount = AccountFromValue(params[0]);
160
161     if (!pwalletMain->IsLocked())
162         pwalletMain->TopUpKeyPool();
163
164     // Generate a new key that is added to wallet
165     CPubKey newKey;
166     if (!pwalletMain->GetKeyFromPool(newKey))
167         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
168     CKeyID keyID = newKey.GetID();
169
170     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
171
172     return EncodeDestination(keyID);
173 }
174
175
176 CTxDestination GetAccountAddress(std::string strAccount, bool bForceNew=false)
177 {
178     CWalletDB walletdb(pwalletMain->strWalletFile);
179
180     CAccount account;
181     walletdb.ReadAccount(strAccount, account);
182
183     bool bKeyUsed = false;
184
185     // Check if the current key has been used
186     if (account.vchPubKey.IsValid())
187     {
188         CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
189         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
190              it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
191              ++it)
192         {
193             const CWalletTx& wtx = (*it).second;
194             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
195                 if (txout.scriptPubKey == scriptPubKey)
196                     bKeyUsed = true;
197         }
198     }
199
200     // Generate a new key
201     if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
202     {
203         if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
204             throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
205
206         pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
207         walletdb.WriteAccount(strAccount, account);
208     }
209
210     return account.vchPubKey.GetID();
211 }
212
213 UniValue getaccountaddress(const UniValue& params, bool fHelp)
214 {
215     if (!EnsureWalletIsAvailable(fHelp))
216         return NullUniValue;
217
218     if (fHelp || params.size() != 1)
219         throw runtime_error(
220             "getaccountaddress \"account\"\n"
221             "\nDEPRECATED. Returns the current " + strprintf("%s",komodo_chainname()) + " address for receiving payments to this account.\n"
222             "\nArguments:\n"
223             "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"
224             "\nResult:\n"
225             "\"" + strprintf("%s",komodo_chainname()) + "_address\"   (string) The account " + strprintf("%s",komodo_chainname()) + " address\n"
226             "\nExamples:\n"
227             + HelpExampleCli("getaccountaddress", "")
228             + HelpExampleCli("getaccountaddress", "\"\"")
229             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
230             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
231         );
232
233     LOCK2(cs_main, pwalletMain->cs_wallet);
234
235     // Parse the account first so we don't generate a key if there's an error
236     string strAccount = AccountFromValue(params[0]);
237
238     UniValue ret(UniValue::VSTR);
239
240     ret = EncodeDestination(GetAccountAddress(strAccount));
241     return ret;
242 }
243
244
245 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
246 {
247     if (!EnsureWalletIsAvailable(fHelp))
248         return NullUniValue;
249
250     if (fHelp || params.size() > 1)
251         throw runtime_error(
252             "getrawchangeaddress\n"
253             "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address, for receiving change.\n"
254             "This is for use with raw transactions, NOT normal use.\n"
255             "\nResult:\n"
256             "\"address\"    (string) The address\n"
257             "\nExamples:\n"
258             + HelpExampleCli("getrawchangeaddress", "")
259             + HelpExampleRpc("getrawchangeaddress", "")
260        );
261
262     LOCK2(cs_main, pwalletMain->cs_wallet);
263
264     if (!pwalletMain->IsLocked())
265         pwalletMain->TopUpKeyPool();
266
267     CReserveKey reservekey(pwalletMain);
268     CPubKey vchPubKey;
269     if (!reservekey.GetReservedKey(vchPubKey))
270         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
271
272     reservekey.KeepKey();
273
274     CKeyID keyID = vchPubKey.GetID();
275
276     return EncodeDestination(keyID);
277 }
278
279
280 UniValue setaccount(const UniValue& params, bool fHelp)
281 {
282     if (!EnsureWalletIsAvailable(fHelp))
283         return NullUniValue;
284
285     if (fHelp || params.size() < 1 || params.size() > 2)
286         throw runtime_error(
287             "setaccount \"" + strprintf("%s",komodo_chainname()) + "_address\" \"account\"\n"
288             "\nDEPRECATED. Sets the account associated with the given address.\n"
289             "\nArguments:\n"
290             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to be associated with an account.\n"
291             "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"
292             "\nExamples:\n"
293             + HelpExampleCli("setaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"tabby\"")
294             + HelpExampleRpc("setaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"tabby\"")
295         );
296
297     LOCK2(cs_main, pwalletMain->cs_wallet);
298
299     CTxDestination dest = DecodeDestination(params[0].get_str());
300     if (!IsValidDestination(dest)) {
301         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Verus address");
302     }
303
304     string strAccount;
305     if (params.size() > 1)
306         strAccount = AccountFromValue(params[1]);
307
308     // Only add the account if the address is yours.
309     if (IsMine(*pwalletMain, dest)) {
310         // Detect when changing the account of an address that is the 'unused current key' of another account:
311         if (pwalletMain->mapAddressBook.count(dest)) {
312             std::string strOldAccount = pwalletMain->mapAddressBook[dest].name;
313             if (dest == GetAccountAddress(strOldAccount)) {
314                 GetAccountAddress(strOldAccount, true);
315             }
316         }
317         pwalletMain->SetAddressBook(dest, strAccount, "receive");
318     }
319     else
320         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
321
322     return NullUniValue;
323 }
324
325
326 UniValue getaccount(const UniValue& params, bool fHelp)
327 {
328     if (!EnsureWalletIsAvailable(fHelp))
329         return NullUniValue;
330
331     if (fHelp || params.size() != 1)
332         throw runtime_error(
333             "getaccount \"" + strprintf("%s",komodo_chainname()) + "_address\"\n"
334             "\nDEPRECATED. Returns the account associated with the given address.\n"
335             "\nArguments:\n"
336             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address for account lookup.\n"
337             "\nResult:\n"
338             "\"accountname\"        (string) the account address\n"
339             "\nExamples:\n"
340             + HelpExampleCli("getaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"")
341             + HelpExampleRpc("getaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"")
342         );
343
344     LOCK2(cs_main, pwalletMain->cs_wallet);
345
346     CTxDestination dest = DecodeDestination(params[0].get_str());
347     if (!IsValidDestination(dest)) {
348         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Verus address");
349     }
350
351     std::string strAccount;
352     std::map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(dest);
353     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) {
354         strAccount = (*mi).second.name;
355     }
356     return strAccount;
357 }
358
359
360 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
361 {
362     if (!EnsureWalletIsAvailable(fHelp))
363         return NullUniValue;
364
365     if (fHelp || params.size() != 1)
366         throw runtime_error(
367             "getaddressesbyaccount \"account\"\n"
368             "\nDEPRECATED. Returns the list of addresses for the given account.\n"
369             "\nArguments:\n"
370             "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"
371             "\nResult:\n"
372             "[                     (json array of string)\n"
373             "  \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string) a " + strprintf("%s",komodo_chainname()) + " address associated with the given account\n"
374             "  ,...\n"
375             "]\n"
376             "\nExamples:\n"
377             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
378             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
379         );
380
381     LOCK2(cs_main, pwalletMain->cs_wallet);
382
383     string strAccount = AccountFromValue(params[0]);
384
385     // Find all addresses that have the given account
386     UniValue ret(UniValue::VARR);
387     for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
388         const CTxDestination& dest = item.first;
389         const std::string& strName = item.second.name;
390         if (strName == strAccount) {
391             ret.push_back(EncodeDestination(dest));
392         }
393     }
394     return ret;
395 }
396
397 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew,uint8_t *opretbuf,int32_t opretlen,long int opretValue)
398 {
399     CAmount curBalance = pwalletMain->GetBalance();
400
401     // Check amount
402     if (nValue <= 0)
403         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
404
405     if (nValue > curBalance)
406         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
407
408     // Parse Zcash address
409     CScript scriptPubKey = GetScriptForDestination(address);
410
411     // Create and send the transaction
412     CReserveKey reservekey(pwalletMain);
413     CAmount nFeeRequired;
414     std::string strError;
415     vector<CRecipient> vecSend;
416     int nChangePosRet = -1;
417     CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
418     vecSend.push_back(recipient);
419     if ( opretlen > 0 && opretbuf != 0 )
420     {
421         CScript opretpubkey; int32_t i; uint8_t *ptr;
422         opretpubkey.resize(opretlen);
423         for (i=0; i<opretlen; i++)
424         {
425             opretpubkey[i] = opretbuf[i];
426             //printf("%02x",ptr[i]);
427         }
428         //printf(" opretbuf[%d]\n",opretlen);
429         CRecipient opret = { opretpubkey, opretValue, false };
430         vecSend.push_back(opret);
431     }
432     if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
433         if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
434             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));
435         throw JSONRPCError(RPC_WALLET_ERROR, strError);
436     }
437     if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
438         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.");
439 }
440
441 UniValue sendtoaddress(const UniValue& params, bool fHelp)
442 {
443     if (!EnsureWalletIsAvailable(fHelp))
444         return NullUniValue;
445
446     if (fHelp || params.size() < 2 || params.size() > 5)
447         throw runtime_error(
448             "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
449             "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
450             + HelpRequiringPassphrase() +
451             "\nArguments:\n"
452             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send to.\n"
453             "2. \"amount\"      (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " to send. eg 0.1\n"
454             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
455             "                             This is not part of the transaction, just kept in your wallet.\n"
456             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
457             "                             to which you're sending the transaction. This is not part of the \n"
458             "                             transaction, just kept in your wallet.\n"
459             "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
460             "                             The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n"
461             "\nResult:\n"
462             "\"transactionid\"  (string) The transaction id.\n"
463             "\nExamples:\n"
464             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1")
465             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"donation\" \"seans outpost\"")
466             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.1 \"\" \"\" true")
467             + HelpExampleRpc("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.1, \"donation\", \"seans outpost\"")
468         );
469
470     if ( ASSETCHAINS_PRIVATE != 0 && AmountFromValue(params[1]) > 0 )
471         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address");
472
473     LOCK2(cs_main, pwalletMain->cs_wallet);
474
475     CTxDestination dest = DecodeDestination(params[0].get_str());
476     if (!IsValidDestination(dest)) {
477         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Verus address");
478     }
479
480     // Amount
481     CAmount nAmount = AmountFromValue(params[1]);
482     if (nAmount <= 0)
483         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
484
485     // Wallet comments
486     CWalletTx wtx;
487     if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
488         wtx.mapValue["comment"] = params[2].get_str();
489     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
490         wtx.mapValue["to"]      = params[3].get_str();
491
492     bool fSubtractFeeFromAmount = false;
493     if (params.size() > 4)
494         fSubtractFeeFromAmount = params[4].get_bool();
495
496     EnsureWalletIsUnlocked();
497
498     SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx,0,0,0);
499
500     return wtx.GetHash().GetHex();
501 }
502
503 #include "komodo_defs.h"
504
505 #define KOMODO_KVPROTECTED 1
506 #define KOMODO_KVBINARY 2
507 #define KOMODO_KVDURATION 1440
508 #define IGUANA_MAXSCRIPTSIZE 10001
509 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);
510 int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen);
511 #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
512 extern int32_t KOMODO_PAX;
513 extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
514 int32_t komodo_is_issuer();
515 int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp);
516 int32_t komodo_isrealtime(int32_t *kmdheightp);
517 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
518 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);
519 int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize);
520 uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen);
521 uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey);
522 int32_t komodo_kvduration(uint32_t flags);
523 uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase);
524 int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig);
525
526 UniValue kvupdate(const UniValue& params, bool fHelp)
527 {
528     static uint256 zeroes;
529     CWalletTx wtx; UniValue ret(UniValue::VOBJ);
530     uint8_t keyvalue[IGUANA_MAXSCRIPTSIZE*8],opretbuf[IGUANA_MAXSCRIPTSIZE*8]; 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;
531     if (fHelp || params.size() < 3 )
532         throw runtime_error(
533             "kvupdate key \"value\" days passphrase\n"
534             "\nStore a key value. This feature is only available for asset chains.\n"
535             "\nArguments:\n"
536             "1. key                      (string, required) key\n"
537             "2. \"value\"                (string, required) value\n"
538             "3. days                     (numeric, required) amount of days(1440 blocks/day) before the key expires. Minimum 1 day\n"
539             "4. passphrase               (string, optional) passphrase required to update this key\n"
540             "\nResult:\n"
541             "{\n"
542             "  \"coin\": \"xxxxx\",          (string) chain the key is stored on\n"
543             "  \"height\": xxxxx,            (numeric) height the key was stored at\n"
544             "  \"expiration\": xxxxx,        (numeric) height the key will expire\n"
545             "  \"flags\": x,                 (string) amount of days the key will be stored \n"
546             "  \"key\": \"xxxxx\",           (numeric) stored key\n"
547             "  \"keylen\": xxxxx,            (numeric) length of the key\n"
548             "  \"value\": \"xxxxx\"          (numeric) stored value\n"
549             "  \"valuesize\": xxxxx,         (string) length of the stored value\n"
550             "  \"fee\": xxxxx                (string) transaction fee paid to store the key\n"
551             "  \"txid\": \"xxxxx\"           (string) transaction id\n"
552             "}\n"
553             "\nExamples:\n"
554             + HelpExampleCli("kvupdate", "examplekey \"examplevalue\" 2 examplepassphrase")
555             + HelpExampleRpc("kvupdate", "examplekey \"examplevalue\" 2 examplepassphrase")
556         );
557     if (!EnsureWalletIsAvailable(fHelp))
558         return 0;
559     if ( ASSETCHAINS_SYMBOL[0] == 0 )
560         return(0);
561     haveprivkey = 0;
562     memset(&sig,0,sizeof(sig));
563     memset(&privkey,0,sizeof(privkey));
564     memset(&refpubkey,0,sizeof(refpubkey));
565     memset(&pubkey,0,sizeof(pubkey));
566     if ( (n= (int32_t)params.size()) >= 3 )
567     {
568         flags = atoi(params[2].get_str().c_str());
569         //printf("flags.%d (%s) n.%d\n",flags,params[2].get_str().c_str(),n);
570     } else flags = 0;
571     if ( n >= 4 )
572         privkey = komodo_kvprivkey(&pubkey,(char *)(n >= 4 ? params[3].get_str().c_str() : "password"));
573     haveprivkey = 1;
574     flags |= 1;
575     /*for (i=0; i<32; i++)
576         printf("%02x",((uint8_t *)&privkey)[i]);
577     printf(" priv, ");
578     for (i=0; i<32; i++)
579         printf("%02x",((uint8_t *)&pubkey)[i]);
580     printf(" pubkey, privkey derived from (%s)\n",(char *)params[3].get_str().c_str());
581     */
582     LOCK2(cs_main, pwalletMain->cs_wallet);
583     if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
584     {
585         key = (uint8_t *)params[0].get_str().c_str();
586         if ( n >= 2 && params[1].get_str().c_str() != 0 )
587         {
588             value = (uint8_t *)params[1].get_str().c_str();
589             valuesize = (int32_t)strlen(params[1].get_str().c_str());
590         }
591         memcpy(keyvalue,key,keylen);
592         if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->GetHeight(),&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 )
593         {
594             if ( (tmpflags & KOMODO_KVPROTECTED) != 0 )
595             {
596                 if ( memcmp(&refpubkey,&pubkey,sizeof(refpubkey)) != 0 )
597                 {
598                     ret.push_back(Pair("error",(char *)"cant modify write once key without passphrase"));
599                     return ret;
600                 }
601             }
602             if ( keylen+refvaluesize <= sizeof(keyvalue) )
603             {
604                 sig = komodo_kvsig(keyvalue,keylen+refvaluesize,privkey);
605                 if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 )
606                 {
607                     ret.push_back(Pair("error",(char *)"error verifying sig, passphrase is probably wrong"));
608                     printf("VERIFY ERROR\n");
609                     return ret;
610                 } // else printf("verified immediately\n");
611             }
612         }
613         //for (i=0; i<32; i++)
614         //    printf("%02x",((uint8_t *)&sig)[i]);
615         //printf(" sig for keylen.%d + valuesize.%d\n",keylen,refvaluesize);
616         ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
617         height = chainActive.LastTip()->GetHeight();
618         if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
619             ret.push_back(Pair("owner",refpubkey.GetHex()));
620         ret.push_back(Pair("height", (int64_t)height));
621         duration = komodo_kvduration(flags); //((flags >> 2) + 1) * KOMODO_KVDURATION;
622         ret.push_back(Pair("expiration", (int64_t)(height+duration)));
623         ret.push_back(Pair("flags",(int64_t)flags));
624         ret.push_back(Pair("key",params[0].get_str()));
625         ret.push_back(Pair("keylen",(int64_t)keylen));
626         if ( n >= 2 && params[1].get_str().c_str() != 0 )
627         {
628             ret.push_back(Pair("value",params[1].get_str()));
629             ret.push_back(Pair("valuesize",valuesize));
630         }
631         iguana_rwnum(1,&keyvalue[0],sizeof(keylen),&keylen);
632         iguana_rwnum(1,&keyvalue[2],sizeof(valuesize),&valuesize);
633         iguana_rwnum(1,&keyvalue[4],sizeof(height),&height);
634         iguana_rwnum(1,&keyvalue[8],sizeof(flags),&flags);
635         memcpy(&keyvalue[12],key,keylen);
636         if ( value != 0 )
637             memcpy(&keyvalue[12 + keylen],value,valuesize);
638         coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(uint16_t)*2+keylen+valuesize);
639         if ( haveprivkey != 0 )
640         {
641             for (i=0; i<32; i++)
642                 keyvalue[12 + keylen + valuesize + i] = ((uint8_t *)&pubkey)[i];
643             coresize += 32;
644             if ( refvaluesize >=0 )
645             {
646                 for (i=0; i<32; i++)
647                     keyvalue[12 + keylen + valuesize + 32 + i] = ((uint8_t *)&sig)[i];
648                 coresize += 32;
649             }
650         }
651         if ( (opretlen= komodo_opreturnscript(opretbuf,'K',keyvalue,coresize)) == 40 )
652             opretlen++;
653         //for (i=0; i<opretlen; i++)
654         //    printf("%02x",opretbuf[i]);
655         //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]);
656         EnsureWalletIsUnlocked();
657         fee = komodo_kvfee(flags,opretlen,keylen);
658         ret.push_back(Pair("fee",(double)fee/COIN));
659         CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
660         if (!destaddress.IsValid())
661             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
662         SendMoney(destaddress.Get(),10000,false,wtx,opretbuf,opretlen,fee);
663         ret.push_back(Pair("txid",wtx.GetHash().GetHex()));
664     } else ret.push_back(Pair("error",(char *)"null key"));
665     return ret;
666 }
667
668 UniValue paxdeposit(const UniValue& params, bool fHelp)
669 {
670     uint64_t available,deposited,issued,withdrawn,approved,redeemed,seed,komodoshis = 0; int32_t height; char destaddr[64]; uint8_t i,pubkey37[33];
671     bool fSubtractFeeFromAmount = false;
672     if ( KOMODO_PAX == 0 )
673     {
674         throw runtime_error("paxdeposit disabled without -pax");
675     }
676     if ( komodo_is_issuer() != 0 )
677         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "paxdeposit only from KMD");
678     if (!EnsureWalletIsAvailable(fHelp))
679         throw runtime_error("paxdeposit needs wallet"); //return Value::null;
680     if (fHelp || params.size() != 3)
681         throw runtime_error("paxdeposit address fiatoshis base");
682     LOCK2(cs_main, pwalletMain->cs_wallet);
683     CBitcoinAddress address(params[0].get_str());
684     if (!address.IsValid())
685         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
686     int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
687     std::string base = params[2].get_str();
688     std::string dest;
689     height = chainActive.LastTip()->GetHeight();
690     if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,(char *)base.c_str()) != 0 || available < fiatoshis )
691     {
692         fprintf(stderr,"available %llu vs fiatoshis %llu\n",(long long)available,(long long)fiatoshis);
693         throw runtime_error("paxdeposit not enough available inventory");
694     }
695     komodoshis = PAX_fiatdest(&seed,0,destaddr,pubkey37,(char *)params[0].get_str().c_str(),height,(char *)base.c_str(),fiatoshis);
696     dest.append(destaddr);
697     CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
698     if (!destaddress.IsValid())
699         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
700     for (i=0; i<33; i++)
701         fprintf(stderr,"%02x",pubkey37[i]);
702     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);
703     EnsureWalletIsUnlocked();
704     CWalletTx wtx;
705     uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000;
706     if ( fee < 10000 )
707         fee = 10000;
708     iguana_rwnum(1,&pubkey37[33],sizeof(height),&height);
709     opretlen = komodo_opreturnscript(opretbuf,'D',pubkey37,37);
710     SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis);
711     return wtx.GetHash().GetHex();
712 }
713
714 UniValue paxwithdraw(const UniValue& params, bool fHelp)
715 {
716     CWalletTx wtx; std::string dest; int32_t kmdheight; uint64_t seed,komodoshis = 0; char destaddr[64]; uint8_t i,pubkey37[37]; bool fSubtractFeeFromAmount = false;
717     if ( ASSETCHAINS_SYMBOL[0] == 0 )
718         return(0);
719     if (!EnsureWalletIsAvailable(fHelp))
720         return 0;
721     throw runtime_error("paxwithdraw deprecated");
722     if (fHelp || params.size() != 2)
723         throw runtime_error("paxwithdraw address fiatamount");
724     if ( komodo_isrealtime(&kmdheight) == 0 )
725         return(0);
726     LOCK2(cs_main, pwalletMain->cs_wallet);
727     CBitcoinAddress address(params[0].get_str());
728     if (!address.IsValid())
729         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
730     int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
731     komodoshis = PAX_fiatdest(&seed,1,destaddr,pubkey37,(char *)params[0].get_str().c_str(),kmdheight,ASSETCHAINS_SYMBOL,fiatoshis);
732     dest.append(destaddr);
733     CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
734     if (!destaddress.IsValid())
735         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
736     for (i=0; i<33; i++)
737         printf("%02x",pubkey37[i]);
738     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);
739     EnsureWalletIsUnlocked();
740     uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = fiatoshis / 1000;
741     if ( fee < 10000 )
742         fee = 10000;
743     iguana_rwnum(1,&pubkey37[33],sizeof(kmdheight),&kmdheight);
744     opretlen = komodo_opreturnscript(opretbuf,'W',pubkey37,37);
745     SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,fiatoshis);
746     return wtx.GetHash().GetHex();
747 }
748
749 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
750 {
751     if (!EnsureWalletIsAvailable(fHelp))
752         return NullUniValue;
753
754     if (fHelp)
755         throw runtime_error(
756             "listaddressgroupings\n"
757             "\nLists groups of addresses which have had their common ownership\n"
758             "made public by common use as inputs or as the resulting change\n"
759             "in past transactions\n"
760             "\nResult:\n"
761             "[\n"
762             "  [\n"
763             "    [\n"
764             "      \"" + strprintf("%s",komodo_chainname()) + " address\",     (string) The " + strprintf("%s",komodo_chainname()) + " address\n"
765             "      amount,                 (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n"
766             "      \"account\"             (string, optional) The account (DEPRECATED)\n"
767             "    ]\n"
768             "    ,...\n"
769             "  ]\n"
770             "  ,...\n"
771             "]\n"
772             "\nExamples:\n"
773             + HelpExampleCli("listaddressgroupings", "")
774             + HelpExampleRpc("listaddressgroupings", "")
775         );
776
777     LOCK2(cs_main, pwalletMain->cs_wallet);
778
779     UniValue jsonGroupings(UniValue::VARR);
780     std::map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
781     for (const std::set<CTxDestination>& grouping : pwalletMain->GetAddressGroupings()) {
782         UniValue jsonGrouping(UniValue::VARR);
783         for (const CTxDestination& address : grouping)
784         {
785             UniValue addressInfo(UniValue::VARR);
786             addressInfo.push_back(EncodeDestination(address));
787             addressInfo.push_back(ValueFromAmount(balances[address]));
788             {
789                 if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) {
790                     addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second.name);
791                 }
792             }
793             jsonGrouping.push_back(addressInfo);
794         }
795         jsonGroupings.push_back(jsonGrouping);
796     }
797     return jsonGroupings;
798 }
799
800 std::string SignMessageHash(const CIdentity &identity, const uint256 &_msgHash, const std::string &signatureStr, uint32_t blockHeight)
801 {
802     int numSigs = 0;
803
804     CIdentitySignature signature;
805     bool fInvalid = false;
806
807     CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
808
809     ss << verusDataSignaturePrefix;
810     ss << ConnectedChains.ThisChain().GetID();
811     ss << blockHeight;
812     ss << identity.GetID();
813     ss << _msgHash;
814
815     uint256 msgHash = ss.GetHash();
816
817     // get the signature, a hex string, which is deserialized into an instance of the ID signature class
818     std::vector<unsigned char> sigVec;
819     try
820     {
821         sigVec = DecodeBase64(signatureStr.c_str(), &fInvalid);
822         if (fInvalid)
823         {
824             sigVec.clear();
825         }
826
827         if (sigVec.size())
828         {
829             signature = CIdentitySignature(sigVec);
830         }
831     }
832     catch(const std::exception& e)
833     {
834         std::cerr << e.what() << '\n';
835         sigVec.clear();
836         signature = CIdentitySignature();
837     }
838
839     signature.blockHeight = blockHeight;
840
841     std::set<uint160> signatureKeyIDs;
842     std::map<uint160, std::vector<unsigned char>> signatureMap;
843     
844     for (auto &oneSig : signature.signatures)
845     {
846         CPubKey pubkey;
847         if (pubkey.RecoverCompact(msgHash, oneSig))
848         {
849             uint160 pkID = pubkey.GetID();
850             signatureKeyIDs.insert(pkID);
851             signatureMap[pkID] = oneSig;
852         }
853     }
854
855     std::set<CKeyID> keysToTry;
856
857     // remove all valid addresses and count
858     for (auto &oneAddr : identity.primaryAddresses)
859     {
860         if (!(oneAddr.which() == COptCCParams::ADDRTYPE_PK || oneAddr.which() == COptCCParams::ADDRTYPE_PKH))
861         {
862             numSigs = 0;
863             break;
864         }
865         uint160 addrID = GetDestinationID(oneAddr);
866
867         if (signatureKeyIDs.count(addrID))
868         {
869             numSigs++;
870             signatureKeyIDs.erase(addrID);
871             if (!signatureKeyIDs.size())
872             {
873                 break;
874             }
875         }
876         else
877         {
878             keysToTry.insert(addrID);
879         }
880     }
881
882     // if there are obsolete signatures, remove them
883     for (auto &oneSigID : signatureKeyIDs)
884     {
885         signatureMap.erase(oneSigID);
886     }
887
888     int numSigsAdded = 0;
889     for (auto &oneKeyID : keysToTry)
890     {
891         CKey key;
892         if (pwalletMain->GetKey(oneKeyID, key)) {
893             vector<unsigned char> vchSig;
894             if (!key.SignCompact(msgHash, vchSig))
895             {
896                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Signing failed");
897             }
898             signatureMap[oneKeyID] = vchSig;
899             numSigsAdded++;
900             numSigs++;
901         }
902     }
903
904     if (numSigs < identity.minSigs && !numSigsAdded)
905     {
906         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No private key available for additional signing");
907     }
908
909     // reset signatures from union of old and new in map
910     signature.signatures.clear();
911     for (auto &sigpair : signatureMap)
912     {
913         signature.signatures.insert(sigpair.second);
914     }
915
916     vector<unsigned char> vchSig = ::AsVector(signature);
917
918     // all signatures must be from valid keys, and if there are enough, it is valid
919     return EncodeBase64(&vchSig[0], vchSig.size());
920 }
921
922 UniValue signhash(const UniValue& params, bool fHelp)
923 {
924     if (!EnsureWalletIsAvailable(fHelp))
925         return NullUniValue;
926
927     if (fHelp || params.size() < 2 || params.size() > 3)
928         throw runtime_error(
929             "signhash \"address or identity\" \"hexhash\" \"curentsig\"\n"
930             "\nSign a hexadecimal hash value with the private key of a t-addr or the authorities present in this wallet for an identity"
931             + HelpRequiringPassphrase() + "\n"
932             "\nNOTE: This API will only work for signing a data hash, but cannot properly sign the hash of a transaction\n"
933             "\nArguments:\n"
934             "1. \"t-addr or identity\" (string, required) The transparent address or identity to use for signing.\n"
935             "2. \"hexhash\"                   (string, required) The hexadecimal hash to create a signature of.\n"
936             "2. \"cursig\"                    (string) The current signature of the message encoded in base 64 if multisig ID\n"
937             "\nResult:\n"
938             "\"signature\"                    (string) The aggregate signature of the message encoded in base 64 if all or partial signing successful\n"
939             "\nExamples:\n"
940             "\nUnlock the wallet for 30 seconds\n"
941             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
942             "\nCreate the signature\n"
943             + HelpExampleCli("signhash", "\"idname@\" \"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\"") +
944             "\nVerify the signature\n"
945             + HelpExampleCli("verifyhash", "\"idname@\" \"signature\" \"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\"") +
946             "\nAs json rpc\n"
947             + HelpExampleRpc("signhash", "\"idname@\", \"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\"")
948         );
949
950     LOCK2(cs_main, pwalletMain->cs_wallet);
951
952     EnsureWalletIsUnlocked();
953
954     string strAddress  = params[0].get_str();
955     string strHash     = params[1].get_str();
956
957     bool fInvalid = false;
958     uint256 msgHash;
959
960     CTxDestination destination = DecodeDestination(strAddress);
961     if (!IsValidDestination(destination)) {
962         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
963     }
964
965     if (!strHash.size())
966     {
967         throw JSONRPCError(RPC_INVALID_PARAMETER, "No hash to verify");
968     }
969
970     try
971     {
972         msgHash = uint256S(strHash.c_str());
973     }
974     catch(const std::exception& e)
975     {
976         throw JSONRPCError(RPC_INVALID_PARAMETER, "hexhash must be a valid, 32 byte hexadecimal hash value");
977     }
978
979     // we expect the hash passed in to be reversed for compatibility with hashing tools
980     // such as sha256sum
981     std::reverse(msgHash.begin(), msgHash.end());
982
983     CTxDestination dest = DecodeDestination(strAddress);
984     if (!IsValidDestination(dest)) {
985         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address or identity");
986     }
987
988     if (dest.which() == COptCCParams::ADDRTYPE_ID)
989     {
990         std::string strSign = params.size() > 2 ? uni_get_str(params[2]) : "";
991
992         CIdentity identity;
993
994         identity = CIdentity::LookupIdentity(GetDestinationID(dest));
995         if (identity.IsValidUnrevoked())
996         {
997             uint32_t blockHeight = (uint32_t)chainActive.Height();
998
999             UniValue ret(UniValue::VOBJ);
1000             std::string sig = SignMessageHash(identity, msgHash, strSign, blockHeight);
1001             std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility with sha256sum
1002             ret.push_back(Pair("hash", msgHash.GetHex()));
1003             ret.push_back(Pair("signature", sig));
1004             return ret;
1005         }
1006         else if (!identity.IsValid())
1007         {
1008             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid identity");
1009         }
1010         else
1011         {
1012             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Identity is revoked and cannot sign");
1013         }
1014     }
1015     else
1016     {
1017         const CKeyID *keyID = boost::get<CKeyID>(&dest);
1018         if (!keyID) {
1019             throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
1020         }
1021
1022         CKey key;
1023         if (!pwalletMain->GetKey(*keyID, key)) {
1024             throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
1025         }
1026
1027         CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
1028         ss << verusDataSignaturePrefix;
1029         ss << msgHash;
1030
1031         vector<unsigned char> vchSig;
1032
1033         if (!key.SignCompact(ss.GetHash(), vchSig))
1034             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
1035
1036         UniValue ret(UniValue::VOBJ);
1037         std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility reasons
1038         ret.push_back(Pair("hash", msgHash.GetHex()));
1039         ret.push_back(Pair("signature", EncodeBase64(&vchSig[0], vchSig.size())));
1040         return ret;
1041     }
1042 }
1043
1044 UniValue signmessage(const UniValue& params, bool fHelp)
1045 {
1046     if (!EnsureWalletIsAvailable(fHelp))
1047         return NullUniValue;
1048
1049     if (fHelp || params.size() < 2 || params.size() > 3)
1050         throw runtime_error(
1051             "signmessage \"address or identity\" \"message\" \"curentsig\"\n"
1052             "\nSign a message with the private key of a t-addr or the authorities present in this wallet for an identity"
1053             + HelpRequiringPassphrase() + "\n"
1054             "\nArguments:\n"
1055             "1. \"t-addr or identity\" (string, required) The transparent address or identity to use for signing.\n"
1056             "2. \"message\"                   (string, required) The message to create a signature of.\n"
1057             "2. \"cursig\"                    (string) The current signature of the message encoded in base 64 if multisig ID\n"
1058             "\nResult:\n"
1059             "{\n"
1060             "  \"hash\":\"hexhash\"         (string) The hash of the message (SHA256, NOT SHA256D)\n"
1061             "  \"signature\":\"base64sig\"  (string) The aggregate signature of the message encoded in base 64 if all or partial signing successful\n"
1062             "}\n"
1063             "\nExamples:\n"
1064             "\nUnlock the wallet for 30 seconds\n"
1065             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
1066             "\nCreate the signature\n"
1067             + HelpExampleCli("signmessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"my message\"") +
1068             "\nVerify the signature\n"
1069             + HelpExampleCli("verifymessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"signature\" \"my message\"") +
1070             "\nAs json rpc\n"
1071             + HelpExampleRpc("signmessage", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"my message\"")
1072         );
1073
1074     LOCK2(cs_main, pwalletMain->cs_wallet);
1075
1076     EnsureWalletIsUnlocked();
1077
1078     string strAddress = params[0].get_str();
1079     string strMessage = params[1].get_str();
1080
1081     CTxDestination dest = DecodeDestination(strAddress);
1082     if (!IsValidDestination(dest)) {
1083         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address or identity");
1084     }
1085
1086     if (dest.which() == COptCCParams::ADDRTYPE_ID)
1087     {
1088         std::string strSign = params.size() > 2 ? uni_get_str(params[2]) : "";
1089
1090         CIdentity identity;
1091
1092         identity = CIdentity::LookupIdentity(GetDestinationID(dest));
1093         if (identity.IsValidUnrevoked())
1094         {
1095             uint32_t blockHeight = (uint32_t)chainActive.Height();
1096             CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
1097             ss << strMessage;
1098             uint256 msgHash = ss.GetHash();
1099             std::string sig = SignMessageHash(identity, msgHash, strSign, blockHeight);
1100
1101             UniValue ret(UniValue::VOBJ);
1102             std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility with sha256sum
1103             ret.push_back(Pair("hash", msgHash.GetHex()));
1104             ret.push_back(Pair("signature", sig));
1105             return ret;
1106         }
1107         else if (!identity.IsValid())
1108         {
1109             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid identity");
1110         }
1111         else
1112         {
1113             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Identity is revoked and cannot sign");
1114         }
1115     }
1116     else
1117     {
1118         const CKeyID *keyID = boost::get<CKeyID>(&dest);
1119         if (!keyID) {
1120             throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
1121         }
1122
1123         CKey key;
1124         if (!pwalletMain->GetKey(*keyID, key)) {
1125             throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
1126         }
1127
1128         CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
1129         ss << strMessage;
1130         uint256 msgHash = ss.GetHash();
1131
1132         ss.Reset();
1133         ss << verusDataSignaturePrefix;
1134         ss << msgHash;
1135  
1136         vector<unsigned char> vchSig;
1137         if (!key.SignCompact(ss.GetHash(), vchSig))
1138             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
1139
1140         UniValue ret(UniValue::VOBJ);
1141         std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility reasons
1142         ret.push_back(Pair("hash", msgHash.GetHex()));
1143         ret.push_back(Pair("signature", EncodeBase64(&vchSig[0], vchSig.size())));
1144         return ret;
1145     }
1146 }
1147
1148 uint256 HashFile(std::string filepath);
1149
1150 bool printoutAPI = false;
1151 UniValue printapis(const UniValue& params, bool fHelp)
1152 {
1153     if (fHelp || params.size() != 1)
1154         throw runtime_error(
1155             "printapis trueorfalse\n"
1156             "\nPrints the name of all APIs if parameter is true"
1157
1158             "\nResult:\n"
1159             ""
1160             "\nExamples:\n"
1161             + HelpExampleCli("signfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"filepath/filename\"") +
1162             "\nVerify the signature\n"
1163             + HelpExampleCli("verifyfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"signature\" \"filepath/filename\"") +
1164             "\nAs json rpc\n"
1165             + HelpExampleRpc("signfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"filepath/filename\"")
1166         );
1167     printoutAPI = uni_get_bool(params[0]);
1168     return NullUniValue;
1169 }
1170
1171 UniValue signfile(const UniValue& params, bool fHelp)
1172 {
1173     if (!EnsureWalletIsAvailable(fHelp))
1174         return NullUniValue;
1175
1176     if (fHelp || params.size() < 2 || params.size() > 3)
1177         throw runtime_error(
1178             "signfile \"address or identity\" \"filepath/filename\" \"curentsig\"\n"
1179             "\nGenerates a SHA256D hash of the file, returns the hash, and signs the hash with the private key specified"
1180             + HelpRequiringPassphrase() + "\n"
1181             "\nArguments:\n"
1182             "1. \"t-addr or identity\" (string, required) The transparent address or identity to use for signing.\n"
1183             "2. \"filename\"        (string, required) Local file to sign\n"
1184             "2. \"cursig\"          (string) The current signature of the message encoded in base 64 if multisig ID\n"
1185             "\nResult:\n"
1186             "{\n"
1187             "  \"hash\":\"hexhash\"         (string) The hash of the message (SHA256, NOT SHA256D)\n"
1188             "  \"signature\":\"base64sig\"  (string) The aggregate signature of the message encoded in base 64 if all or partial signing successful\n"
1189             "}\n"
1190             "\nExamples:\n"
1191             "\nCreate the signature\n"
1192             + HelpExampleCli("signfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"filepath/filename\"") +
1193             "\nVerify the signature\n"
1194             + HelpExampleCli("verifyfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"signature\" \"filepath/filename\"") +
1195             "\nAs json rpc\n"
1196             + HelpExampleRpc("signfile", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"filepath/filename\"")
1197         );
1198
1199     LOCK2(cs_main, pwalletMain->cs_wallet);
1200
1201     EnsureWalletIsUnlocked();
1202
1203     string strAddress = params[0].get_str();
1204     string strFileName = params[1].get_str();
1205
1206     CTxDestination dest = DecodeDestination(strAddress);
1207     if (!IsValidDestination(dest)) {
1208         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address or identity");
1209     }
1210
1211     if (dest.which() == COptCCParams::ADDRTYPE_ID)
1212     {
1213         string strSign = params.size() > 2 ? uni_get_str(params[2]) : "";
1214
1215         CIdentity identity;
1216
1217         identity = CIdentity::LookupIdentity(GetDestinationID(dest));
1218         if (identity.IsValidUnrevoked())
1219         {
1220             CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
1221             uint256 msgHash = HashFile(strFileName);
1222             if (msgHash.IsNull())
1223             {
1224                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot open file " + strFileName);
1225             }
1226             else
1227             {
1228                 std::string sig = SignMessageHash(identity, msgHash, strSign, (uint32_t)chainActive.Height());
1229
1230                 UniValue ret(UniValue::VOBJ);
1231                 std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility with sha256sum
1232                 ret.push_back(Pair("hash", msgHash.GetHex()));
1233                 ret.push_back(Pair("signature", sig));
1234                 return ret;
1235             }
1236         }
1237         else if (!identity.IsValid())
1238         {
1239             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid identity");
1240         }
1241         else
1242         {
1243             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Identity is revoked and cannot sign");
1244         }
1245     }
1246     else
1247     {
1248         const CKeyID *keyID = boost::get<CKeyID>(&dest);
1249         if (!keyID) {
1250             throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
1251         }
1252
1253         CKey key;
1254         if (!pwalletMain->GetKey(*keyID, key)) {
1255             throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
1256         }
1257
1258         CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
1259         uint256 msgHash = HashFile(strFileName);
1260         if (msgHash.IsNull())
1261         {
1262             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot open file " + strFileName);
1263         }
1264         else
1265         {
1266             ss << verusDataSignaturePrefix;
1267             ss << msgHash;
1268         }
1269
1270         vector<unsigned char> vchSig;
1271         if (!key.SignCompact(ss.GetHash(), vchSig))
1272             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
1273
1274         UniValue ret(UniValue::VOBJ);
1275         std::reverse(msgHash.begin(), msgHash.end());   // return a reversed hash for compatibility with sha256sum
1276         ret.push_back(Pair("hash", msgHash.GetHex()));
1277         ret.push_back(Pair("signature", EncodeBase64(&vchSig[0], vchSig.size())));
1278         return ret;
1279     }
1280 }
1281
1282 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
1283 {
1284     if (!EnsureWalletIsAvailable(fHelp))
1285         return NullUniValue;
1286
1287     if (fHelp || params.size() < 1 || params.size() > 2)
1288         throw runtime_error(
1289             "getreceivedbyaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" ( minconf )\n"
1290             "\nReturns the total amount received by the given " + strprintf("%s",komodo_chainname()) + " address in transactions with at least minconf confirmations.\n"
1291             "\nArguments:\n"
1292             "1. \"" + strprintf("%s",komodo_chainname()) + "_address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address for transactions.\n"
1293             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
1294             "\nResult:\n"
1295             "amount   (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received at this address.\n"
1296             "\nExamples:\n"
1297             "\nThe amount from transactions with at least 1 confirmation\n"
1298             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"") +
1299             "\nThe amount including unconfirmed transactions, zero confirmations\n"
1300             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0") +
1301             "\nThe amount with at least 6 confirmations, very safe\n"
1302             + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 6") +
1303             "\nAs a json rpc call\n"
1304             + HelpExampleRpc("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 6")
1305        );
1306
1307     LOCK2(cs_main, pwalletMain->cs_wallet);
1308
1309     // Bitcoin address
1310     CTxDestination dest = DecodeDestination(params[0].get_str());
1311     if (!IsValidDestination(dest)) {
1312         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Verus address");
1313     }
1314     CScript scriptPubKey = GetScriptForDestination(dest);
1315     if (!IsMine(*pwalletMain, scriptPubKey)) {
1316         return ValueFromAmount(0);
1317     }
1318
1319     // Minimum confirmations
1320     int nMinDepth = 1;
1321     if (params.size() > 1)
1322         nMinDepth = params[1].get_int();
1323
1324     // Tally
1325     CAmount nAmount = 0;
1326     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1327     {
1328         const CWalletTx& wtx = (*it).second;
1329         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1330             continue;
1331
1332         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1333             if (txout.scriptPubKey == scriptPubKey)
1334                 if (wtx.GetDepthInMainChain() >= nMinDepth)
1335                     nAmount += txout.nValue; // komodo_interest?
1336     }
1337
1338     return  ValueFromAmount(nAmount);
1339 }
1340
1341
1342 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
1343 {
1344     if (!EnsureWalletIsAvailable(fHelp))
1345         return NullUniValue;
1346
1347     if (fHelp || params.size() < 1 || params.size() > 2)
1348         throw runtime_error(
1349             "getreceivedbyaccount \"account\" ( minconf )\n"
1350             "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
1351             "\nArguments:\n"
1352             "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"
1353             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
1354             "\nResult:\n"
1355             "amount              (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n"
1356             "\nExamples:\n"
1357             "\nAmount received by the default account with at least 1 confirmation\n"
1358             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
1359             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
1360             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
1361             "\nThe amount with at least 6 confirmation, very safe\n"
1362             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
1363             "\nAs a json rpc call\n"
1364             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
1365         );
1366
1367     LOCK2(cs_main, pwalletMain->cs_wallet);
1368
1369     // Minimum confirmations
1370     int nMinDepth = 1;
1371     if (params.size() > 1)
1372         nMinDepth = params[1].get_int();
1373
1374     // Get the set of pub keys assigned to account
1375     string strAccount = AccountFromValue(params[0]);
1376     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
1377
1378     // Tally
1379     CAmount nAmount = 0;
1380     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1381     {
1382         const CWalletTx& wtx = (*it).second;
1383         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1384             continue;
1385
1386         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1387         {
1388             CTxDestination address;
1389             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
1390                 if (wtx.GetDepthInMainChain() >= nMinDepth)
1391                     nAmount += txout.nValue; // komodo_interest?
1392         }
1393     }
1394
1395     return ValueFromAmount(nAmount);
1396 }
1397
1398
1399 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
1400 {
1401     CAmount nBalance = 0;
1402
1403     // Tally wallet transactions
1404     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1405     {
1406         const CWalletTx& wtx = (*it).second;
1407         if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
1408             continue;
1409
1410         CAmount nReceived, nSent, nFee;
1411         wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
1412
1413         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1414             nBalance += nReceived;
1415         nBalance -= nSent + nFee;
1416     }
1417
1418     // Tally internal accounting entries
1419     nBalance += walletdb.GetAccountCreditDebit(strAccount);
1420
1421     return nBalance;
1422 }
1423
1424 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
1425 {
1426     CWalletDB walletdb(pwalletMain->strWalletFile);
1427     return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
1428 }
1429
1430
1431 UniValue getbalance(const UniValue& params, bool fHelp)
1432 {
1433     if (!EnsureWalletIsAvailable(fHelp))
1434         return NullUniValue;
1435
1436     if (fHelp || params.size() > 3)
1437         throw runtime_error(
1438             "getbalance ( \"account\" minconf includeWatchonly )\n"
1439             "\nReturns the server's total available balance.\n"
1440             "\nArguments:\n"
1441             "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"
1442             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
1443             "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
1444             "\nResult:\n"
1445             "amount              (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n"
1446             "\nExamples:\n"
1447             "\nThe total amount in the wallet\n"
1448             + HelpExampleCli("getbalance", "") +
1449             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
1450             + HelpExampleCli("getbalance", "\"*\" 6") +
1451             "\nAs a json rpc call\n"
1452             + HelpExampleRpc("getbalance", "\"*\", 6")
1453         );
1454
1455     LOCK2(cs_main, pwalletMain->cs_wallet);
1456
1457     if (params.size() == 0)
1458         return  ValueFromAmount(pwalletMain->GetBalance());
1459
1460     int nMinDepth = 1;
1461     if (params.size() > 1)
1462         nMinDepth = params[1].get_int();
1463     isminefilter filter = ISMINE_SPENDABLE;
1464     if(params.size() > 2)
1465         if(params[2].get_bool())
1466             filter = filter | ISMINE_WATCH_ONLY;
1467
1468     if (params[0].get_str() == "*") {
1469         // Calculate total balance a different way from GetBalance()
1470         // (GetBalance() sums up all unspent TxOuts)
1471         // getbalance and "getbalance * 1 true" should return the same number
1472         CAmount nBalance = 0;
1473         //CAmount altBalance = 0;
1474         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1475         {
1476             const CWalletTx& wtx = (*it).second;
1477             if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
1478                 continue;
1479
1480             CAmount allFee;
1481             string strSentAccount;
1482             list<COutputEntry> listReceived;
1483             list<COutputEntry> listSent;
1484             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
1485             if (wtx.GetDepthInMainChain() >= nMinDepth)
1486             {
1487                 //altBalance += wtx.GetAvailableCredit();
1488                 BOOST_FOREACH(const COutputEntry& r, listReceived)
1489                     nBalance += r.amount;
1490             }
1491             BOOST_FOREACH(const COutputEntry& s, listSent)
1492                 nBalance -= s.amount;
1493             nBalance -= allFee;
1494         }
1495         //printf("alternate wallet balance: %s\n", ValueFromAmount(nBalance).write().c_str());
1496         return ValueFromAmount(nBalance);
1497     }
1498
1499     string strAccount = AccountFromValue(params[0]);
1500
1501     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
1502
1503     return ValueFromAmount(nBalance);
1504 }
1505
1506 UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
1507 {
1508     if (!EnsureWalletIsAvailable(fHelp))
1509         return NullUniValue;
1510
1511     if (fHelp || params.size() > 0)
1512         throw runtime_error(
1513                 "getunconfirmedbalance\n"
1514                 "Returns the server's total unconfirmed balance\n");
1515
1516     LOCK2(cs_main, pwalletMain->cs_wallet);
1517
1518     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
1519 }
1520
1521
1522 UniValue movecmd(const UniValue& params, bool fHelp)
1523 {
1524     if (!EnsureWalletIsAvailable(fHelp))
1525         return NullUniValue;
1526
1527     if (fHelp || params.size() < 3 || params.size() > 5)
1528         throw runtime_error(
1529             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
1530             "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
1531             "\nArguments:\n"
1532             "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"
1533             "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"
1534             "3. amount            (numeric) Quantity of " + strprintf("%s",komodo_chainname()) + " to move between accounts.\n"
1535             "4. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
1536             "5. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
1537             "\nResult:\n"
1538             "true|false           (boolean) true if successful.\n"
1539             "\nExamples:\n"
1540             "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the account named tabby\n"
1541             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
1542             "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " timotei to akiko with a comment and funds have 6 confirmations\n"
1543             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
1544             "\nAs a json rpc call\n"
1545             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
1546         );
1547     if ( ASSETCHAINS_PRIVATE != 0 )
1548         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1549
1550     LOCK2(cs_main, pwalletMain->cs_wallet);
1551
1552     string strFrom = AccountFromValue(params[0]);
1553     string strTo = AccountFromValue(params[1]);
1554     CAmount nAmount = AmountFromValue(params[2]);
1555     if (nAmount <= 0)
1556         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1557     if (params.size() > 3)
1558         // unused parameter, used to be nMinDepth, keep type-checking it though
1559         (void)params[3].get_int();
1560     string strComment;
1561     if (params.size() > 4)
1562         strComment = params[4].get_str();
1563
1564     CWalletDB walletdb(pwalletMain->strWalletFile);
1565     if (!walletdb.TxnBegin())
1566         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
1567
1568     int64_t nNow = GetAdjustedTime();
1569
1570     // Debit
1571     CAccountingEntry debit;
1572     debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
1573     debit.strAccount = strFrom;
1574     debit.nCreditDebit = -nAmount;
1575     debit.nTime = nNow;
1576     debit.strOtherAccount = strTo;
1577     debit.strComment = strComment;
1578     walletdb.WriteAccountingEntry(debit);
1579
1580     // Credit
1581     CAccountingEntry credit;
1582     credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
1583     credit.strAccount = strTo;
1584     credit.nCreditDebit = nAmount;
1585     credit.nTime = nNow;
1586     credit.strOtherAccount = strFrom;
1587     credit.strComment = strComment;
1588     walletdb.WriteAccountingEntry(credit);
1589
1590     if (!walletdb.TxnCommit())
1591         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
1592
1593     return true;
1594 }
1595
1596
1597 UniValue sendfrom(const UniValue& params, bool fHelp)
1598 {
1599     if (!EnsureWalletIsAvailable(fHelp))
1600         return NullUniValue;
1601
1602     if (fHelp || params.size() < 3 || params.size() > 6)
1603         throw runtime_error(
1604             "sendfrom \"fromaccount\" \"to" + strprintf("%s",komodo_chainname()) + "address\" amount ( minconf \"comment\" \"comment-to\" )\n"
1605             "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a " + strprintf("%s",komodo_chainname()) + " address.\n"
1606             "The amount is a real and is rounded to the nearest 0.00000001."
1607             + HelpRequiringPassphrase() + "\n"
1608             "\nArguments:\n"
1609             "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"
1610             "2. \"to" + strprintf("%s",komodo_chainname()) + "address\"  (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send funds to.\n"
1611             "3. amount                (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " (transaction fee is added on top).\n"
1612             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
1613             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
1614             "                                     This is not part of the transaction, just kept in your wallet.\n"
1615             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
1616             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
1617             "                                     it is just kept in your wallet.\n"
1618             "\nResult:\n"
1619             "\"transactionid\"        (string) The transaction id.\n"
1620             "\nExamples:\n"
1621             "\nSend 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the address, must have at least 1 confirmation\n"
1622             + HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") +
1623             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
1624             + HelpExampleCli("sendfrom", "\"tabby\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01 6 \"donation\" \"seans outpost\"") +
1625             "\nAs a json rpc call\n"
1626             + HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"seans outpost\"")
1627         );
1628     if ( ASSETCHAINS_PRIVATE != 0 )
1629         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1630
1631     LOCK2(cs_main, pwalletMain->cs_wallet);
1632
1633     std::string strAccount = AccountFromValue(params[0]);
1634     CTxDestination dest = DecodeDestination(params[1].get_str());
1635     if (!IsValidDestination(dest)) {
1636         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Verus address");
1637     }
1638     CAmount nAmount = AmountFromValue(params[2]);
1639     if (nAmount <= 0)
1640         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1641     int nMinDepth = 1;
1642     if (params.size() > 3)
1643         nMinDepth = params[3].get_int();
1644
1645     CWalletTx wtx;
1646     wtx.strFromAccount = strAccount;
1647     if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
1648         wtx.mapValue["comment"] = params[4].get_str();
1649     if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
1650         wtx.mapValue["to"]      = params[5].get_str();
1651
1652     EnsureWalletIsUnlocked();
1653
1654     // Check funds
1655     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1656     if (nAmount > nBalance)
1657         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1658
1659     SendMoney(dest, nAmount, false, wtx, 0, 0, 0);
1660
1661     return wtx.GetHash().GetHex();
1662 }
1663
1664
1665 UniValue sendmany(const UniValue& params, bool fHelp)
1666 {
1667     if (!EnsureWalletIsAvailable(fHelp))
1668         return NullUniValue;
1669
1670     if (fHelp || params.size() < 2 || params.size() > 5)
1671         throw runtime_error(
1672             "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
1673             "\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
1674             + HelpRequiringPassphrase() + "\n"
1675             "\nArguments:\n"
1676             "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"
1677             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
1678             "    {\n"
1679             "      \"address\":amount   (numeric) The " + strprintf("%s",komodo_chainname()) + " address is the key, the numeric amount in " + strprintf("%s",komodo_chainname()) + " is the value\n"
1680             "      ,...\n"
1681             "    }\n"
1682             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
1683             "4. \"comment\"             (string, optional) A comment\n"
1684             "5. subtractfeefromamount   (string, optional) A json array with addresses.\n"
1685             "                           The fee will be equally deducted from the amount of each selected address.\n"
1686             "                           Those recipients will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in their corresponding amount field.\n"
1687             "                           If no addresses are specified here, the sender pays the fee.\n"
1688             "    [\n"
1689             "      \"address\"            (string) Subtract fee from this address\n"
1690             "      ,...\n"
1691             "    ]\n"
1692             "\nResult:\n"
1693             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
1694             "                                    the number of addresses.\n"
1695             "\nExamples:\n"
1696             "\nSend two amounts to two different addresses:\n"
1697             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\"") +
1698             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
1699             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\" 6 \"testing\"") +
1700             "\nSend two amounts to two different addresses, subtract fee from amount:\n"
1701             + HelpExampleCli("sendmany", "\"\" \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\" 1 \"\" \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"") +
1702             "\nAs a json rpc call\n"
1703             + HelpExampleRpc("sendmany", "\"\", \"{\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.01,\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\":0.02}\", 6, \"testing\"")
1704         );
1705     if ( ASSETCHAINS_PRIVATE != 0 )
1706         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
1707
1708     LOCK2(cs_main, pwalletMain->cs_wallet);
1709
1710     string strAccount = AccountFromValue(params[0]);
1711     UniValue sendTo = params[1].get_obj();
1712     int nMinDepth = 1;
1713     if (params.size() > 2)
1714         nMinDepth = params[2].get_int();
1715
1716     CWalletTx wtx;
1717     wtx.strFromAccount = strAccount;
1718     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
1719         wtx.mapValue["comment"] = params[3].get_str();
1720
1721     UniValue subtractFeeFromAmount(UniValue::VARR);
1722     if (params.size() > 4)
1723         subtractFeeFromAmount = params[4].get_array();
1724
1725     std::set<CTxDestination> destinations;
1726     std::vector<CRecipient> vecSend;
1727
1728     CAmount totalAmount = 0;
1729     std::vector<std::string> keys = sendTo.getKeys();
1730     for (const std::string& name_ : keys) {
1731         CTxDestination dest = DecodeDestination(name_);
1732         if (!IsValidDestination(dest)) {
1733             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Verus address: ") + name_);
1734         }
1735
1736         if (destinations.count(dest)) {
1737             throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
1738         }
1739         destinations.insert(dest);
1740
1741         CScript scriptPubKey = GetScriptForDestination(dest);
1742         CAmount nAmount = AmountFromValue(sendTo[name_]);
1743         if (nAmount <= 0)
1744             throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1745         totalAmount += nAmount;
1746
1747         bool fSubtractFeeFromAmount = false;
1748         for (size_t idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1749             const UniValue& addr = subtractFeeFromAmount[idx];
1750             if (addr.get_str() == name_)
1751                 fSubtractFeeFromAmount = true;
1752         }
1753
1754         CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1755         vecSend.push_back(recipient);
1756     }
1757
1758     EnsureWalletIsUnlocked();
1759
1760     // Check funds
1761     CAmount nBalance = pwalletMain->GetBalance();
1762     //CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1763     if (totalAmount > nBalance)
1764         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1765
1766     // Send
1767     CReserveKey keyChange(pwalletMain);
1768     CAmount nFeeRequired = 0;
1769     int nChangePosRet = -1;
1770     string strFailReason;
1771     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1772     if (!fCreated)
1773         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1774     if (!pwalletMain->CommitTransaction(wtx, keyChange))
1775         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
1776
1777     return wtx.GetHash().GetHex();
1778 }
1779
1780 // Defined in rpc/misc.cpp
1781 extern CScript _createmultisig_redeemScript(const UniValue& params);
1782
1783 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
1784 {
1785     if (!EnsureWalletIsAvailable(fHelp))
1786         return NullUniValue;
1787
1788     if (fHelp || params.size() < 2 || params.size() > 3)
1789     {
1790         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1791             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1792             "Each key is a " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key.\n"
1793             "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1794
1795             "\nArguments:\n"
1796             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1797             "2. \"keysobject\"   (string, required) A json array of " + strprintf("%s",komodo_chainname()) + " addresses or hex-encoded public keys\n"
1798             "     [\n"
1799             "       \"address\"  (string) " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key\n"
1800             "       ...,\n"
1801             "     ]\n"
1802             "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"
1803
1804             "\nResult:\n"
1805             "\"" + strprintf("%s",komodo_chainname()) + "_address\"  (string) A " + strprintf("%s",komodo_chainname()) + " address associated with the keys.\n"
1806
1807             "\nExamples:\n"
1808             "\nAdd a multisig address from 2 addresses\n"
1809             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"") +
1810             "\nAs json rpc call\n"
1811             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
1812         ;
1813         throw runtime_error(msg);
1814     }
1815
1816     LOCK2(cs_main, pwalletMain->cs_wallet);
1817
1818     string strAccount;
1819     if (params.size() > 2)
1820         strAccount = AccountFromValue(params[2]);
1821
1822     // Construct using pay-to-script-hash:
1823     CScript inner = _createmultisig_redeemScript(params);
1824     CScriptID innerID(inner);
1825     pwalletMain->AddCScript(inner);
1826
1827     pwalletMain->SetAddressBook(innerID, strAccount, "send");
1828     return EncodeDestination(innerID);
1829 }
1830
1831
1832 struct tallyitem
1833 {
1834     CAmount nAmount;
1835     int nConf;
1836     vector<uint256> txids;
1837     bool fIsWatchonly;
1838     tallyitem()
1839     {
1840         nAmount = 0;
1841         nConf = std::numeric_limits<int>::max();
1842         fIsWatchonly = false;
1843     }
1844 };
1845
1846 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1847 {
1848     // Minimum confirmations
1849     int nMinDepth = 1;
1850     if (params.size() > 0)
1851         nMinDepth = params[0].get_int();
1852
1853     // Whether to include empty accounts
1854     bool fIncludeEmpty = false;
1855     if (params.size() > 1)
1856         fIncludeEmpty = params[1].get_bool();
1857
1858     isminefilter filter = ISMINE_SPENDABLE;
1859     if(params.size() > 2)
1860         if(params[2].get_bool())
1861             filter = filter | ISMINE_WATCH_ONLY;
1862
1863     // Tally
1864     std::map<CTxDestination, tallyitem> mapTally;
1865     for (const std::pair<uint256, CWalletTx>& pairWtx : pwalletMain->mapWallet) {
1866         const CWalletTx& wtx = pairWtx.second;
1867
1868         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1869             continue;
1870
1871         int nDepth = wtx.GetDepthInMainChain();
1872         if (nDepth < nMinDepth)
1873             continue;
1874
1875         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1876         {
1877             CTxDestination address;
1878             if (!ExtractDestination(txout.scriptPubKey, address))
1879                 continue;
1880
1881             isminefilter mine = IsMine(*pwalletMain, address);
1882             if(!(mine & filter))
1883                 continue;
1884
1885             tallyitem& item = mapTally[address];
1886             item.nAmount += txout.nValue; // komodo_interest?
1887             item.nConf = min(item.nConf, nDepth);
1888             item.txids.push_back(wtx.GetHash());
1889             if (mine & ISMINE_WATCH_ONLY)
1890                 item.fIsWatchonly = true;
1891         }
1892     }
1893
1894     // Reply
1895     UniValue ret(UniValue::VARR);
1896     std::map<std::string, tallyitem> mapAccountTally;
1897     for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
1898         const CTxDestination& dest = item.first;
1899         const std::string& strAccount = item.second.name;
1900         std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
1901         if (it == mapTally.end() && !fIncludeEmpty)
1902             continue;
1903
1904         CAmount nAmount = 0;
1905         int nConf = std::numeric_limits<int>::max();
1906         bool fIsWatchonly = false;
1907         if (it != mapTally.end())
1908         {
1909             nAmount = (*it).second.nAmount;
1910             nConf = (*it).second.nConf;
1911             fIsWatchonly = (*it).second.fIsWatchonly;
1912         }
1913
1914         if (fByAccounts)
1915         {
1916             tallyitem& item = mapAccountTally[strAccount];
1917             item.nAmount += nAmount;
1918             item.nConf = min(item.nConf, nConf);
1919             item.fIsWatchonly = fIsWatchonly;
1920         }
1921         else
1922         {
1923             UniValue obj(UniValue::VOBJ);
1924             if(fIsWatchonly)
1925                 obj.push_back(Pair("involvesWatchonly", true));
1926             obj.push_back(Pair("address",       EncodeDestination(dest)));
1927             obj.push_back(Pair("account",       strAccount));
1928             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1929             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1930             UniValue transactions(UniValue::VARR);
1931             if (it != mapTally.end())
1932             {
1933                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1934                 {
1935                     transactions.push_back(item.GetHex());
1936                 }
1937             }
1938             obj.push_back(Pair("txids", transactions));
1939             ret.push_back(obj);
1940         }
1941     }
1942
1943     if (fByAccounts)
1944     {
1945         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1946         {
1947             CAmount nAmount = (*it).second.nAmount;
1948             int nConf = (*it).second.nConf;
1949             UniValue obj(UniValue::VOBJ);
1950             if((*it).second.fIsWatchonly)
1951                 obj.push_back(Pair("involvesWatchonly", true));
1952             obj.push_back(Pair("account",       (*it).first));
1953             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1954             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1955             ret.push_back(obj);
1956         }
1957     }
1958
1959     return ret;
1960 }
1961
1962 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1963 {
1964     if (!EnsureWalletIsAvailable(fHelp))
1965         return NullUniValue;
1966
1967     if (fHelp || params.size() > 3)
1968         throw runtime_error(
1969             "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1970             "\nList balances by receiving address.\n"
1971             "\nArguments:\n"
1972             "1. minconf       (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1973             "2. includeempty  (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1974             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1975
1976             "\nResult:\n"
1977             "[\n"
1978             "  {\n"
1979             "    \"involvesWatchonly\" : true,        (bool) Only returned if imported addresses were involved in transaction\n"
1980             "    \"address\" : \"receivingaddress\",  (string) The receiving address\n"
1981             "    \"account\" : \"accountname\",       (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1982             "    \"amount\" : x.xxx,                  (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received by the address\n"
1983             "    \"confirmations\" : n                (numeric) The number of confirmations of the most recent transaction included\n"
1984             "  }\n"
1985             "  ,...\n"
1986             "]\n"
1987
1988             "\nExamples:\n"
1989             + HelpExampleCli("listreceivedbyaddress", "")
1990             + HelpExampleCli("listreceivedbyaddress", "6 true")
1991             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1992         );
1993
1994     LOCK2(cs_main, pwalletMain->cs_wallet);
1995
1996     return ListReceived(params, false);
1997 }
1998
1999 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
2000 {
2001     if (!EnsureWalletIsAvailable(fHelp))
2002         return NullUniValue;
2003
2004     if (fHelp || params.size() > 3)
2005         throw runtime_error(
2006             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
2007             "\nDEPRECATED. List balances by account.\n"
2008             "\nArguments:\n"
2009             "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
2010             "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
2011             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
2012
2013             "\nResult:\n"
2014             "[\n"
2015             "  {\n"
2016             "    \"involvesWatchonly\" : true,   (bool) Only returned if imported addresses were involved in transaction\n"
2017             "    \"account\" : \"accountname\",  (string) The account name of the receiving account\n"
2018             "    \"amount\" : x.xxx,             (numeric) The total amount received by addresses with this account\n"
2019             "    \"confirmations\" : n           (numeric) The number of confirmations of the most recent transaction included\n"
2020             "  }\n"
2021             "  ,...\n"
2022             "]\n"
2023
2024             "\nExamples:\n"
2025             + HelpExampleCli("listreceivedbyaccount", "")
2026             + HelpExampleCli("listreceivedbyaccount", "6 true")
2027             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
2028         );
2029
2030     LOCK2(cs_main, pwalletMain->cs_wallet);
2031
2032     return ListReceived(params, true);
2033 }
2034
2035 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
2036 {
2037     if (IsValidDestination(dest)) {
2038         entry.push_back(Pair("address", EncodeDestination(dest)));
2039     }
2040 }
2041
2042 bool ValidateStakeTransaction(const CTransaction &stakeTx, CStakeParams &stakeParams, bool validateSig = true);
2043
2044 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
2045 {
2046     CAmount nFee;
2047     string strSentAccount;
2048     list<COutputEntry> listReceived;
2049     list<COutputEntry> listSent;
2050
2051     CStakeParams p;
2052     bool bIsStake = false;
2053     bool bIsCoinbase = false;
2054     bool bIsMint = false;
2055     bool bIsReserve = ConnectedChains.ThisChain().IsReserve();
2056     CReserveTransactionDescriptor rtxd;
2057     CCoinsViewCache view(pcoinsTip);
2058     uint32_t nHeight = chainActive.Height();
2059
2060     if (ValidateStakeTransaction(wtx, p, false))
2061     {
2062         bIsStake = true;
2063     }
2064     else
2065     {
2066         bIsCoinbase = wtx.IsCoinBase();
2067         bIsMint = bIsCoinbase && wtx.vout.size() > 0 && wtx.vout[0].scriptPubKey.IsPayToCryptoCondition();
2068     }
2069
2070     if (bIsReserve && (rtxd = CReserveTransactionDescriptor(wtx, view, nHeight)).IsReserve())
2071     {
2072         ret.push_back(Pair("isreserve", true));
2073         bool isReserveExchange = rtxd.IsReserveExchange();
2074         ret.push_back(Pair("isreserveexchange", isReserveExchange));
2075         if (isReserveExchange)
2076         {
2077             if (rtxd.IsMarket())
2078             {
2079                 ret.push_back(Pair("exchangetype", "market"));
2080             }
2081             else if (rtxd.IsLimit())
2082             {
2083                 ret.push_back(Pair("exchangetype", "limit"));
2084             }
2085         }
2086         ret.push_back(Pair("nativefees", rtxd.NativeFees()));
2087         ret.push_back(Pair("reservefees", rtxd.ReserveFees().ToUniValue()));
2088         if (rtxd.nativeConversionFees || (rtxd.ReserveConversionFeesMap() > CCurrencyValueMap()))
2089         {
2090             ret.push_back(Pair("nativeconversionfees", rtxd.nativeConversionFees));
2091             ret.push_back(Pair("reserveconversionfees", rtxd.ReserveConversionFeesMap().ToUniValue()));
2092         }
2093     }
2094     else
2095     {
2096         ret.push_back(Pair("isreserve", false));
2097     }
2098
2099     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, bIsStake ? ISMINE_ALLANDCHANGE : filter);
2100
2101     bool fAllAccounts = (strAccount == string("*"));
2102     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
2103
2104     // Sent
2105     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
2106     {
2107         BOOST_FOREACH(const COutputEntry& s, listSent)
2108         {
2109             UniValue entry(UniValue::VOBJ);
2110             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
2111                 entry.push_back(Pair("involvesWatchonly", true));
2112             entry.push_back(Pair("account", strSentAccount));
2113             MaybePushAddress(entry, s.destination);
2114             entry.push_back(Pair("category", bIsStake ? "stake" : "send"));
2115             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
2116             entry.push_back(Pair("vout", s.vout));
2117             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
2118             if (fLong)
2119                 WalletTxToJSON(wtx, entry);
2120             entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
2121             ret.push_back(entry);
2122         }
2123     }
2124
2125     // Received
2126     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
2127     {
2128         BOOST_FOREACH(const COutputEntry& r, listReceived)
2129         {
2130             string account;
2131             if (pwalletMain->mapAddressBook.count(r.destination))
2132                 account = pwalletMain->mapAddressBook[r.destination].name;
2133             if (fAllAccounts || (account == strAccount))
2134             {
2135                 UniValue entry(UniValue::VOBJ);
2136                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
2137                     entry.push_back(Pair("involvesWatchonly", true));
2138                 entry.push_back(Pair("account", account));
2139                 
2140                 CTxDestination dest;
2141                 if (CScriptExt::ExtractVoutDestination(wtx, r.vout, dest))
2142                     MaybePushAddress(entry, dest);
2143                 else
2144                     MaybePushAddress(entry, r.destination);
2145
2146                 if (bIsCoinbase)
2147                 {
2148                     int btm;
2149                     if (wtx.GetDepthInMainChain() < 1)
2150                         entry.push_back(Pair("category", "orphan"));
2151                     else if ((btm = wtx.GetBlocksToMaturity()) > 0)
2152                     {
2153                         entry.push_back(Pair("category", "immature"));
2154                         entry.push_back(Pair("blockstomaturity", btm));
2155                     }
2156                     else
2157                         entry.push_back(Pair("category", bIsMint ? "mint" : "generate"));
2158                 }
2159                 else
2160                 {
2161                     entry.push_back(Pair("category", bIsStake ? "stake" : "receive"));
2162                 }
2163                 
2164                 COptCCParams p;
2165                 if (rtxd.IsValid() && wtx.vout[r.vout].scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
2166                 {
2167                     UniValue ccUni;
2168                     ScriptPubKeyToJSON(wtx.vout[r.vout].scriptPubKey, ccUni, false, false);
2169                     entry.push_back(Pair("cryptocondition", ccUni));
2170                 }
2171
2172                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
2173                 if (rtxd.IsReserve())
2174                 {
2175                     entry.push_back(Pair("reserveamount", wtx.vout[r.vout].scriptPubKey.ReserveOutValue().ToUniValue()));
2176                 }
2177                 entry.push_back(Pair("vout", r.vout));
2178                 if (fLong)
2179                     WalletTxToJSON(wtx, entry);
2180                 entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
2181                 ret.push_back(entry);
2182             }
2183         }
2184     }
2185 }
2186
2187 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
2188 {
2189     bool fAllAccounts = (strAccount == string("*"));
2190
2191     if (fAllAccounts || acentry.strAccount == strAccount)
2192     {
2193         UniValue entry(UniValue::VOBJ);
2194         entry.push_back(Pair("account", acentry.strAccount));
2195         entry.push_back(Pair("category", "move"));
2196         entry.push_back(Pair("time", acentry.nTime));
2197         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
2198         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
2199         entry.push_back(Pair("comment", acentry.strComment));
2200         ret.push_back(entry);
2201     }
2202 }
2203
2204 UniValue listtransactions(const UniValue& params, bool fHelp)
2205 {
2206     if (!EnsureWalletIsAvailable(fHelp))
2207         return NullUniValue;
2208
2209     if (fHelp || params.size() > 4)
2210         throw runtime_error(
2211             "listtransactions ( \"account\" count from includeWatchonly)\n"
2212             "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
2213             "\nArguments:\n"
2214             "1. \"account\"    (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
2215             "2. count          (numeric, optional, default=10) The number of transactions to return\n"
2216             "3. from           (numeric, optional, default=0) The number of transactions to skip\n"
2217             "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
2218             "\nResult:\n"
2219             "[\n"
2220             "  {\n"
2221             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. \n"
2222             "                                                It will be \"\" for the default account.\n"
2223             "    \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\",    (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for \n"
2224             "                                                move transactions (category = move).\n"
2225             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
2226             "                                                transaction between accounts, and not associated with an address,\n"
2227             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
2228             "                                                associated with an address, transaction id and block details\n"
2229             "    \"amount\": x.xxx,          (numeric) The amount in " + strprintf("%s",komodo_chainname()) + ". This is negative for the 'send' category, and for the\n"
2230             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
2231             "                                         and for the 'move' category for inbound funds.\n"
2232             "    \"vout\" : n,               (numeric) the vout value\n"
2233             "    \"fee\": x.xxx,             (numeric) The amount of the fee in " + strprintf("%s",komodo_chainname()) + ". This is negative and only available for the \n"
2234             "                                         'send' category of transactions.\n"
2235             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
2236             "                                         'receive' category of transactions.\n"
2237             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
2238             "                                          category of transactions.\n"
2239             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
2240             "                                          category of transactions.\n"
2241             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
2242             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
2243             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
2244             "                                          for 'send' and 'receive' category of transactions.\n"
2245             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
2246             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
2247             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
2248             "                                          negative amounts).\n"
2249             "    \"size\": n,                (numeric) Transaction size in bytes\n"
2250             "  }\n"
2251             "]\n"
2252
2253             "\nExamples:\n"
2254             "\nList the most recent 10 transactions in the systems\n"
2255             + HelpExampleCli("listtransactions", "") +
2256             "\nList transactions 100 to 120\n"
2257             + HelpExampleCli("listtransactions", "\"*\" 20 100") +
2258             "\nAs a json rpc call\n"
2259             + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
2260         );
2261
2262     LOCK2(cs_main, pwalletMain->cs_wallet);
2263
2264     string strAccount = "*";
2265     if (params.size() > 0)
2266         strAccount = params[0].get_str();
2267     int nCount = 10;
2268     if (params.size() > 1)
2269         nCount = params[1].get_int();
2270     int nFrom = 0;
2271     if (params.size() > 2)
2272         nFrom = params[2].get_int();
2273     isminefilter filter = ISMINE_SPENDABLE;
2274     if(params.size() > 3)
2275         if(params[3].get_bool())
2276             filter = filter | ISMINE_WATCH_ONLY;
2277
2278     if (nCount < 0)
2279         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
2280     if (nFrom < 0)
2281         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
2282
2283     UniValue ret(UniValue::VARR);
2284
2285     std::list<CAccountingEntry> acentries;
2286     CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
2287
2288     // iterate backwards until we have nCount items to return:
2289     for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
2290     {
2291         CWalletTx *const pwtx = (*it).second.first;
2292         if (pwtx != 0)
2293             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
2294         CAccountingEntry *const pacentry = (*it).second.second;
2295         if (pacentry != 0)
2296             AcentryToJSON(*pacentry, strAccount, ret);
2297
2298         if ((int)ret.size() >= (nCount+nFrom)) break;
2299     }
2300     // ret is newest to oldest
2301
2302     if (nFrom > (int)ret.size())
2303         nFrom = ret.size();
2304     if ((nFrom + nCount) > (int)ret.size())
2305         nCount = ret.size() - nFrom;
2306
2307     vector<UniValue> arrTmp = ret.getValues();
2308
2309     vector<UniValue>::iterator first = arrTmp.begin();
2310     std::advance(first, nFrom);
2311     vector<UniValue>::iterator last = arrTmp.begin();
2312     std::advance(last, nFrom+nCount);
2313
2314     if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
2315     if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
2316
2317     std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
2318
2319     ret.clear();
2320     ret.setArray();
2321     ret.push_backV(arrTmp);
2322
2323     return ret;
2324 }
2325
2326 UniValue listaccounts(const UniValue& params, bool fHelp)
2327 {
2328     if (!EnsureWalletIsAvailable(fHelp))
2329         return NullUniValue;
2330
2331     if (fHelp || params.size() > 2)
2332         throw runtime_error(
2333             "listaccounts ( minconf includeWatchonly)\n"
2334             "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
2335             "\nArguments:\n"
2336             "1. minconf          (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
2337             "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
2338             "\nResult:\n"
2339             "{                      (json object where keys are account names, and values are numeric balances\n"
2340             "  \"account\": x.xxx,  (numeric) The property name is the account name, and the value is the total balance for the account.\n"
2341             "  ...\n"
2342             "}\n"
2343             "\nExamples:\n"
2344             "\nList account balances where there at least 1 confirmation\n"
2345             + HelpExampleCli("listaccounts", "") +
2346             "\nList account balances including zero confirmation transactions\n"
2347             + HelpExampleCli("listaccounts", "0") +
2348             "\nList account balances for 6 or more confirmations\n"
2349             + HelpExampleCli("listaccounts", "6") +
2350             "\nAs json rpc call\n"
2351             + HelpExampleRpc("listaccounts", "6")
2352         );
2353
2354     LOCK2(cs_main, pwalletMain->cs_wallet);
2355
2356     int nMinDepth = 1;
2357     if (params.size() > 0)
2358         nMinDepth = params[0].get_int();
2359     isminefilter includeWatchonly = ISMINE_SPENDABLE;
2360     if(params.size() > 1)
2361         if(params[1].get_bool())
2362             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
2363
2364     map<string, CAmount> mapAccountBalances;
2365     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
2366         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
2367             mapAccountBalances[entry.second.name] = 0;
2368     }
2369
2370     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
2371     {
2372         const CWalletTx& wtx = (*it).second;
2373         CAmount nFee;
2374         string strSentAccount;
2375         list<COutputEntry> listReceived;
2376         list<COutputEntry> listSent;
2377         int nDepth = wtx.GetDepthInMainChain();
2378         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
2379             continue;
2380         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
2381         mapAccountBalances[strSentAccount] -= nFee;
2382         BOOST_FOREACH(const COutputEntry& s, listSent)
2383             mapAccountBalances[strSentAccount] -= s.amount;
2384         if (nDepth >= nMinDepth)
2385         {
2386             BOOST_FOREACH(const COutputEntry& r, listReceived)
2387                 if (pwalletMain->mapAddressBook.count(r.destination))
2388                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
2389                 else
2390                     mapAccountBalances[""] += r.amount;
2391         }
2392     }
2393
2394     list<CAccountingEntry> acentries;
2395     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
2396     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
2397         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
2398
2399     UniValue ret(UniValue::VOBJ);
2400     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
2401         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
2402     }
2403     return ret;
2404 }
2405
2406 UniValue listsinceblock(const UniValue& params, bool fHelp)
2407 {
2408     if (!EnsureWalletIsAvailable(fHelp))
2409         return NullUniValue;
2410
2411     if (fHelp)
2412         throw runtime_error(
2413             "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
2414             "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
2415             "\nArguments:\n"
2416             "1. \"blockhash\"   (string, optional) The block hash to list transactions since\n"
2417             "2. target-confirmations:    (numeric, optional) The confirmations required, must be 1 or more\n"
2418             "3. includeWatchonly:        (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
2419             "\nResult:\n"
2420             "{\n"
2421             "  \"transactions\": [\n"
2422             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
2423             "    \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\",    (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for move transactions (category = move).\n"
2424             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
2425             "    \"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"
2426             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
2427             "    \"vout\" : n,               (numeric) the vout value\n"
2428             "    \"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"
2429             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
2430             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
2431             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
2432             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
2433             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
2434             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
2435             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
2436             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
2437             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
2438              "  ],\n"
2439             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
2440             "}\n"
2441             "\nExamples:\n"
2442             + HelpExampleCli("listsinceblock", "")
2443             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
2444             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
2445         );
2446
2447     LOCK2(cs_main, pwalletMain->cs_wallet);
2448
2449     CBlockIndex *pindex = NULL;
2450     int target_confirms = 1;
2451     isminefilter filter = ISMINE_SPENDABLE;
2452
2453     if (params.size() > 0)
2454     {
2455         uint256 blockId;
2456
2457         blockId.SetHex(params[0].get_str());
2458         BlockMap::iterator it = mapBlockIndex.find(blockId);
2459         if (it != mapBlockIndex.end())
2460             pindex = it->second;
2461     }
2462
2463     if (params.size() > 1)
2464     {
2465         target_confirms = params[1].get_int();
2466
2467         if (target_confirms < 1)
2468             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
2469     }
2470
2471     if(params.size() > 2)
2472         if(params[2].get_bool())
2473             filter = filter | ISMINE_WATCH_ONLY;
2474
2475     int depth = pindex ? (1 + chainActive.Height() - pindex->GetHeight()) : -1;
2476
2477     UniValue transactions(UniValue::VARR);
2478
2479     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
2480     {
2481         CWalletTx tx = (*it).second;
2482
2483         if (depth == -1 || tx.GetDepthInMainChain() < depth)
2484             ListTransactions(tx, "*", 0, true, transactions, filter);
2485     }
2486
2487     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
2488     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
2489
2490     UniValue ret(UniValue::VOBJ);
2491     ret.push_back(Pair("transactions", transactions));
2492     ret.push_back(Pair("lastblock", lastblock.GetHex()));
2493
2494     return ret;
2495 }
2496
2497 UniValue gettransaction(const UniValue& params, bool fHelp)
2498 {
2499     if (!EnsureWalletIsAvailable(fHelp))
2500         return NullUniValue;
2501
2502     if (fHelp || params.size() < 1 || params.size() > 2)
2503         throw runtime_error(
2504             "gettransaction \"txid\" ( includeWatchonly )\n"
2505             "\nGet detailed information about in-wallet transaction <txid>\n"
2506             "\nArguments:\n"
2507             "1. \"txid\"    (string, required) The transaction id\n"
2508             "2. \"includeWatchonly\"    (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
2509             "\nResult:\n"
2510             "{\n"
2511             "  \"amount\" : x.xxx,        (numeric) The transaction amount in " + strprintf("%s",komodo_chainname()) + "\n"
2512             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
2513             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
2514             "  \"blockindex\" : xx,       (numeric) The block index\n"
2515             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
2516             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
2517             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
2518             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
2519             "  \"details\" : [\n"
2520             "    {\n"
2521             "      \"account\" : \"accountname\",  (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
2522             "      \"address\" : \"" + strprintf("%s",komodo_chainname()) + "_address\",   (string) The " + strprintf("%s",komodo_chainname()) + " address involved in the transaction\n"
2523             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
2524             "      \"amount\" : x.xxx                  (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n"
2525             "      \"vout\" : n,                       (numeric) the vout value\n"
2526             "    }\n"
2527             "    ,...\n"
2528             "  ],\n"
2529             "  \"vjoinsplit\" : [\n"
2530             "    {\n"
2531             "      \"anchor\" : \"treestateref\",          (string) Merkle root of note commitment tree\n"
2532             "      \"nullifiers\" : [ string, ... ]      (string) Nullifiers of input notes\n"
2533             "      \"commitments\" : [ string, ... ]     (string) Note commitments for note outputs\n"
2534             "      \"macs\" : [ string, ... ]            (string) Message authentication tags\n"
2535             "      \"vpub_old\" : x.xxx                  (numeric) The amount removed from the transparent value pool\n"
2536             "      \"vpub_new\" : x.xxx,                 (numeric) The amount added to the transparent value pool\n"
2537             "    }\n"
2538             "    ,...\n"
2539             "  ],\n"
2540             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
2541             "}\n"
2542
2543             "\nExamples:\n"
2544             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2545             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
2546             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2547         );
2548
2549     LOCK2(cs_main, pwalletMain->cs_wallet);
2550
2551     uint256 hash;
2552     hash.SetHex(params[0].get_str());
2553
2554     isminefilter filter = ISMINE_SPENDABLE;
2555     if(params.size() > 1)
2556         if(params[1].get_bool())
2557             filter = filter | ISMINE_WATCH_ONLY;
2558
2559     UniValue entry(UniValue::VOBJ);
2560     if (!pwalletMain->mapWallet.count(hash))
2561         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2562     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
2563
2564     CAmount nCredit = wtx.GetCredit(filter);
2565     CAmount nDebit = wtx.GetDebit(filter);
2566     CAmount nNet = nCredit - nDebit;
2567     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
2568
2569     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
2570     if (wtx.IsFromMe(filter))
2571         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
2572
2573     WalletTxToJSON(wtx, entry);
2574
2575     UniValue details(UniValue::VARR);
2576     ListTransactions(wtx, "*", 0, false, details, filter);
2577     entry.push_back(Pair("details", details));
2578
2579     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
2580     entry.push_back(Pair("hex", strHex));
2581
2582     return entry;
2583 }
2584
2585
2586 UniValue backupwallet(const UniValue& params, bool fHelp)
2587 {
2588     if (!EnsureWalletIsAvailable(fHelp))
2589         return NullUniValue;
2590
2591     if (fHelp || params.size() != 1)
2592         throw runtime_error(
2593             "backupwallet \"destination\"\n"
2594             "\nSafely copies wallet.dat to destination filename\n"
2595             "\nArguments:\n"
2596             "1. \"destination\"   (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
2597             "\nResult:\n"
2598             "\"path\"             (string) The full path of the destination file\n"
2599             "\nExamples:\n"
2600             + HelpExampleCli("backupwallet", "\"backupdata\"")
2601             + HelpExampleRpc("backupwallet", "\"backupdata\"")
2602         );
2603
2604     LOCK2(cs_main, pwalletMain->cs_wallet);
2605
2606     boost::filesystem::path exportdir;
2607     try {
2608         exportdir = GetExportDir();
2609     } catch (const std::runtime_error& e) {
2610         throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
2611     }
2612     if (exportdir.empty()) {
2613         throw JSONRPCError(RPC_WALLET_ERROR, "Cannot backup wallet until the -exportdir option has been set");
2614     }
2615     std::string unclean = params[0].get_str();
2616     std::string clean = SanitizeFilename(unclean);
2617     if (clean.compare(unclean) != 0) {
2618         throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Filename is invalid as only alphanumeric characters are allowed.  Try '%s' instead.", clean));
2619     }
2620     boost::filesystem::path exportfilepath = exportdir / clean;
2621
2622     if (!BackupWallet(*pwalletMain, exportfilepath.string()))
2623         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
2624
2625     return exportfilepath.string();
2626 }
2627
2628
2629 UniValue keypoolrefill(const UniValue& params, bool fHelp)
2630 {
2631     if (!EnsureWalletIsAvailable(fHelp))
2632         return NullUniValue;
2633
2634     if (fHelp || params.size() > 1)
2635         throw runtime_error(
2636             "keypoolrefill ( newsize )\n"
2637             "\nFills the keypool."
2638             + HelpRequiringPassphrase() + "\n"
2639             "\nArguments\n"
2640             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
2641             "\nExamples:\n"
2642             + HelpExampleCli("keypoolrefill", "")
2643             + HelpExampleRpc("keypoolrefill", "")
2644         );
2645
2646     LOCK2(cs_main, pwalletMain->cs_wallet);
2647
2648     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
2649     unsigned int kpSize = 0;
2650     if (params.size() > 0) {
2651         if (params[0].get_int() < 0)
2652             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
2653         kpSize = (unsigned int)params[0].get_int();
2654     }
2655
2656     EnsureWalletIsUnlocked();
2657     pwalletMain->TopUpKeyPool(kpSize);
2658
2659     if (pwalletMain->GetKeyPoolSize() < kpSize)
2660         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
2661
2662     return NullUniValue;
2663 }
2664
2665
2666 static void LockWallet(CWallet* pWallet)
2667 {
2668     LOCK(cs_nWalletUnlockTime);
2669     nWalletUnlockTime = 0;
2670     pWallet->Lock();
2671 }
2672
2673 UniValue walletpassphrase(const UniValue& params, bool fHelp)
2674 {
2675     if (!EnsureWalletIsAvailable(fHelp))
2676         return NullUniValue;
2677
2678     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
2679         throw runtime_error(
2680             "walletpassphrase \"passphrase\" timeout\n"
2681             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
2682             "This is needed prior to performing transactions related to private keys such as sending " + strprintf("%s",komodo_chainname()) + "\n"
2683             "\nArguments:\n"
2684             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
2685             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
2686             "\nNote:\n"
2687             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
2688             "time that overrides the old one.\n"
2689             "\nExamples:\n"
2690             "\nunlock the wallet for 60 seconds\n"
2691             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
2692             "\nLock the wallet again (before 60 seconds)\n"
2693             + HelpExampleCli("walletlock", "") +
2694             "\nAs json rpc call\n"
2695             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
2696         );
2697
2698     LOCK2(cs_main, pwalletMain->cs_wallet);
2699
2700     if (fHelp)
2701         return true;
2702     if (!pwalletMain->IsCrypted())
2703         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
2704
2705     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
2706     SecureString strWalletPass;
2707     strWalletPass.reserve(100);
2708     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2709     // Alternately, find a way to make params[0] mlock()'d to begin with.
2710     strWalletPass = params[0].get_str().c_str();
2711
2712     if (strWalletPass.length() > 0)
2713     {
2714         if (!pwalletMain->Unlock(strWalletPass))
2715             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2716     }
2717     else
2718         throw runtime_error(
2719             "walletpassphrase <passphrase> <timeout>\n"
2720             "Stores the wallet decryption key in memory for <timeout> seconds.");
2721
2722     // No need to check return values, because the wallet was unlocked above
2723     pwalletMain->UpdateNullifierNoteMap();
2724     pwalletMain->TopUpKeyPool();
2725
2726     int64_t nSleepTime = params[1].get_int64();
2727     LOCK(cs_nWalletUnlockTime);
2728     nWalletUnlockTime = GetTime() + nSleepTime;
2729     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
2730
2731     return NullUniValue;
2732 }
2733
2734
2735 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
2736 {
2737     if (!EnsureWalletIsAvailable(fHelp))
2738         return NullUniValue;
2739
2740     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
2741         throw runtime_error(
2742             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
2743             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
2744             "\nArguments:\n"
2745             "1. \"oldpassphrase\"      (string) The current passphrase\n"
2746             "2. \"newpassphrase\"      (string) The new passphrase\n"
2747             "\nExamples:\n"
2748             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
2749             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
2750         );
2751
2752     LOCK2(cs_main, pwalletMain->cs_wallet);
2753
2754     if (fHelp)
2755         return true;
2756     if (!pwalletMain->IsCrypted())
2757         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
2758
2759     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
2760     // Alternately, find a way to make params[0] mlock()'d to begin with.
2761     SecureString strOldWalletPass;
2762     strOldWalletPass.reserve(100);
2763     strOldWalletPass = params[0].get_str().c_str();
2764
2765     SecureString strNewWalletPass;
2766     strNewWalletPass.reserve(100);
2767     strNewWalletPass = params[1].get_str().c_str();
2768
2769     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
2770         throw runtime_error(
2771             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
2772             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
2773
2774     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
2775         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2776
2777     return NullUniValue;
2778 }
2779
2780
2781 UniValue walletlock(const UniValue& params, bool fHelp)
2782 {
2783     if (!EnsureWalletIsAvailable(fHelp))
2784         return NullUniValue;
2785
2786     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
2787         throw runtime_error(
2788             "walletlock\n"
2789             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2790             "After calling this method, you will need to call walletpassphrase again\n"
2791             "before being able to call any methods which require the wallet to be unlocked.\n"
2792             "\nExamples:\n"
2793             "\nSet the passphrase for 2 minutes to perform a transaction\n"
2794             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2795             "\nPerform a send (requires passphrase set)\n"
2796             + HelpExampleCli("sendtoaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 1.0") +
2797             "\nClear the passphrase since we are done before 2 minutes is up\n"
2798             + HelpExampleCli("walletlock", "") +
2799             "\nAs json rpc call\n"
2800             + HelpExampleRpc("walletlock", "")
2801         );
2802
2803     LOCK2(cs_main, pwalletMain->cs_wallet);
2804
2805     if (fHelp)
2806         return true;
2807     if (!pwalletMain->IsCrypted())
2808         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2809
2810     {
2811         LOCK(cs_nWalletUnlockTime);
2812         pwalletMain->Lock();
2813         nWalletUnlockTime = 0;
2814     }
2815
2816     return NullUniValue;
2817 }
2818
2819
2820 UniValue encryptwallet(const UniValue& params, bool fHelp)
2821 {
2822     if (!EnsureWalletIsAvailable(fHelp))
2823         return NullUniValue;
2824
2825     string enableArg = "developerencryptwallet";
2826     auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, false);
2827
2828     std::string strWalletEncryptionDisabledMsg = "";
2829     if (!fEnableWalletEncryption) {
2830         strWalletEncryptionDisabledMsg = experimentalDisabledHelpMsg("encryptwallet", enableArg);
2831     }
2832
2833     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2834         throw runtime_error(
2835             "encryptwallet \"passphrase\"\n"
2836             + strWalletEncryptionDisabledMsg +
2837             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2838             "After this, any calls that interact with private keys such as sending or signing \n"
2839             "will require the passphrase to be set prior the making these calls.\n"
2840             "Use the walletpassphrase call for this, and then walletlock call.\n"
2841             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2842             "Note that this will shutdown the server.\n"
2843             "\nArguments:\n"
2844             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2845             "\nExamples:\n"
2846             "\nEncrypt you wallet\n"
2847             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2848             "\nNow set the passphrase to use the wallet, such as for signing or sending " + strprintf("%s",komodo_chainname()) + "\n"
2849             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2850             "\nNow we can so something like sign\n"
2851             + HelpExampleCli("signmessage", "\"" + strprintf("%s",komodo_chainname()) + "_address\" \"test message\"") +
2852             "\nNow lock the wallet again by removing the passphrase\n"
2853             + HelpExampleCli("walletlock", "") +
2854             "\nAs a json rpc call\n"
2855             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2856         );
2857
2858     LOCK2(cs_main, pwalletMain->cs_wallet);
2859
2860     if (fHelp)
2861         return true;
2862     if (!fEnableWalletEncryption) {
2863         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
2864     }
2865     if (pwalletMain->IsCrypted())
2866         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2867
2868     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2869     // Alternately, find a way to make params[0] mlock()'d to begin with.
2870     SecureString strWalletPass;
2871     strWalletPass.reserve(100);
2872     strWalletPass = params[0].get_str().c_str();
2873
2874     if (strWalletPass.length() < 1)
2875         throw runtime_error(
2876             "encryptwallet <passphrase>\n"
2877             "Encrypts the wallet with <passphrase>.");
2878
2879     if (!pwalletMain->EncryptWallet(strWalletPass))
2880         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2881
2882     // BDB seems to have a bad habit of writing old data into
2883     // slack space in .dat files; that is bad if the old data is
2884     // unencrypted private keys. So:
2885     StartShutdown();
2886     return "wallet encrypted; Verus server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
2887 }
2888
2889 UniValue lockunspent(const UniValue& params, bool fHelp)
2890 {
2891     if (!EnsureWalletIsAvailable(fHelp))
2892         return NullUniValue;
2893
2894     if (fHelp || params.size() < 1 || params.size() > 2)
2895         throw runtime_error(
2896             "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2897             "\nUpdates list of temporarily unspendable outputs.\n"
2898             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2899             "A locked transaction output will not be chosen by automatic coin selection, when spending " + strprintf("%s",komodo_chainname()) + ".\n"
2900             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2901             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2902             "Also see the listunspent call\n"
2903             "\nArguments:\n"
2904             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2905             "2. \"transactions\"  (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2906             "     [           (json array of json objects)\n"
2907             "       {\n"
2908             "         \"txid\":\"id\",    (string) The transaction id\n"
2909             "         \"vout\": n         (numeric) The output number\n"
2910             "       }\n"
2911             "       ,...\n"
2912             "     ]\n"
2913
2914             "\nResult:\n"
2915             "true|false    (boolean) Whether the command was successful or not\n"
2916
2917             "\nExamples:\n"
2918             "\nList the unspent transactions\n"
2919             + HelpExampleCli("listunspent", "") +
2920             "\nLock an unspent transaction\n"
2921             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2922             "\nList the locked transactions\n"
2923             + HelpExampleCli("listlockunspent", "") +
2924             "\nUnlock the transaction again\n"
2925             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2926             "\nAs a json rpc call\n"
2927             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2928         );
2929
2930     LOCK2(cs_main, pwalletMain->cs_wallet);
2931
2932     if (params.size() == 1)
2933         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2934     else
2935         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2936
2937     bool fUnlock = params[0].get_bool();
2938
2939     if (params.size() == 1) {
2940         if (fUnlock)
2941             pwalletMain->UnlockAllCoins();
2942         return true;
2943     }
2944
2945     UniValue outputs = params[1].get_array();
2946     for (size_t idx = 0; idx < outputs.size(); idx++) {
2947         const UniValue& output = outputs[idx];
2948         if (!output.isObject())
2949             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2950         const UniValue& o = output.get_obj();
2951
2952         RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
2953
2954         string txid = find_value(o, "txid").get_str();
2955         if (!IsHex(txid))
2956             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2957
2958         int nOutput = find_value(o, "vout").get_int();
2959         if (nOutput < 0)
2960             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2961
2962         COutPoint outpt(uint256S(txid), nOutput);
2963
2964         if (fUnlock)
2965             pwalletMain->UnlockCoin(outpt);
2966         else
2967             pwalletMain->LockCoin(outpt);
2968     }
2969
2970     return true;
2971 }
2972
2973 UniValue listlockunspent(const UniValue& params, bool fHelp)
2974 {
2975     if (!EnsureWalletIsAvailable(fHelp))
2976         return NullUniValue;
2977
2978     if (fHelp || params.size() > 0)
2979         throw runtime_error(
2980             "listlockunspent\n"
2981             "\nReturns list of temporarily unspendable outputs.\n"
2982             "See the lockunspent call to lock and unlock transactions for spending.\n"
2983             "\nResult:\n"
2984             "[\n"
2985             "  {\n"
2986             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
2987             "    \"vout\" : n                      (numeric) The vout value\n"
2988             "  }\n"
2989             "  ,...\n"
2990             "]\n"
2991             "\nExamples:\n"
2992             "\nList the unspent transactions\n"
2993             + HelpExampleCli("listunspent", "") +
2994             "\nLock an unspent transaction\n"
2995             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2996             "\nList the locked transactions\n"
2997             + HelpExampleCli("listlockunspent", "") +
2998             "\nUnlock the transaction again\n"
2999             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
3000             "\nAs a json rpc call\n"
3001             + HelpExampleRpc("listlockunspent", "")
3002         );
3003
3004     LOCK2(cs_main, pwalletMain->cs_wallet);
3005
3006     vector<COutPoint> vOutpts;
3007     pwalletMain->ListLockedCoins(vOutpts);
3008
3009     UniValue ret(UniValue::VARR);
3010
3011     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
3012         UniValue o(UniValue::VOBJ);
3013
3014         o.push_back(Pair("txid", outpt.hash.GetHex()));
3015         o.push_back(Pair("vout", (int)outpt.n));
3016         ret.push_back(o);
3017     }
3018
3019     return ret;
3020 }
3021
3022 UniValue settxfee(const UniValue& params, bool fHelp)
3023 {
3024     if (!EnsureWalletIsAvailable(fHelp))
3025         return NullUniValue;
3026
3027     if (fHelp || params.size() < 1 || params.size() > 1)
3028         throw runtime_error(
3029             "settxfee amount\n"
3030             "\nSet the transaction fee per kB.\n"
3031             "\nArguments:\n"
3032             "1. amount         (numeric, required) The transaction fee in " + strprintf("%s",komodo_chainname()) + "/kB rounded to the nearest 0.00000001\n"
3033             "\nResult\n"
3034             "true|false        (boolean) Returns true if successful\n"
3035             "\nExamples:\n"
3036             + HelpExampleCli("settxfee", "0.00001")
3037             + HelpExampleRpc("settxfee", "0.00001")
3038         );
3039
3040     LOCK2(cs_main, pwalletMain->cs_wallet);
3041
3042     // Amount
3043     CAmount nAmount = AmountFromValue(params[0]);
3044
3045     payTxFee = CFeeRate(nAmount, 1000);
3046     return true;
3047 }
3048
3049 UniValue getwalletinfo(const UniValue& params, bool fHelp)
3050 {
3051     if (!EnsureWalletIsAvailable(fHelp))
3052         return NullUniValue;
3053
3054     if (fHelp || params.size() != 0)
3055         throw runtime_error(
3056             "getwalletinfo\n"
3057             "Returns an object containing various wallet state info.\n"
3058             "\nResult:\n"
3059             "{\n"
3060             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
3061             "  \"balance\": xxxxxxx,         (numeric) the total confirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3062             "  \"reserve_balance\": xxxxxxx, (numeric) for PBaaS reserve chains, the total confirmed reserve balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3063             "  \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3064             "  \"unconfirmed_reserve_balance\": xxx, (numeric) total unconfirmed reserve balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3065             "  \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3066             "  \"immature_reserve_balance\": xxxxxx, (numeric) total immature reserve balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n"
3067             "  \"eligible_staking_balance\": xxxxxx, (numeric) eligible staking balance in " + strprintf("%s",komodo_chainname()) + "\n"
3068             "  \"txcount\": xxxxxxx,         (numeric) the total number of transactions in the wallet\n"
3069             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
3070             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
3071             "  \"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"
3072             "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
3073             "  \"seedfp\": \"uint256\",        (string) the BLAKE2b-256 hash of the HD seed\n"
3074             "}\n"
3075             "\nExamples:\n"
3076             + HelpExampleCli("getwalletinfo", "")
3077             + HelpExampleRpc("getwalletinfo", "")
3078         );
3079
3080     LOCK2(cs_main, pwalletMain->cs_wallet);
3081
3082     UniValue obj(UniValue::VOBJ);
3083     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
3084     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
3085     obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
3086     obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
3087
3088     std::vector<COutput> vecOutputs;
3089     CAmount totalStakingAmount = 0;
3090
3091     pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
3092
3093     for (int i = 0; i < vecOutputs.size(); i++)
3094     {
3095         auto &txout = vecOutputs[i];
3096
3097         if (txout.tx &&
3098             txout.i < txout.tx->vout.size() &&
3099             txout.tx->vout[txout.i].nValue > 0 &&
3100             txout.fSpendable &&
3101             (txout.nDepth >= VERUS_MIN_STAKEAGE) &&
3102             !txout.tx->vout[txout.i].scriptPubKey.IsPayToCryptoCondition())
3103         {
3104             totalStakingAmount += txout.tx->vout[txout.i].nValue;
3105         }
3106     }
3107
3108     obj.push_back(Pair("eligible_staking_balance", ValueFromAmount(totalStakingAmount)));
3109
3110     CCurrencyDefinition &chainDef = ConnectedChains.ThisChain();
3111     UniValue reserveBal(UniValue::VOBJ);
3112     for (auto &oneBalance : pwalletMain->GetReserveBalance().valueMap)
3113     {
3114         reserveBal.push_back(make_pair(ConnectedChains.GetCachedCurrency(oneBalance.first).name, ValueFromAmount(oneBalance.second)));
3115     }
3116     if (reserveBal.size())
3117     {
3118         obj.push_back(Pair("reserve_balance", reserveBal));
3119     }
3120
3121     UniValue unconfirmedReserveBal(UniValue::VARR);
3122     for (auto &oneBalance : pwalletMain->GetUnconfirmedReserveBalance().valueMap)
3123     {
3124         UniValue oneCurObj(UniValue::VOBJ);
3125         oneCurObj.push_back(make_pair(ConnectedChains.GetCachedCurrency(oneBalance.first).name, ValueFromAmount(oneBalance.second)));
3126         unconfirmedReserveBal.push_back(oneCurObj);
3127     }
3128     if (unconfirmedReserveBal.size())
3129     {
3130         obj.push_back(Pair("unconfirmed_reserve_balance", unconfirmedReserveBal));
3131     }
3132
3133     UniValue immatureReserveBal(UniValue::VARR);
3134     for (auto &oneBalance : pwalletMain->GetImmatureReserveBalance().valueMap)
3135     {
3136         UniValue oneCurObj(UniValue::VOBJ);
3137         oneCurObj.push_back(make_pair(ConnectedChains.GetCachedCurrency(oneBalance.first).name, ValueFromAmount(oneBalance.second)));
3138         immatureReserveBal.push_back(oneCurObj);
3139     }
3140     if (immatureReserveBal.size())
3141     {
3142         obj.push_back(Pair("immature_reserve_balance", immatureReserveBal));
3143     }
3144
3145     uint32_t height = chainActive.LastTip() ? chainActive.LastTip()->GetHeight() : 0;
3146
3147     if ((ConnectedChains.ThisChain().IsReserve() || ConnectedChains.ThisChain().startBlock < height) && 
3148         ConnectedChains.ThisChain().currencies.size())
3149     {
3150         UniValue pricesInReserve(UniValue::VARR);
3151         CCoinbaseCurrencyState thisCurState(ConnectedChains.GetCurrencyState(height));
3152         std::vector<CAmount> prices(thisCurState.PricesInReserve());
3153         for (int i = 0; i < thisCurState.currencies.size(); i++)
3154         {
3155             UniValue oneCurObj(UniValue::VOBJ);
3156             oneCurObj.push_back(make_pair(ConnectedChains.GetCachedCurrency(thisCurState.currencies[i]).name, ValueFromAmount(prices[i])));
3157             pricesInReserve.push_back(oneCurObj);
3158         }
3159         obj.push_back(Pair("prices", pricesInReserve));
3160     }
3161
3162     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
3163     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
3164     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
3165     if (pwalletMain->IsCrypted())
3166         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
3167     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
3168     uint256 seedFp = pwalletMain->GetHDChain().seedFp;
3169     if (!seedFp.IsNull())
3170          obj.push_back(Pair("seedfp", seedFp.GetHex()));
3171     return obj;
3172 }
3173
3174 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
3175 {
3176     if (!EnsureWalletIsAvailable(fHelp))
3177         return NullUniValue;
3178
3179     if (fHelp || params.size() != 0)
3180         throw runtime_error(
3181             "resendwallettransactions\n"
3182             "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
3183             "Intended only for testing; the wallet code periodically re-broadcasts\n"
3184             "automatically.\n"
3185             "Returns array of transaction ids that were re-broadcast.\n"
3186             );
3187
3188     LOCK2(cs_main, pwalletMain->cs_wallet);
3189
3190     std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
3191     UniValue result(UniValue::VARR);
3192     BOOST_FOREACH(const uint256& txid, txids)
3193     {
3194         result.push_back(txid.ToString());
3195     }
3196     return result;
3197 }
3198
3199 UniValue listunspent(const UniValue& params, bool fHelp)
3200 {
3201     if (!EnsureWalletIsAvailable(fHelp))
3202         return NullUniValue;
3203
3204     if (fHelp || params.size() > 3)
3205         throw runtime_error(
3206             "listunspent ( minconf maxconf  [\"address\",...] )\n"
3207             "\nReturns array of unspent transaction outputs\n"
3208             "with between minconf and maxconf (inclusive) confirmations.\n"
3209             "Optionally filter to only include txouts paid to specified addresses.\n"
3210             "Results are an array of Objects, each of which has:\n"
3211             "{txid, vout, scriptPubKey, amount, confirmations}\n"
3212             "\nArguments:\n"
3213             "1. minconf          (numeric, optional, default=1) The minimum confirmations to filter\n"
3214             "2. maxconf          (numeric, optional, default=9999999) The maximum confirmations to filter\n"
3215             "3. \"addresses\"    (string) A json array of " + strprintf("%s",komodo_chainname()) + " addresses to filter\n"
3216             "    [\n"
3217             "      \"address\"   (string) " + strprintf("%s",komodo_chainname()) + " address\n"
3218             "      ,...\n"
3219             "    ]\n"
3220             "\nResult\n"
3221             "[                   (array of json object)\n"
3222             "  {\n"
3223             "    \"txid\" : \"txid\",          (string) the transaction id \n"
3224             "    \"vout\" : n,               (numeric) the vout value\n"
3225             "    \"generated\" : true|false  (boolean) true if txout is a coinbase transaction output\n"
3226             "    \"address\" : \"address\",    (string) the Zcash address\n"
3227             "    \"account\" : \"account\",    (string) DEPRECATED. The associated account, or \"\" for the default account\n"
3228             "    \"scriptPubKey\" : \"key\",   (string) the script key\n"
3229             "    \"amount\" : x.xxx,         (numeric) the transaction amount in " + CURRENCY_UNIT + "\n"
3230             "    \"confirmations\" : n,      (numeric) The number of confirmations\n"
3231             "    \"redeemScript\" : n        (string) The redeemScript if scriptPubKey is P2SH\n"
3232             "    \"spendable\" : xxx         (bool) Whether we have the private keys to spend this output\n"
3233             "  }\n"
3234             "  ,...\n"
3235             "]\n"
3236
3237             "\nExamples\n"
3238             + HelpExampleCli("listunspent", "")
3239             + HelpExampleCli("listunspent", "6 9999999 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
3240             + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\",\\\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\\\"]\"")
3241         );
3242
3243     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
3244
3245     int nMinDepth = 1;
3246     if (params.size() > 0)
3247         nMinDepth = params[0].get_int();
3248
3249     int nMaxDepth = 9999999;
3250     if (params.size() > 1)
3251         nMaxDepth = params[1].get_int();
3252
3253     std::set<CTxDestination> destinations;
3254     if (params.size() > 2) {
3255         UniValue inputs = params[2].get_array();
3256         for (size_t idx = 0; idx < inputs.size(); idx++) {
3257             const UniValue& input = inputs[idx];
3258             CTxDestination dest = DecodeDestination(input.get_str());
3259             if (!IsValidDestination(dest)) {
3260                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Verus address: ") + input.get_str());
3261             }
3262             if (!destinations.insert(dest).second) {
3263                 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
3264             }
3265         }
3266     }
3267
3268     UniValue results(UniValue::VARR);
3269     vector<COutput> vecOutputs;
3270     assert(pwalletMain != NULL);
3271     LOCK2(cs_main, pwalletMain->cs_wallet);
3272     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
3273     BOOST_FOREACH(const COutput& out, vecOutputs) {
3274         if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
3275             continue;
3276
3277         CTxDestination address;
3278         const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
3279         bool fValidAddress = ExtractDestination(scriptPubKey, address);
3280
3281         if (destinations.size() && (!fValidAddress || !destinations.count(address)))
3282             continue;
3283
3284         UniValue entry(UniValue::VOBJ);
3285         entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
3286         entry.push_back(Pair("vout", out.i));
3287         entry.push_back(Pair("generated", out.tx->IsCoinBase()));
3288
3289         if (fValidAddress) {
3290             entry.push_back(Pair("address", EncodeDestination(address)));
3291
3292             if (pwalletMain->mapAddressBook.count(address))
3293                 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
3294
3295             if (scriptPubKey.IsPayToScriptHash()) {
3296                 const CScriptID& hash = boost::get<CScriptID>(address);
3297                 CScript redeemScript;
3298                 if (pwalletMain->GetCScript(hash, redeemScript))
3299                     entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
3300             }
3301         }
3302         CAmount nValue = out.tx->vout[out.i].nValue;
3303         entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue)));
3304
3305         CCurrencyValueMap reserveOut;
3306         if (ConnectedChains.ThisChain().IsReserve() && (reserveOut = out.tx->vout[out.i].scriptPubKey.ReserveOutValue()).valueMap.size())
3307         {
3308             entry.push_back(Pair("reserveAmount", reserveOut.ToUniValue()));
3309         }
3310         if ( out.tx->nLockTime != 0 )
3311         {
3312             BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
3313             CBlockIndex *tipindex,*pindex = it->second;
3314             uint64_t interest; uint32_t locktime; int32_t txheight;
3315             if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
3316             {
3317                 interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->GetHeight());
3318                 //interest = komodo_interest(txheight,nValue,out.tx->nLockTime,tipindex->nTime);
3319                 entry.push_back(Pair("interest",ValueFromAmount(interest)));
3320             }
3321             //fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.LastTip(),locktime,txheight,pindex->GetHeight());
3322         }
3323         entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
3324         entry.push_back(Pair("confirmations", out.nDepth));
3325         entry.push_back(Pair("spendable", out.fSpendable));
3326         results.push_back(entry);
3327     }
3328
3329     return results;
3330 }
3331
3332 uint64_t komodo_interestsum()
3333 {
3334 #ifdef ENABLE_WALLET
3335     if ( GetBoolArg("-disablewallet", false) == 0 )
3336     {
3337         uint64_t interest,sum = 0; int32_t txheight; uint32_t locktime;
3338         vector<COutput> vecOutputs;
3339         assert(pwalletMain != NULL);
3340         LOCK2(cs_main, pwalletMain->cs_wallet);
3341         pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
3342         BOOST_FOREACH(const COutput& out,vecOutputs)
3343         {
3344             CAmount nValue = out.tx->vout[out.i].nValue;
3345             if ( out.tx->nLockTime != 0 && out.fSpendable != 0 )
3346             {
3347                 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
3348                 CBlockIndex *tipindex,*pindex = it->second;
3349                 if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 )
3350                 {
3351                     interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->GetHeight());
3352                     //interest = komodo_interest(pindex->GetHeight(),nValue,out.tx->nLockTime,tipindex->nTime);
3353                     sum += interest;
3354                 }
3355             }
3356         }
3357         KOMODO_INTERESTSUM = sum;
3358         KOMODO_WALLETBALANCE = pwalletMain->GetBalance();
3359         return(sum);
3360     }
3361 #endif
3362     return(0);
3363 }
3364
3365
3366 UniValue z_listunspent(const UniValue& params, bool fHelp)
3367 {
3368     if (!EnsureWalletIsAvailable(fHelp))
3369         return NullUniValue;
3370
3371     if (fHelp || params.size() > 4)
3372         throw runtime_error(
3373             "z_listunspent ( minconf maxconf includeWatchonly [\"zaddr\",...] )\n"
3374             "\nReturns array of unspent shielded notes with between minconf and maxconf (inclusive) confirmations.\n"
3375             "Optionally filter to only include notes sent to specified addresses.\n"
3376             "When minconf is 0, unspent notes with zero confirmations are returned, even though they are not immediately spendable.\n"
3377             "Results are an array of Objects, each of which has:\n"
3378             "{txid, jsindex, jsoutindex, confirmations, address, amount, memo} (Sprout)\n"
3379             "{txid, outindex, confirmations, address, amount, memo} (Sapling)\n"
3380             "\nArguments:\n"
3381             "1. minconf          (numeric, optional, default=1) The minimum confirmations to filter\n"
3382             "2. maxconf          (numeric, optional, default=9999999) The maximum confirmations to filter\n"
3383             "3. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
3384             "4. \"addresses\"      (string) A json array of zaddrs (both Sprout and Sapling) to filter on.  Duplicate addresses not allowed.\n"
3385             "    [\n"
3386             "      \"address\"     (string) zaddr\n"
3387             "      ,...\n"
3388             "    ]\n"
3389             "\nResult\n"
3390             "[                             (array of json object)\n"
3391             "  {\n"
3392             "    \"txid\" : \"txid\",          (string) the transaction id \n"
3393             "    \"jsindex\" (sprout) : n,       (numeric) the joinsplit index\n"
3394             "    \"jsoutindex\" (sprout) : n,       (numeric) the output index of the joinsplit\n"
3395             "    \"outindex\" (sapling) : n,       (numeric) the output index\n"
3396             "    \"confirmations\" : n,       (numeric) the number of confirmations\n"
3397             "    \"spendable\" : true|false,  (boolean) true if note can be spent by wallet, false if address is watchonly\n"
3398             "    \"address\" : \"address\",    (string) the shielded address\n"
3399             "    \"amount\": xxxxx,          (numeric) the amount of value in the note\n"
3400             "    \"memo\": xxxxx,            (string) hexademical string representation of memo field\n"
3401             "    \"change\": true|false,     (boolean) true if the address that received the note is also one of the sending addresses\n"
3402             "  }\n"
3403             "  ,...\n"
3404             "]\n"
3405
3406             "\nExamples\n"
3407             + HelpExampleCli("z_listunspent", "")
3408             + HelpExampleCli("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
3409             + HelpExampleRpc("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
3410         );
3411
3412     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VBOOL)(UniValue::VARR));
3413
3414     int nMinDepth = 1;
3415     if (params.size() > 0) {
3416         nMinDepth = params[0].get_int();
3417     }
3418     if (nMinDepth < 0) {
3419         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3420     }
3421
3422     int nMaxDepth = 9999999;
3423     if (params.size() > 1) {
3424         nMaxDepth = params[1].get_int();
3425     }
3426     if (nMaxDepth < nMinDepth) {
3427         throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum number of confirmations must be greater or equal to the minimum number of confirmations");
3428     }
3429
3430     std::set<libzcash::PaymentAddress> zaddrs = {};
3431
3432     bool fIncludeWatchonly = false;
3433     if (params.size() > 2) {
3434         fIncludeWatchonly = params[2].get_bool();
3435     }
3436
3437     LOCK2(cs_main, pwalletMain->cs_wallet);
3438
3439     // User has supplied zaddrs to filter on
3440     if (params.size() > 3) {
3441         UniValue addresses = params[3].get_array();
3442         if (addresses.size()==0)
3443             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, addresses array is empty.");
3444
3445         // Keep track of addresses to spot duplicates
3446         set<std::string> setAddress;
3447
3448         // Sources
3449         for (const UniValue& o : addresses.getValues()) {
3450             if (!o.isStr()) {
3451                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
3452             }
3453             string address = o.get_str();
3454             auto zaddr = DecodePaymentAddress(address);
3455             if (!IsValidPaymentAddress(zaddr)) {
3456                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address);
3457             }
3458             auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
3459             if (!fIncludeWatchonly && !hasSpendingKey) {
3460                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
3461             }
3462             zaddrs.insert(zaddr);
3463
3464             if (setAddress.count(address)) {
3465                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
3466             }
3467             setAddress.insert(address);
3468         }
3469     }
3470     else {
3471         // User did not provide zaddrs, so use default i.e. all addresses
3472         std::set<libzcash::SproutPaymentAddress> sproutzaddrs = {};
3473         pwalletMain->GetSproutPaymentAddresses(sproutzaddrs);
3474         
3475         // Sapling support
3476         std::set<libzcash::SaplingPaymentAddress> saplingzaddrs = {};
3477         pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs);
3478         
3479         zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end());
3480         zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end());
3481     }
3482
3483     UniValue results(UniValue::VARR);
3484
3485     if (zaddrs.size() > 0) {
3486         std::vector<SproutNoteEntry> sproutEntries;
3487         std::vector<SaplingNoteEntry> saplingEntries;
3488         pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
3489         std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
3490         
3491         for (auto & entry : sproutEntries) {
3492             UniValue obj(UniValue::VOBJ);
3493             obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
3494             obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
3495             obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
3496             obj.push_back(Pair("confirmations", entry.confirmations));
3497             bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get<libzcash::SproutPaymentAddress>(entry.address));
3498             obj.push_back(Pair("spendable", hasSproutSpendingKey));
3499             obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
3500             obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value()))));
3501             std::string data(entry.memo.begin(), entry.memo.end());
3502             obj.push_back(Pair("memo", HexStr(data)));
3503             if (hasSproutSpendingKey) {
3504                 obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop)));
3505             }
3506             results.push_back(obj);
3507         }
3508         
3509         for (auto & entry : saplingEntries) {
3510             UniValue obj(UniValue::VOBJ);
3511             obj.push_back(Pair("txid", entry.op.hash.ToString()));
3512             obj.push_back(Pair("outindex", (int)entry.op.n));
3513             obj.push_back(Pair("confirmations", entry.confirmations));
3514             libzcash::SaplingIncomingViewingKey ivk;
3515             libzcash::SaplingFullViewingKey fvk;
3516             pwalletMain->GetSaplingIncomingViewingKey(boost::get<libzcash::SaplingPaymentAddress>(entry.address), ivk);
3517             pwalletMain->GetSaplingFullViewingKey(ivk, fvk);
3518             bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk);
3519             obj.push_back(Pair("spendable", hasSaplingSpendingKey));
3520             obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
3521             obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value()
3522             obj.push_back(Pair("memo", HexStr(entry.memo)));
3523             if (hasSaplingSpendingKey) {
3524                 obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op)));
3525             }
3526             results.push_back(obj);
3527         }
3528     }
3529
3530     return results;
3531 }
3532
3533
3534 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
3535 {
3536     if (!EnsureWalletIsAvailable(fHelp))
3537         return NullUniValue;
3538
3539     if (fHelp || params.size() != 1)
3540         throw runtime_error(
3541                             "fundrawtransaction \"hexstring\"\n"
3542                             "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
3543                             "This will not modify existing inputs, and will add one change output to the outputs.\n"
3544                             "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
3545                             "The inputs added will not be signed, use signrawtransaction for that.\n"
3546                             "\nArguments:\n"
3547                             "1. \"hexstring\"    (string, required) The hex string of the raw transaction\n"
3548                             "\nResult:\n"
3549                             "{\n"
3550                             "  \"hex\":       \"value\", (string)  The resulting raw transaction (hex-encoded string)\n"
3551                             "  \"fee\":       n,         (numeric) The fee added to the transaction\n"
3552                             "  \"changepos\": n          (numeric) The position of the added change output, or -1\n"
3553                             "}\n"
3554                             "\"hex\"             \n"
3555                             "\nExamples:\n"
3556                             "\nCreate a transaction with no inputs\n"
3557                             + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
3558                             "\nAdd sufficient unsigned inputs to meet the output value\n"
3559                             + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3560                             "\nSign the transaction\n"
3561                             + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
3562                             "\nSend the transaction\n"
3563                             + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
3564                             );
3565
3566     RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
3567
3568     // parse hex string from parameter
3569     CTransaction origTx;
3570     if (!DecodeHexTx(origTx, params[0].get_str()))
3571         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3572
3573     CMutableTransaction tx(origTx);
3574     CAmount nFee;
3575     string strFailReason;
3576     int nChangePos = -1;
3577     if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason))
3578         throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
3579
3580     UniValue result(UniValue::VOBJ);
3581     result.push_back(Pair("hex", EncodeHexTx(tx)));
3582     result.push_back(Pair("changepos", nChangePos));
3583     result.push_back(Pair("fee", ValueFromAmount(nFee)));
3584
3585     return result;
3586 }
3587
3588 UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
3589 {
3590     if (fHelp) {
3591         throw runtime_error(
3592             "zcsamplejoinsplit\n"
3593             "\n"
3594             "Perform a joinsplit and return the JSDescription.\n"
3595             );
3596     }
3597
3598     LOCK(cs_main);
3599
3600     uint256 joinSplitPubKey;
3601     uint256 anchor = SproutMerkleTree().root();
3602     JSDescription samplejoinsplit(true,
3603                                   *pzcashParams,
3604                                   joinSplitPubKey,
3605                                   anchor,
3606                                   {JSInput(), JSInput()},
3607                                   {JSOutput(), JSOutput()},
3608                                   0,
3609                                   0);
3610
3611     CDataStream ss(SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
3612     ss << samplejoinsplit;
3613
3614     return HexStr(ss.begin(), ss.end());
3615 }
3616
3617 UniValue zc_benchmark(const UniValue& params, bool fHelp)
3618 {
3619     if (!EnsureWalletIsAvailable(fHelp)) {
3620         return NullUniValue;
3621     }
3622
3623     if (fHelp || params.size() < 2) {
3624         throw runtime_error(
3625             "zcbenchmark benchmarktype samplecount\n"
3626             "\n"
3627             "Runs a benchmark of the selected type samplecount times,\n"
3628             "returning the running times of each sample.\n"
3629             "\n"
3630             "Output: [\n"
3631             "  {\n"
3632             "    \"runningtime\": runningtime\n"
3633             "  },\n"
3634             "  {\n"
3635             "    \"runningtime\": runningtime\n"
3636             "  }\n"
3637             "  ...\n"
3638             "]\n"
3639             );
3640     }
3641
3642     LOCK(cs_main);
3643
3644     std::string benchmarktype = params[0].get_str();
3645     int samplecount = params[1].get_int();
3646
3647     if (samplecount <= 0) {
3648         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid samplecount");
3649     }
3650
3651     std::vector<double> sample_times;
3652
3653     JSDescription samplejoinsplit;
3654
3655     if (benchmarktype == "verifyjoinsplit") {
3656         CDataStream ss(ParseHexV(params[2].get_str(), "js"), SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
3657         ss >> samplejoinsplit;
3658     }
3659
3660     for (int i = 0; i < samplecount; i++) {
3661         if (benchmarktype == "sleep") {
3662             sample_times.push_back(benchmark_sleep());
3663         } else if (benchmarktype == "parameterloading") {
3664             sample_times.push_back(benchmark_parameter_loading());
3665         } else if (benchmarktype == "createjoinsplit") {
3666             if (params.size() < 3) {
3667                 sample_times.push_back(benchmark_create_joinsplit());
3668             } else {
3669                 int nThreads = params[2].get_int();
3670                 std::vector<double> vals = benchmark_create_joinsplit_threaded(nThreads);
3671                 // Divide by nThreads^2 to get average seconds per JoinSplit because
3672                 // we are running one JoinSplit per thread.
3673                 sample_times.push_back(std::accumulate(vals.begin(), vals.end(), 0.0) / (nThreads*nThreads));
3674             }
3675         } else if (benchmarktype == "verifyjoinsplit") {
3676             sample_times.push_back(benchmark_verify_joinsplit(samplejoinsplit));
3677 #ifdef ENABLE_MINING
3678         } else if (benchmarktype == "solveequihash") {
3679             if (params.size() < 3) {
3680                 sample_times.push_back(benchmark_solve_equihash());
3681             } else {
3682                 int nThreads = params[2].get_int();
3683                 std::vector<double> vals = benchmark_solve_equihash_threaded(nThreads);
3684                 sample_times.insert(sample_times.end(), vals.begin(), vals.end());
3685             }
3686 #endif
3687         } else if (benchmarktype == "verifyequihash") {
3688             sample_times.push_back(benchmark_verify_equihash());
3689         } else if (benchmarktype == "validatelargetx") {
3690             // Number of inputs in the spending transaction that we will simulate
3691             int nInputs = 11130;
3692             if (params.size() >= 3) {
3693                 nInputs = params[2].get_int();
3694             }
3695             sample_times.push_back(benchmark_large_tx(nInputs));
3696         } else if (benchmarktype == "trydecryptnotes") {
3697             int nKeys = params[2].get_int();
3698             sample_times.push_back(benchmark_try_decrypt_sprout_notes(nKeys));
3699         } else if (benchmarktype == "trydecryptsaplingnotes") {
3700             int nKeys = params[2].get_int();
3701             sample_times.push_back(benchmark_try_decrypt_sapling_notes(nKeys));
3702         } else if (benchmarktype == "incnotewitnesses") {
3703             int nTxs = params[2].get_int();
3704             sample_times.push_back(benchmark_increment_sprout_note_witnesses(nTxs));
3705         } else if (benchmarktype == "incsaplingnotewitnesses") {
3706             int nTxs = params[2].get_int();
3707             sample_times.push_back(benchmark_increment_sapling_note_witnesses(nTxs));
3708         } else if (benchmarktype == "connectblockslow") {
3709             if (Params().NetworkIDString() != "regtest") {
3710                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
3711             }
3712             sample_times.push_back(benchmark_connectblock_slow());
3713         } else if (benchmarktype == "sendtoaddress") {
3714             if (Params().NetworkIDString() != "regtest") {
3715                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
3716             }
3717             auto amount = AmountFromValue(params[2]);
3718             sample_times.push_back(benchmark_sendtoaddress(amount));
3719         } else if (benchmarktype == "loadwallet") {
3720             if (Params().NetworkIDString() != "regtest") {
3721                 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
3722             }
3723             sample_times.push_back(benchmark_loadwallet());
3724         } else if (benchmarktype == "listunspent") {
3725             sample_times.push_back(benchmark_listunspent());
3726         } else if (benchmarktype == "createsaplingspend") {
3727             sample_times.push_back(benchmark_create_sapling_spend());
3728         } else if (benchmarktype == "createsaplingoutput") {
3729             sample_times.push_back(benchmark_create_sapling_output());
3730         } else if (benchmarktype == "verifysaplingspend") {
3731             sample_times.push_back(benchmark_verify_sapling_spend());
3732         } else if (benchmarktype == "verifysaplingoutput") {
3733             sample_times.push_back(benchmark_verify_sapling_output());
3734         } else {
3735             throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
3736         }
3737     }
3738
3739     UniValue results(UniValue::VARR);
3740     for (auto time : sample_times) {
3741         UniValue result(UniValue::VOBJ);
3742         result.push_back(Pair("runningtime", time));
3743         results.push_back(result);
3744     }
3745
3746     return results;
3747 }
3748
3749 UniValue zc_raw_receive(const UniValue& params, bool fHelp)
3750 {
3751     if (!EnsureWalletIsAvailable(fHelp)) {
3752         return NullUniValue;
3753     }
3754
3755     if (fHelp || params.size() != 2) {
3756         throw runtime_error(
3757             "zcrawreceive zcsecretkey encryptednote\n"
3758             "\n"
3759             "DEPRECATED. Decrypts encryptednote and checks if the coin commitments\n"
3760             "are in the blockchain as indicated by the \"exists\" result.\n"
3761             "\n"
3762             "Output: {\n"
3763             "  \"amount\": value,\n"
3764             "  \"note\": noteplaintext,\n"
3765             "  \"exists\": exists\n"
3766             "}\n"
3767             );
3768     }
3769
3770     RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR));
3771
3772     LOCK(cs_main);
3773
3774     auto spendingkey = DecodeSpendingKey(params[0].get_str());
3775     if (!IsValidSpendingKey(spendingkey)) {
3776         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
3777     }
3778     if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
3779         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
3780     }
3781     SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
3782
3783     uint256 epk;
3784     unsigned char nonce;
3785     ZCNoteEncryption::Ciphertext ct;
3786     uint256 h_sig;
3787
3788     {
3789         CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
3790         try {
3791             ssData >> nonce;
3792             ssData >> epk;
3793             ssData >> ct;
3794             ssData >> h_sig;
3795         } catch(const std::exception &) {
3796             throw runtime_error(
3797                 "encrypted_note could not be decoded"
3798             );
3799         }
3800     }
3801
3802     ZCNoteDecryption decryptor(k.receiving_key());
3803
3804     SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
3805         decryptor,
3806         ct,
3807         epk,
3808         h_sig,
3809         nonce
3810     );
3811     SproutPaymentAddress payment_addr = k.address();
3812     SproutNote decrypted_note = npt.note(payment_addr);
3813
3814     assert(pwalletMain != NULL);
3815     std::vector<boost::optional<SproutWitness>> witnesses;
3816     uint256 anchor;
3817     uint256 commitment = decrypted_note.cm();
3818     pwalletMain->WitnessNoteCommitment(
3819         {commitment},
3820         witnesses,
3821         anchor
3822     );
3823
3824     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3825     ss << npt;
3826
3827     UniValue result(UniValue::VOBJ);
3828     result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value())));
3829     result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
3830     result.push_back(Pair("exists", (bool) witnesses[0]));
3831     return result;
3832 }
3833
3834
3835
3836 UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
3837 {
3838     if (!EnsureWalletIsAvailable(fHelp)) {
3839         return NullUniValue;
3840     }
3841
3842     if (fHelp || params.size() != 5) {
3843         throw runtime_error(
3844             "zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
3845             "  inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
3846             "  outputs: a JSON object mapping {zcaddr: value, ...}\n"
3847             "\n"
3848             "DEPRECATED. Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
3849             "Outputs are confidential between sender/receiver. The vpub_old and\n"
3850             "vpub_new values are globally public and move transparent value into\n"
3851             "or out of the confidential value store, respectively.\n"
3852             "\n"
3853             "Note: The caller is responsible for delivering the output enc1 and\n"
3854             "enc2 to the appropriate recipients, as well as signing rawtxout and\n"
3855             "ensuring it is mined. (A future RPC call will deliver the confidential\n"
3856             "payments in-band on the blockchain.)\n"
3857             "\n"
3858             "Output: {\n"
3859             "  \"encryptednote1\": enc1,\n"
3860             "  \"encryptednote2\": enc2,\n"
3861             "  \"rawtxn\": rawtxout\n"
3862             "}\n"
3863             );
3864     }
3865
3866     LOCK(cs_main);
3867
3868     CTransaction tx;
3869     if (!DecodeHexTx(tx, params[0].get_str()))
3870         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3871
3872     UniValue inputs = params[1].get_obj();
3873     UniValue outputs = params[2].get_obj();
3874
3875     CAmount vpub_old(0);
3876     CAmount vpub_new(0);
3877
3878     if (params[3].get_real() != 0.0)
3879         vpub_old = AmountFromValue(params[3]);
3880
3881     if (params[4].get_real() != 0.0)
3882         vpub_new = AmountFromValue(params[4]);
3883
3884     std::vector<JSInput> vjsin;
3885     std::vector<JSOutput> vjsout;
3886     std::vector<SproutNote> notes;
3887     std::vector<SproutSpendingKey> keys;
3888     std::vector<uint256> commitments;
3889
3890     for (const string& name_ : inputs.getKeys()) {
3891         auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
3892         if (!IsValidSpendingKey(spendingkey)) {
3893             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
3894         }
3895         if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
3896             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
3897         }
3898         SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
3899
3900         keys.push_back(k);
3901
3902         SproutNotePlaintext npt;
3903
3904         {
3905             CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
3906             ssData >> npt;
3907         }
3908
3909         SproutPaymentAddress addr = k.address();
3910         SproutNote note = npt.note(addr);
3911         notes.push_back(note);
3912         commitments.push_back(note.cm());
3913     }
3914
3915     uint256 anchor;
3916     std::vector<boost::optional<SproutWitness>> witnesses;
3917     pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
3918
3919     assert(witnesses.size() == notes.size());
3920     assert(notes.size() == keys.size());
3921
3922     {
3923         for (size_t i = 0; i < witnesses.size(); i++) {
3924             if (!witnesses[i]) {
3925                 throw runtime_error(
3926                     "joinsplit input could not be found in tree"
3927                 );
3928             }
3929
3930             vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
3931         }
3932     }
3933
3934     while (vjsin.size() < ZC_NUM_JS_INPUTS) {
3935         vjsin.push_back(JSInput());
3936     }
3937
3938     for (const string& name_ : outputs.getKeys()) {
3939         auto addrTo = DecodePaymentAddress(name_);
3940         if (!IsValidPaymentAddress(addrTo)) {
3941             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
3942         }
3943         if (boost::get<libzcash::SproutPaymentAddress>(&addrTo) == nullptr) {
3944             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout payment addresses");
3945         }
3946         CAmount nAmount = AmountFromValue(outputs[name_]);
3947
3948         vjsout.push_back(JSOutput(boost::get<libzcash::SproutPaymentAddress>(addrTo), nAmount));
3949     }
3950
3951     while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
3952         vjsout.push_back(JSOutput());
3953     }
3954
3955     // TODO
3956     if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
3957         throw runtime_error("unsupported joinsplit input/output counts");
3958     }
3959
3960     uint256 joinSplitPubKey;
3961     unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
3962     crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
3963
3964     CMutableTransaction mtx(tx);
3965     mtx.nVersion = 2;
3966     mtx.joinSplitPubKey = joinSplitPubKey;
3967
3968     JSDescription jsdesc(false,
3969                          *pzcashParams,
3970                          joinSplitPubKey,
3971                          anchor,
3972                          {vjsin[0], vjsin[1]},
3973                          {vjsout[0], vjsout[1]},
3974                          vpub_old,
3975                          vpub_new);
3976
3977     {
3978         auto verifier = libzcash::ProofVerifier::Strict();
3979         assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
3980     }
3981
3982     mtx.vJoinSplit.push_back(jsdesc);
3983
3984     // Empty output script.
3985     CScript scriptCode;
3986     CTransaction signTx(mtx);
3987     auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
3988     uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
3989
3990     // Add the signature
3991     assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
3992                          dataToBeSigned.begin(), 32,
3993                          joinSplitPrivKey
3994                         ) == 0);
3995
3996     // Sanity check
3997     assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
3998                                        dataToBeSigned.begin(), 32,
3999                                        mtx.joinSplitPubKey.begin()
4000                                       ) == 0);
4001
4002     CTransaction rawTx(mtx);
4003
4004     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
4005     ss << rawTx;
4006
4007     std::string encryptedNote1;
4008     std::string encryptedNote2;
4009     {
4010         CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
4011         ss2 << ((unsigned char) 0x00);
4012         ss2 << jsdesc.ephemeralKey;
4013         ss2 << jsdesc.ciphertexts[0];
4014         ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
4015
4016         encryptedNote1 = HexStr(ss2.begin(), ss2.end());
4017     }
4018     {
4019         CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
4020         ss2 << ((unsigned char) 0x01);
4021         ss2 << jsdesc.ephemeralKey;
4022         ss2 << jsdesc.ciphertexts[1];
4023         ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
4024
4025         encryptedNote2 = HexStr(ss2.begin(), ss2.end());
4026     }
4027
4028     UniValue result(UniValue::VOBJ);
4029     result.push_back(Pair("encryptednote1", encryptedNote1));
4030     result.push_back(Pair("encryptednote2", encryptedNote2));
4031     result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
4032     return result;
4033 }
4034
4035 UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
4036 {
4037     if (!EnsureWalletIsAvailable(fHelp)) {
4038         return NullUniValue;
4039     }
4040
4041     if (fHelp || params.size() != 0) {
4042         throw runtime_error(
4043             "zcrawkeygen\n"
4044             "\n"
4045             "DEPRECATED. Generate a zcaddr which can send and receive confidential values.\n"
4046             "\n"
4047             "Output: {\n"
4048             "  \"zcaddress\": zcaddr,\n"
4049             "  \"zcsecretkey\": zcsecretkey,\n"
4050             "  \"zcviewingkey\": zcviewingkey,\n"
4051             "}\n"
4052             );
4053     }
4054
4055     auto k = SproutSpendingKey::random();
4056     auto addr = k.address();
4057     auto viewing_key = k.viewing_key();
4058
4059     UniValue result(UniValue::VOBJ);
4060     result.push_back(Pair("zcaddress", EncodePaymentAddress(addr)));
4061     result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k)));
4062     result.push_back(Pair("zcviewingkey", EncodeViewingKey(viewing_key)));
4063     return result;
4064 }
4065
4066
4067 UniValue z_getnewaddress(const UniValue& params, bool fHelp)
4068 {
4069     if (!EnsureWalletIsAvailable(fHelp))
4070         return NullUniValue;
4071
4072     std::string defaultType = ADDR_TYPE_SAPLING;
4073
4074     if (fHelp || params.size() > 1)
4075         throw runtime_error(
4076             "z_getnewaddress ( type )\n"
4077             "\nReturns a new shielded address for receiving payments.\n"
4078             "\nWith no arguments, returns a Sapling address.\n"
4079             "\nArguments:\n"
4080             "1. \"type\"         (string, optional, default=\"" + defaultType + "\") The type of address. One of [\""
4081             + ADDR_TYPE_SPROUT + "\", \"" + ADDR_TYPE_SAPLING + "\"].\n"
4082             "\nResult:\n"
4083             "\"" + strprintf("%s",komodo_chainname()) + "_address\"    (string) The new shielded address.\n"
4084             "\nExamples:\n"
4085             + HelpExampleCli("z_getnewaddress", "")
4086             + HelpExampleCli("z_getnewaddress", ADDR_TYPE_SAPLING)
4087             + HelpExampleRpc("z_getnewaddress", "")
4088         );
4089
4090     LOCK2(cs_main, pwalletMain->cs_wallet);
4091
4092     EnsureWalletIsUnlocked();
4093
4094     auto addrType = defaultType;
4095     if (params.size() > 0) {
4096         addrType = params[0].get_str();
4097     }
4098
4099     if (addrType == ADDR_TYPE_SPROUT) {
4100         return EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey());
4101     } else if (addrType == ADDR_TYPE_SAPLING) {
4102         return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
4103     } else {
4104         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");
4105     }
4106 }
4107
4108
4109 UniValue z_listaddresses(const UniValue& params, bool fHelp)
4110 {
4111     if (!EnsureWalletIsAvailable(fHelp))
4112         return NullUniValue;
4113
4114     if (fHelp || params.size() > 1)
4115         throw runtime_error(
4116             "z_listaddresses ( includeWatchonly )\n"
4117             "\nReturns the list of Sprout and Sapling shielded addresses belonging to the wallet.\n"
4118             "\nArguments:\n"
4119             "1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
4120             "\nResult:\n"
4121             "[                     (json array of string)\n"
4122             "  \"zaddr\"           (string) a zaddr belonging to the wallet\n"
4123             "  ,...\n"
4124             "]\n"
4125             "\nExamples:\n"
4126             + HelpExampleCli("z_listaddresses", "")
4127             + HelpExampleRpc("z_listaddresses", "")
4128         );
4129
4130     LOCK2(cs_main, pwalletMain->cs_wallet);
4131
4132     bool fIncludeWatchonly = false;
4133     if (params.size() > 0) {
4134         fIncludeWatchonly = params[0].get_bool();
4135     }
4136
4137     UniValue ret(UniValue::VARR);
4138     {
4139         std::set<libzcash::SproutPaymentAddress> addresses;
4140         pwalletMain->GetSproutPaymentAddresses(addresses);
4141         for (auto addr : addresses) {
4142             if (fIncludeWatchonly || pwalletMain->HaveSproutSpendingKey(addr)) {
4143                 ret.push_back(EncodePaymentAddress(addr));
4144             }
4145         }
4146     }
4147     {
4148         std::set<libzcash::SaplingPaymentAddress> addresses;
4149         pwalletMain->GetSaplingPaymentAddresses(addresses);
4150         libzcash::SaplingIncomingViewingKey ivk;
4151         libzcash::SaplingFullViewingKey fvk;
4152         for (auto addr : addresses) {
4153             if (fIncludeWatchonly || (
4154                 pwalletMain->GetSaplingIncomingViewingKey(addr, ivk) &&
4155                 pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
4156                 pwalletMain->HaveSaplingSpendingKey(fvk)
4157             )) {
4158                 ret.push_back(EncodePaymentAddress(addr));
4159             }
4160         }
4161     }
4162     return ret;
4163 }
4164
4165 CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
4166     std::set<CTxDestination> destinations;
4167     vector<COutput> vecOutputs;
4168     CAmount balance = 0;
4169
4170     if (transparentAddress.length() > 0) {
4171         CTxDestination taddr = DecodeDestination(transparentAddress);
4172         if (!IsValidDestination(taddr)) {
4173             throw std::runtime_error("invalid transparent address");
4174         }
4175         destinations.insert(taddr);
4176     }
4177
4178     LOCK2(cs_main, pwalletMain->cs_wallet);
4179
4180     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
4181
4182     BOOST_FOREACH(const COutput& out, vecOutputs) {
4183         if (out.nDepth < minDepth) {
4184             continue;
4185         }
4186
4187         if (ignoreUnspendable && !out.fSpendable) {
4188             continue;
4189         }
4190
4191         if (destinations.size()) {
4192             CTxDestination address;
4193             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
4194                 continue;
4195             }
4196
4197             if (!destinations.count(address)) {
4198                 continue;
4199             }
4200         }
4201
4202         CAmount nValue = out.tx->vout[out.i].nValue; // komodo_interest
4203         balance += nValue;
4204     }
4205     return balance;
4206 }
4207
4208 CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
4209     CAmount balance = 0;
4210     std::vector<SproutNoteEntry> sproutEntries;
4211     std::vector<SaplingNoteEntry> saplingEntries;
4212     LOCK2(cs_main, pwalletMain->cs_wallet);
4213     pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, address, minDepth, true, ignoreUnspendable);
4214     for (auto & entry : sproutEntries) {
4215         balance += CAmount(entry.note.value());
4216     }
4217     for (auto & entry : saplingEntries) {
4218         balance += CAmount(entry.note.value());
4219     }
4220     return balance;
4221 }
4222
4223
4224 UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
4225 {
4226     if (!EnsureWalletIsAvailable(fHelp))
4227         return NullUniValue;
4228
4229     if (fHelp || params.size()==0 || params.size() >2)
4230         throw runtime_error(
4231             "z_listreceivedbyaddress \"address\" ( minconf )\n"
4232             "\nReturn a list of amounts received by a zaddr belonging to the node's wallet.\n"
4233             "\nArguments:\n"
4234             "1. \"address\"      (string) The private address.\n"
4235             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
4236             "\nResult:\n"
4237             "{\n"
4238             "  \"txid\": \"txid\",           (string) the transaction id\n"
4239             "  \"amount\": xxxxx,         (numeric) the amount of value in the note\n"
4240             "  \"memo\": xxxxx,           (string) hexadecimal string representation of memo field\n"
4241             "  \"jsindex\" (sprout) : n,     (numeric) the joinsplit index\n"
4242             "  \"jsoutindex\" (sprout) : n,     (numeric) the output index of the joinsplit\n"
4243             "  \"outindex\" (sapling) : n,     (numeric) the output index\n"
4244             "  \"change\": true|false,    (boolean) true if the address that received the note is also one of the sending addresses\n"
4245             "}\n"
4246             "\nExamples:\n"
4247             + HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4248             + HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4249         );
4250
4251     LOCK2(cs_main, pwalletMain->cs_wallet);
4252
4253     int nMinDepth = 1;
4254     if (params.size() > 1) {
4255         nMinDepth = params[1].get_int();
4256     }
4257     if (nMinDepth < 0) {
4258         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
4259     }
4260
4261     // Check that the from address is valid.
4262     auto fromaddress = params[0].get_str();
4263
4264     auto zaddr = DecodePaymentAddress(fromaddress);
4265     if (!IsValidPaymentAddress(zaddr)) {
4266         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
4267     }
4268
4269     // Visitor to support Sprout and Sapling addrs
4270     if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), zaddr)) {
4271         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
4272     }
4273
4274     UniValue result(UniValue::VARR);
4275     std::vector<SproutNoteEntry> sproutEntries;
4276     std::vector<SaplingNoteEntry> saplingEntries;
4277     pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false);
4278
4279     std::set<std::pair<PaymentAddress, uint256>> nullifierSet;
4280     auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
4281     if (hasSpendingKey) {
4282         nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr});
4283     }
4284
4285     if (boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr) {
4286         for (SproutNoteEntry & entry : sproutEntries) {
4287             UniValue obj(UniValue::VOBJ);
4288             obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
4289             obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value()))));
4290             std::string data(entry.memo.begin(), entry.memo.end());
4291             obj.push_back(Pair("memo", HexStr(data)));
4292             obj.push_back(Pair("jsindex", entry.jsop.js));
4293             obj.push_back(Pair("jsoutindex", entry.jsop.n));
4294             if (hasSpendingKey) {
4295                 obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop)));
4296             }
4297             result.push_back(obj);
4298         }
4299     } else if (boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
4300         for (SaplingNoteEntry & entry : saplingEntries) {
4301             UniValue obj(UniValue::VOBJ);
4302             obj.push_back(Pair("txid", entry.op.hash.ToString()));
4303             obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value()))));
4304             obj.push_back(Pair("memo", HexStr(entry.memo)));
4305             obj.push_back(Pair("outindex", (int)entry.op.n));
4306             if (hasSpendingKey) {
4307               obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op)));
4308             }
4309             result.push_back(obj);
4310         }
4311     }
4312     return result;
4313 }
4314
4315 UniValue z_getbalance(const UniValue& params, bool fHelp)
4316 {
4317     if (!EnsureWalletIsAvailable(fHelp))
4318         return NullUniValue;
4319
4320     if (fHelp || params.size()==0 || params.size() >2)
4321         throw runtime_error(
4322             "z_getbalance \"address\" ( minconf )\n"
4323             "\nReturns the balance of a taddr or zaddr belonging to the node's wallet.\n"
4324             "\nCAUTION: If the wallet has only an incoming viewing key for this address, then spends cannot be"
4325             "\ndetected, and so the returned balance may be larger than the actual balance.\n"
4326             "\nArguments:\n"
4327             "1. \"address\"      (string) The selected address. It may be a transparent or private address.\n"
4328             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
4329             "\nResult:\n"
4330             "amount              (numeric) The total amount in KMD received for this address.\n"
4331             "\nExamples:\n"
4332             "\nThe total amount received by address \"myaddress\"\n"
4333             + HelpExampleCli("z_getbalance", "\"myaddress\"") +
4334             "\nThe total amount received by address \"myaddress\" at least 5 blocks confirmed\n"
4335             + HelpExampleCli("z_getbalance", "\"myaddress\" 5") +
4336             "\nAs a json rpc call\n"
4337             + HelpExampleRpc("z_getbalance", "\"myaddress\", 5")
4338         );
4339
4340     LOCK2(cs_main, pwalletMain->cs_wallet);
4341
4342     int nMinDepth = 1;
4343     if (params.size() > 1) {
4344         nMinDepth = params[1].get_int();
4345     }
4346     if (nMinDepth < 0) {
4347         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
4348     }
4349
4350     // Check that the from address is valid.
4351     auto fromaddress = params[0].get_str();
4352     bool fromTaddr = false;
4353     CTxDestination taddr = DecodeDestination(fromaddress);
4354     fromTaddr = IsValidDestination(taddr);
4355     if (!fromTaddr) {
4356         auto res = DecodePaymentAddress(fromaddress);
4357         if (!IsValidPaymentAddress(res)) {
4358             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
4359         }
4360         if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), res)) {
4361              throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, spending key or viewing key not found.");
4362         }
4363     }
4364
4365     CAmount nBalance = 0;
4366     if (fromTaddr) {
4367         nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
4368     } else {
4369         nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
4370     }
4371
4372     return ValueFromAmount(nBalance);
4373 }
4374
4375
4376 UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
4377 {
4378     if (!EnsureWalletIsAvailable(fHelp))
4379         return NullUniValue;
4380
4381     if (fHelp || params.size() > 2)
4382         throw runtime_error(
4383             "z_gettotalbalance ( minconf includeWatchonly )\n"
4384             "\nReturn the total value of funds stored in the node's wallet.\n"
4385             "\nCAUTION: If the wallet contains any addresses for which it only has incoming viewing keys,"
4386             "\nthe returned private balance may be larger than the actual balance, because spends cannot"
4387             "\nbe detected with incoming viewing keys.\n"
4388             "\nArguments:\n"
4389             "1. minconf          (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
4390             "2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
4391             "\nResult:\n"
4392             "{\n"
4393             "  \"transparent\": xxxxx,     (numeric) the total balance of transparent funds\n"
4394             "  \"private\": xxxxx,         (numeric) the total balance of shielded funds (in both Sprout and Sapling addresses)\n"
4395             "  \"total\": xxxxx,           (numeric) the total balance of both transparent and shielded funds\n"
4396             "}\n"
4397             "\nExamples:\n"
4398             "\nThe total amount in the wallet\n"
4399             + HelpExampleCli("z_gettotalbalance", "") +
4400             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
4401             + HelpExampleCli("z_gettotalbalance", "5") +
4402             "\nAs a json rpc call\n"
4403             + HelpExampleRpc("z_gettotalbalance", "5")
4404         );
4405
4406     LOCK2(cs_main, pwalletMain->cs_wallet);
4407
4408     int nMinDepth = 1;
4409     if (params.size() > 0) {
4410         nMinDepth = params[0].get_int();
4411     }
4412     if (nMinDepth < 0) {
4413         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
4414     }
4415
4416     bool fIncludeWatchonly = false;
4417     if (params.size() > 1) {
4418         fIncludeWatchonly = params[1].get_bool();
4419     }
4420
4421     // getbalance and "getbalance * 1 true" should return the same number
4422     // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
4423     // pwalletMain->GetBalance() does not accept min depth parameter
4424     // so we use our own method to get balance of utxos.
4425     CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
4426     CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
4427     uint64_t interest = komodo_interestsum();
4428     CAmount nTotalBalance = nBalance + nPrivateBalance;
4429     UniValue result(UniValue::VOBJ);
4430     result.push_back(Pair("transparent", FormatMoney(nBalance)));
4431     //result.push_back(Pair("interest", FormatMoney(interest)));
4432     result.push_back(Pair("private", FormatMoney(nPrivateBalance)));
4433     result.push_back(Pair("total", FormatMoney(nTotalBalance)));
4434     return result;
4435 }
4436
4437 UniValue z_viewtransaction(const UniValue& params, bool fHelp)
4438 {
4439     if (!EnsureWalletIsAvailable(fHelp))
4440         return NullUniValue;
4441
4442     if (fHelp || params.size() != 1)
4443         throw runtime_error(
4444             "z_viewtransaction \"txid\"\n"
4445             "\nGet detailed shielded information about in-wallet transaction <txid>\n"
4446             "\nArguments:\n"
4447             "1. \"txid\" (string, required) The transaction id\n"
4448             "\nResult:\n"
4449             "{\n"
4450             "  \"txid\" : \"transactionid\",   (string) The transaction id\n"
4451             "  \"spends\" : [\n"
4452             "    {\n"
4453             "      \"type\" : \"sprout|sapling\",      (string) The type of address\n"
4454             "      \"js\" : n,                       (numeric, sprout) the index of the JSDescription within vJoinSplit\n"
4455             "      \"jsSpend\" : n,                  (numeric, sprout) the index of the spend within the JSDescription\n"
4456             "      \"spend\" : n,                    (numeric, sapling) the index of the spend within vShieldedSpend\n"
4457             "      \"txidPrev\" : \"transactionid\",   (string) The id for the transaction this note was created in\n"
4458             "      \"jsPrev\" : n,                   (numeric, sprout) the index of the JSDescription within vJoinSplit\n"
4459             "      \"jsOutputPrev\" : n,             (numeric, sprout) the index of the output within the JSDescription\n"
4460             "      \"outputPrev\" : n,               (numeric, sapling) the index of the output within the vShieldedOutput\n"
4461             "      \"address\" : \"zaddress\",       (string) The z address involved in the transaction\n"
4462             "      \"value\" : x.xxx                 (numeric) The amount in " + CURRENCY_UNIT + "\n"
4463             "      \"valueZat\" : xxxx               (numeric) The amount in zatoshis\n"
4464             "    }\n"
4465             "    ,...\n"
4466             "  ],\n"
4467             "  \"outputs\" : [\n"
4468             "    {\n"
4469             "      \"type\" : \"sprout|sapling\",      (string) The type of address\n"
4470             "      \"js\" : n,                       (numeric, sprout) the index of the JSDescription within vJoinSplit\n"
4471             "      \"jsOutput\" : n,                 (numeric, sprout) the index of the output within the JSDescription\n"
4472             "      \"output\" : n,                   (numeric, sapling) the index of the output within the vShieldedOutput\n"
4473             "      \"address\" : \"address\",        (string) The Verus private address involved in the transaction\n"
4474             "      \"recovered\" : true|false        (boolean, sapling) True if the output is not for an address in the wallet\n"
4475             "      \"value\" : x.xxx                 (numeric) The amount in " + CURRENCY_UNIT + "\n"
4476             "      \"valueZat\" : xxxx               (numeric) The amount in zatoshis\n"
4477             "      \"memo\" : \"hexmemo\",             (string) Hexademical string representation of the memo field\n"
4478             "      \"memoStr\" : \"memo\",             (string) Only returned if memo contains valid UTF-8 text.\n"
4479             "    }\n"
4480             "    ,...\n"
4481             "  ],\n"
4482             "}\n"
4483
4484             "\nExamples:\n"
4485             + HelpExampleCli("z_viewtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
4486             + HelpExampleRpc("z_viewtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
4487         );
4488
4489     LOCK2(cs_main, pwalletMain->cs_wallet);
4490
4491     uint256 hash;
4492     hash.SetHex(params[0].get_str());
4493
4494     UniValue entry(UniValue::VOBJ);
4495     if (!pwalletMain->mapWallet.count(hash))
4496         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
4497     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
4498
4499     entry.push_back(Pair("txid", hash.GetHex()));
4500
4501     UniValue spends(UniValue::VARR);
4502     UniValue outputs(UniValue::VARR);
4503
4504     // Sprout spends - retained for old sprout addresses and transactions
4505     for (size_t i = 0; i < wtx.vJoinSplit.size(); ++i) {
4506         for (size_t j = 0; j < wtx.vJoinSplit[i].nullifiers.size(); ++j) {
4507             auto nullifier = wtx.vJoinSplit[i].nullifiers[j];
4508
4509             // Fetch the note that is being spent, if ours
4510             auto res = pwalletMain->mapSproutNullifiersToNotes.find(nullifier);
4511             if (res == pwalletMain->mapSproutNullifiersToNotes.end()) {
4512                 continue;
4513             }
4514             auto jsop = res->second;
4515             auto wtxPrev = pwalletMain->mapWallet.at(jsop.hash);
4516
4517             auto decrypted = wtxPrev.DecryptSproutNote(jsop);
4518             auto notePt = decrypted.first;
4519             auto pa = decrypted.second;
4520
4521             UniValue entry(UniValue::VOBJ);
4522             entry.push_back(Pair("type", ADDR_TYPE_SPROUT));
4523             entry.push_back(Pair("js", (int)i));
4524             entry.push_back(Pair("jsSpend", (int)j));
4525             entry.push_back(Pair("txidPrev", jsop.hash.GetHex()));
4526             entry.push_back(Pair("jsPrev", (int)jsop.js));
4527             entry.push_back(Pair("jsOutputPrev", (int)jsop.n));
4528             entry.push_back(Pair("address", EncodePaymentAddress(pa)));
4529             entry.push_back(Pair("value", ValueFromAmount(notePt.value())));
4530             entry.push_back(Pair("valueZat", notePt.value()));
4531             outputs.push_back(entry);
4532         }
4533     }
4534
4535     // Sprout outputs
4536     for (auto & pair : wtx.mapSproutNoteData) {
4537         JSOutPoint jsop = pair.first;
4538
4539         auto decrypted = wtx.DecryptSproutNote(jsop);
4540         auto notePt = decrypted.first;
4541         auto pa = decrypted.second;
4542         auto memo = notePt.memo();
4543
4544         UniValue entry(UniValue::VOBJ);
4545         entry.push_back(Pair("type", ADDR_TYPE_SPROUT));
4546         entry.push_back(Pair("js", (int)jsop.js));
4547         entry.push_back(Pair("jsOutput", (int)jsop.n));
4548         entry.push_back(Pair("address", EncodePaymentAddress(pa)));
4549         entry.push_back(Pair("value", ValueFromAmount(notePt.value())));
4550         entry.push_back(Pair("valueZat", notePt.value()));
4551         entry.push_back(Pair("memo", HexStr(memo)));
4552         if (memo[0] <= 0xf4) {
4553             auto end = std::find_if(memo.rbegin(), memo.rend(), [](unsigned char v) { return v != 0; });
4554             std::string memoStr(memo.begin(), end.base());
4555             //if (utf8::is_valid(memoStr))
4556             {
4557                 entry.push_back(Pair("memoStr", memoStr));
4558             }
4559         }
4560         outputs.push_back(entry);
4561     }
4562
4563     // Sapling spends
4564     std::set<uint256> ovks;
4565     for (size_t i = 0; i < wtx.vShieldedSpend.size(); ++i) {
4566         auto spend = wtx.vShieldedSpend[i];
4567
4568         // Fetch teh note that is being spent
4569         auto res = pwalletMain->mapSaplingNullifiersToNotes.find(spend.nullifier);
4570         if (res == pwalletMain->mapSaplingNullifiersToNotes.end()) {
4571             continue;
4572         }
4573         auto op = res->second;
4574         auto wtxPrev = pwalletMain->mapWallet.at(op.hash);
4575
4576         auto decrypted = wtxPrev.DecryptSaplingNote(op).get();
4577         auto notePt = decrypted.first;
4578         auto pa = decrypted.second;
4579
4580         // Store the OutgoingViewingKey for recovering outputs
4581         libzcash::SaplingFullViewingKey fvk;
4582         assert(pwalletMain->GetSaplingFullViewingKey(wtxPrev.mapSaplingNoteData.at(op).ivk, fvk));
4583         ovks.insert(fvk.ovk);
4584
4585         UniValue entry(UniValue::VOBJ);
4586         entry.push_back(Pair("type", ADDR_TYPE_SAPLING));
4587         entry.push_back(Pair("spend", (int)i));
4588         entry.push_back(Pair("txidPrev", op.hash.GetHex()));
4589         entry.push_back(Pair("outputPrev", (int)op.n));
4590         entry.push_back(Pair("address", EncodePaymentAddress(pa)));
4591         entry.push_back(Pair("value", ValueFromAmount(notePt.value())));
4592         entry.push_back(Pair("valueZat", notePt.value()));
4593         spends.push_back(entry);
4594     }
4595
4596     // Sapling outputs
4597     for (uint32_t i = 0; i < wtx.vShieldedOutput.size(); ++i) {
4598         auto op = SaplingOutPoint(hash, i);
4599
4600         SaplingNotePlaintext notePt;
4601         SaplingPaymentAddress pa;
4602         bool isRecovered;
4603
4604         auto decrypted = wtx.DecryptSaplingNote(op);
4605         if (decrypted) {
4606             notePt = decrypted->first;
4607             pa = decrypted->second;
4608             isRecovered = false;
4609         } else {
4610             // Try recovering the output
4611             auto recovered = wtx.RecoverSaplingNote(op, ovks);
4612             if (recovered) {
4613                 notePt = recovered->first;
4614                 pa = recovered->second;
4615                 isRecovered = true;
4616             } else {
4617                 // Unreadable
4618                 continue;
4619             }
4620         }
4621         auto memo = notePt.memo();
4622
4623         UniValue entry(UniValue::VOBJ);
4624         entry.push_back(Pair("type", ADDR_TYPE_SAPLING));
4625         entry.push_back(Pair("output", (int)op.n));
4626         entry.push_back(Pair("recovered", isRecovered));
4627         entry.push_back(Pair("address", EncodePaymentAddress(pa)));
4628         entry.push_back(Pair("value", ValueFromAmount(notePt.value())));
4629         entry.push_back(Pair("valueZat", notePt.value()));
4630         entry.push_back(Pair("memo", HexStr(memo)));
4631         if (memo[0] <= 0xf4) {
4632             auto end = std::find_if(memo.rbegin(), memo.rend(), [](unsigned char v) { return v != 0; });
4633             std::string memoStr(memo.begin(), end.base());
4634             //if (utf8::is_valid(memoStr))
4635             {
4636                 entry.push_back(Pair("memoStr", memoStr));
4637             }
4638         }
4639         outputs.push_back(entry);
4640     }
4641
4642     entry.push_back(Pair("spends", spends));
4643     entry.push_back(Pair("outputs", outputs));
4644
4645     return entry;
4646 }
4647
4648 UniValue z_getoperationresult(const UniValue& params, bool fHelp)
4649 {
4650     if (!EnsureWalletIsAvailable(fHelp))
4651         return NullUniValue;
4652
4653     if (fHelp || params.size() > 1)
4654         throw runtime_error(
4655             "z_getoperationresult ([\"operationid\", ... ]) \n"
4656             "\nRetrieve the result and status of an operation which has finished, and then remove the operation from memory."
4657             + HelpRequiringPassphrase() + "\n"
4658             "\nArguments:\n"
4659             "1. \"operationid\"         (array, optional) A list of operation ids we are interested in.  If not provided, examine all operations known to the node.\n"
4660             "\nResult:\n"
4661             "\"    [object, ...]\"      (array) A list of JSON objects\n"
4662             "\nExamples:\n"
4663             + HelpExampleCli("z_getoperationresult", "'[\"operationid\", ... ]'")
4664             + HelpExampleRpc("z_getoperationresult", "'[\"operationid\", ... ]'")
4665         );
4666
4667     // This call will remove finished operations
4668     return z_getoperationstatus_IMPL(params, true);
4669 }
4670
4671 UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
4672 {
4673    if (!EnsureWalletIsAvailable(fHelp))
4674         return NullUniValue;
4675
4676     if (fHelp || params.size() > 1)
4677         throw runtime_error(
4678             "z_getoperationstatus ([\"operationid\", ... ]) \n"
4679             "\nGet operation status and any associated result or error data.  The operation will remain in memory."
4680             + HelpRequiringPassphrase() + "\n"
4681             "\nArguments:\n"
4682             "1. \"operationid\"         (array, optional) A list of operation ids we are interested in.  If not provided, examine all operations known to the node.\n"
4683             "\nResult:\n"
4684             "\"    [object, ...]\"      (array) A list of JSON objects\n"
4685             "\nExamples:\n"
4686             + HelpExampleCli("z_getoperationstatus", "'[\"operationid\", ... ]'")
4687             + HelpExampleRpc("z_getoperationstatus", "'[\"operationid\", ... ]'")
4688         );
4689
4690    // This call is idempotent so we don't want to remove finished operations
4691    return z_getoperationstatus_IMPL(params, false);
4692 }
4693
4694 UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedOperations=false)
4695 {
4696     LOCK2(cs_main, pwalletMain->cs_wallet);
4697
4698     std::set<AsyncRPCOperationId> filter;
4699     if (params.size()==1) {
4700         UniValue ids = params[0].get_array();
4701         for (const UniValue & v : ids.getValues()) {
4702             filter.insert(v.get_str());
4703         }
4704     }
4705     bool useFilter = (filter.size()>0);
4706
4707     UniValue ret(UniValue::VARR);
4708     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4709     std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
4710
4711     for (auto id : ids) {
4712         if (useFilter && !filter.count(id))
4713             continue;
4714
4715         std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
4716         if (!operation) {
4717             continue;
4718             // It's possible that the operation was removed from the internal queue and map during this loop
4719             // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id.");
4720         }
4721
4722         UniValue obj = operation->getStatus();
4723         std::string s = obj["status"].get_str();
4724         if (fRemoveFinishedOperations) {
4725             // Caller is only interested in retrieving finished results
4726             if ("success"==s || "failed"==s || "cancelled"==s) {
4727                 ret.push_back(obj);
4728                 q->popOperationForId(id);
4729             }
4730         } else {
4731             ret.push_back(obj);
4732         }
4733     }
4734
4735     std::vector<UniValue> arrTmp = ret.getValues();
4736
4737     // sort results chronologically by creation_time
4738     std::sort(arrTmp.begin(), arrTmp.end(), [](UniValue a, UniValue b) -> bool {
4739         const int64_t t1 = find_value(a.get_obj(), "creation_time").get_int64();
4740         const int64_t t2 = find_value(b.get_obj(), "creation_time").get_int64();
4741         return t1 < t2;
4742     });
4743
4744     ret.clear();
4745     ret.setArray();
4746     ret.push_backV(arrTmp);
4747
4748     return ret;
4749 }
4750
4751
4752 // JSDescription size depends on the transaction version
4753 #define V3_JS_DESCRIPTION_SIZE    (GetSerializeSize(JSDescription(), SER_NETWORK, (OVERWINTER_TX_VERSION | (1 << 31))))
4754 // Here we define the maximum number of zaddr outputs that can be included in a transaction.
4755 // If input notes are small, we might actually require more than one joinsplit per zaddr output.
4756 // For now though, we assume we use one joinsplit per zaddr output (and the second output note is change).
4757 // We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data.
4758 #define Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING    ((MAX_TX_SIZE_BEFORE_SAPLING / V3_JS_DESCRIPTION_SIZE) - 1)
4759
4760 // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes
4761 #define CTXIN_SPEND_DUST_SIZE   148
4762 #define CTXOUT_REGULAR_SIZE     34
4763
4764 UniValue z_sendmany(const UniValue& params, bool fHelp)
4765 {
4766     if (!EnsureWalletIsAvailable(fHelp))
4767         return NullUniValue;
4768
4769     if (fHelp || params.size() < 2 || params.size() > 4)
4770         throw runtime_error(
4771             "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
4772             "\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
4773             "\nChange generated from a taddr flows to a new taddr address, while change generated from a zaddr returns to itself."
4774             "\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
4775             + strprintf("\nBefore Sapling activates, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING)
4776             + HelpRequiringPassphrase() + "\n"
4777             "\nArguments:\n"
4778             "1. \"fromaddress\"         (string, required) The taddr or zaddr to send the funds from.\n"
4779             "2. \"amounts\"             (array, required) An array of json objects representing the amounts to send.\n"
4780             "    [{\n"
4781             "      \"address\":address  (string, required) The address is a taddr or zaddr\n"
4782             "      \"amount\":amount    (numeric, required) The numeric amount in KMD is the value\n"
4783             "      \"memo\":memo        (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
4784             "    }, ... ]\n"
4785             "3. minconf               (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
4786             "4. fee                   (numeric, optional, default="
4787             + strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
4788             "\nResult:\n"
4789             "\"operationid\"          (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
4790             "\nExamples:\n"
4791             + HelpExampleCli("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
4792             + HelpExampleRpc("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
4793         );
4794
4795     LOCK2(cs_main, pwalletMain->cs_wallet);
4796
4797     // Check that the from address is valid.
4798     auto fromaddress = params[0].get_str();
4799     bool fromTaddr = false;
4800     bool fromSapling = false;
4801
4802     uint32_t branchId = CurrentEpochBranchId(chainActive.Height(), Params().GetConsensus());
4803
4804     CTxDestination taddr = DecodeDestination(fromaddress);
4805     fromTaddr = IsValidDestination(taddr);
4806     if (!fromTaddr) {
4807         auto res = DecodePaymentAddress(fromaddress);
4808         if (!IsValidPaymentAddress(res, branchId)) {
4809             // invalid
4810             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
4811         }
4812
4813         // Check that we have the spending key
4814         if (!boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), res)) {
4815              throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
4816         }
4817
4818         // Remember whether this is a Sprout or Sapling address
4819         fromSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
4820     }
4821     // This logic will need to be updated if we add a new shielded pool
4822     bool fromSprout = !(fromTaddr || fromSapling);
4823
4824     UniValue outputs = params[1].get_array();
4825
4826     if (outputs.size()==0)
4827         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty.");
4828
4829     // Keep track of addresses to spot duplicates
4830     set<std::string> setAddress;
4831
4832     // Track whether we see any Sprout addresses
4833     bool noSproutAddrs = !fromSprout;
4834
4835     // Recipients
4836     std::vector<SendManyRecipient> taddrRecipients;
4837     std::vector<SendManyRecipient> zaddrRecipients;
4838     CAmount nTotalOut = 0;
4839
4840     bool containsSproutOutput = false;
4841     bool containsSaplingOutput = false;
4842
4843     for (const UniValue& o : outputs.getValues()) {
4844         if (!o.isObject())
4845             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
4846
4847         // sanity check, report error if unknown key-value pairs
4848         for (const string& name_ : o.getKeys()) {
4849             std::string s = name_;
4850             if (s != "address" && s != "amount" && s!="memo")
4851                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown key: ")+s);
4852         }
4853
4854         string address = find_value(o, "address").get_str();
4855         bool isZaddr = false;
4856         CTxDestination taddr = DecodeDestination(address);
4857         if (!IsValidDestination(taddr)) {
4858             auto res = DecodePaymentAddress(address);
4859             if (IsValidPaymentAddress(res, branchId)) {
4860                 isZaddr = true;
4861
4862                 bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
4863                 bool toSprout = !toSapling;
4864                 noSproutAddrs = noSproutAddrs && toSapling;
4865
4866                 containsSproutOutput |= toSprout;
4867                 containsSaplingOutput |= toSapling;
4868
4869                 // Sending to both Sprout and Sapling is currently unsupported using z_sendmany
4870                 if (containsSproutOutput && containsSaplingOutput) {
4871                     throw JSONRPCError(
4872                         RPC_INVALID_PARAMETER,
4873                         "Cannot send to both Sprout and Sapling addresses using z_sendmany");
4874                 }
4875
4876                 // If sending between shielded addresses, they must be the same type
4877                 if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
4878                     throw JSONRPCError(
4879                         RPC_INVALID_PARAMETER,
4880                         "Cannot send between Sprout and Sapling addresses using z_sendmany");
4881                 }
4882             } else {
4883                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
4884             }
4885         }
4886         else if ( ASSETCHAINS_PRIVATE != 0 )
4887             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
4888
4889         if (setAddress.count(address))
4890             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address);
4891         setAddress.insert(address);
4892
4893         UniValue memoValue = find_value(o, "memo");
4894         string memo;
4895         if (!memoValue.isNull()) {
4896             memo = memoValue.get_str();
4897             if (!isZaddr) {
4898                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo cannot be used with a taddr.  It can only be used with a zaddr.");
4899             } else if (!IsHex(memo)) {
4900                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
4901             }
4902             if (memo.length() > ZC_MEMO_SIZE*2) {
4903                 throw JSONRPCError(RPC_INVALID_PARAMETER,  strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
4904             }
4905         }
4906
4907         UniValue av = find_value(o, "amount");
4908         CAmount nAmount = AmountFromValue( av );
4909         if (nAmount < 0)
4910             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");
4911
4912         if (isZaddr) {
4913             zaddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
4914         } else {
4915             taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
4916         }
4917
4918         nTotalOut += nAmount;
4919     }
4920
4921     int nextBlockHeight = chainActive.Height() + 1;
4922     CMutableTransaction mtx;
4923     mtx.fOverwintered = true;
4924     mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
4925     mtx.nVersion = SAPLING_TX_VERSION;
4926     unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
4927     if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) {
4928         if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) {
4929             mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
4930             mtx.nVersion = OVERWINTER_TX_VERSION;
4931         } else {
4932             mtx.fOverwintered = false;
4933             mtx.nVersion = 2;
4934         }
4935
4936         max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
4937
4938         // Check the number of zaddr outputs does not exceed the limit.
4939         if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING)  {
4940             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs");
4941         }
4942         // If Sapling is not active, do not allow sending from or sending to Sapling addresses.
4943         if (fromSapling || containsSaplingOutput) {
4944             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
4945         }
4946     }
4947
4948     // As a sanity check, estimate and verify that the size of the transaction will be valid.
4949     // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
4950     size_t txsize = 0;
4951     for (int i = 0; i < zaddrRecipients.size(); i++) {
4952         auto address = std::get<0>(zaddrRecipients[i]);
4953         auto res = DecodePaymentAddress(address);
4954         bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
4955         if (toSapling) {
4956             mtx.vShieldedOutput.push_back(OutputDescription());
4957         } else {
4958             JSDescription jsdesc;
4959             if (mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)) {
4960                 jsdesc.proof = GrothProof();
4961             }
4962             mtx.vJoinSplit.push_back(jsdesc);
4963         }
4964     }
4965     CTransaction tx(mtx);
4966     txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
4967     if (fromTaddr) {
4968         txsize += CTXIN_SPEND_DUST_SIZE;
4969         txsize += CTXOUT_REGULAR_SIZE;      // There will probably be taddr change
4970     }
4971     txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size();
4972     if (txsize > max_tx_size) {
4973         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", max_tx_size ));
4974     }
4975
4976     // Minimum confirmations
4977     int nMinDepth = 1;
4978     if (params.size() > 2) {
4979         nMinDepth = params[2].get_int();
4980     }
4981     if (nMinDepth < 0) {
4982         throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
4983     }
4984
4985     // Fee in Zatoshis, not currency format)
4986     CAmount nFee        = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
4987     CAmount nDefaultFee = nFee;
4988
4989     if (params.size() > 3) {
4990         if (params[3].get_real() == 0.0) {
4991             nFee = 0;
4992         } else {
4993             nFee = AmountFromValue( params[3] );
4994         }
4995
4996         // Check that the user specified fee is not absurd.
4997         // This allows amount=0 (and all amount < nDefaultFee) transactions to use the default network fee
4998         // or anything less than nDefaultFee instead of being forced to use a custom fee and leak metadata
4999         if (nTotalOut < nDefaultFee) {
5000             if (nFee > nDefaultFee) {
5001                 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Small transaction amount %s has fee %s that is greater than the default fee %s", FormatMoney(nTotalOut), FormatMoney(nFee), FormatMoney(nDefaultFee)));
5002             }
5003         } else {
5004             // Check that the user specified fee is not absurd.
5005             if (nFee > nTotalOut) {
5006                 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut)));
5007             }
5008         }
5009     }
5010
5011     // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
5012     UniValue o(UniValue::VOBJ);
5013     o.push_back(Pair("fromaddress", params[0]));
5014     o.push_back(Pair("amounts", params[1]));
5015     o.push_back(Pair("minconf", nMinDepth));
5016     o.push_back(Pair("fee", std::stod(FormatMoney(nFee))));
5017     UniValue contextInfo = o;
5018
5019     // Builder (used if Sapling addresses are involved)
5020     boost::optional<TransactionBuilder> builder;
5021     if (noSproutAddrs) {
5022         builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
5023     }
5024
5025     // Contextual transaction we will build on
5026     // (used if no Sapling addresses are involved)
5027     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
5028     bool isShielded = !fromTaddr || zaddrRecipients.size() > 0;
5029     if (contextualTx.nVersion == 1 && isShielded) {
5030         contextualTx.nVersion = 2; // Tx format should support vjoinsplits
5031     }
5032
5033     // Create operation and add to global queue
5034     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
5035     std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(builder, contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
5036     q->addOperation(operation);
5037     AsyncRPCOperationId operationId = operation->getId();
5038     return operationId;
5039 }
5040
5041 UniValue z_setmigration(const UniValue& params, bool fHelp) {
5042     if (!EnsureWalletIsAvailable(fHelp))
5043         return NullUniValue;
5044     if (fHelp || params.size() != 1)
5045         throw runtime_error(
5046             "z_setmigration enabled\n"
5047             "When enabled the Sprout to Sapling migration will attempt to migrate all funds from this wallet’s\n"
5048             "Sprout addresses to either the address for Sapling account 0 or the address specified by the parameter\n"
5049             "'-migrationdestaddress'.\n"
5050             "\n"
5051             "This migration is designed to minimize information leakage. As a result for wallets with a significant\n"
5052             "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n"
5053             "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n"
5054             "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n"
5055             "the wallet’s Sprout balance is below " + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n"
5056             "\nArguments:\n"
5057             "1. enabled  (boolean, required) 'true' or 'false' to enable or disable respectively.\n"
5058         );
5059     LOCK(pwalletMain->cs_wallet);
5060     pwalletMain->fSaplingMigrationEnabled = params[0].get_bool();
5061     return NullUniValue;
5062 }
5063
5064 UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) {
5065     if (!EnsureWalletIsAvailable(fHelp))
5066         return NullUniValue;
5067     if (fHelp || params.size() != 0)
5068         throw runtime_error(
5069             "z_getmigrationstatus\n"
5070             "Returns information about the status of the Sprout to Sapling migration.\n"
5071             "Note: A transaction is defined as finalized if it has at least ten confirmations.\n"
5072             "Also, it is possible that manually created transactions involving this wallet\n"
5073             "will be included in the result.\n"
5074             "\nResult:\n"
5075             "{\n"
5076             "  \"enabled\": true|false,                    (boolean) Whether or not migration is enabled\n"
5077             "  \"destination_address\": \"zaddr\",           (string) The Sapling address that will receive Sprout funds\n"
5078             "  \"unmigrated_amount\": nnn.n,               (numeric) The total amount of unmigrated " + CURRENCY_UNIT +" \n"
5079             "  \"unfinalized_migrated_amount\": nnn.n,     (numeric) The total amount of unfinalized " + CURRENCY_UNIT + " \n"
5080             "  \"finalized_migrated_amount\": nnn.n,       (numeric) The total amount of finalized " + CURRENCY_UNIT + " \n"
5081             "  \"finalized_migration_transactions\": nnn,  (numeric) The number of migration transactions involving this wallet\n"
5082             "  \"time_started\": ttt,                      (numeric, optional) The block time of the first migration transaction as a Unix timestamp\n"
5083             "  \"migration_txids\": [txids]                (json array of strings) An array of all migration txids involving this wallet\n"
5084             "}\n"
5085         );
5086     LOCK2(cs_main, pwalletMain->cs_wallet);
5087     UniValue migrationStatus(UniValue::VOBJ);
5088     migrationStatus.push_back(Pair("enabled", pwalletMain->fSaplingMigrationEnabled));
5089     //  The "destination_address" field MAY be omitted if the "-migrationdestaddress"
5090     // parameter is not set and no default address has yet been generated.
5091     // Note: The following function may return the default address even if it has not been added to the wallet
5092     auto destinationAddress = AsyncRPCOperation_saplingmigration::getMigrationDestAddress(pwalletMain->GetHDSeedForRPC());
5093     migrationStatus.push_back(Pair("destination_address", EncodePaymentAddress(destinationAddress)));
5094     //  The values of "unmigrated_amount" and "migrated_amount" MUST take into
5095     // account failed transactions, that were not mined within their expiration
5096     // height.
5097     {
5098         std::vector<SproutNoteEntry> sproutEntries;
5099         std::vector<SaplingNoteEntry> saplingEntries;
5100         std::set<PaymentAddress> noFilter;
5101         // Here we are looking for any and all Sprout notes for which we have the spending key, including those
5102         // which are locked and/or only exist in the mempool, as they should be included in the unmigrated amount.
5103         pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false);
5104         CAmount unmigratedAmount = 0;
5105         for (const auto& sproutEntry : sproutEntries) {
5106             unmigratedAmount += sproutEntry.note.value();
5107         }
5108         migrationStatus.push_back(Pair("unmigrated_amount", FormatMoney(unmigratedAmount)));
5109     }
5110     //  "migration_txids" is a list of strings representing transaction IDs of all
5111     // known migration transactions involving this wallet, as lowercase hexadecimal
5112     // in RPC byte order.
5113     UniValue migrationTxids(UniValue::VARR);
5114     CAmount unfinalizedMigratedAmount = 0;
5115     CAmount finalizedMigratedAmount = 0;
5116     int numFinalizedMigrationTxs = 0;
5117     uint64_t timeStarted = 0;
5118     for (const auto& txPair : pwalletMain->mapWallet) {
5119         CWalletTx tx = txPair.second;
5120         // A given transaction is defined as a migration transaction iff it has:
5121         // * one or more Sprout JoinSplits with nonzero vpub_new field; and
5122         // * no Sapling Spends, and;
5123         // * one or more Sapling Outputs.
5124         if (tx.vJoinSplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) {
5125             bool nonZeroVPubNew = false;
5126             for (const auto& js : tx.vJoinSplit) {
5127                 if (js.vpub_new > 0) {
5128                     nonZeroVPubNew = true;
5129                     break;
5130                 }
5131             }
5132             if (!nonZeroVPubNew) {
5133                 continue;
5134             }
5135             migrationTxids.push_back(txPair.first.ToString());
5136             //  A transaction is "finalized" iff it has at least 10 confirmations.
5137             // TODO: subject to change, if the recommended number of confirmations changes.
5138             if (tx.GetDepthInMainChain() >= 10) {
5139                 finalizedMigratedAmount -= tx.valueBalance;
5140                 ++numFinalizedMigrationTxs;
5141             } else {
5142                 unfinalizedMigratedAmount -= tx.valueBalance;
5143             }
5144             // If the transaction is in the mempool it will not be associated with a block yet
5145             if (tx.hashBlock.IsNull() || mapBlockIndex[tx.hashBlock] == nullptr) {
5146                 continue;
5147             }
5148             CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock];
5149             //  The value of "time_started" is the earliest Unix timestamp of any known
5150             // migration transaction involving this wallet; if there is no such transaction,
5151             // then the field is absent.
5152             if (timeStarted == 0 || timeStarted > blockIndex->GetBlockTime()) {
5153                 timeStarted = blockIndex->GetBlockTime();
5154             }
5155         }
5156     }
5157     migrationStatus.push_back(Pair("unfinalized_migrated_amount", FormatMoney(unfinalizedMigratedAmount)));
5158     migrationStatus.push_back(Pair("finalized_migrated_amount", FormatMoney(finalizedMigratedAmount)));
5159     migrationStatus.push_back(Pair("finalized_migration_transactions", numFinalizedMigrationTxs));
5160     if (timeStarted > 0) {
5161         migrationStatus.push_back(Pair("time_started", timeStarted));
5162     }
5163     migrationStatus.push_back(Pair("migration_txids", migrationTxids));
5164     return migrationStatus;
5165 }
5166
5167 /**
5168 When estimating the number of coinbase utxos we can shield in a single transaction:
5169 1. Joinsplit description is 1802 bytes.
5170 2. Transaction overhead ~ 100 bytes
5171 3. Spending a typical P2PKH is >=148 bytes, as defined in CTXIN_SPEND_DUST_SIZE.
5172 4. Spending a multi-sig P2SH address can vary greatly:
5173    https://github.com/bitcoin/bitcoin/blob/c3ad56f4e0b587d8d763af03d743fdfc2d180c9b/src/main.cpp#L517
5174    In real-world coinbase utxos, we consider a 3-of-3 multisig, where the size is roughly:
5175     (3*(33+1))+3 = 105 byte redeem script
5176     105 + 1 + 3*(73+1) = 328 bytes of scriptSig, rounded up to 400 based on testnet experiments.
5177 */
5178 #define CTXIN_SPEND_P2SH_SIZE 400
5179
5180 #define SHIELD_COINBASE_DEFAULT_LIMIT 50
5181
5182 UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
5183 {
5184     if (!EnsureWalletIsAvailable(fHelp))
5185         return NullUniValue;
5186
5187     if (fHelp || params.size() < 2 || params.size() > 4)
5188         throw runtime_error(
5189             "z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n"
5190             "\nShield transparent coinbase funds by sending to a shielded zaddr.  This is an asynchronous operation and utxos"
5191             "\nselected for shielding will be locked.  If there is an error, they are unlocked.  The RPC call `listlockunspent`"
5192             "\ncan be used to return a list of locked utxos.  The number of coinbase utxos selected for shielding can be limited"
5193             "\nby the caller.  If the limit parameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit"
5194             "\noption will determine the number of uxtos.  Any limit is constrained by the consensus rule defining a maximum"
5195             "\ntransaction size of "
5196             + strprintf("%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
5197             + HelpRequiringPassphrase() + "\n"
5198             "\nArguments:\n"
5199             "1. \"fromaddress\"         (string, required) The address is a taddr or \"*\" for all taddrs belonging to the wallet.\n"
5200             "2. \"toaddress\"           (string, required) The address is a zaddr.\n"
5201             "3. fee                   (numeric, optional, default="
5202             + strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
5203             "4. limit                 (numeric, optional, default="
5204             + strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield.  Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
5205             "\nResult:\n"
5206             "{\n"
5207             "  \"remainingUTXOs\": xxx       (numeric) Number of coinbase utxos still available for shielding.\n"
5208             "  \"remainingValue\": xxx       (numeric) Value of coinbase utxos still available for shielding.\n"
5209             "  \"shieldingUTXOs\": xxx        (numeric) Number of coinbase utxos being shielded.\n"
5210             "  \"shieldingValue\": xxx        (numeric) Value of coinbase utxos being shielded.\n"
5211             "  \"opid\": xxx          (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
5212             "}\n"
5213             "\nExamples:\n"
5214             + HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
5215             + HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
5216         );
5217
5218     LOCK2(cs_main, pwalletMain->cs_wallet);
5219
5220     // Validate the from address
5221     auto fromaddress = params[0].get_str();
5222     bool isFromWildcard = fromaddress == "*";
5223     CTxDestination taddr;
5224     if (!isFromWildcard) {
5225         taddr = DecodeDestination(fromaddress);
5226         if (!IsValidDestination(taddr)) {
5227             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
5228         }
5229     }
5230
5231     // Validate the destination address
5232     auto destaddress = params[1].get_str();
5233     if (!IsValidPaymentAddressString(destaddress, CurrentEpochBranchId(chainActive.Height(), Params().GetConsensus()))) {
5234         throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
5235     }
5236
5237     // Convert fee from currency format to zatoshis
5238     CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
5239     if (params.size() > 2) {
5240         if (params[2].get_real() == 0.0) {
5241             nFee = 0;
5242         } else {
5243             nFee = AmountFromValue( params[2] );
5244         }
5245     }
5246
5247     int nLimit = SHIELD_COINBASE_DEFAULT_LIMIT;
5248     if (params.size() > 3) {
5249         nLimit = params[3].get_int();
5250         if (nLimit < 0) {
5251             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of utxos cannot be negative");
5252         }
5253     }
5254
5255     int nextBlockHeight = chainActive.Height() + 1;
5256     bool overwinterActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER);
5257     unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
5258     if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) {
5259         max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
5260         auto res = DecodePaymentAddress(destaddress);
5261         // If Sapling is not active, do not allow sending to a Sapling address.
5262         if (IsValidPaymentAddress(res)) {
5263             bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
5264             if (toSapling) {
5265                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
5266             }
5267         } else {
5268             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
5269         }
5270     }
5271
5272     // Prepare to get coinbase utxos
5273     std::vector<ShieldCoinbaseUTXO> inputs;
5274     CAmount shieldedValue = 0;
5275     CAmount remainingValue = 0;
5276     size_t estimatedTxSize = 2000;  // 1802 joinsplit description + tx overhead + wiggle room
5277
5278     #ifdef __LP64__
5279     uint64_t utxoCounter = 0;
5280     #else
5281     size_t utxoCounter = 0;
5282     #endif
5283
5284     bool maxedOutFlag = false;
5285     size_t mempoolLimit = (nLimit != 0) ? nLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
5286
5287     // Set of addresses to filter utxos by
5288     std::set<CTxDestination> destinations = {};
5289     if (!isFromWildcard) {
5290         destinations.insert(taddr);
5291     }
5292
5293     // Get available utxos
5294     vector<COutput> vecOutputs;
5295     pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, true);
5296
5297     // Find unspent coinbase utxos and update estimated size
5298     BOOST_FOREACH(const COutput& out, vecOutputs) {
5299         if (!out.fSpendable) {
5300             continue;
5301         }
5302
5303         CTxDestination address;
5304         if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
5305             continue;
5306         }
5307
5308         // If taddr is not wildcard "*", filter utxos
5309         if (destinations.size() > 0 && !destinations.count(address)) {
5310             continue;
5311         }
5312
5313         if (!out.tx->IsCoinBase()) {
5314             continue;
5315         }
5316
5317         utxoCounter++;
5318         auto scriptPubKey = out.tx->vout[out.i].scriptPubKey;
5319         CAmount nValue = out.tx->vout[out.i].nValue;
5320
5321         if (!maxedOutFlag) {
5322             size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
5323             if (estimatedTxSize + increase >= max_tx_size ||
5324                 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
5325             {
5326                 maxedOutFlag = true;
5327             } else {
5328                 estimatedTxSize += increase;
5329                 ShieldCoinbaseUTXO utxo = {out.tx->GetHash(), out.i, scriptPubKey, nValue};
5330                 inputs.push_back(utxo);
5331                 shieldedValue += nValue;
5332             }
5333         }
5334
5335         if (maxedOutFlag) {
5336             remainingValue += nValue;
5337         }
5338     }
5339
5340     #ifdef __LP64__
5341     uint64_t numUtxos = inputs.size();
5342     #else
5343     size_t numUtxos = inputs.size();
5344     #endif
5345
5346     if (numUtxos == 0) {
5347         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase funds to shield.");
5348     }
5349
5350     if (shieldedValue < nFee) {
5351         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
5352             strprintf("Insufficient coinbase funds, have %s, which is less than miners fee %s",
5353             FormatMoney(shieldedValue), FormatMoney(nFee)));
5354     }
5355
5356     // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
5357     CAmount netAmount = shieldedValue - nFee;
5358     if (nFee > netAmount) {
5359         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
5360     }
5361
5362     // Keep record of parameters in context object
5363     UniValue contextInfo(UniValue::VOBJ);
5364     contextInfo.push_back(Pair("fromaddress", params[0]));
5365     contextInfo.push_back(Pair("toaddress", params[1]));
5366     contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
5367
5368     // Builder (used if Sapling addresses are involved)
5369     TransactionBuilder builder = TransactionBuilder(
5370         Params().GetConsensus(), nextBlockHeight, pwalletMain);
5371
5372     // Contextual transaction we will build on
5373     int blockHeight = chainActive.LastTip()->GetHeight();
5374     nextBlockHeight = blockHeight + 1;
5375     // (used if no Sapling addresses are involved)
5376     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
5377         Params().GetConsensus(), nextBlockHeight);
5378     contextualTx.nLockTime = chainActive.LastTip()->GetHeight();
5379
5380     if (contextualTx.nVersion == 1) {
5381         contextualTx.nVersion = 2; // Tx format should support vjoinsplits
5382     }
5383
5384     // Create operation and add to global queue
5385     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
5386     std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress, nFee, contextInfo) );
5387     q->addOperation(operation);
5388     AsyncRPCOperationId operationId = operation->getId();
5389
5390     // Return continuation information
5391     UniValue o(UniValue::VOBJ);
5392     o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
5393     o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue)));
5394     o.push_back(Pair("shieldingUTXOs", static_cast<uint64_t>(numUtxos)));
5395     o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
5396     o.push_back(Pair("opid", operationId));
5397     return o;
5398 }
5399
5400
5401 #define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
5402 #define MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT 20
5403 #define MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT 200
5404
5405 #define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)
5406 #define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION)
5407 #define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION)
5408
5409 UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
5410 {
5411     if (!EnsureWalletIsAvailable(fHelp))
5412         return NullUniValue;
5413
5414     string enableArg = "zmergetoaddress";
5415     auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, false);
5416     std::string strDisabledMsg = "";
5417     if (!fEnableMergeToAddress) {
5418         strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
5419     }
5420
5421     if (fHelp || params.size() < 2 || params.size() > 6)
5422         throw runtime_error(
5423             "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
5424             + strDisabledMsg +
5425             "\nMerge multiple UTXOs and notes into a single UTXO or note. Protected coinbase UTXOs are ignored, use `z_shieldcoinbase`"
5426             "\nto combine those into a single note."
5427             "\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked.  If there is an error, they"
5428             "\nare unlocked.  The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
5429             "\n\nThe number of UTXOs and notes selected for merging can be limited by the caller.  If the transparent limit"
5430             "\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
5431             "\nnumber of UTXOs.  After Overwinter has activated -mempooltxinputlimit is ignored and having a transparent"
5432             "\ninput limit of zero will mean limit the number of UTXOs based on the size of the transaction.  Any limit is"
5433             "\nconstrained by the consensus rule defining a maximum transaction size of "
5434             + strprintf("%d bytes before Sapling, and %d", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
5435             + "\nbytes once Sapling activates."
5436             + HelpRequiringPassphrase() + "\n"
5437             "\nArguments:\n"
5438             "1. fromaddresses         (array, required) A JSON array with addresses.\n"
5439             "                         The following special strings are accepted inside the array:\n"
5440             "                             - \"ANY_TADDR\":   Merge UTXOs from any t-addrs belonging to the wallet.\n"
5441             "                             - \"ANY_SPROUT\":  Merge notes from any Sprout zaddrs belonging to the wallet.\n"
5442             "                             - \"ANY_SAPLING\": Merge notes from any Sapling zaddrs belonging to the wallet.\n"
5443             "                         While it is possible to use a variety of different combinations of addresses and the above values,\n"
5444             "                         it is not possible to send funds from both sprout and sapling addresses simultaneously. If a special\n"
5445             "                         string is given, any given addresses of that type will be counted as duplicates and cause an error.\n"
5446             "    [\n"
5447             "      \"address\"          (string) Can be a t-addr or a zaddr\n"
5448             "      ,...\n"
5449             "    ]\n"
5450             "2. \"toaddress\"           (string, required) The t-addr or zaddr to send the funds to.\n"
5451             "3. fee                   (numeric, optional, default="
5452             + strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
5453             "4. transparent_limit     (numeric, optional, default="
5454             + 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 (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
5455             "5. shielded_limit        (numeric, optional, default="
5456             + strprintf("%d Sprout or %d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT, MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge.  Set to 0 to merge as many as will fit in the transaction.\n"
5457             "6. \"memo\"                (string, optional) Encoded as hex. When toaddress is a zaddr, this will be stored in the memo field of the new note.\n"
5458             "\nResult:\n"
5459             "{\n"
5460             "  \"remainingUTXOs\": xxx               (numeric) Number of UTXOs still available for merging.\n"
5461             "  \"remainingTransparentValue\": xxx    (numeric) Value of UTXOs still available for merging.\n"
5462             "  \"remainingNotes\": xxx               (numeric) Number of notes still available for merging.\n"
5463             "  \"remainingShieldedValue\": xxx       (numeric) Value of notes still available for merging.\n"
5464             "  \"mergingUTXOs\": xxx                 (numeric) Number of UTXOs being merged.\n"
5465             "  \"mergingTransparentValue\": xxx      (numeric) Value of UTXOs being merged.\n"
5466             "  \"mergingNotes\": xxx                 (numeric) Number of notes being merged.\n"
5467             "  \"mergingShieldedValue\": xxx         (numeric) Value of notes being merged.\n"
5468             "  \"opid\": xxx                         (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
5469             "}\n"
5470             "\nExamples:\n"
5471             + HelpExampleCli("z_mergetoaddress", "'[\"ANY_SAPLING\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
5472             + HelpExampleRpc("z_mergetoaddress", "[\"ANY_SAPLING\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
5473         );
5474
5475     if (!fEnableMergeToAddress) {
5476         throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled. Run './zcash-cli help z_mergetoaddress' for instructions on how to enable this feature.");
5477     }
5478
5479     LOCK2(cs_main, pwalletMain->cs_wallet);
5480
5481     bool useAnyUTXO = false;
5482     bool useAnySprout = false;
5483     bool useAnySapling = false;
5484     std::set<CTxDestination> taddrs = {};
5485     std::set<libzcash::PaymentAddress> zaddrs = {};
5486
5487     uint32_t branchId = CurrentEpochBranchId(chainActive.Height(), Params().GetConsensus());
5488
5489     UniValue addresses = params[0].get_array();
5490     if (addresses.size()==0)
5491         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
5492
5493     // Keep track of addresses to spot duplicates
5494     std::set<std::string> setAddress;
5495
5496     // Sources
5497     for (const UniValue& o : addresses.getValues()) {
5498         if (!o.isStr())
5499             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
5500
5501         std::string address = o.get_str();
5502
5503         if (address == "ANY_TADDR") {
5504             useAnyUTXO = true;
5505         } else if (address == "ANY_SPROUT") {
5506             useAnySprout = true;
5507         } else if (address == "ANY_SAPLING") {
5508             useAnySapling = true;
5509         } else {
5510             CTxDestination taddr = DecodeDestination(address);
5511             if (IsValidDestination(taddr)) {
5512                 taddrs.insert(taddr);
5513             } else {
5514                 auto zaddr = DecodePaymentAddress(address);
5515                 if (IsValidPaymentAddress(zaddr)) {
5516                     zaddrs.insert(zaddr);
5517                 } else {
5518                     throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
5519                 }
5520             }
5521         }
5522
5523         if (setAddress.count(address))
5524             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
5525         setAddress.insert(address);
5526     }
5527
5528     if (useAnyUTXO && taddrs.size() > 0) {
5529         throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific taddrs when using \"ANY_TADDR\"");
5530     }
5531     if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) {
5532         throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific zaddrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\"");
5533     }
5534
5535     const int nextBlockHeight = chainActive.Height() + 1;
5536     const bool overwinterActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER);
5537     const bool saplingActive =  Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING);
5538
5539     // Validate the destination address
5540     auto destaddress = params[1].get_str();
5541     bool isToSproutZaddr = false;
5542     bool isToSaplingZaddr = false;
5543     CTxDestination taddr = DecodeDestination(destaddress);
5544     if (!IsValidDestination(taddr)) {
5545         if (IsValidPaymentAddressString(destaddress, branchId)) {
5546             // Is this a Sapling address?
5547             auto res = DecodePaymentAddress(destaddress);
5548             if (IsValidPaymentAddress(res)) {
5549                 isToSaplingZaddr = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
5550             } else {
5551                 isToSproutZaddr = true;
5552             }
5553         } else {
5554             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
5555         }
5556     }
5557     else if ( ASSETCHAINS_PRIVATE != 0 )
5558         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
5559
5560     // Convert fee from currency format to zatoshis
5561     CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
5562     if (params.size() > 2) {
5563         if (params[2].get_real() == 0.0) {
5564             nFee = 0;
5565         } else {
5566             nFee = AmountFromValue( params[2] );
5567         }
5568     }
5569
5570     int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
5571     if (params.size() > 3) {
5572         nUTXOLimit = params[3].get_int();
5573         if (nUTXOLimit < 0) {
5574             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
5575         }
5576     }
5577
5578     int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT;
5579     int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT;
5580     if (params.size() > 4) {
5581         int nNoteLimit = params[4].get_int();
5582         if (nNoteLimit < 0) {
5583             throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
5584         }
5585         sproutNoteLimit = nNoteLimit;
5586         saplingNoteLimit = nNoteLimit;
5587     }
5588
5589     std::string memo;
5590     if (params.size() > 5) {
5591         memo = params[5].get_str();
5592         if (!(isToSproutZaddr || isToSaplingZaddr)) {
5593             throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr.  It can only be used with a zaddr.");
5594         } else if (!IsHex(memo)) {
5595             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
5596         }
5597         if (memo.length() > ZC_MEMO_SIZE*2) {
5598             throw JSONRPCError(RPC_INVALID_PARAMETER,  strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
5599         }
5600     }
5601
5602     MergeToAddressRecipient recipient(destaddress, memo);
5603
5604     // Prepare to get UTXOs and notes
5605     std::vector<MergeToAddressInputUTXO> utxoInputs;
5606     std::vector<MergeToAddressInputSproutNote> sproutNoteInputs;
5607     std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs;
5608     CAmount mergedUTXOValue = 0;
5609     CAmount mergedNoteValue = 0;
5610     CAmount remainingUTXOValue = 0;
5611     CAmount remainingNoteValue = 0;
5612     #ifdef __LP64__
5613     uint64_t utxoCounter = 0;
5614     uint64_t noteCounter = 0;
5615     #else
5616     size_t utxoCounter = 0;
5617     size_t noteCounter = 0;
5618     #endif
5619     bool maxedOutUTXOsFlag = false;
5620     bool maxedOutNotesFlag = false;
5621     size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
5622
5623     unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING;
5624     size_t estimatedTxSize = 200;  // tx overhead + wiggle room
5625     if (isToSproutZaddr) {
5626         estimatedTxSize += JOINSPLIT_SIZE;
5627     } else if (isToSaplingZaddr) {
5628         estimatedTxSize += OUTPUTDESCRIPTION_SIZE;
5629     }
5630
5631     if (useAnyUTXO || taddrs.size() > 0) {
5632         // Get available utxos
5633         vector<COutput> vecOutputs;
5634         pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
5635
5636         // Find unspent utxos and update estimated size
5637         for (const COutput& out : vecOutputs) {
5638             if (!out.fSpendable) {
5639                 continue;
5640             }
5641
5642             CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey;
5643
5644             CTxDestination address;
5645             if (!ExtractDestination(scriptPubKey, address)) {
5646                 continue;
5647             }
5648             // If taddr is not wildcard "*", filter utxos
5649             if (taddrs.size() > 0 && !taddrs.count(address)) {
5650                 continue;
5651             }
5652
5653             utxoCounter++;
5654             CAmount nValue = out.tx->vout[out.i].nValue;
5655
5656             if (!maxedOutUTXOsFlag) {
5657                 size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
5658                 if (estimatedTxSize + increase >= max_tx_size ||
5659                     (mempoolLimit > 0 && utxoCounter > mempoolLimit))
5660                 {
5661                     maxedOutUTXOsFlag = true;
5662                 } else {
5663                     estimatedTxSize += increase;
5664                     COutPoint utxo(out.tx->GetHash(), out.i);
5665                     utxoInputs.emplace_back(utxo, nValue, scriptPubKey);
5666                     mergedUTXOValue += nValue;
5667                 }
5668             }
5669
5670             if (maxedOutUTXOsFlag) {
5671                 remainingUTXOValue += nValue;
5672             }
5673         }
5674     }
5675
5676     if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
5677         // Get available notes
5678         std::vector<SproutNoteEntry> sproutEntries;
5679         std::vector<SaplingNoteEntry> saplingEntries;
5680         pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
5681
5682         // If Sapling is not active, do not allow sending from a sapling addresses.
5683         if (!saplingActive && saplingEntries.size() > 0) {
5684             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
5685         }
5686         // Do not include Sprout/Sapling notes if using "ANY_SAPLING"/"ANY_SPROUT" respectively
5687         if (useAnySprout) {
5688             saplingEntries.clear();
5689         }
5690         if (useAnySapling) {
5691             sproutEntries.clear();
5692         }
5693         // Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress
5694         if ((sproutEntries.size() > 0 && saplingEntries.size() > 0) || (useAnySprout && useAnySapling)) {
5695             throw JSONRPCError(
5696                 RPC_INVALID_PARAMETER,
5697                 "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress");
5698         }
5699         // If sending between shielded addresses, they must be the same type
5700         if ((saplingEntries.size() > 0 && isToSproutZaddr) || (sproutEntries.size() > 0 && isToSaplingZaddr)) {
5701             throw JSONRPCError(
5702                 RPC_INVALID_PARAMETER,
5703                 "Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
5704         }
5705
5706         // Find unspent notes and update estimated size
5707         for (const SproutNoteEntry& entry : sproutEntries) {
5708             noteCounter++;
5709             CAmount nValue = entry.note.value();
5710
5711             if (!maxedOutNotesFlag) {
5712                 // If we haven't added any notes yet and the merge is to a
5713                 // z-address, we have already accounted for the first JoinSplit.
5714                 size_t increase = (sproutNoteInputs.empty() && !isToSproutZaddr) || (sproutNoteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
5715                 if (estimatedTxSize + increase >= max_tx_size ||
5716                     (sproutNoteLimit > 0 && noteCounter > sproutNoteLimit))
5717                 {
5718                     maxedOutNotesFlag = true;
5719                 } else {
5720                     estimatedTxSize += increase;
5721                     auto zaddr = entry.address;
5722                     SproutSpendingKey zkey;
5723                     pwalletMain->GetSproutSpendingKey(zaddr, zkey);
5724                     sproutNoteInputs.emplace_back(entry.jsop, entry.note, nValue, zkey);
5725                     mergedNoteValue += nValue;
5726                 }
5727             }
5728
5729             if (maxedOutNotesFlag) {
5730                 remainingNoteValue += nValue;
5731             }
5732         }
5733
5734         for (const SaplingNoteEntry& entry : saplingEntries) {
5735             noteCounter++;
5736             CAmount nValue = entry.note.value();
5737             if (!maxedOutNotesFlag) {
5738                 size_t increase = SPENDDESCRIPTION_SIZE;
5739                 if (estimatedTxSize + increase >= max_tx_size ||
5740                     (saplingNoteLimit > 0 && noteCounter > saplingNoteLimit))
5741                 {
5742                     maxedOutNotesFlag = true;
5743                 } else {
5744                     estimatedTxSize += increase;
5745                     libzcash::SaplingExtendedSpendingKey extsk;
5746                     if (!pwalletMain->GetSaplingExtendedSpendingKey(entry.address, extsk)) {
5747                         throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find spending key for payment address.");
5748                     }
5749                     saplingNoteInputs.emplace_back(entry.op, entry.note, nValue, extsk.expsk);
5750                     mergedNoteValue += nValue;
5751                 }
5752             }
5753
5754             if (maxedOutNotesFlag) {
5755                 remainingNoteValue += nValue;
5756             }
5757         }
5758     }
5759
5760     #ifdef __LP64__
5761     uint64_t numUtxos = utxoInputs.size(); //ca333
5762     #else
5763     size_t numUtxos = utxoInputs.size();
5764     #endif
5765
5766     size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
5767
5768     if (numUtxos == 0 && numNotes == 0) {
5769         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
5770     }
5771
5772     // Sanity check: Don't do anything if:
5773     // - We only have one from address
5774     // - It's equal to toaddress
5775     // - The address only contains a single UTXO or note
5776     if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
5777         throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
5778     }
5779
5780     CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
5781     if (mergedValue < nFee) {
5782         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
5783             strprintf("Insufficient funds, have %s, which is less than miners fee %s",
5784             FormatMoney(mergedValue), FormatMoney(nFee)));
5785     }
5786
5787     // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
5788     CAmount netAmount = mergedValue - nFee;
5789     if (nFee > netAmount) {
5790         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
5791     }
5792
5793     // Keep record of parameters in context object
5794     UniValue contextInfo(UniValue::VOBJ);
5795     contextInfo.push_back(Pair("fromaddresses", params[0]));
5796     contextInfo.push_back(Pair("toaddress", params[1]));
5797     contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
5798
5799     // Contextual transaction we will build on
5800     CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
5801         Params().GetConsensus(),
5802         nextBlockHeight);
5803     bool isSproutShielded = sproutNoteInputs.size() > 0 || isToSproutZaddr;
5804     if (contextualTx.nVersion == 1 && isSproutShielded) {
5805         contextualTx.nVersion = 2; // Tx format should support vJoinSplit
5806     }
5807
5808     // Builder (used if Sapling addresses are involved)
5809     boost::optional<TransactionBuilder> builder;
5810     if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
5811         builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
5812     }
5813     // Create operation and add to global queue
5814     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
5815     std::shared_ptr<AsyncRPCOperation> operation(
5816         new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
5817     q->addOperation(operation);
5818     AsyncRPCOperationId operationId = operation->getId();
5819
5820     // Return continuation information
5821     UniValue o(UniValue::VOBJ);
5822     o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
5823     o.push_back(Pair("remainingTransparentValue", ValueFromAmount(remainingUTXOValue)));
5824     o.push_back(Pair("remainingNotes", static_cast<uint64_t>(noteCounter - numNotes)));
5825     o.push_back(Pair("remainingShieldedValue", ValueFromAmount(remainingNoteValue)));
5826     o.push_back(Pair("mergingUTXOs", static_cast<uint64_t>(numUtxos)));
5827     o.push_back(Pair("mergingTransparentValue", ValueFromAmount(mergedUTXOValue)));
5828     o.push_back(Pair("mergingNotes", static_cast<uint64_t>(numNotes)));
5829     o.push_back(Pair("mergingShieldedValue", ValueFromAmount(mergedNoteValue)));
5830     o.push_back(Pair("opid", operationId));
5831     return o;
5832 }
5833
5834
5835 UniValue z_listoperationids(const UniValue& params, bool fHelp)
5836 {
5837     if (!EnsureWalletIsAvailable(fHelp))
5838         return NullUniValue;
5839
5840     if (fHelp || params.size() > 1)
5841         throw runtime_error(
5842             "z_listoperationids\n"
5843             "\nReturns the list of operation ids currently known to the wallet.\n"
5844             "\nArguments:\n"
5845             "1. \"status\"         (string, optional) Filter result by the operation's state e.g. \"success\".\n"
5846             "\nResult:\n"
5847             "[                     (json array of string)\n"
5848             "  \"operationid\"       (string) an operation id belonging to the wallet\n"
5849             "  ,...\n"
5850             "]\n"
5851             "\nExamples:\n"
5852             + HelpExampleCli("z_listoperationids", "")
5853             + HelpExampleRpc("z_listoperationids", "")
5854         );
5855
5856     LOCK2(cs_main, pwalletMain->cs_wallet);
5857
5858     std::string filter;
5859     bool useFilter = false;
5860     if (params.size()==1) {
5861         filter = params[0].get_str();
5862         useFilter = true;
5863     }
5864
5865     UniValue ret(UniValue::VARR);
5866     std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
5867     std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
5868     for (auto id : ids) {
5869         std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
5870         if (!operation) {
5871             continue;
5872         }
5873         std::string state = operation->getStateAsString();
5874         if (useFilter && filter.compare(state)!=0)
5875             continue;
5876         ret.push_back(id);
5877     }
5878
5879     return ret;
5880 }
5881
5882
5883 #include "script/sign.h"
5884 int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
5885 extern std::string NOTARY_PUBKEY;
5886 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);
5887 int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout);
5888 void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n);
5889
5890 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
5891 {
5892     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;
5893     bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr;
5894     auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
5895     const CKeyStore& keystore = *pwalletMain;
5896     assert(pwalletMain != NULL);
5897     LOCK2(cs_main, pwalletMain->cs_wallet);
5898     utxovalue = 0;
5899     memset(&utxotxid,0,sizeof(utxotxid));
5900     memset(&utxovout,0,sizeof(utxovout));
5901     memset(utxosig,0,sizeof(utxosig));
5902     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
5903     BOOST_FOREACH(const COutput& out, vecOutputs)
5904     {
5905         if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
5906             continue;
5907         if ( setAddress.size() )
5908         {
5909             CTxDestination address;
5910             if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
5911                 continue;
5912             if (!setAddress.count(address))
5913                 continue;
5914         }
5915         CAmount nValue = out.tx->vout[out.i].nValue;
5916         if ( nValue != 10000 )
5917             continue;
5918         const CScript& pk = out.tx->vout[out.i].scriptPubKey;
5919         CTxDestination address;
5920         if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
5921         {
5922             //entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
5923             //if (pwalletMain->mapAddressBook.count(address))
5924             //    entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
5925         }
5926         script = (uint8_t *)&out.tx->vout[out.i].scriptPubKey[0];
5927         if ( out.tx->vout[out.i].scriptPubKey.size() != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(notarypub33,script+1,33) != 0 )
5928         {
5929             //fprintf(stderr,"scriptsize.%d [0] %02x\n",(int32_t)out.tx->vout[out.i].scriptPubKey.size(),script[0]);
5930             continue;
5931         }
5932         utxovalue = (uint64_t)nValue;
5933         //decode_hex((uint8_t *)&utxotxid,32,(char *)out.tx->GetHash().GetHex().c_str());
5934         utxotxid = out.tx->GetHash();
5935         utxovout = out.i;
5936         best_scriptPubKey = out.tx->vout[out.i].scriptPubKey;
5937         //fprintf(stderr,"check %s/v%d %llu\n",(char *)utxotxid.GetHex().c_str(),utxovout,(long long)utxovalue);
5938
5939         txNew.vin.resize(1);
5940         txNew.vout.resize(1);
5941         txfee = utxovalue / 2;
5942         //for (i=0; i<32; i++)
5943         //    ((uint8_t *)&revtxid)[i] = ((uint8_t *)&utxotxid)[31 - i];
5944         txNew.vin[0].prevout.hash = utxotxid; //revtxid;
5945         txNew.vin[0].prevout.n = utxovout;
5946         txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG;
5947         txNew.vout[0].nValue = utxovalue - txfee;
5948         CTransaction txNewConst(txNew);
5949         signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, utxovalue, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
5950         if (!signSuccess)
5951             fprintf(stderr,"notaryvin failed to create signature\n");
5952         else
5953         {
5954             UpdateTransaction(txNew,0,sigdata);
5955             ptr = (uint8_t *)&sigdata.scriptSig[0];
5956             siglen = sigdata.scriptSig.size();
5957             for (i=0; i<siglen; i++)
5958                 utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
5959             //fprintf(stderr," siglen.%d notaryvin %s/v%d\n",siglen,utxotxid.GetHex().c_str(),utxovout);
5960             break;
5961         }
5962     }
5963     return(siglen);
5964 }
5965
5966 struct komodo_staking
5967 {
5968     char address[64];
5969     uint256 txid;
5970     arith_uint256 hashval;
5971     uint64_t nValue;
5972     uint32_t segid32,txtime;
5973     int32_t vout;
5974     CScript scriptPubKey;
5975 };
5976
5977 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)
5978 {
5979     uint256 hash; uint32_t segid32; struct komodo_staking *kp;
5980     segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
5981     if ( *numkp >= *maxkp )
5982     {
5983         *maxkp += 1000;
5984         array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
5985     }
5986     kp = &array[(*numkp)++];
5987     memset(kp,0,sizeof(*kp));
5988     strcpy(kp->address,address);
5989     kp->txid = txid;
5990     kp->vout = vout;
5991     kp->hashval = UintToArith256(hash);
5992     kp->txtime = txtime;
5993     kp->segid32 = segid32;
5994     kp->nValue = nValue;
5995     kp->scriptPubKey = pk;
5996     return(array);
5997 }
5998
5999 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)
6000 {
6001     int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval;
6002     diff = (iter + blocktime - kp->txtime - minage);
6003     if ( diff < 0 )
6004         diff = 60;
6005     else if ( diff > 3600*24*30 )
6006         diff = 3600*24*30;
6007     if ( iter > 0 )
6008         diff += segid*2;
6009     coinage = ((uint64_t)kp->nValue/COIN * diff);
6010     if ( blocktime+iter+segid*2 > prevtime+480 )
6011         coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
6012     //if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
6013     //    coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
6014     coinage256 = arith_uint256(coinage+1);
6015     hashval = ratio * (kp->hashval / coinage256);
6016     //if ( nHeight >= 900 && nHeight < 916 )
6017     //    hashval = (hashval / coinage256);
6018     return(hashval);
6019 }
6020
6021 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)
6022 {
6023     int32_t maxiters = 600; uint256 hash;
6024     int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256;
6025     komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout);
6026     kp->hashval = UintToArith256(hash);
6027     segid = ((nHeight + kp->segid32) & 0x3f);
6028     hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime);
6029     //for (int i=32; i>=0; i--)
6030     //    fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
6031     //fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime);
6032     if ( hashval <= bnTarget )
6033     {
6034         for (iter=0; iter<maxiters; iter++)
6035         {
6036             if ( blocktime+iter+segid*2 < kp->txtime+minage )
6037                 continue;
6038             hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime);
6039             if ( hashval <= bnTarget )
6040             {
6041                 //fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid);
6042                 blocktime += iter;
6043                 blocktime += segid * 2;
6044                 return(blocktime);
6045             }
6046         }
6047     }
6048     return(0);
6049 }
6050
6051 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)
6052 {
6053     static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime;
6054     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;
6055     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
6056     mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
6057     ratio = (mindiff / bnTarget);
6058     assert(pwalletMain != NULL);
6059     LOCK2(cs_main, pwalletMain->cs_wallet);
6060     *utxovaluep = 0;
6061     memset(utxotxidp,0,sizeof(*utxotxidp));
6062     memset(utxovoutp,0,sizeof(*utxovoutp));
6063     memset(utxosig,0,72);
6064     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
6065     if ( (tipindex= chainActive.Tip()) == 0 )
6066         return(0);
6067     nHeight = tipindex->GetHeight() + 1;
6068     if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
6069         minage = 6000;
6070     komodo_segids(hashbuf,nHeight-101,100);
6071     if ( *blocktimep > tipindex->nTime+60 )
6072         *blocktimep = tipindex->nTime+60;
6073     //fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
6074     if ( time(NULL) > lasttime+600 )
6075     {
6076         if ( array != 0 )
6077         {
6078             free(array);
6079             array = 0;
6080             maxkp = numkp = 0;
6081             lasttime = 0;
6082         }
6083         BOOST_FOREACH(const COutput& out, vecOutputs)
6084         {
6085             if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight )
6086             {
6087                 fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
6088                 return(0);
6089             }
6090             counter++;
6091             if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
6092             {
6093                 //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
6094                 continue;
6095             }
6096             CAmount nValue = out.tx->vout[out.i].nValue;
6097             if ( nValue < COIN  || !out.fSpendable )
6098                 continue;
6099             const CScript& pk = out.tx->vout[out.i].scriptPubKey;
6100             if ( ExtractDestination(pk,address) != 0 )
6101             {
6102                 if ( IsMine(*pwalletMain,address) == 0 )
6103                     continue;
6104                 if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && mapBlockIndex.count(hashBlock) && (pindex= mapBlockIndex[hashBlock]) != 0 )
6105                 {
6106                     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);
6107                 }
6108             }
6109         }
6110         lasttime = (uint32_t)time(NULL);
6111         //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
6112     }
6113     block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
6114     for (i=winners=0; i<numkp; i++)
6115     {
6116         if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight )
6117         {
6118             fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
6119             return(0);
6120         }
6121         kp = &array[i];
6122         if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
6123             continue;
6124         eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
6125         //fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
6126         if ( eligible > 0 )
6127         {
6128             besttime = m = 0;
6129             if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
6130             {
6131                 while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
6132                 {
6133                     besttime = eligible;
6134                     eligible--;
6135                     if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
6136                         break;
6137                     m++;
6138                     //fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
6139                 }
6140             }
6141             else
6142             {
6143                 fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
6144                 continue;
6145             }
6146             eligible = besttime;
6147             winners++;
6148             //fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
6149             if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
6150             {
6151                 earliest = eligible;
6152                 best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey;
6153                 *utxovaluep = (uint64_t)kp->nValue;
6154                 //decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str());
6155                 decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
6156                 *utxovoutp = kp->vout;
6157                 *txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime;
6158                 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);
6159             }
6160         } //else fprintf(stderr,"utxo not eligible\n");
6161     } //else fprintf(stderr,"no tipindex\n");
6162     if ( numkp < 10000 && array != 0 )
6163     {
6164         free(array);
6165         array = 0;
6166         maxkp = numkp = 0;
6167         lasttime = 0;
6168     }
6169     if ( earliest != 0 )
6170     {
6171         bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid;
6172         auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
6173         const CKeyStore& keystore = *pwalletMain;
6174         txNew.vin.resize(1);
6175         txNew.vout.resize(1);
6176         txfee = 0;
6177         for (i=0; i<32; i++)
6178             ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i];
6179         txNew.vin[0].prevout.hash = revtxid;
6180         txNew.vin[0].prevout.n = *utxovoutp;
6181         txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
6182         txNew.vout[0].nValue = *utxovaluep - txfee;
6183         txNew.nLockTime = earliest;
6184         CTransaction txNewConst(txNew);
6185         signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
6186         if (!signSuccess)
6187             fprintf(stderr,"failed to create signature\n");
6188         else
6189         {
6190             UpdateTransaction(txNew,0,sigdata);
6191             ptr = (uint8_t *)&sigdata.scriptSig[0];
6192             siglen = sigdata.scriptSig.size();
6193             for (i=0; i<siglen; i++)
6194                 utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
6195             //fprintf(stderr," siglen.%d\n",siglen);
6196             //fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
6197             *blocktimep = earliest;
6198         }
6199     } //else fprintf(stderr,"no earliest utxo for staking\n");
6200     //fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners);
6201     return(siglen);
6202 }
6203
6204 int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk)
6205 {
6206     return pwalletMain->VerusStakeTransaction(pBlock, txNew, nBits, hashResult, utxosig, pk);
6207 }
6208
6209 int32_t ensure_CCrequirements()
6210 {
6211     extern uint8_t NOTARY_PUBKEY33[];
6212     CCerror = "";
6213     if ( NOTARY_PUBKEY33[0] == 0 )
6214         return(-1);
6215     else if ( GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX) == 0 )
6216         return(-1);
6217     else if ( GetBoolArg("-spentindex", DEFAULT_SPENTINDEX) == 0 )
6218         return(-1);
6219     else return(0);
6220 }
6221
6222 #include "../cc/CCfaucet.h"
6223 #include "../cc/CCassets.h"
6224 #include "../cc/CCrewards.h"
6225 #include "../cc/CCdice.h"
6226 #include "../cc/CCfsm.h"
6227 #include "../cc/CCauction.h"
6228 #include "../cc/CClotto.h"
6229 #include "../cc/CCchannels.h"
6230 #include "../cc/CCOracles.h"
6231 #include "../cc/CCGateways.h"
6232
6233 UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey)
6234 {
6235     UniValue result(UniValue::VOBJ); char destaddr[64],str[64]; CPubKey pk;
6236     pk = GetUnspendable(cp,0);
6237     GetCCaddress(cp,destaddr,pk);
6238     if ( strcmp(destaddr,cp->unspendableCCaddr) != 0 )
6239     {
6240         uint8_t priv[32];
6241         Myprivkey(priv); // it is assumed the CC's normal address'es -pubkey was used
6242         fprintf(stderr,"fix mismatched CCaddr %s -> %s\n",cp->unspendableCCaddr,destaddr);
6243         strcpy(cp->unspendableCCaddr,destaddr);
6244     }
6245     result.push_back(Pair("result", "success"));
6246     sprintf(str,"%sCCaddress",name);
6247     result.push_back(Pair(str,cp->unspendableCCaddr));
6248     sprintf(str,"%smarker",name);
6249     result.push_back(Pair(str,cp->normaladdr));
6250     result.push_back(Pair("GatewaysPubkey","03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40"));
6251     if ( _GetCCaddress(destaddr,EVAL_ASSETS,pubkey2pk(pubkey)) > 0 )
6252     {
6253         sprintf(str,"%sCCassets",name);
6254         result.push_back(Pair(str,destaddr));
6255     }
6256     if ( pubkey.size() == 33 )
6257     {
6258         if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 )
6259             result.push_back(Pair("CCaddress",destaddr));
6260     }
6261     if ( GetCCaddress(cp,destaddr,pubkey2pk(Mypubkey())) != 0 )
6262         result.push_back(Pair("myCCaddress",destaddr));
6263     if ( Getscriptaddress(destaddr,(CScript() << Mypubkey() << OP_CHECKSIG)) != 0 )
6264         result.push_back(Pair("myaddress",destaddr));
6265     return(result);
6266 }
6267
6268 UniValue channelsaddress(const UniValue& params, bool fHelp)
6269 {
6270     UniValue result(UniValue::VOBJ);  struct CCcontract_info *cp,C; std::vector<unsigned char> destpubkey; CPubKey pk,pk2; char destaddr[64];
6271     cp = CCinit(&C,EVAL_CHANNELS);
6272     if ( fHelp || params.size() != 1 )
6273         throw runtime_error("channelsaddress destpubkey\n");
6274     if ( ensure_CCrequirements() < 0 )
6275         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6276     destpubkey = ParseHex(params[0].get_str().c_str());
6277     pk = pubkey2pk(Mypubkey());
6278     pk2 = pubkey2pk(destpubkey);
6279     result = CCaddress(cp,(char *)"Channels",destpubkey);
6280     result.push_back(Pair("otherpubkey", params[0].get_str()));
6281     GetCCaddress1of2(cp,destaddr,pk,pk2);
6282     result.push_back(Pair("channeladdress",destaddr));
6283     return(result);
6284 }
6285
6286 UniValue oraclesaddress(const UniValue& params, bool fHelp)
6287 {
6288     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6289     cp = CCinit(&C,EVAL_ORACLES);
6290     if ( fHelp || params.size() > 1 )
6291         throw runtime_error("oraclesaddress [pubkey]\n");
6292     if ( ensure_CCrequirements() < 0 )
6293         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6294     if ( params.size() == 1 )
6295         pubkey = ParseHex(params[0].get_str().c_str());
6296     return(CCaddress(cp,(char *)"Oracles",pubkey));
6297 }
6298
6299 UniValue pricesaddress(const UniValue& params, bool fHelp)
6300 {
6301     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6302     cp = CCinit(&C,EVAL_PRICES);
6303     if ( fHelp || params.size() > 1 )
6304         throw runtime_error("pricesaddress [pubkey]\n");
6305     if ( ensure_CCrequirements() < 0 )
6306         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6307     if ( params.size() == 1 )
6308         pubkey = ParseHex(params[0].get_str().c_str());
6309     return(CCaddress(cp,(char *)"Prices",pubkey));
6310 }
6311
6312 UniValue pegsaddress(const UniValue& params, bool fHelp)
6313 {
6314     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6315     cp = CCinit(&C,EVAL_PEGS);
6316     if ( fHelp || params.size() > 1 )
6317         throw runtime_error("pegssaddress [pubkey]\n");
6318     if ( ensure_CCrequirements() < 0 )
6319         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6320     if ( params.size() == 1 )
6321         pubkey = ParseHex(params[0].get_str().c_str());
6322     return(CCaddress(cp,(char *)"Pegs",pubkey));
6323 }
6324
6325 UniValue triggersaddress(const UniValue& params, bool fHelp)
6326 {
6327     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6328     cp = CCinit(&C,EVAL_TRIGGERS);
6329     if ( fHelp || params.size() > 1 )
6330         throw runtime_error("triggersaddress [pubkey]\n");
6331     if ( ensure_CCrequirements() < 0 )
6332         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6333     if ( params.size() == 1 )
6334         pubkey = ParseHex(params[0].get_str().c_str());
6335     return(CCaddress(cp,(char *)"Triggers",pubkey));
6336 }
6337
6338 UniValue paymentsaddress(const UniValue& params, bool fHelp)
6339 {
6340     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6341     cp = CCinit(&C,EVAL_PAYMENTS);
6342     if ( fHelp || params.size() > 1 )
6343         throw runtime_error("paymentsaddress [pubkey]\n");
6344     if ( ensure_CCrequirements() < 0 )
6345         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6346     if ( params.size() == 1 )
6347         pubkey = ParseHex(params[0].get_str().c_str());
6348     return(CCaddress(cp,(char *)"Payments",pubkey));
6349 }
6350
6351 UniValue gatewaysaddress(const UniValue& params, bool fHelp)
6352 {
6353     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6354     cp = CCinit(&C,EVAL_GATEWAYS);
6355     if ( fHelp || params.size() > 1 )
6356         throw runtime_error("gatewaysaddress [pubkey]\n");
6357     if ( ensure_CCrequirements() < 0 )
6358         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6359     if ( params.size() == 1 )
6360         pubkey = ParseHex(params[0].get_str().c_str());
6361     return(CCaddress(cp,(char *)"Gateways",pubkey));
6362 }
6363
6364 UniValue mofnaddress(const UniValue& params, bool fHelp)
6365 {
6366     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6367     cp = CCinit(&C,EVAL_MOFN);
6368     if ( fHelp || params.size() > 1 )
6369         throw runtime_error("mofnaddress [pubkey]\n");
6370     if ( ensure_CCrequirements() < 0 )
6371         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6372     if ( params.size() == 1 )
6373         pubkey = ParseHex(params[0].get_str().c_str());
6374     return(CCaddress(cp,(char *)"MofN",pubkey));
6375 }
6376
6377 UniValue lottoaddress(const UniValue& params, bool fHelp)
6378 {
6379     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6380     cp = CCinit(&C,EVAL_LOTTO);
6381     if ( fHelp || params.size() > 1 )
6382         throw runtime_error("lottoaddress [pubkey]\n");
6383     if ( ensure_CCrequirements() < 0 )
6384         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6385     if ( params.size() == 1 )
6386         pubkey = ParseHex(params[0].get_str().c_str());
6387     return(CCaddress(cp,(char *)"Lotto",pubkey));
6388 }
6389
6390 UniValue FSMaddress(const UniValue& params, bool fHelp)
6391 {
6392     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6393     cp = CCinit(&C,EVAL_FSM);
6394     if ( fHelp || params.size() > 1 )
6395         throw runtime_error("FSMaddress [pubkey]\n");
6396     if ( ensure_CCrequirements() < 0 )
6397         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6398     if ( params.size() == 1 )
6399         pubkey = ParseHex(params[0].get_str().c_str());
6400     return(CCaddress(cp,(char *)"FSM",pubkey));
6401 }
6402
6403 UniValue auctionaddress(const UniValue& params, bool fHelp)
6404 {
6405     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6406     cp = CCinit(&C,EVAL_AUCTION);
6407     if ( fHelp || params.size() > 1 )
6408         throw runtime_error("auctionaddress [pubkey]\n");
6409     if ( ensure_CCrequirements() < 0 )
6410         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6411     if ( params.size() == 1 )
6412         pubkey = ParseHex(params[0].get_str().c_str());
6413     return(CCaddress(cp,(char *)"Auction",pubkey));
6414 }
6415
6416 UniValue diceaddress(const UniValue& params, bool fHelp)
6417 {
6418     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6419     cp = CCinit(&C,EVAL_DICE);
6420     if ( fHelp || params.size() > 1 )
6421         throw runtime_error("diceaddress [pubkey]\n");
6422     if ( ensure_CCrequirements() < 0 )
6423         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6424     if ( params.size() == 1 )
6425         pubkey = ParseHex(params[0].get_str().c_str());
6426     return(CCaddress(cp,(char *)"Dice",pubkey));
6427 }
6428
6429 UniValue faucetaddress(const UniValue& params, bool fHelp)
6430 {
6431     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6432     int32_t errno;
6433     cp = CCinit(&C,EVAL_FAUCET);
6434     if ( fHelp || params.size() > 1 )
6435         throw runtime_error("faucetaddress [pubkey]\n");
6436     errno = ensure_CCrequirements();
6437     if ( errno < 0 )
6438         throw runtime_error(strprintf("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet. ERR=%d\n", errno));
6439     if ( params.size() == 1 )
6440         pubkey = ParseHex(params[0].get_str().c_str());
6441     return(CCaddress(cp,(char *)"Faucet",pubkey));
6442 }
6443
6444 UniValue rewardsaddress(const UniValue& params, bool fHelp)
6445 {
6446     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6447     cp = CCinit(&C,EVAL_REWARDS);
6448     if ( fHelp || params.size() > 1 )
6449         throw runtime_error("rewardsaddress [pubkey]\n");
6450     if ( ensure_CCrequirements() < 0 )
6451         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6452     if ( params.size() == 1 )
6453         pubkey = ParseHex(params[0].get_str().c_str());
6454     return(CCaddress(cp,(char *)"Rewards",pubkey));
6455 }
6456
6457 UniValue tokenaddress(const UniValue& params, bool fHelp)
6458 {
6459     struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
6460     cp = CCinit(&C,EVAL_ASSETS);
6461     if ( fHelp || params.size() > 1 )
6462         throw runtime_error("tokenaddress [pubkey]\n");
6463     if ( ensure_CCrequirements() < 0 )
6464         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6465     if ( params.size() == 1 )
6466         pubkey = ParseHex(params[0].get_str().c_str());
6467     return(CCaddress(cp,(char *)"Assets",pubkey));
6468 }
6469
6470 UniValue channelsinfo(const UniValue& params, bool fHelp)
6471 {
6472     if ( fHelp || params.size() != 0 )
6473         throw runtime_error("channelsinfo\n");
6474     if ( ensure_CCrequirements() < 0 )
6475         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6476     return(ChannelsInfo());
6477 }
6478
6479 UniValue channelsopen(const UniValue& params, bool fHelp)
6480 {
6481     UniValue result(UniValue::VOBJ); int32_t numpayments; int64_t payment; std::vector<unsigned char> destpub; struct CCcontract_info *cp,C; std::string hex;
6482     cp = CCinit(&C,EVAL_CHANNELS);
6483     if ( fHelp || params.size() != 3 )
6484         throw runtime_error("channelsopen destpubkey numpayments payment\n");
6485     if ( ensure_CCrequirements() < 0 )
6486         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6487     LOCK(cs_main);
6488     destpub = ParseHex(params[0].get_str().c_str());
6489     numpayments = atoi(params[1].get_str().c_str());
6490     payment = atol(params[2].get_str().c_str());
6491     hex = ChannelOpen(0,pubkey2pk(destpub),numpayments,payment);
6492     if ( hex.size() > 0 )
6493     {
6494         result.push_back(Pair("result", "success"));
6495         result.push_back(Pair("hex", hex));
6496     } else ERR_RESULT("couldnt create channelsopen transaction");
6497     return(result);
6498 }
6499
6500 UniValue channelsstop(const UniValue& params, bool fHelp)
6501 {
6502     UniValue result(UniValue::VOBJ); std::vector<unsigned char> destpub; struct CCcontract_info *cp,C; std::string hex; uint256 origtxid;
6503     cp = CCinit(&C,EVAL_CHANNELS);
6504     if ( fHelp || params.size() != 2 )
6505         throw runtime_error("channelsstop destpubkey origtxid\n");
6506     if ( ensure_CCrequirements() < 0 )
6507         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6508     LOCK(cs_main);
6509     destpub = ParseHex(params[0].get_str().c_str());
6510     origtxid = Parseuint256((char *)params[1].get_str().c_str());
6511     hex = ChannelStop(0,pubkey2pk(destpub),origtxid);
6512     if ( hex.size() > 0 )
6513     {
6514         result.push_back(Pair("result", "success"));
6515         result.push_back(Pair("hex", hex));
6516     } else ERR_RESULT("couldnt create channelsstop transaction");
6517     return(result);
6518 }
6519
6520 UniValue channelspayment(const UniValue& params, bool fHelp)
6521 {
6522     UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,prevtxid; int32_t n; int64_t amount;
6523     cp = CCinit(&C,EVAL_CHANNELS);
6524     if ( fHelp || params.size() != 4 )
6525         throw runtime_error("channelspayment prevtxid origtxid n amount\n");
6526     if ( ensure_CCrequirements() < 0 )
6527         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6528     LOCK(cs_main);
6529     prevtxid = Parseuint256((char *)params[0].get_str().c_str());
6530     origtxid = Parseuint256((char *)params[1].get_str().c_str());
6531     n = atoi((char *)params[2].get_str().c_str());
6532     amount = atoi((char *)params[3].get_str().c_str());
6533     hex = ChannelPayment(0,prevtxid,origtxid,n,amount);
6534     if ( hex.size() > 0 )
6535     {
6536         result.push_back(Pair("result", "success"));
6537         result.push_back(Pair("hex", hex));
6538     } else ERR_RESULT("couldnt create channelspayment transaction");
6539     return(result);
6540 }
6541
6542 UniValue channelscollect(const UniValue& params, bool fHelp)
6543 {
6544     UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,paytxid; int32_t n; int64_t amount;
6545     cp = CCinit(&C,EVAL_CHANNELS);
6546     if ( fHelp || params.size() != 4 )
6547         throw runtime_error("channelscollect paytxid origtxid n amount\n");
6548     if ( ensure_CCrequirements() < 0 )
6549         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6550     LOCK(cs_main);
6551     paytxid = Parseuint256((char *)params[0].get_str().c_str());
6552     origtxid = Parseuint256((char *)params[1].get_str().c_str());
6553     n = atoi((char *)params[2].get_str().c_str());
6554     amount = atoi((char *)params[3].get_str().c_str());
6555     hex = ChannelCollect(0,paytxid,origtxid,n,amount);
6556     if ( hex.size() > 0 )
6557     {
6558         result.push_back(Pair("result", "success"));
6559         result.push_back(Pair("hex", hex));
6560     } else ERR_RESULT("couldnt create channelscollect transaction");
6561     return(result);
6562 }
6563
6564 UniValue channelsrefund(const UniValue& params, bool fHelp)
6565 {
6566     UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 origtxid,stoptxid;
6567     cp = CCinit(&C,EVAL_CHANNELS);
6568     if ( fHelp || params.size() != 2 )
6569         throw runtime_error("channelsrefund stoptxid origtxid\n");
6570     if ( ensure_CCrequirements() < 0 )
6571         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6572     LOCK(cs_main);
6573     stoptxid = Parseuint256((char *)params[0].get_str().c_str());
6574     origtxid = Parseuint256((char *)params[1].get_str().c_str());
6575     hex = ChannelRefund(0,stoptxid,origtxid);
6576     if ( hex.size() > 0 )
6577     {
6578         result.push_back(Pair("result", "success"));
6579         result.push_back(Pair("hex", hex));
6580     } else ERR_RESULT("couldnt create channelsrefund transaction");
6581     return(result);
6582 }
6583
6584 UniValue rewardscreatefunding(const UniValue& params, bool fHelp)
6585 {
6586     UniValue result(UniValue::VOBJ); char *name; int64_t funds,APR,minseconds,maxseconds,mindeposit; std::string hex;
6587     if ( fHelp || params.size() > 6 || params.size() < 2 )
6588         throw runtime_error("rewardscreatefunding name amount APR mindays maxdays mindeposit\n");
6589     if ( ensure_CCrequirements() < 0 )
6590         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6591     const CKeyStore& keystore = *pwalletMain;
6592     LOCK2(cs_main, pwalletMain->cs_wallet);
6593    // default to OOT params
6594     APR = 5 * COIN;
6595     minseconds = maxseconds = 60 * 3600 * 24;
6596     mindeposit = 100 * COIN;
6597     name = (char *)params[0].get_str().c_str();
6598     funds = atof(params[1].get_str().c_str()) * COIN;
6599
6600     if (!VALID_PLAN_NAME(name)) {
6601         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
6602         return(result);
6603     }
6604
6605     if ( funds <= 0 ) {
6606         ERR_RESULT("funds must be positive");
6607         return result;
6608     }
6609     if ( params.size() > 2 )
6610     {
6611         APR = atof(params[2].get_str().c_str()) * COIN;
6612         if ( APR > REWARDSCC_MAXAPR )
6613         {
6614             ERR_RESULT("25% APR is maximum");
6615             return result;
6616         }
6617         if ( params.size() > 3 )
6618         {
6619             minseconds = atol(params[3].get_str().c_str()) * 3600 * 24;
6620             if ( minseconds < 0 ) {
6621                 ERR_RESULT("mindays must be non-negative");
6622                 return result;
6623             }
6624             if ( params.size() > 4 )
6625             {
6626                 maxseconds = atol(params[4].get_str().c_str()) * 3600 * 24;
6627                 if ( maxseconds <= 0 ) {
6628                     ERR_RESULT("maxdays must be positive");
6629                     return result;
6630                 }
6631                 if ( maxseconds < minseconds ) {
6632                     ERR_RESULT("maxdays must be greater than mindays");
6633                     return result;
6634                 }
6635                 if ( params.size() > 5 )
6636                     mindeposit = atof(params[5].get_str().c_str()) * COIN;
6637                     if ( mindeposit <= 0 ) {
6638                         ERR_RESULT("mindeposit must be positive");
6639                         return result;
6640                     }
6641             }
6642         }
6643     }
6644     hex = RewardsCreateFunding(0,name,funds,APR,minseconds,maxseconds,mindeposit);
6645     if ( hex.size() > 0 )
6646     {
6647         result.push_back(Pair("result", "success"));
6648         result.push_back(Pair("hex", hex));
6649     } else ERR_RESULT("couldnt create rewards funding transaction");
6650     return(result);
6651 }
6652
6653 UniValue rewardslock(const UniValue& params, bool fHelp)
6654 {
6655     UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex;
6656     if ( fHelp || params.size() != 3 )
6657         throw runtime_error("rewardslock name fundingtxid amount\n");
6658     if ( ensure_CCrequirements() < 0 )
6659         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6660     const CKeyStore& keystore = *pwalletMain;
6661     LOCK2(cs_main, pwalletMain->cs_wallet);
6662     name = (char *)params[0].get_str().c_str();
6663     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
6664     amount = atof(params[2].get_str().c_str()) * COIN;
6665     hex = RewardsLock(0,name,fundingtxid,amount);
6666
6667     if (!VALID_PLAN_NAME(name)) {
6668             ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
6669             return(result);
6670     }
6671     if ( CCerror != "" ){
6672         ERR_RESULT(CCerror);
6673     } else if ( amount > 0 ) {
6674         if ( hex.size() > 0 )
6675         {
6676             result.push_back(Pair("result", "success"));
6677             result.push_back(Pair("hex", hex));
6678         } else ERR_RESULT( "couldnt create rewards lock transaction");
6679     } else ERR_RESULT("amount must be positive");
6680     return(result);
6681 }
6682
6683 UniValue rewardsaddfunding(const UniValue& params, bool fHelp)
6684 {
6685     UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex;
6686     if ( fHelp || params.size() != 3 )
6687         throw runtime_error("rewardsaddfunding name fundingtxid amount\n");
6688     if ( ensure_CCrequirements() < 0 )
6689         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6690     const CKeyStore& keystore = *pwalletMain;
6691     LOCK2(cs_main, pwalletMain->cs_wallet);
6692     name = (char *)params[0].get_str().c_str();
6693     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
6694     amount = atof(params[2].get_str().c_str()) * COIN;
6695     hex = RewardsAddfunding(0,name,fundingtxid,amount);
6696
6697     if (!VALID_PLAN_NAME(name)) {
6698             ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
6699             return(result);
6700     }
6701     if (CCerror != "") {
6702         ERR_RESULT(CCerror);
6703     } else if (amount > 0) {
6704         if ( hex.size() > 0 )
6705         {
6706             result.push_back(Pair("result", "success"));
6707             result.push_back(Pair("hex", hex));
6708         } else {
6709             result.push_back(Pair("result", "error"));
6710             result.push_back(Pair("error", "couldnt create rewards addfunding transaction"));
6711         }
6712     } else {
6713             ERR_RESULT("funding amount must be positive");
6714     }
6715     return(result);
6716 }
6717
6718 UniValue rewardsunlock(const UniValue& params, bool fHelp)
6719 {
6720     UniValue result(UniValue::VOBJ); std::string hex; char *name; uint256 fundingtxid,txid;
6721     if ( fHelp || params.size() > 3 || params.size() < 2 )
6722         throw runtime_error("rewardsunlock name fundingtxid [txid]\n");
6723     if ( ensure_CCrequirements() < 0 )
6724         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6725     const CKeyStore& keystore = *pwalletMain;
6726     LOCK2(cs_main, pwalletMain->cs_wallet);
6727     name = (char *)params[0].get_str().c_str();
6728     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
6729
6730     if (!VALID_PLAN_NAME(name)) {
6731             ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
6732             return(result);
6733     }
6734     if ( params.size() > 2 )
6735         txid = Parseuint256((char *)params[2].get_str().c_str());
6736     else memset(&txid,0,sizeof(txid));
6737     hex = RewardsUnlock(0,name,fundingtxid,txid);
6738     if (CCerror != "") {
6739         ERR_RESULT(CCerror);
6740     } else if ( hex.size() > 0 ) {
6741         result.push_back(Pair("result", "success"));
6742         result.push_back(Pair("hex", hex));
6743     } else ERR_RESULT("couldnt create rewards unlock transaction");
6744     return(result);
6745 }
6746
6747 UniValue rewardslist(const UniValue& params, bool fHelp)
6748 {
6749     if ( fHelp || params.size() > 0 )
6750         throw runtime_error("rewardslist\n");
6751     if ( ensure_CCrequirements() < 0 )
6752         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6753     return(RewardsList());
6754 }
6755
6756 UniValue rewardsinfo(const UniValue& params, bool fHelp)
6757 {
6758     uint256 fundingtxid;
6759     if ( fHelp || params.size() != 1 )
6760         throw runtime_error("rewardsinfo fundingtxid\n");
6761     if ( ensure_CCrequirements() < 0 )
6762         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6763     fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
6764     return(RewardsInfo(fundingtxid));
6765 }
6766
6767 UniValue gatewayslist(const UniValue& params, bool fHelp)
6768 {
6769     if ( fHelp || params.size() > 0 )
6770         throw runtime_error("gatewayslist\n");
6771     if ( ensure_CCrequirements() < 0 )
6772         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6773     return(GatewaysList());
6774 }
6775
6776 UniValue gatewaysinfo(const UniValue& params, bool fHelp)
6777 {
6778     uint256 txid;
6779     if ( fHelp || params.size() != 1 )
6780         throw runtime_error("gatewaysinfo bindtxid\n");
6781     if ( ensure_CCrequirements() < 0 )
6782         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6783     txid = Parseuint256((char *)params[0].get_str().c_str());
6784     return(GatewaysInfo(txid));
6785 }
6786
6787 UniValue gatewaysbind(const UniValue& params, bool fHelp)
6788 {
6789     UniValue result(UniValue::VOBJ); uint256 tokenid,oracletxid; int32_t i; int64_t totalsupply; std::vector<CPubKey> pubkeys; uint8_t M,N; std::string hex,coin; std::vector<unsigned char> pubkey;
6790     if ( fHelp || params.size() < 6 )
6791         throw runtime_error("gatewaysbind tokenid oracletxid coin tokensupply M N pubkey(s)\n");
6792     if ( ensure_CCrequirements() < 0 )
6793         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6794     tokenid = Parseuint256((char *)params[0].get_str().c_str());
6795     oracletxid = Parseuint256((char *)params[1].get_str().c_str());
6796     coin = params[2].get_str();
6797     totalsupply = atol((char *)params[3].get_str().c_str());
6798     M = atoi((char *)params[4].get_str().c_str());
6799     N = atoi((char *)params[5].get_str().c_str());
6800     if ( M > N || N == 0 || N > 15 || totalsupply < COIN/100 || tokenid == zeroid )
6801         throw runtime_error("illegal M or N > 15 or tokensupply or invalid tokenid\n");
6802     for (i=0; i<N; i++)
6803     {
6804         if ( params.size() < 6+i+1 )
6805             throw runtime_error("not enough parameters for N pubkeys\n");
6806         pubkey = ParseHex(params[6+i].get_str().c_str());
6807         pubkeys.push_back(pubkey2pk(pubkey));
6808     }
6809     hex = GatewaysBind(0,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys);
6810     if ( hex.size() > 0 )
6811     {
6812         result.push_back(Pair("result", "success"));
6813         result.push_back(Pair("hex", hex));
6814     } else ERR_RESULT("couldnt gatewaysbind");
6815     return(result);
6816 }
6817
6818 UniValue gatewaysdeposit(const UniValue& params, bool fHelp)
6819 {
6820     UniValue result(UniValue::VOBJ); int32_t i,claimvout,height; int64_t amount; std::string hex,coin,deposithex; uint256 bindtxid,cointxid; std::vector<uint8_t>proof,destpub,pubkey;
6821     if ( fHelp || params.size() != 9 )
6822         throw runtime_error("gatewaysdeposit bindtxid height coin cointxid claimvout deposithex proof destpub amount\n");
6823     if ( ensure_CCrequirements() < 0 )
6824         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6825     bindtxid = Parseuint256((char *)params[0].get_str().c_str());
6826     height = atoi((char *)params[1].get_str().c_str());
6827     coin = params[2].get_str();
6828     cointxid = Parseuint256((char *)params[3].get_str().c_str());
6829     claimvout = atoi((char *)params[4].get_str().c_str());
6830     deposithex = params[5].get_str();
6831     proof = ParseHex(params[6].get_str());
6832     destpub = ParseHex(params[7].get_str());
6833     amount = atof((char *)params[8].get_str().c_str()) * COIN;
6834     if ( amount <= 0 || claimvout < 0 )
6835         throw runtime_error("invalid param: amount, numpks or claimvout\n");
6836     hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount);
6837     if ( hex.size() > 0 )
6838     {
6839         result.push_back(Pair("result", "success"));
6840         result.push_back(Pair("hex", hex));
6841     } else ERR_RESULT("couldnt gatewaysdeposit");
6842     return(result);
6843 }
6844
6845 UniValue gatewaysclaim(const UniValue& params, bool fHelp)
6846 {
6847     UniValue result(UniValue::VOBJ); std::string hex,coin; uint256 bindtxid,deposittxid; std::vector<uint8_t>destpub; int64_t amount;
6848     if ( fHelp || params.size() != 5 )
6849         throw runtime_error("gatewaysclaim bindtxid coin deposittxid destpub amount\n");
6850     if ( ensure_CCrequirements() < 0 )
6851         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6852     bindtxid = Parseuint256((char *)params[0].get_str().c_str());
6853     coin = params[1].get_str();
6854     deposittxid = Parseuint256((char *)params[2].get_str().c_str());
6855     destpub = ParseHex(params[3].get_str());
6856     amount = atof((char *)params[4].get_str().c_str()) * COIN;
6857     hex = GatewaysClaim(0,bindtxid,coin,deposittxid,pubkey2pk(destpub),amount);
6858     if ( hex.size() > 0 )
6859     {
6860         result.push_back(Pair("result", "success"));
6861         result.push_back(Pair("hex", hex));
6862     } else ERR_RESULT("couldnt gatewaysclaim");
6863     return(result);
6864 }
6865
6866 UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
6867 {
6868     UniValue result(UniValue::VOBJ); uint256 bindtxid; int64_t amount; std::string hex,coin; std::vector<uint8_t> withdrawpub;
6869     if ( fHelp || params.size() != 4 )
6870         throw runtime_error("gatewayswithdraw bindtxid coin withdrawpub amount\n");
6871     if ( ensure_CCrequirements() < 0 )
6872         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6873     bindtxid = Parseuint256((char *)params[0].get_str().c_str());
6874     coin = params[1].get_str();
6875     withdrawpub = ParseHex(params[2].get_str());
6876     amount = atof((char *)params[3].get_str().c_str()) * COIN;
6877     hex = GatewaysWithdraw(0,bindtxid,coin,withdrawpub,amount);
6878     if ( hex.size() > 0 )
6879     {
6880         result.push_back(Pair("result", "success"));
6881         result.push_back(Pair("hex", hex));
6882     } else ERR_RESULT("couldnt gatewayswithdraw");
6883     return(result);
6884 }
6885
6886 UniValue gatewaysmarkdone(const UniValue& params, bool fHelp)
6887 {
6888     UniValue result(UniValue::VOBJ); uint256 withdrawtxid; std::string hex;
6889     if ( fHelp || params.size() != 1 )
6890         throw runtime_error("gatewaysmarkdone withdrawtxid\n");
6891     if ( ensure_CCrequirements() < 0 )
6892         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6893     withdrawtxid = Parseuint256((char *)params[0].get_str().c_str());
6894     hex = GatewaysMarkdone(0,withdrawtxid);
6895     if ( hex.size() > 0 )
6896     {
6897         result.push_back(Pair("result", "success"));
6898         result.push_back(Pair("hex", hex));
6899     } else ERR_RESULT("couldnt gatewaysmarkdone");
6900     return(result);
6901 }
6902
6903 UniValue gatewayspending(const UniValue& params, bool fHelp)
6904 {
6905     uint256 bindtxid; std::string coin;
6906     if ( fHelp || params.size() != 2 )
6907         throw runtime_error("gatewayspending bindtxid coin\n");
6908     if ( ensure_CCrequirements() < 0 )
6909         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6910     bindtxid = Parseuint256((char *)params[0].get_str().c_str());
6911     coin = params[1].get_str();
6912     return(GatewaysPendingWithdraws(bindtxid,coin));
6913 }
6914
6915 UniValue oracleslist(const UniValue& params, bool fHelp)
6916 {
6917     if ( fHelp || params.size() > 0 )
6918         throw runtime_error("oracleslist\n");
6919     if ( ensure_CCrequirements() < 0 )
6920         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6921     return(OraclesList());
6922 }
6923
6924 UniValue oraclesinfo(const UniValue& params, bool fHelp)
6925 {
6926     uint256 txid;
6927     if ( fHelp || params.size() != 1 )
6928         throw runtime_error("oraclesinfo oracletxid\n");
6929     if ( ensure_CCrequirements() < 0 )
6930         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6931     txid = Parseuint256((char *)params[0].get_str().c_str());
6932     return(OracleInfo(txid));
6933 }
6934
6935 UniValue oraclesregister(const UniValue& params, bool fHelp)
6936 {
6937     UniValue result(UniValue::VOBJ); uint256 txid; int64_t datafee; std::string hex;
6938     if ( fHelp || params.size() != 2 )
6939         throw runtime_error("oraclesregister oracletxid datafee\n");
6940     if ( ensure_CCrequirements() < 0 )
6941         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6942     txid = Parseuint256((char *)params[0].get_str().c_str());
6943     datafee = atol((char *)params[1].get_str().c_str());
6944     hex = OracleRegister(0,txid,datafee);
6945     if ( hex.size() > 0 )
6946     {
6947         result.push_back(Pair("result", "success"));
6948         result.push_back(Pair("hex", hex));
6949     } else ERR_RESULT("couldnt register with oracle txid");
6950     return(result);
6951 }
6952
6953 UniValue oraclessubscribe(const UniValue& params, bool fHelp)
6954 {
6955     UniValue result(UniValue::VOBJ); uint256 txid; int64_t amount; std::string hex; std::vector<unsigned char> pubkey;
6956     if ( fHelp || params.size() != 3 )
6957         throw runtime_error("oraclessubscribe oracletxid publisher amount\n");
6958     if ( ensure_CCrequirements() < 0 )
6959         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6960     txid = Parseuint256((char *)params[0].get_str().c_str());
6961     pubkey = ParseHex(params[1].get_str().c_str());
6962     amount = atof((char *)params[2].get_str().c_str()) * COIN;
6963     hex = OracleSubscribe(0,txid,pubkey2pk(pubkey),amount);
6964     if ( hex.size() > 0 )
6965     {
6966         result.push_back(Pair("result", "success"));
6967         result.push_back(Pair("hex", hex));
6968     } else ERR_RESULT("couldnt subscribe with oracle txid");
6969     return(result);
6970 }
6971
6972 UniValue oraclessamples(const UniValue& params, bool fHelp)
6973 {
6974     UniValue result(UniValue::VOBJ); uint256 txid,batontxid; int32_t num; 
6975     if ( fHelp || params.size() != 3 )
6976         throw runtime_error("oraclessamples oracletxid batonutxo num\n");
6977     if ( ensure_CCrequirements() < 0 )
6978         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6979     txid = Parseuint256((char *)params[0].get_str().c_str());
6980     batontxid = Parseuint256((char *)params[1].get_str().c_str());
6981     num = atoi((char *)params[2].get_str().c_str());
6982     return(OracleDataSamples(txid,batontxid,num));
6983 }
6984
6985 UniValue oraclesdata(const UniValue& params, bool fHelp)
6986 {
6987     UniValue result(UniValue::VOBJ); uint256 txid; std::vector<unsigned char> data; std::string hex;
6988     if ( fHelp || params.size() != 2 )
6989         throw runtime_error("oraclesdata oracletxid hexstr\n");
6990     if ( ensure_CCrequirements() < 0 )
6991         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
6992     txid = Parseuint256((char *)params[0].get_str().c_str());
6993     data = ParseHex(params[1].get_str().c_str());
6994     hex = OracleData(0,txid,data);
6995     if ( hex.size() > 0 )
6996     {
6997         result.push_back(Pair("result", "success"));
6998         result.push_back(Pair("hex", hex));
6999     } else ERR_RESULT("couldnt publish data with oracle txid");
7000     return(result);
7001 }
7002
7003 UniValue oraclescreate(const UniValue& params, bool fHelp)
7004 {
7005     UniValue result(UniValue::VOBJ); std::string name,description,format,hex;
7006     if ( fHelp || params.size() != 3 )
7007         throw runtime_error("oraclescreate name description format\n");
7008     if ( ensure_CCrequirements() < 0 )
7009         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7010     const CKeyStore& keystore = *pwalletMain;
7011     LOCK2(cs_main, pwalletMain->cs_wallet);
7012     name = params[0].get_str();
7013     if ( name.size() == 0 || name.size() > 32)
7014     {
7015         ERR_RESULT("oracles name must not be empty and up to 32 characters");
7016         return(result);
7017     }
7018     description = params[1].get_str();
7019     if ( description.size() > 4096 )
7020     {
7021         ERR_RESULT("oracles description must be <= 4096 characters");
7022         return(result);
7023     }
7024     format = params[2].get_str();
7025     if ( format.size() > 4096 )
7026     {
7027         ERR_RESULT("oracles format must be <= 4096 characters");
7028         return(result);
7029     }
7030     hex = OracleCreate(0,name,description,format);
7031     if ( hex.size() > 0 )
7032     {
7033         result.push_back(Pair("result", "success"));
7034         result.push_back(Pair("hex", hex));
7035     } else ERR_RESULT("couldnt create oracle");
7036     return(result);
7037 }
7038
7039 UniValue FSMcreate(const UniValue& params, bool fHelp)
7040 {
7041     UniValue result(UniValue::VOBJ); std::string name,states,hex;
7042     if ( fHelp || params.size() != 2 )
7043         throw runtime_error("FSMcreate name states\n");
7044     if ( ensure_CCrequirements() < 0 )
7045         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7046     const CKeyStore& keystore = *pwalletMain;
7047     LOCK2(cs_main, pwalletMain->cs_wallet);
7048     name = params[0].get_str();
7049     states = params[1].get_str();
7050     hex = FSMCreate(0,name,states);
7051     if ( hex.size() > 0 )
7052     {
7053         result.push_back(Pair("result", "success"));
7054         result.push_back(Pair("hex", hex));
7055     } else result.push_back(Pair("error", "couldnt create FSM transaction"));
7056     return(result);
7057 }
7058
7059 UniValue FSMlist(const UniValue& params, bool fHelp)
7060 {
7061     uint256 tokenid;
7062     if ( fHelp || params.size() > 0 )
7063         throw runtime_error("FSMlist\n");
7064     if ( ensure_CCrequirements() < 0 )
7065         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7066     return(FSMList());
7067 }
7068
7069 UniValue FSMinfo(const UniValue& params, bool fHelp)
7070 {
7071     uint256 FSMtxid;
7072     if ( fHelp || params.size() != 1 )
7073         throw runtime_error("FSMinfo fundingtxid\n");
7074     if ( ensure_CCrequirements() < 0 )
7075         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7076     FSMtxid = Parseuint256((char *)params[0].get_str().c_str());
7077     return(FSMInfo(FSMtxid));
7078 }
7079
7080 UniValue faucetinfo(const UniValue& params, bool fHelp)
7081 {
7082     uint256 fundingtxid;
7083     if ( fHelp || params.size() != 0 )
7084         throw runtime_error("faucetinfo\n");
7085     if ( ensure_CCrequirements() < 0 )
7086         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7087     return(FaucetInfo());
7088 }
7089
7090 UniValue faucetfund(const UniValue& params, bool fHelp)
7091 {
7092     UniValue result(UniValue::VOBJ); int64_t funds; std::string hex;
7093     if ( fHelp || params.size() > 1 )
7094         throw runtime_error("faucetfund amount\n");
7095     if ( ensure_CCrequirements() < 0 )
7096         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7097     const CKeyStore& keystore = *pwalletMain;
7098     LOCK2(cs_main, pwalletMain->cs_wallet);
7099     funds = atof(params[0].get_str().c_str()) * COIN;
7100     if (funds > 0) {
7101         hex = FaucetFund(0,(uint64_t) funds);
7102         if ( hex.size() > 0 )
7103         {
7104             result.push_back(Pair("result", "success"));
7105             result.push_back(Pair("hex", hex));
7106         } else ERR_RESULT("couldnt create faucet funding transaction");
7107     } else ERR_RESULT( "funding amount must be positive");
7108     return(result);
7109 }
7110
7111 UniValue faucetget(const UniValue& params, bool fHelp)
7112 {
7113     UniValue result(UniValue::VOBJ); std::string hex;
7114     if ( fHelp || params.size() > 0 )
7115         throw runtime_error("faucetget\n");
7116     if ( ensure_CCrequirements() < 0 )
7117         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7118     const CKeyStore& keystore = *pwalletMain;
7119     LOCK2(cs_main, pwalletMain->cs_wallet);
7120     hex = FaucetGet(0);
7121     if ( hex.size() > 0 ) {
7122         result.push_back(Pair("result", "success"));
7123         result.push_back(Pair("hex", hex));
7124     } else ERR_RESULT("couldnt create faucet get transaction");
7125     return(result);
7126 }
7127
7128 UniValue dicefund(const UniValue& params, bool fHelp)
7129 {
7130     UniValue result(UniValue::VOBJ); int64_t funds,minbet,maxbet,maxodds,timeoutblocks; std::string hex; char *name;
7131     if ( fHelp || params.size() != 6 )
7132         throw runtime_error("dicefund name funds minbet maxbet maxodds timeoutblocks\n");
7133     if ( ensure_CCrequirements() < 0 )
7134         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7135     const CKeyStore& keystore = *pwalletMain;
7136     LOCK2(cs_main, pwalletMain->cs_wallet);
7137     name = (char *)params[0].get_str().c_str();
7138     funds = atof(params[1].get_str().c_str()) * COIN;
7139     minbet = atof(params[2].get_str().c_str()) * COIN;
7140     maxbet = atof(params[3].get_str().c_str()) * COIN;
7141     maxodds = atol(params[4].get_str().c_str());
7142     timeoutblocks = atol(params[5].get_str().c_str());
7143
7144     if (!VALID_PLAN_NAME(name)) {
7145         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
7146         return(result);
7147     }
7148
7149     hex = DiceCreateFunding(0,name,funds,minbet,maxbet,maxodds,timeoutblocks);
7150     if (CCerror != "") {
7151         ERR_RESULT(CCerror);
7152     } else if ( hex.size() > 0 ) {
7153         result.push_back(Pair("result", "success"));
7154         result.push_back(Pair("hex", hex));
7155     } else  {
7156         ERR_RESULT( "couldnt create dice funding transaction");
7157     }
7158     return(result);
7159 }
7160
7161 UniValue diceaddfunds(const UniValue& params, bool fHelp)
7162 {
7163     UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex;
7164     if ( fHelp || params.size() != 3 )
7165         throw runtime_error("diceaddfunds name fundingtxid amount\n");
7166     if ( ensure_CCrequirements() < 0 )
7167         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7168     const CKeyStore& keystore = *pwalletMain;
7169     LOCK2(cs_main, pwalletMain->cs_wallet);
7170     name = (char *)params[0].get_str().c_str();
7171     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
7172     amount = atof(params[2].get_str().c_str()) * COIN;
7173     if (!VALID_PLAN_NAME(name)) {
7174         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
7175         return(result);
7176     }
7177     if ( amount > 0 ) {
7178         hex = DiceAddfunding(0,name,fundingtxid,amount);
7179         if (CCerror != "") {
7180             ERR_RESULT(CCerror);
7181         } else if ( hex.size() > 0 ) {
7182             result.push_back(Pair("result", "success"));
7183             result.push_back(Pair("hex", hex));
7184         } else ERR_RESULT("couldnt create dice addfunding transaction");
7185     } else ERR_RESULT("amount must be positive");
7186     return(result);
7187 }
7188
7189 UniValue dicebet(const UniValue& params, bool fHelp)
7190 {
7191     UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid; int64_t amount,odds; char *name;
7192     if ( fHelp || params.size() != 4 )
7193         throw runtime_error("dicebet name fundingtxid amount odds\n");
7194     if ( ensure_CCrequirements() < 0 )
7195         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7196     const CKeyStore& keystore = *pwalletMain;
7197     LOCK2(cs_main, pwalletMain->cs_wallet);
7198     name = (char *)params[0].get_str().c_str();
7199     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
7200     amount = atof(params[2].get_str().c_str()) * COIN;
7201     odds = atol(params[3].get_str().c_str());
7202
7203     if (!VALID_PLAN_NAME(name)) {
7204         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
7205         return(result);
7206     }
7207     if (amount > 0 && odds > 0) {
7208         hex = DiceBet(0,name,fundingtxid,amount,odds);
7209         if ( hex.size() > 0 )
7210         {
7211             result.push_back(Pair("result", "success"));
7212             result.push_back(Pair("hex", hex));
7213         } else ERR_RESULT("couldnt create dice bet transaction. make sure your address has funds");
7214     } else {
7215         ERR_RESULT("amount and odds must be positive");
7216     }
7217     return(result);
7218 }
7219
7220 UniValue dicefinish(const UniValue& params, bool fHelp)
7221 {
7222     UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; std::string hex; int32_t r;
7223     if ( fHelp || params.size() != 3 )
7224         throw runtime_error("dicefinish name fundingtxid bettxid\n");
7225     if ( ensure_CCrequirements() < 0 )
7226         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7227     const CKeyStore& keystore = *pwalletMain;
7228     LOCK2(cs_main, pwalletMain->cs_wallet);
7229     name = (char *)params[0].get_str().c_str();
7230     if (!VALID_PLAN_NAME(name)) {
7231         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
7232         return(result);
7233     }
7234     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
7235     bettxid = Parseuint256((char *)params[2].get_str().c_str());
7236     hex = DiceBetFinish(&r,0,name,fundingtxid,bettxid,1);
7237     if ( CCerror != "" )
7238     {
7239         ERR_RESULT(CCerror);
7240     } else if ( hex.size() > 0 )
7241     {
7242         result.push_back(Pair("result", "success"));
7243         result.push_back(Pair("hex", hex));
7244     } else ERR_RESULT( "couldnt create dicefinish transaction");
7245     return(result);
7246 }
7247
7248 UniValue dicestatus(const UniValue& params, bool fHelp)
7249 {
7250     UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; std::string status; double winnings;
7251     if ( fHelp || (params.size() != 2 && params.size() != 3) )
7252         throw runtime_error("dicestatus name fundingtxid bettxid\n");
7253     if ( ensure_CCrequirements() < 0 )
7254         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7255     const CKeyStore& keystore = *pwalletMain;
7256     LOCK2(cs_main, pwalletMain->cs_wallet);
7257     name = (char *)params[0].get_str().c_str();
7258     if (!VALID_PLAN_NAME(name)) {
7259         ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
7260         return(result);
7261     }
7262     fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
7263     memset(&bettxid,0,sizeof(bettxid));
7264     if ( params.size() == 3 )
7265         bettxid = Parseuint256((char *)params[2].get_str().c_str());
7266     winnings = DiceStatus(0,name,fundingtxid,bettxid);
7267     if (CCerror != "") {
7268         ERR_RESULT(CCerror);
7269         return result;
7270     }
7271     result.push_back(Pair("result", "success"));
7272     if ( winnings >= 0. )
7273     {
7274         if ( winnings > 0. )
7275         {
7276             if ( params.size() == 3 )
7277             {
7278                 result.push_back(Pair("status", "win"));
7279                 result.push_back(Pair("won", winnings));
7280             }
7281             else
7282             {
7283                 result.push_back(Pair("status", "finalized"));
7284                 result.push_back(Pair("n", (int64_t)winnings));
7285             }
7286         }
7287         else
7288         {
7289             if ( params.size() == 3 )
7290                 result.push_back(Pair("status", "loss"));
7291             else result.push_back(Pair("status", "no pending bets"));
7292         }
7293     } else result.push_back(Pair("status", "bet still pending"));
7294     return(result);
7295 }
7296
7297 UniValue dicelist(const UniValue& params, bool fHelp)
7298 {
7299     uint256 tokenid;
7300     if ( fHelp || params.size() > 0 )
7301         throw runtime_error("dicelist\n");
7302     if ( ensure_CCrequirements() < 0 )
7303         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7304     return(DiceList());
7305 }
7306
7307 UniValue diceinfo(const UniValue& params, bool fHelp)
7308 {
7309     uint256 fundingtxid;
7310     if ( fHelp || params.size() != 1 )
7311         throw runtime_error("diceinfo fundingtxid\n");
7312     if ( ensure_CCrequirements() < 0 )
7313         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7314     fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
7315     return(DiceInfo(fundingtxid));
7316 }
7317
7318 UniValue tokenlist(const UniValue& params, bool fHelp)
7319 {
7320     uint256 tokenid;
7321     if ( fHelp || params.size() > 0 )
7322         throw runtime_error("tokenlist\n");
7323     if ( ensure_CCrequirements() < 0 )
7324         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7325     return(AssetList());
7326 }
7327
7328 UniValue tokeninfo(const UniValue& params, bool fHelp)
7329 {
7330     uint256 tokenid;
7331     if ( fHelp || params.size() != 1 )
7332         throw runtime_error("tokeninfo tokenid\n");
7333     if ( ensure_CCrequirements() < 0 )
7334         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7335     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7336     return(AssetInfo(tokenid));
7337 }
7338
7339 UniValue tokenorders(const UniValue& params, bool fHelp)
7340 {
7341     uint256 tokenid;
7342     if ( fHelp || params.size() > 1 )
7343         throw runtime_error("tokenorders [tokenid]\n");
7344     if ( ensure_CCrequirements() < 0 )
7345         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7346     if ( params.size() == 1 )
7347         tokenid = Parseuint256((char *)params[0].get_str().c_str());
7348     else memset(&tokenid,0,sizeof(tokenid));
7349     return(AssetOrders(tokenid));
7350 }
7351
7352 UniValue tokenbalance(const UniValue& params, bool fHelp)
7353 {
7354     UniValue result(UniValue::VOBJ); char destaddr[64]; uint256 tokenid; uint64_t balance; std::vector<unsigned char> pubkey; struct CCcontract_info *cp,C;
7355     cp = CCinit(&C,EVAL_ASSETS);
7356     if ( fHelp || params.size() > 2 )
7357         throw runtime_error("tokenbalance tokenid [pubkey]\n");
7358     if ( ensure_CCrequirements() < 0 )
7359         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7360     LOCK(cs_main);
7361     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7362     if ( params.size() == 2 )
7363         pubkey = ParseHex(params[1].get_str().c_str());
7364     else pubkey = Mypubkey();
7365     result.push_back(Pair("result", "success"));
7366     if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 )
7367         result.push_back(Pair("CCaddress",destaddr));
7368     balance = GetAssetBalance(pubkey2pk(pubkey),tokenid);
7369     result.push_back(Pair("tokenid", params[0].get_str()));
7370     result.push_back(Pair("balance", (int64_t)balance));
7371     return(result);
7372 }
7373
7374 UniValue tokencreate(const UniValue& params, bool fHelp)
7375 {
7376     UniValue result(UniValue::VOBJ); std::string name,description,hex; uint64_t supply;
7377     if ( fHelp || params.size() > 3 || params.size() < 2 )
7378         throw runtime_error("tokencreate name supply description\n");
7379     if ( ensure_CCrequirements() < 0 )
7380         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7381     const CKeyStore& keystore = *pwalletMain;
7382     LOCK2(cs_main, pwalletMain->cs_wallet);
7383     name = params[0].get_str();
7384     supply = atof(params[1].get_str().c_str()) * COIN;
7385     if ( name.size() == 0 || name.size() > 32)
7386     {
7387         ERR_RESULT("Token name must not be empty and up to 32 characters");
7388         return(result);
7389     }
7390     if ( supply <= 0 )
7391     {
7392         ERR_RESULT("Token supply must be positive");
7393         return(result);
7394     }
7395     if ( params.size() == 3 )
7396     {
7397         description = params[2].get_str();
7398         if ( description.size() > 4096 )
7399         {
7400             ERR_RESULT("Token description must be <= 4096 characters");
7401             return(result);
7402         }
7403     }
7404     hex = CreateAsset(0,supply,name,description);
7405     if ( hex.size() > 0 )
7406     {
7407         result.push_back(Pair("result", "success"));
7408         result.push_back(Pair("hex", hex));
7409     } else ERR_RESULT("couldnt create transaction");
7410     return(result);
7411 }
7412
7413 UniValue tokentransfer(const UniValue& params, bool fHelp)
7414 {
7415     UniValue result(UniValue::VOBJ); std::string hex; int64_t amount; uint256 tokenid;
7416     if ( fHelp || params.size() != 3 )
7417         throw runtime_error("tokentransfer tokenid destpubkey amount\n");
7418     if ( ensure_CCrequirements() < 0 )
7419         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7420     const CKeyStore& keystore = *pwalletMain;
7421     LOCK2(cs_main, pwalletMain->cs_wallet);
7422     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7423     std::vector<unsigned char> pubkey(ParseHex(params[1].get_str().c_str()));
7424     amount = atol(params[2].get_str().c_str());
7425     if ( tokenid == zeroid )
7426     {
7427         ERR_RESULT("invalid tokenid");
7428         return(result);
7429     }
7430     if ( amount <= 0 )
7431     {
7432         ERR_RESULT("amount must be positive");
7433         return(result);
7434     }
7435     hex = AssetTransfer(0,tokenid,pubkey,amount);
7436     if (amount > 0) {
7437         if ( hex.size() > 0 )
7438         {
7439             result.push_back(Pair("result", "success"));
7440             result.push_back(Pair("hex", hex));
7441         } else ERR_RESULT("couldnt transfer assets");
7442     } else {
7443         ERR_RESULT("amount must be positive");
7444     }
7445     return(result);
7446 }
7447
7448 UniValue tokenbid(const UniValue& params, bool fHelp)
7449 {
7450     UniValue result(UniValue::VOBJ); int64_t bidamount,numtokens; std::string hex; double price; uint256 tokenid;
7451     if ( fHelp || params.size() != 3 )
7452         throw runtime_error("tokenbid numtokens tokenid price\n");
7453     if ( ensure_CCrequirements() < 0 )
7454         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7455     const CKeyStore& keystore = *pwalletMain;
7456     LOCK2(cs_main, pwalletMain->cs_wallet);
7457     numtokens = atoi(params[0].get_str().c_str());
7458     tokenid = Parseuint256((char *)params[1].get_str().c_str());
7459     price = atof(params[2].get_str().c_str());
7460     bidamount = (price * numtokens) * COIN + 0.0000000049999;
7461     if ( price <= 0 )
7462     {
7463         ERR_RESULT("price must be positive");
7464         return(result);
7465     }
7466     if ( tokenid == zeroid )
7467     {
7468         ERR_RESULT("invalid tokenid");
7469         return(result);
7470     }
7471     if ( bidamount <= 0 )
7472     {
7473         ERR_RESULT("bid amount must be positive");
7474         return(result);
7475     }
7476     hex = CreateBuyOffer(0,bidamount,tokenid,numtokens);
7477     if (price > 0 && numtokens > 0) {
7478         if ( hex.size() > 0 )
7479         {
7480             result.push_back(Pair("result", "success"));
7481             result.push_back(Pair("hex", hex));
7482         } else ERR_RESULT("couldnt create bid");
7483     } else {
7484         ERR_RESULT("price and numtokens must be positive");
7485     }
7486     return(result);
7487 }
7488
7489 UniValue tokencancelbid(const UniValue& params, bool fHelp)
7490 {
7491     UniValue result(UniValue::VOBJ); std::string hex; int32_t i; uint256 tokenid,bidtxid;
7492     if ( fHelp || params.size() != 2 )
7493         throw runtime_error("tokencancelbid tokenid bidtxid\n");
7494     if ( ensure_CCrequirements() < 0 )
7495         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7496     const CKeyStore& keystore = *pwalletMain;
7497     LOCK2(cs_main, pwalletMain->cs_wallet);
7498     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7499     bidtxid = Parseuint256((char *)params[1].get_str().c_str());
7500     if ( tokenid == zeroid || bidtxid == zeroid )
7501     {
7502         result.push_back(Pair("error", "invalid parameter"));
7503         return(result);
7504     }
7505     hex = CancelBuyOffer(0,tokenid,bidtxid);
7506     if ( hex.size() > 0 )
7507     {
7508         result.push_back(Pair("result", "success"));
7509         result.push_back(Pair("hex", hex));
7510     } else ERR_RESULT("couldnt cancel bid");
7511     return(result);
7512 }
7513
7514 UniValue tokenfillbid(const UniValue& params, bool fHelp)
7515 {
7516     UniValue result(UniValue::VOBJ); int64_t fillamount; std::string hex; uint256 tokenid,bidtxid;
7517     if ( fHelp || params.size() != 3 )
7518         throw runtime_error("tokenfillbid tokenid bidtxid fillamount\n");
7519     if ( ensure_CCrequirements() < 0 )
7520         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7521     const CKeyStore& keystore = *pwalletMain;
7522     LOCK2(cs_main, pwalletMain->cs_wallet);
7523     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7524     bidtxid = Parseuint256((char *)params[1].get_str().c_str());
7525     fillamount = atol(params[2].get_str().c_str());
7526     if ( fillamount <= 0 )
7527     {
7528         ERR_RESULT("fillamount must be positive");
7529         return(result);
7530     }
7531     if ( tokenid == zeroid || bidtxid == zeroid )
7532     {
7533         ERR_RESULT("must provide tokenid and bidtxid");
7534         return(result);
7535     }
7536     hex = FillBuyOffer(0,tokenid,bidtxid,fillamount);
7537     if ( hex.size() > 0 )
7538     {
7539         result.push_back(Pair("result", "success"));
7540         result.push_back(Pair("hex", hex));
7541     } else ERR_RESULT("couldnt fill bid");
7542     return(result);
7543 }
7544
7545 UniValue tokenask(const UniValue& params, bool fHelp)
7546 {
7547     UniValue result(UniValue::VOBJ); int64_t askamount,numtokens; std::string hex; double price; uint256 tokenid;
7548     if ( fHelp || params.size() != 3 )
7549         throw runtime_error("tokenask numtokens tokenid price\n");
7550     if ( ensure_CCrequirements() < 0 )
7551         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7552     const CKeyStore& keystore = *pwalletMain;
7553     LOCK2(cs_main, pwalletMain->cs_wallet);
7554     numtokens = atoi(params[0].get_str().c_str());
7555     tokenid = Parseuint256((char *)params[1].get_str().c_str());
7556     price = atof(params[2].get_str().c_str());
7557     askamount = (price * numtokens) * COIN + 0.0000000049999;
7558     if ( tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0 )
7559     {
7560         ERR_RESULT("invalid parameter");
7561         return(result);
7562     }
7563     hex = CreateSell(0,numtokens,tokenid,askamount);
7564     if (price > 0 && numtokens > 0) {
7565         if ( hex.size() > 0 )
7566         {
7567             result.push_back(Pair("result", "success"));
7568             result.push_back(Pair("hex", hex));
7569         } else ERR_RESULT("couldnt create ask");
7570     } else {
7571         ERR_RESULT("price and numtokens must be positive");
7572     }
7573     return(result);
7574 }
7575
7576 UniValue tokenswapask(const UniValue& params, bool fHelp)
7577 {
7578     static uint256 zeroid;
7579     UniValue result(UniValue::VOBJ); int64_t askamount,numtokens; std::string hex; double price; uint256 tokenid,otherid;
7580     if ( fHelp || params.size() != 4 )
7581         throw runtime_error("tokenswapask numtokens tokenid otherid price\n");
7582     if ( ensure_CCrequirements() < 0 )
7583         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7584     const CKeyStore& keystore = *pwalletMain;
7585     LOCK2(cs_main, pwalletMain->cs_wallet);
7586     numtokens = atoi(params[0].get_str().c_str());
7587     tokenid = Parseuint256((char *)params[1].get_str().c_str());
7588     otherid = Parseuint256((char *)params[2].get_str().c_str());
7589     price = atof(params[3].get_str().c_str());
7590     askamount = (price * numtokens);
7591     hex = CreateSwap(0,numtokens,tokenid,otherid,askamount);
7592     if (price > 0 && numtokens > 0) {
7593         if ( hex.size() > 0 )
7594         {
7595             result.push_back(Pair("result", "success"));
7596             result.push_back(Pair("hex", hex));
7597         } else ERR_RESULT("couldnt create swap");
7598     } else {
7599         ERR_RESULT("price and numtokens must be positive");
7600     }
7601     return(result);
7602 }
7603
7604 UniValue tokencancelask(const UniValue& params, bool fHelp)
7605 {
7606     UniValue result(UniValue::VOBJ); std::string hex; int32_t i; uint256 tokenid,asktxid;
7607     if ( fHelp || params.size() != 2 )
7608         throw runtime_error("tokencancelask tokenid asktxid\n");
7609     if ( ensure_CCrequirements() < 0 )
7610         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7611     const CKeyStore& keystore = *pwalletMain;
7612     LOCK2(cs_main, pwalletMain->cs_wallet);
7613     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7614     asktxid = Parseuint256((char *)params[1].get_str().c_str());
7615     if ( tokenid == zeroid || asktxid == zeroid )
7616     {
7617         result.push_back(Pair("error", "invalid parameter"));
7618         return(result);
7619     }
7620     hex = CancelSell(0,tokenid,asktxid);
7621     if ( hex.size() > 0 )
7622     {
7623         result.push_back(Pair("result", "success"));
7624         result.push_back(Pair("hex", hex));
7625     } else ERR_RESULT("couldnt cancel ask");
7626     return(result);
7627 }
7628
7629 UniValue tokenfillask(const UniValue& params, bool fHelp)
7630 {
7631     UniValue result(UniValue::VOBJ); int64_t fillunits; std::string hex; uint256 tokenid,asktxid;
7632     if ( fHelp || params.size() != 3 )
7633         throw runtime_error("tokenfillask tokenid asktxid fillunits\n");
7634     if ( ensure_CCrequirements() < 0 )
7635         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7636     const CKeyStore& keystore = *pwalletMain;
7637     LOCK2(cs_main, pwalletMain->cs_wallet);
7638     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7639     asktxid = Parseuint256((char *)params[1].get_str().c_str());
7640     fillunits = atol(params[2].get_str().c_str());
7641     if ( fillunits <= 0 )
7642     {
7643         ERR_RESULT("fillunits must be positive");
7644         return(result);
7645     }
7646     if ( tokenid == zeroid || asktxid == zeroid )
7647     {
7648         result.push_back(Pair("error", "invalid parameter"));
7649         return(result);
7650     }
7651     hex = FillSell(0,tokenid,zeroid,asktxid,fillunits);
7652     if (fillunits > 0) {
7653         if (CCerror != "") {
7654             ERR_RESULT(CCerror);
7655         } else if ( hex.size() > 0) {
7656             result.push_back(Pair("result", "success"));
7657             result.push_back(Pair("hex", hex));
7658         } else {
7659             ERR_RESULT("couldnt fill bid");
7660         }
7661     } else {
7662         ERR_RESULT("fillunits must be positive");
7663     }
7664     return(result);
7665 }
7666
7667 UniValue tokenfillswap(const UniValue& params, bool fHelp)
7668 {
7669     static uint256 zeroid;
7670     UniValue result(UniValue::VOBJ); int64_t fillunits; std::string hex; uint256 tokenid,otherid,asktxid;
7671     if ( fHelp || params.size() != 4 )
7672         throw runtime_error("tokenfillswap tokenid otherid asktxid fillunits\n");
7673     if ( ensure_CCrequirements() < 0 )
7674         throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
7675     const CKeyStore& keystore = *pwalletMain;
7676     LOCK2(cs_main, pwalletMain->cs_wallet);
7677     tokenid = Parseuint256((char *)params[0].get_str().c_str());
7678     otherid = Parseuint256((char *)params[1].get_str().c_str());
7679     asktxid = Parseuint256((char *)params[2].get_str().c_str());
7680     fillunits = atol(params[3].get_str().c_str());
7681     hex = FillSell(0,tokenid,otherid,asktxid,fillunits);
7682     if (fillunits > 0) {
7683         if ( hex.size() > 0 ) {
7684             result.push_back(Pair("result", "success"));
7685             result.push_back(Pair("hex", hex));
7686         } else ERR_RESULT("couldnt fill bid");
7687     } else {
7688         ERR_RESULT("fillunits must be positive");
7689     }
7690     return(result);
7691 }
7692
7693 UniValue getbalance64(const UniValue& params, bool fHelp)
7694 {
7695     set<CBitcoinAddress> setAddress; vector<COutput> vecOutputs;
7696     UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR),b(UniValue::VARR); CTxDestination address;
7697     const CKeyStore& keystore = *pwalletMain;
7698     CAmount nValues[64],nValues2[64],nValue,total,total2; int32_t i,segid;
7699     if (!EnsureWalletIsAvailable(fHelp))
7700         return NullUniValue;
7701     if (params.size() > 0)
7702         throw runtime_error("getbalance64\n");
7703     total = total2 = 0;
7704     memset(nValues,0,sizeof(nValues));
7705     memset(nValues2,0,sizeof(nValues2));
7706     LOCK2(cs_main, pwalletMain->cs_wallet);
7707     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
7708     BOOST_FOREACH(const COutput& out, vecOutputs)
7709     {
7710         nValue = out.tx->vout[out.i].nValue;
7711         if ( ExtractDestination(out.tx->vout[out.i].scriptPubKey, address) )
7712         {
7713             segid = (komodo_segid32((char *)CBitcoinAddress(address).ToString().c_str()) & 0x3f);
7714             if ( out.nDepth < 100 )
7715                 nValues2[segid] += nValue, total2 += nValue;
7716             else nValues[segid] += nValue, total += nValue;
7717             //fprintf(stderr,"%s %.8f depth.%d segid.%d\n",(char *)CBitcoinAddress(address).ToString().c_str(),(double)nValue/COIN,(int32_t)out.nDepth,segid);
7718         } else fprintf(stderr,"no destination\n");
7719     }
7720     ret.push_back(Pair("mature",(double)total/COIN));
7721     ret.push_back(Pair("immature",(double)total2/COIN));
7722     for (i=0; i<64; i++)
7723     {
7724         a.push_back((uint64_t)nValues[i]);
7725         b.push_back((uint64_t)nValues2[i]);
7726     }
7727     ret.push_back(Pair("staking", a));
7728     ret.push_back(Pair("notstaking", b));
7729     return ret;
7730 }
7731
7732 extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
7733 extern UniValue importprivkey(const UniValue& params, bool fHelp);
7734 extern UniValue importaddress(const UniValue& params, bool fHelp);
7735 extern UniValue dumpwallet(const UniValue& params, bool fHelp);
7736 extern UniValue importwallet(const UniValue& params, bool fHelp);
7737 extern UniValue z_exportkey(const UniValue& params, bool fHelp);
7738 extern UniValue z_importkey(const UniValue& params, bool fHelp);
7739 extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp);
7740 extern UniValue z_importviewingkey(const UniValue& params, bool fHelp);
7741 extern UniValue z_exportwallet(const UniValue& params, bool fHelp);
7742 extern UniValue z_importwallet(const UniValue& params, bool fHelp);
7743
7744 extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp
7745 extern UniValue z_validatepaymentdisclosure(const UniValue &params, bool fHelp);
7746
7747 static const CRPCCommand commands[] =
7748 { //  category              name                        actor (function)           okSafeMode
7749     //  --------------------- ------------------------    -----------------------    ----------
7750     { "rawtransactions",    "fundrawtransaction",       &fundrawtransaction,       false },
7751     { "hidden",             "resendwallettransactions", &resendwallettransactions, true  },
7752     { "wallet",             "addmultisigaddress",       &addmultisigaddress,       true  },
7753     { "wallet",             "backupwallet",             &backupwallet,             true  },
7754     { "wallet",             "dumpprivkey",              &dumpprivkey,              true  },
7755     { "wallet",             "dumpwallet",               &dumpwallet,               true  },
7756     { "wallet",             "encryptwallet",            &encryptwallet,            true  },
7757     { "wallet",             "getaccountaddress",        &getaccountaddress,        true  },
7758     { "wallet",             "getaccount",               &getaccount,               true  },
7759     { "wallet",             "getaddressesbyaccount",    &getaddressesbyaccount,    true  },
7760     { "wallet",             "getbalance",               &getbalance,               false },
7761     { "wallet",             "getnewaddress",            &getnewaddress,            true  },
7762     { "wallet",             "getrawchangeaddress",      &getrawchangeaddress,      true  },
7763     { "wallet",             "getreceivedbyaccount",     &getreceivedbyaccount,     false },
7764     { "wallet",             "getreceivedbyaddress",     &getreceivedbyaddress,     false },
7765     { "wallet",             "gettransaction",           &gettransaction,           false },
7766     { "wallet",             "getunconfirmedbalance",    &getunconfirmedbalance,    false },
7767     { "wallet",             "getwalletinfo",            &getwalletinfo,            false },
7768     { "wallet",             "convertpassphrase",        &convertpassphrase,        true  },
7769     { "wallet",             "importprivkey",            &importprivkey,            true  },
7770     { "wallet",             "importwallet",             &importwallet,             true  },
7771     { "wallet",             "importaddress",            &importaddress,            true  },
7772     { "wallet",             "keypoolrefill",            &keypoolrefill,            true  },
7773     { "wallet",             "listaccounts",             &listaccounts,             false },
7774     { "wallet",             "listaddressgroupings",     &listaddressgroupings,     false },
7775     { "wallet",             "listlockunspent",          &listlockunspent,          false },
7776     { "wallet",             "listreceivedbyaccount",    &listreceivedbyaccount,    false },
7777     { "wallet",             "listreceivedbyaddress",    &listreceivedbyaddress,    false },
7778     { "wallet",             "listsinceblock",           &listsinceblock,           false },
7779     { "wallet",             "listtransactions",         &listtransactions,         false },
7780     { "wallet",             "listunspent",              &listunspent,              false },
7781     { "wallet",             "lockunspent",              &lockunspent,              true  },
7782     { "wallet",             "move",                     &movecmd,                  false },
7783     { "wallet",             "sendfrom",                 &sendfrom,                 false },
7784     { "wallet",             "sendmany",                 &sendmany,                 false },
7785     { "wallet",             "sendtoaddress",            &sendtoaddress,            false },
7786     { "wallet",             "setaccount",               &setaccount,               true  },
7787     { "wallet",             "settxfee",                 &settxfee,                 true  },
7788     { "wallet",             "signmessage",              &signmessage,              true  },
7789     { "wallet",             "signfile",                 &signfile,                 true  },
7790     { "hidden",             "printapis",                &printapis,                true  },
7791     // { "hidden",             "signhash",                 &signhash,                 true  }, // disable due to risk of signing something that doesn't contain the content
7792     { "wallet",             "walletlock",               &walletlock,               true  },
7793     { "wallet",             "walletpassphrasechange",   &walletpassphrasechange,   true  },
7794     { "wallet",             "walletpassphrase",         &walletpassphrase,         true  },
7795     { "wallet",             "zcbenchmark",              &zc_benchmark,             true  },
7796     { "wallet",             "zcrawkeygen",              &zc_raw_keygen,            true  },
7797     { "wallet",             "zcrawjoinsplit",           &zc_raw_joinsplit,         true  },
7798     { "wallet",             "zcrawreceive",             &zc_raw_receive,           true  },
7799     { "wallet",             "zcsamplejoinsplit",        &zc_sample_joinsplit,      true  },
7800     { "wallet",             "z_listreceivedbyaddress",  &z_listreceivedbyaddress,  false },
7801     { "wallet",             "z_listunspent",            &z_listunspent,            false },
7802     { "wallet",             "z_getbalance",             &z_getbalance,             false },
7803     { "wallet",             "z_gettotalbalance",        &z_gettotalbalance,        false },
7804     { "wallet",             "z_mergetoaddress",         &z_mergetoaddress,         false },
7805     { "wallet",             "z_sendmany",               &z_sendmany,               false },
7806     { "wallet",             "z_setmigration",           &z_setmigration,           false },
7807     { "wallet",             "z_getmigrationstatus",     &z_getmigrationstatus,     false },
7808     { "wallet",             "z_shieldcoinbase",         &z_shieldcoinbase,         false },
7809     { "wallet",             "z_getoperationstatus",     &z_getoperationstatus,     true  },
7810     { "wallet",             "z_getoperationresult",     &z_getoperationresult,     true  },
7811     { "wallet",             "z_listoperationids",       &z_listoperationids,       true  },
7812     { "wallet",             "z_getnewaddress",          &z_getnewaddress,          true  },
7813     { "wallet",             "z_listaddresses",          &z_listaddresses,          true  },
7814     { "wallet",             "z_exportkey",              &z_exportkey,              true  },
7815     { "wallet",             "z_importkey",              &z_importkey,              true  },
7816     { "wallet",             "z_exportviewingkey",       &z_exportviewingkey,       true  },
7817     { "wallet",             "z_importviewingkey",       &z_importviewingkey,       true  },
7818     { "wallet",             "z_exportwallet",           &z_exportwallet,           true  },
7819     { "wallet",             "z_importwallet",           &z_importwallet,           true  },
7820     { "wallet",             "z_viewtransaction",        &z_viewtransaction,        true  },
7821     // TODO: rearrange into another category
7822     { "disclosure",         "z_getpaymentdisclosure",   &z_getpaymentdisclosure,   true  },
7823     { "disclosure",         "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true }
7824 };
7825
7826 void RegisterWalletRPCCommands(CRPCTable &tableRPC)
7827 {
7828     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
7829         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
7830 }
This page took 0.481462 seconds and 4 git commands to generate.