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