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