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.
7 #include "consensus/upgrades.h"
14 #include "rpc/server.h"
16 #include "transaction_builder.h"
18 #include "utilmoneystr.h"
21 #include "primitives/transaction.h"
22 #include "zcbenchmarks.h"
23 #include "script/interpreter.h"
24 #include "zcash/zip32.h"
27 #include "asyncrpcoperation.h"
28 #include "asyncrpcqueue.h"
29 #include "wallet/asyncrpcoperation_mergetoaddress.h"
30 #include "wallet/asyncrpcoperation_saplingmigration.h"
31 #include "wallet/asyncrpcoperation_sendmany.h"
32 #include "wallet/asyncrpcoperation_shieldcoinbase.h"
38 #include <boost/assign/list_of.hpp>
46 using namespace libzcash;
48 const std::string ADDR_TYPE_SPROUT = "sprout";
49 const std::string ADDR_TYPE_SAPLING = "sapling";
51 extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
53 int64_t nWalletUnlockTime;
54 static CCriticalSection cs_nWalletUnlockTime;
57 UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
59 std::string HelpRequiringPassphrase()
61 return pwalletMain && pwalletMain->IsCrypted()
62 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
66 bool EnsureWalletIsAvailable(bool avoidException)
71 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
78 void EnsureWalletIsUnlocked()
80 if (pwalletMain->IsLocked())
81 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
84 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
86 int confirms = wtx.GetDepthInMainChain();
87 entry.push_back(Pair("confirmations", confirms));
89 entry.push_back(Pair("generated", true));
92 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
93 entry.push_back(Pair("blockindex", wtx.nIndex));
94 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
95 entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
97 uint256 hash = wtx.GetHash();
98 entry.push_back(Pair("txid", hash.GetHex()));
99 UniValue conflicts(UniValue::VARR);
100 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
101 conflicts.push_back(conflict.GetHex());
102 entry.push_back(Pair("walletconflicts", conflicts));
103 entry.push_back(Pair("time", wtx.GetTxTime()));
104 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
105 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
106 entry.push_back(Pair(item.first, item.second));
108 entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx)));
111 string AccountFromValue(const UniValue& value)
113 string strAccount = value.get_str();
114 if (strAccount != "")
115 throw JSONRPCError(RPC_WALLET_ACCOUNTS_UNSUPPORTED, "Accounts are unsupported");
119 UniValue getnewaddress(const UniValue& params, bool fHelp)
121 if (!EnsureWalletIsAvailable(fHelp))
124 if (fHelp || params.size() > 1)
126 "getnewaddress ( \"account\" )\n"
127 "\nReturns a new Zcash address for receiving payments.\n"
129 "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"
131 "\"zcashaddress\" (string) The new Zcash address\n"
133 + HelpExampleCli("getnewaddress", "")
134 + HelpExampleRpc("getnewaddress", "")
137 LOCK2(cs_main, pwalletMain->cs_wallet);
139 // Parse the account first so we don't generate a key if there's an error
141 if (params.size() > 0)
142 strAccount = AccountFromValue(params[0]);
144 if (!pwalletMain->IsLocked())
145 pwalletMain->TopUpKeyPool();
147 // Generate a new key that is added to wallet
149 if (!pwalletMain->GetKeyFromPool(newKey))
150 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
151 CKeyID keyID = newKey.GetID();
153 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
155 return EncodeDestination(keyID);
159 CTxDestination GetAccountAddress(std::string strAccount, bool bForceNew=false)
161 CWalletDB walletdb(pwalletMain->strWalletFile);
164 walletdb.ReadAccount(strAccount, account);
166 bool bKeyUsed = false;
168 // Check if the current key has been used
169 if (account.vchPubKey.IsValid())
171 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
172 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
173 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
176 const CWalletTx& wtx = (*it).second;
177 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
178 if (txout.scriptPubKey == scriptPubKey)
183 // Generate a new key
184 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
186 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
187 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
189 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
190 walletdb.WriteAccount(strAccount, account);
193 return account.vchPubKey.GetID();
196 UniValue getaccountaddress(const UniValue& params, bool fHelp)
198 if (!EnsureWalletIsAvailable(fHelp))
201 if (fHelp || params.size() != 1)
203 "getaccountaddress \"account\"\n"
204 "\nDEPRECATED. Returns the current Zcash address for receiving payments to this account.\n"
206 "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"
208 "\"zcashaddress\" (string) The account Zcash address\n"
210 + HelpExampleCli("getaccountaddress", "")
211 + HelpExampleCli("getaccountaddress", "\"\"")
212 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
213 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
216 LOCK2(cs_main, pwalletMain->cs_wallet);
218 // Parse the account first so we don't generate a key if there's an error
219 string strAccount = AccountFromValue(params[0]);
221 UniValue ret(UniValue::VSTR);
223 ret = EncodeDestination(GetAccountAddress(strAccount));
228 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
230 if (!EnsureWalletIsAvailable(fHelp))
233 if (fHelp || params.size() > 1)
235 "getrawchangeaddress\n"
236 "\nReturns a new Zcash address, for receiving change.\n"
237 "This is for use with raw transactions, NOT normal use.\n"
239 "\"address\" (string) The address\n"
241 + HelpExampleCli("getrawchangeaddress", "")
242 + HelpExampleRpc("getrawchangeaddress", "")
245 LOCK2(cs_main, pwalletMain->cs_wallet);
247 if (!pwalletMain->IsLocked())
248 pwalletMain->TopUpKeyPool();
250 CReserveKey reservekey(pwalletMain);
252 if (!reservekey.GetReservedKey(vchPubKey))
253 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
255 reservekey.KeepKey();
257 CKeyID keyID = vchPubKey.GetID();
259 return EncodeDestination(keyID);
263 UniValue setaccount(const UniValue& params, bool fHelp)
265 if (!EnsureWalletIsAvailable(fHelp))
268 if (fHelp || params.size() < 1 || params.size() > 2)
270 "setaccount \"zcashaddress\" \"account\"\n"
271 "\nDEPRECATED. Sets the account associated with the given address.\n"
273 "1. \"zcashaddress\" (string, required) The Zcash address to be associated with an account.\n"
274 "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"
276 + HelpExampleCli("setaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"tabby\"")
277 + HelpExampleRpc("setaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"tabby\"")
280 LOCK2(cs_main, pwalletMain->cs_wallet);
282 CTxDestination dest = DecodeDestination(params[0].get_str());
283 if (!IsValidDestination(dest)) {
284 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
288 if (params.size() > 1)
289 strAccount = AccountFromValue(params[1]);
291 // Only add the account if the address is yours.
292 if (IsMine(*pwalletMain, dest)) {
293 // Detect when changing the account of an address that is the 'unused current key' of another account:
294 if (pwalletMain->mapAddressBook.count(dest)) {
295 std::string strOldAccount = pwalletMain->mapAddressBook[dest].name;
296 if (dest == GetAccountAddress(strOldAccount)) {
297 GetAccountAddress(strOldAccount, true);
300 pwalletMain->SetAddressBook(dest, strAccount, "receive");
303 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
309 UniValue getaccount(const UniValue& params, bool fHelp)
311 if (!EnsureWalletIsAvailable(fHelp))
314 if (fHelp || params.size() != 1)
316 "getaccount \"zcashaddress\"\n"
317 "\nDEPRECATED. Returns the account associated with the given address.\n"
319 "1. \"zcashaddress\" (string, required) The Zcash address for account lookup.\n"
321 "\"accountname\" (string) the account address\n"
323 + HelpExampleCli("getaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"")
324 + HelpExampleRpc("getaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"")
327 LOCK2(cs_main, pwalletMain->cs_wallet);
329 CTxDestination dest = DecodeDestination(params[0].get_str());
330 if (!IsValidDestination(dest)) {
331 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
334 std::string strAccount;
335 std::map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(dest);
336 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) {
337 strAccount = (*mi).second.name;
343 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
345 if (!EnsureWalletIsAvailable(fHelp))
348 if (fHelp || params.size() != 1)
350 "getaddressesbyaccount \"account\"\n"
351 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
353 "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"
355 "[ (json array of string)\n"
356 " \"zcashaddress\" (string) a Zcash address associated with the given account\n"
360 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
361 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
364 LOCK2(cs_main, pwalletMain->cs_wallet);
366 string strAccount = AccountFromValue(params[0]);
368 // Find all addresses that have the given account
369 UniValue ret(UniValue::VARR);
370 for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
371 const CTxDestination& dest = item.first;
372 const std::string& strName = item.second.name;
373 if (strName == strAccount) {
374 ret.push_back(EncodeDestination(dest));
380 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
382 CAmount curBalance = pwalletMain->GetBalance();
386 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
388 if (nValue > curBalance)
389 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
391 // Parse Zcash address
392 CScript scriptPubKey = GetScriptForDestination(address);
394 // Create and send the transaction
395 CReserveKey reservekey(pwalletMain);
396 CAmount nFeeRequired;
397 std::string strError;
398 vector<CRecipient> vecSend;
399 int nChangePosRet = -1;
400 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
401 vecSend.push_back(recipient);
402 if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
403 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
404 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));
405 throw JSONRPCError(RPC_WALLET_ERROR, strError);
407 if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
408 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.");
411 UniValue sendtoaddress(const UniValue& params, bool fHelp)
413 if (!EnsureWalletIsAvailable(fHelp))
416 if (fHelp || params.size() < 2 || params.size() > 5)
418 "sendtoaddress \"zcashaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
419 "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
420 + HelpRequiringPassphrase() +
422 "1. \"zcashaddress\" (string, required) The Zcash address to send to.\n"
423 "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
424 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
425 " This is not part of the transaction, just kept in your wallet.\n"
426 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
427 " to which you're sending the transaction. This is not part of the \n"
428 " transaction, just kept in your wallet.\n"
429 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
430 " The recipient will receive less Zcash than you enter in the amount field.\n"
432 "\"transactionid\" (string) The transaction id.\n"
434 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
435 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
436 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
437 + HelpExampleRpc("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
440 LOCK2(cs_main, pwalletMain->cs_wallet);
442 CTxDestination dest = DecodeDestination(params[0].get_str());
443 if (!IsValidDestination(dest)) {
444 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
448 CAmount nAmount = AmountFromValue(params[1]);
450 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
454 if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
455 wtx.mapValue["comment"] = params[2].get_str();
456 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
457 wtx.mapValue["to"] = params[3].get_str();
459 bool fSubtractFeeFromAmount = false;
460 if (params.size() > 4)
461 fSubtractFeeFromAmount = params[4].get_bool();
463 EnsureWalletIsUnlocked();
465 SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx);
467 return wtx.GetHash().GetHex();
470 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
472 if (!EnsureWalletIsAvailable(fHelp))
477 "listaddressgroupings\n"
478 "\nLists groups of addresses which have had their common ownership\n"
479 "made public by common use as inputs or as the resulting change\n"
480 "in past transactions\n"
485 " \"zcashaddress\", (string) The zcash address\n"
486 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
487 " \"account\" (string, optional) The account (DEPRECATED)\n"
494 + HelpExampleCli("listaddressgroupings", "")
495 + HelpExampleRpc("listaddressgroupings", "")
498 LOCK2(cs_main, pwalletMain->cs_wallet);
500 UniValue jsonGroupings(UniValue::VARR);
501 std::map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
502 for (const std::set<CTxDestination>& grouping : pwalletMain->GetAddressGroupings()) {
503 UniValue jsonGrouping(UniValue::VARR);
504 for (const CTxDestination& address : grouping)
506 UniValue addressInfo(UniValue::VARR);
507 addressInfo.push_back(EncodeDestination(address));
508 addressInfo.push_back(ValueFromAmount(balances[address]));
510 if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) {
511 addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second.name);
514 jsonGrouping.push_back(addressInfo);
516 jsonGroupings.push_back(jsonGrouping);
518 return jsonGroupings;
521 UniValue signmessage(const UniValue& params, bool fHelp)
523 if (!EnsureWalletIsAvailable(fHelp))
526 if (fHelp || params.size() != 2)
528 "signmessage \"t-addr\" \"message\"\n"
529 "\nSign a message with the private key of a t-addr"
530 + HelpRequiringPassphrase() + "\n"
532 "1. \"t-addr\" (string, required) The transparent address to use for the private key.\n"
533 "2. \"message\" (string, required) The message to create a signature of.\n"
535 "\"signature\" (string) The signature of the message encoded in base 64\n"
537 "\nUnlock the wallet for 30 seconds\n"
538 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
539 "\nCreate the signature\n"
540 + HelpExampleCli("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"my message\"") +
541 "\nVerify the signature\n"
542 + HelpExampleCli("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"signature\" \"my message\"") +
544 + HelpExampleRpc("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"my message\"")
547 LOCK2(cs_main, pwalletMain->cs_wallet);
549 EnsureWalletIsUnlocked();
551 string strAddress = params[0].get_str();
552 string strMessage = params[1].get_str();
554 CTxDestination dest = DecodeDestination(strAddress);
555 if (!IsValidDestination(dest)) {
556 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
559 const CKeyID *keyID = boost::get<CKeyID>(&dest);
561 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
565 if (!pwalletMain->GetKey(*keyID, key)) {
566 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
569 CHashWriter ss(SER_GETHASH, 0);
570 ss << strMessageMagic;
573 vector<unsigned char> vchSig;
574 if (!key.SignCompact(ss.GetHash(), vchSig))
575 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
577 return EncodeBase64(&vchSig[0], vchSig.size());
580 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
582 if (!EnsureWalletIsAvailable(fHelp))
585 if (fHelp || params.size() < 1 || params.size() > 2)
587 "getreceivedbyaddress \"zcashaddress\" ( minconf )\n"
588 "\nReturns the total amount received by the given Zcash address in transactions with at least minconf confirmations.\n"
590 "1. \"zcashaddress\" (string, required) The Zcash address for transactions.\n"
591 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
593 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
595 "\nThe amount from transactions with at least 1 confirmation\n"
596 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"") +
597 "\nThe amount including unconfirmed transactions, zero confirmations\n"
598 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" 0") +
599 "\nThe amount with at least 6 confirmations, very safe\n"
600 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" 6") +
601 "\nAs a json rpc call\n"
602 + HelpExampleRpc("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", 6")
605 LOCK2(cs_main, pwalletMain->cs_wallet);
608 CTxDestination dest = DecodeDestination(params[0].get_str());
609 if (!IsValidDestination(dest)) {
610 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
612 CScript scriptPubKey = GetScriptForDestination(dest);
613 if (!IsMine(*pwalletMain, scriptPubKey)) {
614 return ValueFromAmount(0);
617 // Minimum confirmations
619 if (params.size() > 1)
620 nMinDepth = params[1].get_int();
624 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
626 const CWalletTx& wtx = (*it).second;
627 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
630 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
631 if (txout.scriptPubKey == scriptPubKey)
632 if (wtx.GetDepthInMainChain() >= nMinDepth)
633 nAmount += txout.nValue;
636 return ValueFromAmount(nAmount);
640 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
642 if (!EnsureWalletIsAvailable(fHelp))
645 if (fHelp || params.size() < 1 || params.size() > 2)
647 "getreceivedbyaccount \"account\" ( minconf )\n"
648 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
650 "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"
651 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
653 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
655 "\nAmount received by the default account with at least 1 confirmation\n"
656 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
657 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
658 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
659 "\nThe amount with at least 6 confirmation, very safe\n"
660 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
661 "\nAs a json rpc call\n"
662 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
665 LOCK2(cs_main, pwalletMain->cs_wallet);
667 // Minimum confirmations
669 if (params.size() > 1)
670 nMinDepth = params[1].get_int();
672 // Get the set of pub keys assigned to account
673 string strAccount = AccountFromValue(params[0]);
674 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
678 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
680 const CWalletTx& wtx = (*it).second;
681 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
684 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
686 CTxDestination address;
687 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
688 if (wtx.GetDepthInMainChain() >= nMinDepth)
689 nAmount += txout.nValue;
693 return ValueFromAmount(nAmount);
697 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
699 CAmount nBalance = 0;
701 // Tally wallet transactions
702 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
704 const CWalletTx& wtx = (*it).second;
705 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
708 CAmount nReceived, nSent, nFee;
709 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
711 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
712 nBalance += nReceived;
713 nBalance -= nSent + nFee;
716 // Tally internal accounting entries
717 nBalance += walletdb.GetAccountCreditDebit(strAccount);
722 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
724 CWalletDB walletdb(pwalletMain->strWalletFile);
725 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
729 UniValue getbalance(const UniValue& params, bool fHelp)
731 if (!EnsureWalletIsAvailable(fHelp))
734 if (fHelp || params.size() > 3)
736 "getbalance ( \"account\" minconf includeWatchonly )\n"
737 "\nReturns the server's total available balance.\n"
739 "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"
740 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
741 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
743 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
745 "\nThe total amount in the wallet\n"
746 + HelpExampleCli("getbalance", "") +
747 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
748 + HelpExampleCli("getbalance", "\"*\" 6") +
749 "\nAs a json rpc call\n"
750 + HelpExampleRpc("getbalance", "\"*\", 6")
753 LOCK2(cs_main, pwalletMain->cs_wallet);
755 if (params.size() == 0)
756 return ValueFromAmount(pwalletMain->GetBalance());
759 if (params.size() > 1)
760 nMinDepth = params[1].get_int();
761 isminefilter filter = ISMINE_SPENDABLE;
762 if(params.size() > 2)
763 if(params[2].get_bool())
764 filter = filter | ISMINE_WATCH_ONLY;
766 if (params[0].get_str() == "*") {
767 // Calculate total balance a different way from GetBalance()
768 // (GetBalance() sums up all unspent TxOuts)
769 // getbalance and "getbalance * 1 true" should return the same number
770 CAmount nBalance = 0;
771 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
773 const CWalletTx& wtx = (*it).second;
774 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
778 string strSentAccount;
779 list<COutputEntry> listReceived;
780 list<COutputEntry> listSent;
781 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
782 if (wtx.GetDepthInMainChain() >= nMinDepth)
784 BOOST_FOREACH(const COutputEntry& r, listReceived)
785 nBalance += r.amount;
787 BOOST_FOREACH(const COutputEntry& s, listSent)
788 nBalance -= s.amount;
791 return ValueFromAmount(nBalance);
794 string strAccount = AccountFromValue(params[0]);
796 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
798 return ValueFromAmount(nBalance);
801 UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp)
803 if (!EnsureWalletIsAvailable(fHelp))
806 if (fHelp || params.size() > 0)
808 "getunconfirmedbalance\n"
809 "Returns the server's total unconfirmed balance\n");
811 LOCK2(cs_main, pwalletMain->cs_wallet);
813 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
817 UniValue movecmd(const UniValue& params, bool fHelp)
819 if (!EnsureWalletIsAvailable(fHelp))
822 if (fHelp || params.size() < 3 || params.size() > 5)
824 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
825 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
827 "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"
828 "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"
829 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
830 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
831 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
833 "true|false (boolean) true if successful.\n"
835 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
836 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
837 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
838 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
839 "\nAs a json rpc call\n"
840 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
843 LOCK2(cs_main, pwalletMain->cs_wallet);
845 string strFrom = AccountFromValue(params[0]);
846 string strTo = AccountFromValue(params[1]);
847 CAmount nAmount = AmountFromValue(params[2]);
849 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
850 if (params.size() > 3)
851 // unused parameter, used to be nMinDepth, keep type-checking it though
852 (void)params[3].get_int();
854 if (params.size() > 4)
855 strComment = params[4].get_str();
857 CWalletDB walletdb(pwalletMain->strWalletFile);
858 if (!walletdb.TxnBegin())
859 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
861 int64_t nNow = GetAdjustedTime();
864 CAccountingEntry debit;
865 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
866 debit.strAccount = strFrom;
867 debit.nCreditDebit = -nAmount;
869 debit.strOtherAccount = strTo;
870 debit.strComment = strComment;
871 walletdb.WriteAccountingEntry(debit);
874 CAccountingEntry credit;
875 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
876 credit.strAccount = strTo;
877 credit.nCreditDebit = nAmount;
879 credit.strOtherAccount = strFrom;
880 credit.strComment = strComment;
881 walletdb.WriteAccountingEntry(credit);
883 if (!walletdb.TxnCommit())
884 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
890 UniValue sendfrom(const UniValue& params, bool fHelp)
892 if (!EnsureWalletIsAvailable(fHelp))
895 if (fHelp || params.size() < 3 || params.size() > 6)
897 "sendfrom \"fromaccount\" \"tozcashaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
898 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a Zcash address.\n"
899 "The amount is a real and is rounded to the nearest 0.00000001."
900 + HelpRequiringPassphrase() + "\n"
902 "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"
903 "2. \"tozcashaddress\" (string, required) The Zcash address to send funds to.\n"
904 "3. amount (numeric, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
905 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
906 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
907 " This is not part of the transaction, just kept in your wallet.\n"
908 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
909 " to which you're sending the transaction. This is not part of the transaction, \n"
910 " it is just kept in your wallet.\n"
912 "\"transactionid\" (string) The transaction id.\n"
914 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
915 + HelpExampleCli("sendfrom", "\"\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
916 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
917 + HelpExampleCli("sendfrom", "\"tabby\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
918 "\nAs a json rpc call\n"
919 + HelpExampleRpc("sendfrom", "\"tabby\", \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
922 LOCK2(cs_main, pwalletMain->cs_wallet);
924 std::string strAccount = AccountFromValue(params[0]);
925 CTxDestination dest = DecodeDestination(params[1].get_str());
926 if (!IsValidDestination(dest)) {
927 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
929 CAmount nAmount = AmountFromValue(params[2]);
931 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
933 if (params.size() > 3)
934 nMinDepth = params[3].get_int();
937 wtx.strFromAccount = strAccount;
938 if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
939 wtx.mapValue["comment"] = params[4].get_str();
940 if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
941 wtx.mapValue["to"] = params[5].get_str();
943 EnsureWalletIsUnlocked();
946 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
947 if (nAmount > nBalance)
948 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
950 SendMoney(dest, nAmount, false, wtx);
952 return wtx.GetHash().GetHex();
956 UniValue sendmany(const UniValue& params, bool fHelp)
958 if (!EnsureWalletIsAvailable(fHelp))
961 if (fHelp || params.size() < 2 || params.size() > 5)
963 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
964 "\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
965 + HelpRequiringPassphrase() + "\n"
967 "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"
968 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
970 " \"address\":amount (numeric) The Zcash address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
973 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
974 "4. \"comment\" (string, optional) A comment\n"
975 "5. subtractfeefromamount (string, optional) A json array with addresses.\n"
976 " The fee will be equally deducted from the amount of each selected address.\n"
977 " Those recipients will receive less Zcash than you enter in their corresponding amount field.\n"
978 " If no addresses are specified here, the sender pays the fee.\n"
980 " \"address\" (string) Subtract fee from this address\n"
984 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
985 " the number of addresses.\n"
987 "\nSend two amounts to two different addresses:\n"
988 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
989 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
990 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
991 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
992 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\",\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
993 "\nAs a json rpc call\n"
994 + HelpExampleRpc("sendmany", "\"\", \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
997 LOCK2(cs_main, pwalletMain->cs_wallet);
999 string strAccount = AccountFromValue(params[0]);
1000 UniValue sendTo = params[1].get_obj();
1002 if (params.size() > 2)
1003 nMinDepth = params[2].get_int();
1006 wtx.strFromAccount = strAccount;
1007 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
1008 wtx.mapValue["comment"] = params[3].get_str();
1010 UniValue subtractFeeFromAmount(UniValue::VARR);
1011 if (params.size() > 4)
1012 subtractFeeFromAmount = params[4].get_array();
1014 std::set<CTxDestination> destinations;
1015 std::vector<CRecipient> vecSend;
1017 CAmount totalAmount = 0;
1018 std::vector<std::string> keys = sendTo.getKeys();
1019 for (const std::string& name_ : keys) {
1020 CTxDestination dest = DecodeDestination(name_);
1021 if (!IsValidDestination(dest)) {
1022 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
1025 if (destinations.count(dest)) {
1026 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
1028 destinations.insert(dest);
1030 CScript scriptPubKey = GetScriptForDestination(dest);
1031 CAmount nAmount = AmountFromValue(sendTo[name_]);
1033 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1034 totalAmount += nAmount;
1036 bool fSubtractFeeFromAmount = false;
1037 for (size_t idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1038 const UniValue& addr = subtractFeeFromAmount[idx];
1039 if (addr.get_str() == name_)
1040 fSubtractFeeFromAmount = true;
1043 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1044 vecSend.push_back(recipient);
1047 EnsureWalletIsUnlocked();
1050 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1051 if (totalAmount > nBalance)
1052 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1055 CReserveKey keyChange(pwalletMain);
1056 CAmount nFeeRequired = 0;
1057 int nChangePosRet = -1;
1058 string strFailReason;
1059 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1061 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1062 if (!pwalletMain->CommitTransaction(wtx, keyChange))
1063 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
1065 return wtx.GetHash().GetHex();
1068 // Defined in rpc/misc.cpp
1069 extern CScript _createmultisig_redeemScript(const UniValue& params);
1071 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
1073 if (!EnsureWalletIsAvailable(fHelp))
1074 return NullUniValue;
1076 if (fHelp || params.size() < 2 || params.size() > 3)
1078 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1079 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1080 "Each key is a Zcash address or hex-encoded public key.\n"
1081 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1084 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1085 "2. \"keysobject\" (string, required) A json array of Zcash addresses or hex-encoded public keys\n"
1087 " \"address\" (string) Zcash address or hex-encoded public key\n"
1090 "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"
1093 "\"zcashaddress\" (string) A Zcash address associated with the keys.\n"
1096 "\nAdd a multisig address from 2 addresses\n"
1097 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1098 "\nAs json rpc call\n"
1099 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1101 throw runtime_error(msg);
1104 LOCK2(cs_main, pwalletMain->cs_wallet);
1107 if (params.size() > 2)
1108 strAccount = AccountFromValue(params[2]);
1110 // Construct using pay-to-script-hash:
1111 CScript inner = _createmultisig_redeemScript(params);
1112 CScriptID innerID(inner);
1113 pwalletMain->AddCScript(inner);
1115 pwalletMain->SetAddressBook(innerID, strAccount, "send");
1116 return EncodeDestination(innerID);
1124 vector<uint256> txids;
1129 nConf = std::numeric_limits<int>::max();
1130 fIsWatchonly = false;
1134 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1136 // Minimum confirmations
1138 if (params.size() > 0)
1139 nMinDepth = params[0].get_int();
1141 // Whether to include empty accounts
1142 bool fIncludeEmpty = false;
1143 if (params.size() > 1)
1144 fIncludeEmpty = params[1].get_bool();
1146 isminefilter filter = ISMINE_SPENDABLE;
1147 if(params.size() > 2)
1148 if(params[2].get_bool())
1149 filter = filter | ISMINE_WATCH_ONLY;
1152 std::map<CTxDestination, tallyitem> mapTally;
1153 for (const std::pair<uint256, CWalletTx>& pairWtx : pwalletMain->mapWallet) {
1154 const CWalletTx& wtx = pairWtx.second;
1156 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1159 int nDepth = wtx.GetDepthInMainChain();
1160 if (nDepth < nMinDepth)
1163 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1165 CTxDestination address;
1166 if (!ExtractDestination(txout.scriptPubKey, address))
1169 isminefilter mine = IsMine(*pwalletMain, address);
1170 if(!(mine & filter))
1173 tallyitem& item = mapTally[address];
1174 item.nAmount += txout.nValue;
1175 item.nConf = min(item.nConf, nDepth);
1176 item.txids.push_back(wtx.GetHash());
1177 if (mine & ISMINE_WATCH_ONLY)
1178 item.fIsWatchonly = true;
1183 UniValue ret(UniValue::VARR);
1184 std::map<std::string, tallyitem> mapAccountTally;
1185 for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
1186 const CTxDestination& dest = item.first;
1187 const std::string& strAccount = item.second.name;
1188 std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
1189 if (it == mapTally.end() && !fIncludeEmpty)
1192 CAmount nAmount = 0;
1193 int nConf = std::numeric_limits<int>::max();
1194 bool fIsWatchonly = false;
1195 if (it != mapTally.end())
1197 nAmount = (*it).second.nAmount;
1198 nConf = (*it).second.nConf;
1199 fIsWatchonly = (*it).second.fIsWatchonly;
1204 tallyitem& item = mapAccountTally[strAccount];
1205 item.nAmount += nAmount;
1206 item.nConf = min(item.nConf, nConf);
1207 item.fIsWatchonly = fIsWatchonly;
1211 UniValue obj(UniValue::VOBJ);
1213 obj.push_back(Pair("involvesWatchonly", true));
1214 obj.push_back(Pair("address", EncodeDestination(dest)));
1215 obj.push_back(Pair("account", strAccount));
1216 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1217 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1218 UniValue transactions(UniValue::VARR);
1219 if (it != mapTally.end())
1221 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1223 transactions.push_back(item.GetHex());
1226 obj.push_back(Pair("txids", transactions));
1233 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1235 CAmount nAmount = (*it).second.nAmount;
1236 int nConf = (*it).second.nConf;
1237 UniValue obj(UniValue::VOBJ);
1238 if((*it).second.fIsWatchonly)
1239 obj.push_back(Pair("involvesWatchonly", true));
1240 obj.push_back(Pair("account", (*it).first));
1241 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1242 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1250 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1252 if (!EnsureWalletIsAvailable(fHelp))
1253 return NullUniValue;
1255 if (fHelp || params.size() > 3)
1256 throw runtime_error(
1257 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1258 "\nList balances by receiving address.\n"
1260 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1261 "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1262 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1267 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1268 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1269 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1270 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1271 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1277 + HelpExampleCli("listreceivedbyaddress", "")
1278 + HelpExampleCli("listreceivedbyaddress", "6 true")
1279 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1282 LOCK2(cs_main, pwalletMain->cs_wallet);
1284 return ListReceived(params, false);
1287 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
1289 if (!EnsureWalletIsAvailable(fHelp))
1290 return NullUniValue;
1292 if (fHelp || params.size() > 3)
1293 throw runtime_error(
1294 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1295 "\nDEPRECATED. List balances by account.\n"
1297 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1298 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1299 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1304 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1305 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1306 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1307 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1313 + HelpExampleCli("listreceivedbyaccount", "")
1314 + HelpExampleCli("listreceivedbyaccount", "6 true")
1315 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1318 LOCK2(cs_main, pwalletMain->cs_wallet);
1320 return ListReceived(params, true);
1323 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1325 if (IsValidDestination(dest)) {
1326 entry.push_back(Pair("address", EncodeDestination(dest)));
1330 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1333 string strSentAccount;
1334 list<COutputEntry> listReceived;
1335 list<COutputEntry> listSent;
1337 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1339 bool fAllAccounts = (strAccount == string("*"));
1340 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1343 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1345 BOOST_FOREACH(const COutputEntry& s, listSent)
1347 UniValue entry(UniValue::VOBJ);
1348 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1349 entry.push_back(Pair("involvesWatchonly", true));
1350 entry.push_back(Pair("account", strSentAccount));
1351 MaybePushAddress(entry, s.destination);
1352 entry.push_back(Pair("category", "send"));
1353 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1354 entry.push_back(Pair("vout", s.vout));
1355 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1357 WalletTxToJSON(wtx, entry);
1358 entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
1359 ret.push_back(entry);
1364 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1366 BOOST_FOREACH(const COutputEntry& r, listReceived)
1369 if (pwalletMain->mapAddressBook.count(r.destination))
1370 account = pwalletMain->mapAddressBook[r.destination].name;
1371 if (fAllAccounts || (account == strAccount))
1373 UniValue entry(UniValue::VOBJ);
1374 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1375 entry.push_back(Pair("involvesWatchonly", true));
1376 entry.push_back(Pair("account", account));
1377 MaybePushAddress(entry, r.destination);
1378 if (wtx.IsCoinBase())
1380 if (wtx.GetDepthInMainChain() < 1)
1381 entry.push_back(Pair("category", "orphan"));
1382 else if (wtx.GetBlocksToMaturity() > 0)
1383 entry.push_back(Pair("category", "immature"));
1385 entry.push_back(Pair("category", "generate"));
1389 entry.push_back(Pair("category", "receive"));
1391 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1392 entry.push_back(Pair("vout", r.vout));
1394 WalletTxToJSON(wtx, entry);
1395 entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
1396 ret.push_back(entry);
1402 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1404 bool fAllAccounts = (strAccount == string("*"));
1406 if (fAllAccounts || acentry.strAccount == strAccount)
1408 UniValue entry(UniValue::VOBJ);
1409 entry.push_back(Pair("account", acentry.strAccount));
1410 entry.push_back(Pair("category", "move"));
1411 entry.push_back(Pair("time", acentry.nTime));
1412 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1413 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1414 entry.push_back(Pair("comment", acentry.strComment));
1415 ret.push_back(entry);
1419 UniValue listtransactions(const UniValue& params, bool fHelp)
1421 if (!EnsureWalletIsAvailable(fHelp))
1422 return NullUniValue;
1424 if (fHelp || params.size() > 4)
1425 throw runtime_error(
1426 "listtransactions ( \"account\" count from includeWatchonly)\n"
1427 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1429 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1430 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1431 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1432 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1436 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1437 " It will be \"\" for the default account.\n"
1438 " \"address\":\"zcashaddress\", (string) The Zcash address of the transaction. Not present for \n"
1439 " move transactions (category = move).\n"
1440 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1441 " transaction between accounts, and not associated with an address,\n"
1442 " transaction id or block. 'send' and 'receive' transactions are \n"
1443 " associated with an address, transaction id and block details\n"
1444 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1445 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1446 " and for the 'move' category for inbound funds.\n"
1447 " \"vout\" : n, (numeric) the vout value\n"
1448 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1449 " 'send' category of transactions.\n"
1450 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1451 " 'receive' category of transactions.\n"
1452 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1453 " category of transactions.\n"
1454 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1455 " category of transactions.\n"
1456 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1457 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1458 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1459 " for 'send' and 'receive' category of transactions.\n"
1460 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1461 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1462 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1463 " negative amounts).\n"
1464 " \"size\": n, (numeric) Transaction size in bytes\n"
1469 "\nList the most recent 10 transactions in the systems\n"
1470 + HelpExampleCli("listtransactions", "") +
1471 "\nList transactions 100 to 120\n"
1472 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1473 "\nAs a json rpc call\n"
1474 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1477 LOCK2(cs_main, pwalletMain->cs_wallet);
1479 string strAccount = "*";
1480 if (params.size() > 0)
1481 strAccount = params[0].get_str();
1483 if (params.size() > 1)
1484 nCount = params[1].get_int();
1486 if (params.size() > 2)
1487 nFrom = params[2].get_int();
1488 isminefilter filter = ISMINE_SPENDABLE;
1489 if(params.size() > 3)
1490 if(params[3].get_bool())
1491 filter = filter | ISMINE_WATCH_ONLY;
1494 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1496 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1498 UniValue ret(UniValue::VARR);
1500 std::list<CAccountingEntry> acentries;
1501 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1503 // iterate backwards until we have nCount items to return:
1504 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1506 CWalletTx *const pwtx = (*it).second.first;
1508 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1509 CAccountingEntry *const pacentry = (*it).second.second;
1511 AcentryToJSON(*pacentry, strAccount, ret);
1513 if ((int)ret.size() >= (nCount+nFrom)) break;
1515 // ret is newest to oldest
1517 if (nFrom > (int)ret.size())
1519 if ((nFrom + nCount) > (int)ret.size())
1520 nCount = ret.size() - nFrom;
1522 vector<UniValue> arrTmp = ret.getValues();
1524 vector<UniValue>::iterator first = arrTmp.begin();
1525 std::advance(first, nFrom);
1526 vector<UniValue>::iterator last = arrTmp.begin();
1527 std::advance(last, nFrom+nCount);
1529 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1530 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1532 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1536 ret.push_backV(arrTmp);
1541 UniValue listaccounts(const UniValue& params, bool fHelp)
1543 if (!EnsureWalletIsAvailable(fHelp))
1544 return NullUniValue;
1546 if (fHelp || params.size() > 2)
1547 throw runtime_error(
1548 "listaccounts ( minconf includeWatchonly)\n"
1549 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1551 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1552 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1554 "{ (json object where keys are account names, and values are numeric balances\n"
1555 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1559 "\nList account balances where there at least 1 confirmation\n"
1560 + HelpExampleCli("listaccounts", "") +
1561 "\nList account balances including zero confirmation transactions\n"
1562 + HelpExampleCli("listaccounts", "0") +
1563 "\nList account balances for 6 or more confirmations\n"
1564 + HelpExampleCli("listaccounts", "6") +
1565 "\nAs json rpc call\n"
1566 + HelpExampleRpc("listaccounts", "6")
1569 LOCK2(cs_main, pwalletMain->cs_wallet);
1572 if (params.size() > 0)
1573 nMinDepth = params[0].get_int();
1574 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1575 if(params.size() > 1)
1576 if(params[1].get_bool())
1577 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1579 map<string, CAmount> mapAccountBalances;
1580 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1581 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1582 mapAccountBalances[entry.second.name] = 0;
1585 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1587 const CWalletTx& wtx = (*it).second;
1589 string strSentAccount;
1590 list<COutputEntry> listReceived;
1591 list<COutputEntry> listSent;
1592 int nDepth = wtx.GetDepthInMainChain();
1593 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1595 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1596 mapAccountBalances[strSentAccount] -= nFee;
1597 BOOST_FOREACH(const COutputEntry& s, listSent)
1598 mapAccountBalances[strSentAccount] -= s.amount;
1599 if (nDepth >= nMinDepth)
1601 BOOST_FOREACH(const COutputEntry& r, listReceived)
1602 if (pwalletMain->mapAddressBook.count(r.destination))
1603 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1605 mapAccountBalances[""] += r.amount;
1609 list<CAccountingEntry> acentries;
1610 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1611 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1612 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1614 UniValue ret(UniValue::VOBJ);
1615 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1616 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1621 UniValue listsinceblock(const UniValue& params, bool fHelp)
1623 if (!EnsureWalletIsAvailable(fHelp))
1624 return NullUniValue;
1627 throw runtime_error(
1628 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1629 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1631 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1632 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1633 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1636 " \"transactions\": [\n"
1637 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1638 " \"address\":\"zcashaddress\", (string) The Zcash address of the transaction. Not present for move transactions (category = move).\n"
1639 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1640 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1641 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1642 " \"vout\" : n, (numeric) the vout value\n"
1643 " \"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"
1644 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1645 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1646 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1647 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1648 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1649 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1650 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1651 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1652 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1654 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1657 + HelpExampleCli("listsinceblock", "")
1658 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1659 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1662 LOCK2(cs_main, pwalletMain->cs_wallet);
1664 CBlockIndex *pindex = NULL;
1665 int target_confirms = 1;
1666 isminefilter filter = ISMINE_SPENDABLE;
1668 if (params.size() > 0)
1672 blockId.SetHex(params[0].get_str());
1673 BlockMap::iterator it = mapBlockIndex.find(blockId);
1674 if (it != mapBlockIndex.end())
1675 pindex = it->second;
1678 if (params.size() > 1)
1680 target_confirms = params[1].get_int();
1682 if (target_confirms < 1)
1683 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1686 if(params.size() > 2)
1687 if(params[2].get_bool())
1688 filter = filter | ISMINE_WATCH_ONLY;
1690 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1692 UniValue transactions(UniValue::VARR);
1694 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1696 CWalletTx tx = (*it).second;
1698 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1699 ListTransactions(tx, "*", 0, true, transactions, filter);
1702 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1703 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1705 UniValue ret(UniValue::VOBJ);
1706 ret.push_back(Pair("transactions", transactions));
1707 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1712 UniValue gettransaction(const UniValue& params, bool fHelp)
1714 if (!EnsureWalletIsAvailable(fHelp))
1715 return NullUniValue;
1717 if (fHelp || params.size() < 1 || params.size() > 2)
1718 throw runtime_error(
1719 "gettransaction \"txid\" ( includeWatchonly )\n"
1720 "\nGet detailed information about in-wallet transaction <txid>\n"
1722 "1. \"txid\" (string, required) The transaction id\n"
1723 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1726 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1727 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1728 " \"blockhash\" : \"hash\", (string) The block hash\n"
1729 " \"blockindex\" : xx, (numeric) The block index\n"
1730 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1731 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1732 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1733 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1734 " \"details\" : [\n"
1736 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
1737 " \"address\" : \"zcashaddress\", (string) The Zcash address involved in the transaction\n"
1738 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1739 " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
1740 " \"vout\" : n, (numeric) the vout value\n"
1744 " \"vjoinsplit\" : [\n"
1746 " \"anchor\" : \"treestateref\", (string) Merkle root of note commitment tree\n"
1747 " \"nullifiers\" : [ string, ... ] (string) Nullifiers of input notes\n"
1748 " \"commitments\" : [ string, ... ] (string) Note commitments for note outputs\n"
1749 " \"macs\" : [ string, ... ] (string) Message authentication tags\n"
1750 " \"vpub_old\" : x.xxx (numeric) The amount removed from the transparent value pool\n"
1751 " \"vpub_new\" : x.xxx, (numeric) The amount added to the transparent value pool\n"
1755 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1759 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1760 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1761 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1764 LOCK2(cs_main, pwalletMain->cs_wallet);
1767 hash.SetHex(params[0].get_str());
1769 isminefilter filter = ISMINE_SPENDABLE;
1770 if(params.size() > 1)
1771 if(params[1].get_bool())
1772 filter = filter | ISMINE_WATCH_ONLY;
1774 UniValue entry(UniValue::VOBJ);
1775 if (!pwalletMain->mapWallet.count(hash))
1776 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1777 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1779 CAmount nCredit = wtx.GetCredit(filter);
1780 CAmount nDebit = wtx.GetDebit(filter);
1781 CAmount nNet = nCredit - nDebit;
1782 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1784 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1785 if (wtx.IsFromMe(filter))
1786 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1788 WalletTxToJSON(wtx, entry);
1790 UniValue details(UniValue::VARR);
1791 ListTransactions(wtx, "*", 0, false, details, filter);
1792 entry.push_back(Pair("details", details));
1794 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1795 entry.push_back(Pair("hex", strHex));
1801 UniValue backupwallet(const UniValue& params, bool fHelp)
1803 if (!EnsureWalletIsAvailable(fHelp))
1804 return NullUniValue;
1806 if (fHelp || params.size() != 1)
1807 throw runtime_error(
1808 "backupwallet \"destination\"\n"
1809 "\nSafely copies wallet.dat to destination filename\n"
1811 "1. \"destination\" (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
1813 "\"path\" (string) The full path of the destination file\n"
1815 + HelpExampleCli("backupwallet", "\"backupdata\"")
1816 + HelpExampleRpc("backupwallet", "\"backupdata\"")
1819 LOCK2(cs_main, pwalletMain->cs_wallet);
1821 boost::filesystem::path exportdir;
1823 exportdir = GetExportDir();
1824 } catch (const std::runtime_error& e) {
1825 throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
1827 if (exportdir.empty()) {
1828 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot backup wallet until the -exportdir option has been set");
1830 std::string unclean = params[0].get_str();
1831 std::string clean = SanitizeFilename(unclean);
1832 if (clean.compare(unclean) != 0) {
1833 throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Filename is invalid as only alphanumeric characters are allowed. Try '%s' instead.", clean));
1835 boost::filesystem::path exportfilepath = exportdir / clean;
1837 if (!BackupWallet(*pwalletMain, exportfilepath.string()))
1838 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1840 return exportfilepath.string();
1844 UniValue keypoolrefill(const UniValue& params, bool fHelp)
1846 if (!EnsureWalletIsAvailable(fHelp))
1847 return NullUniValue;
1849 if (fHelp || params.size() > 1)
1850 throw runtime_error(
1851 "keypoolrefill ( newsize )\n"
1852 "\nFills the keypool."
1853 + HelpRequiringPassphrase() + "\n"
1855 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1857 + HelpExampleCli("keypoolrefill", "")
1858 + HelpExampleRpc("keypoolrefill", "")
1861 LOCK2(cs_main, pwalletMain->cs_wallet);
1863 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1864 unsigned int kpSize = 0;
1865 if (params.size() > 0) {
1866 if (params[0].get_int() < 0)
1867 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1868 kpSize = (unsigned int)params[0].get_int();
1871 EnsureWalletIsUnlocked();
1872 pwalletMain->TopUpKeyPool(kpSize);
1874 if (pwalletMain->GetKeyPoolSize() < kpSize)
1875 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1877 return NullUniValue;
1881 static void LockWallet(CWallet* pWallet)
1883 LOCK(cs_nWalletUnlockTime);
1884 nWalletUnlockTime = 0;
1888 UniValue walletpassphrase(const UniValue& params, bool fHelp)
1890 if (!EnsureWalletIsAvailable(fHelp))
1891 return NullUniValue;
1893 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1894 throw runtime_error(
1895 "walletpassphrase \"passphrase\" timeout\n"
1896 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1897 "This is needed prior to performing transactions related to private keys such as sending Zcash\n"
1899 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1900 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1902 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1903 "time that overrides the old one.\n"
1905 "\nunlock the wallet for 60 seconds\n"
1906 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1907 "\nLock the wallet again (before 60 seconds)\n"
1908 + HelpExampleCli("walletlock", "") +
1909 "\nAs json rpc call\n"
1910 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1913 LOCK2(cs_main, pwalletMain->cs_wallet);
1917 if (!pwalletMain->IsCrypted())
1918 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1920 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1921 SecureString strWalletPass;
1922 strWalletPass.reserve(100);
1923 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1924 // Alternately, find a way to make params[0] mlock()'d to begin with.
1925 strWalletPass = params[0].get_str().c_str();
1927 if (strWalletPass.length() > 0)
1929 if (!pwalletMain->Unlock(strWalletPass))
1930 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1933 throw runtime_error(
1934 "walletpassphrase <passphrase> <timeout>\n"
1935 "Stores the wallet decryption key in memory for <timeout> seconds.");
1937 // No need to check return values, because the wallet was unlocked above
1938 pwalletMain->UpdateNullifierNoteMap();
1939 pwalletMain->TopUpKeyPool();
1941 int64_t nSleepTime = params[1].get_int64();
1942 LOCK(cs_nWalletUnlockTime);
1943 nWalletUnlockTime = GetTime() + nSleepTime;
1944 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1946 return NullUniValue;
1950 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
1952 if (!EnsureWalletIsAvailable(fHelp))
1953 return NullUniValue;
1955 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1956 throw runtime_error(
1957 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1958 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1960 "1. \"oldpassphrase\" (string) The current passphrase\n"
1961 "2. \"newpassphrase\" (string) The new passphrase\n"
1963 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1964 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1967 LOCK2(cs_main, pwalletMain->cs_wallet);
1971 if (!pwalletMain->IsCrypted())
1972 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1974 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1975 // Alternately, find a way to make params[0] mlock()'d to begin with.
1976 SecureString strOldWalletPass;
1977 strOldWalletPass.reserve(100);
1978 strOldWalletPass = params[0].get_str().c_str();
1980 SecureString strNewWalletPass;
1981 strNewWalletPass.reserve(100);
1982 strNewWalletPass = params[1].get_str().c_str();
1984 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1985 throw runtime_error(
1986 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1987 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1989 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1990 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1992 return NullUniValue;
1996 UniValue walletlock(const UniValue& params, bool fHelp)
1998 if (!EnsureWalletIsAvailable(fHelp))
1999 return NullUniValue;
2001 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
2002 throw runtime_error(
2004 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2005 "After calling this method, you will need to call walletpassphrase again\n"
2006 "before being able to call any methods which require the wallet to be unlocked.\n"
2008 "\nSet the passphrase for 2 minutes to perform a transaction\n"
2009 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2010 "\nPerform a send (requires passphrase set)\n"
2011 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2012 "\nClear the passphrase since we are done before 2 minutes is up\n"
2013 + HelpExampleCli("walletlock", "") +
2014 "\nAs json rpc call\n"
2015 + HelpExampleRpc("walletlock", "")
2018 LOCK2(cs_main, pwalletMain->cs_wallet);
2022 if (!pwalletMain->IsCrypted())
2023 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2026 LOCK(cs_nWalletUnlockTime);
2027 pwalletMain->Lock();
2028 nWalletUnlockTime = 0;
2031 return NullUniValue;
2035 UniValue encryptwallet(const UniValue& params, bool fHelp)
2037 if (!EnsureWalletIsAvailable(fHelp))
2038 return NullUniValue;
2040 string enableArg = "developerencryptwallet";
2041 auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, false);
2043 std::string strWalletEncryptionDisabledMsg = "";
2044 if (!fEnableWalletEncryption) {
2045 strWalletEncryptionDisabledMsg = experimentalDisabledHelpMsg("encryptwallet", enableArg);
2048 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2049 throw runtime_error(
2050 "encryptwallet \"passphrase\"\n"
2051 + strWalletEncryptionDisabledMsg +
2052 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2053 "After this, any calls that interact with private keys such as sending or signing \n"
2054 "will require the passphrase to be set prior the making these calls.\n"
2055 "Use the walletpassphrase call for this, and then walletlock call.\n"
2056 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2057 "Note that this will shutdown the server.\n"
2059 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2061 "\nEncrypt you wallet\n"
2062 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2063 "\nNow set the passphrase to use the wallet, such as for signing or sending Zcash\n"
2064 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2065 "\nNow we can so something like sign\n"
2066 + HelpExampleCli("signmessage", "\"zcashaddress\" \"test message\"") +
2067 "\nNow lock the wallet again by removing the passphrase\n"
2068 + HelpExampleCli("walletlock", "") +
2069 "\nAs a json rpc call\n"
2070 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2073 LOCK2(cs_main, pwalletMain->cs_wallet);
2077 if (!fEnableWalletEncryption) {
2078 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
2080 if (pwalletMain->IsCrypted())
2081 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2083 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2084 // Alternately, find a way to make params[0] mlock()'d to begin with.
2085 SecureString strWalletPass;
2086 strWalletPass.reserve(100);
2087 strWalletPass = params[0].get_str().c_str();
2089 if (strWalletPass.length() < 1)
2090 throw runtime_error(
2091 "encryptwallet <passphrase>\n"
2092 "Encrypts the wallet with <passphrase>.");
2094 if (!pwalletMain->EncryptWallet(strWalletPass))
2095 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2097 // BDB seems to have a bad habit of writing old data into
2098 // slack space in .dat files; that is bad if the old data is
2099 // unencrypted private keys. So:
2101 return "wallet encrypted; Zcash server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
2104 UniValue lockunspent(const UniValue& params, bool fHelp)
2106 if (!EnsureWalletIsAvailable(fHelp))
2107 return NullUniValue;
2109 if (fHelp || params.size() < 1 || params.size() > 2)
2110 throw runtime_error(
2111 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2112 "\nUpdates list of temporarily unspendable outputs.\n"
2113 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2114 "A locked transaction output will not be chosen by automatic coin selection, when spending Zcash.\n"
2115 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2116 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2117 "Also see the listunspent call\n"
2119 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2120 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2121 " [ (json array of json objects)\n"
2123 " \"txid\":\"id\", (string) The transaction id\n"
2124 " \"vout\": n (numeric) The output number\n"
2130 "true|false (boolean) Whether the command was successful or not\n"
2133 "\nList the unspent transactions\n"
2134 + HelpExampleCli("listunspent", "") +
2135 "\nLock an unspent transaction\n"
2136 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2137 "\nList the locked transactions\n"
2138 + HelpExampleCli("listlockunspent", "") +
2139 "\nUnlock the transaction again\n"
2140 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2141 "\nAs a json rpc call\n"
2142 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2145 LOCK2(cs_main, pwalletMain->cs_wallet);
2147 if (params.size() == 1)
2148 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2150 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2152 bool fUnlock = params[0].get_bool();
2154 if (params.size() == 1) {
2156 pwalletMain->UnlockAllCoins();
2160 UniValue outputs = params[1].get_array();
2161 for (size_t idx = 0; idx < outputs.size(); idx++) {
2162 const UniValue& output = outputs[idx];
2163 if (!output.isObject())
2164 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2165 const UniValue& o = output.get_obj();
2167 RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
2169 string txid = find_value(o, "txid").get_str();
2171 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2173 int nOutput = find_value(o, "vout").get_int();
2175 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2177 COutPoint outpt(uint256S(txid), nOutput);
2180 pwalletMain->UnlockCoin(outpt);
2182 pwalletMain->LockCoin(outpt);
2188 UniValue listlockunspent(const UniValue& params, bool fHelp)
2190 if (!EnsureWalletIsAvailable(fHelp))
2191 return NullUniValue;
2193 if (fHelp || params.size() > 0)
2194 throw runtime_error(
2196 "\nReturns list of temporarily unspendable outputs.\n"
2197 "See the lockunspent call to lock and unlock transactions for spending.\n"
2201 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2202 " \"vout\" : n (numeric) The vout value\n"
2207 "\nList the unspent transactions\n"
2208 + HelpExampleCli("listunspent", "") +
2209 "\nLock an unspent transaction\n"
2210 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2211 "\nList the locked transactions\n"
2212 + HelpExampleCli("listlockunspent", "") +
2213 "\nUnlock the transaction again\n"
2214 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2215 "\nAs a json rpc call\n"
2216 + HelpExampleRpc("listlockunspent", "")
2219 LOCK2(cs_main, pwalletMain->cs_wallet);
2221 vector<COutPoint> vOutpts;
2222 pwalletMain->ListLockedCoins(vOutpts);
2224 UniValue ret(UniValue::VARR);
2226 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2227 UniValue o(UniValue::VOBJ);
2229 o.push_back(Pair("txid", outpt.hash.GetHex()));
2230 o.push_back(Pair("vout", (int)outpt.n));
2237 UniValue settxfee(const UniValue& params, bool fHelp)
2239 if (!EnsureWalletIsAvailable(fHelp))
2240 return NullUniValue;
2242 if (fHelp || params.size() < 1 || params.size() > 1)
2243 throw runtime_error(
2245 "\nSet the transaction fee per kB.\n"
2247 "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n"
2249 "true|false (boolean) Returns true if successful\n"
2251 + HelpExampleCli("settxfee", "0.00001")
2252 + HelpExampleRpc("settxfee", "0.00001")
2255 LOCK2(cs_main, pwalletMain->cs_wallet);
2258 CAmount nAmount = AmountFromValue(params[0]);
2260 payTxFee = CFeeRate(nAmount, 1000);
2264 UniValue getwalletinfo(const UniValue& params, bool fHelp)
2266 if (!EnsureWalletIsAvailable(fHelp))
2267 return NullUniValue;
2269 if (fHelp || params.size() != 0)
2270 throw runtime_error(
2272 "Returns an object containing various wallet state info.\n"
2275 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2276 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2277 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2278 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2279 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2280 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
2281 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
2282 " \"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"
2283 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2284 " \"seedfp\": \"uint256\", (string) the BLAKE2b-256 hash of the HD seed\n"
2287 + HelpExampleCli("getwalletinfo", "")
2288 + HelpExampleRpc("getwalletinfo", "")
2291 LOCK2(cs_main, pwalletMain->cs_wallet);
2293 UniValue obj(UniValue::VOBJ);
2294 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2295 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
2296 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2297 obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
2298 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
2299 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2300 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2301 if (pwalletMain->IsCrypted())
2302 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2303 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2304 uint256 seedFp = pwalletMain->GetHDChain().seedFp;
2305 if (!seedFp.IsNull())
2306 obj.push_back(Pair("seedfp", seedFp.GetHex()));
2310 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
2312 if (!EnsureWalletIsAvailable(fHelp))
2313 return NullUniValue;
2315 if (fHelp || params.size() != 0)
2316 throw runtime_error(
2317 "resendwallettransactions\n"
2318 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2319 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2321 "Returns array of transaction ids that were re-broadcast.\n"
2324 LOCK2(cs_main, pwalletMain->cs_wallet);
2326 std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2327 UniValue result(UniValue::VARR);
2328 BOOST_FOREACH(const uint256& txid, txids)
2330 result.push_back(txid.ToString());
2335 UniValue listunspent(const UniValue& params, bool fHelp)
2337 if (!EnsureWalletIsAvailable(fHelp))
2338 return NullUniValue;
2340 if (fHelp || params.size() > 3)
2341 throw runtime_error(
2342 "listunspent ( minconf maxconf [\"address\",...] )\n"
2343 "\nReturns array of unspent transaction outputs\n"
2344 "with between minconf and maxconf (inclusive) confirmations.\n"
2345 "Optionally filter to only include txouts paid to specified addresses.\n"
2346 "Results are an array of Objects, each of which has:\n"
2347 "{txid, vout, scriptPubKey, amount, confirmations}\n"
2349 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2350 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2351 "3. \"addresses\" (string) A json array of Zcash addresses to filter\n"
2353 " \"address\" (string) Zcash address\n"
2357 "[ (array of json object)\n"
2359 " \"txid\" : \"txid\", (string) the transaction id \n"
2360 " \"vout\" : n, (numeric) the vout value\n"
2361 " \"generated\" : true|false (boolean) true if txout is a coinbase transaction output\n"
2362 " \"address\" : \"address\", (string) the Zcash address\n"
2363 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2364 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2365 " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n"
2366 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2367 " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
2368 " \"spendable\" : xxx (bool) Whether we have the private keys to spend this output\n"
2374 + HelpExampleCli("listunspent", "")
2375 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"t1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"t1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2376 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"t1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"t1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2379 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
2382 if (params.size() > 0)
2383 nMinDepth = params[0].get_int();
2385 int nMaxDepth = 9999999;
2386 if (params.size() > 1)
2387 nMaxDepth = params[1].get_int();
2389 std::set<CTxDestination> destinations;
2390 if (params.size() > 2) {
2391 UniValue inputs = params[2].get_array();
2392 for (size_t idx = 0; idx < inputs.size(); idx++) {
2393 const UniValue& input = inputs[idx];
2394 CTxDestination dest = DecodeDestination(input.get_str());
2395 if (!IsValidDestination(dest)) {
2396 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + input.get_str());
2398 if (!destinations.insert(dest).second) {
2399 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
2404 UniValue results(UniValue::VARR);
2405 vector<COutput> vecOutputs;
2406 assert(pwalletMain != NULL);
2407 LOCK2(cs_main, pwalletMain->cs_wallet);
2408 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2409 BOOST_FOREACH(const COutput& out, vecOutputs) {
2410 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2413 CTxDestination address;
2414 const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
2415 bool fValidAddress = ExtractDestination(scriptPubKey, address);
2417 if (destinations.size() && (!fValidAddress || !destinations.count(address)))
2420 UniValue entry(UniValue::VOBJ);
2421 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2422 entry.push_back(Pair("vout", out.i));
2423 entry.push_back(Pair("generated", out.tx->IsCoinBase()));
2425 if (fValidAddress) {
2426 entry.push_back(Pair("address", EncodeDestination(address)));
2428 if (pwalletMain->mapAddressBook.count(address))
2429 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2431 if (scriptPubKey.IsPayToScriptHash()) {
2432 const CScriptID& hash = boost::get<CScriptID>(address);
2433 CScript redeemScript;
2434 if (pwalletMain->GetCScript(hash, redeemScript))
2435 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2439 entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2440 entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue)));
2441 entry.push_back(Pair("confirmations", out.nDepth));
2442 entry.push_back(Pair("spendable", out.fSpendable));
2443 results.push_back(entry);
2450 UniValue z_listunspent(const UniValue& params, bool fHelp)
2452 if (!EnsureWalletIsAvailable(fHelp))
2453 return NullUniValue;
2455 if (fHelp || params.size() > 4)
2456 throw runtime_error(
2457 "z_listunspent ( minconf maxconf includeWatchonly [\"zaddr\",...] )\n"
2458 "\nReturns array of unspent shielded notes with between minconf and maxconf (inclusive) confirmations.\n"
2459 "Optionally filter to only include notes sent to specified addresses.\n"
2460 "When minconf is 0, unspent notes with zero confirmations are returned, even though they are not immediately spendable.\n"
2461 "Results are an array of Objects, each of which has:\n"
2462 "{txid, jsindex, jsoutindex, confirmations, address, amount, memo} (Sprout)\n"
2463 "{txid, outindex, confirmations, address, amount, memo} (Sapling)\n"
2465 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2466 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2467 "3. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
2468 "4. \"addresses\" (string) A json array of zaddrs (both Sprout and Sapling) to filter on. Duplicate addresses not allowed.\n"
2470 " \"address\" (string) zaddr\n"
2474 "[ (array of json object)\n"
2476 " \"txid\" : \"txid\", (string) the transaction id \n"
2477 " \"jsindex\" (sprout) : n, (numeric) the joinsplit index\n"
2478 " \"jsoutindex\" (sprout) : n, (numeric) the output index of the joinsplit\n"
2479 " \"outindex\" (sapling) : n, (numeric) the output index\n"
2480 " \"confirmations\" : n, (numeric) the number of confirmations\n"
2481 " \"spendable\" : true|false, (boolean) true if note can be spent by wallet, false if address is watchonly\n"
2482 " \"address\" : \"address\", (string) the shielded address\n"
2483 " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
2484 " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
2485 " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
2491 + HelpExampleCli("z_listunspent", "")
2492 + HelpExampleCli("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
2493 + HelpExampleRpc("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
2496 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VBOOL)(UniValue::VARR));
2499 if (params.size() > 0) {
2500 nMinDepth = params[0].get_int();
2502 if (nMinDepth < 0) {
2503 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
2506 int nMaxDepth = 9999999;
2507 if (params.size() > 1) {
2508 nMaxDepth = params[1].get_int();
2510 if (nMaxDepth < nMinDepth) {
2511 throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum number of confirmations must be greater or equal to the minimum number of confirmations");
2514 std::set<libzcash::PaymentAddress> zaddrs = {};
2516 bool fIncludeWatchonly = false;
2517 if (params.size() > 2) {
2518 fIncludeWatchonly = params[2].get_bool();
2521 LOCK2(cs_main, pwalletMain->cs_wallet);
2523 // User has supplied zaddrs to filter on
2524 if (params.size() > 3) {
2525 UniValue addresses = params[3].get_array();
2526 if (addresses.size()==0)
2527 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, addresses array is empty.");
2529 // Keep track of addresses to spot duplicates
2530 set<std::string> setAddress;
2533 for (const UniValue& o : addresses.getValues()) {
2535 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
2537 string address = o.get_str();
2538 auto zaddr = DecodePaymentAddress(address);
2539 if (!IsValidPaymentAddress(zaddr)) {
2540 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address);
2542 auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
2543 if (!fIncludeWatchonly && !hasSpendingKey) {
2544 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
2546 zaddrs.insert(zaddr);
2548 if (setAddress.count(address)) {
2549 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
2551 setAddress.insert(address);
2555 // User did not provide zaddrs, so use default i.e. all addresses
2556 std::set<libzcash::SproutPaymentAddress> sproutzaddrs = {};
2557 pwalletMain->GetSproutPaymentAddresses(sproutzaddrs);
2560 std::set<libzcash::SaplingPaymentAddress> saplingzaddrs = {};
2561 pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs);
2563 zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end());
2564 zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end());
2567 UniValue results(UniValue::VARR);
2569 if (zaddrs.size() > 0) {
2570 std::vector<CSproutNotePlaintextEntry> sproutEntries;
2571 std::vector<SaplingNoteEntry> saplingEntries;
2572 pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
2573 std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
2575 for (auto & entry : sproutEntries) {
2576 UniValue obj(UniValue::VOBJ);
2577 obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
2578 obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
2579 obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
2580 obj.push_back(Pair("confirmations", entry.confirmations));
2581 bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get<libzcash::SproutPaymentAddress>(entry.address));
2582 obj.push_back(Pair("spendable", hasSproutSpendingKey));
2583 obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
2584 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
2585 std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
2586 obj.push_back(Pair("memo", HexStr(data)));
2587 if (hasSproutSpendingKey) {
2588 obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop)));
2590 results.push_back(obj);
2593 for (auto & entry : saplingEntries) {
2594 UniValue obj(UniValue::VOBJ);
2595 obj.push_back(Pair("txid", entry.op.hash.ToString()));
2596 obj.push_back(Pair("outindex", (int)entry.op.n));
2597 obj.push_back(Pair("confirmations", entry.confirmations));
2598 libzcash::SaplingIncomingViewingKey ivk;
2599 libzcash::SaplingFullViewingKey fvk;
2600 pwalletMain->GetSaplingIncomingViewingKey(boost::get<libzcash::SaplingPaymentAddress>(entry.address), ivk);
2601 pwalletMain->GetSaplingFullViewingKey(ivk, fvk);
2602 bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk);
2603 obj.push_back(Pair("spendable", hasSaplingSpendingKey));
2604 obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
2605 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value()
2606 obj.push_back(Pair("memo", HexStr(entry.memo)));
2607 if (hasSaplingSpendingKey) {
2608 obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op)));
2610 results.push_back(obj);
2618 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
2620 if (!EnsureWalletIsAvailable(fHelp))
2621 return NullUniValue;
2623 if (fHelp || params.size() != 1)
2624 throw runtime_error(
2625 "fundrawtransaction \"hexstring\"\n"
2626 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2627 "This will not modify existing inputs, and will add one change output to the outputs.\n"
2628 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2629 "The inputs added will not be signed, use signrawtransaction for that.\n"
2631 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
2634 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
2635 " \"fee\": n, (numeric) The fee added to the transaction\n"
2636 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
2640 "\nCreate a transaction with no inputs\n"
2641 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2642 "\nAdd sufficient unsigned inputs to meet the output value\n"
2643 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2644 "\nSign the transaction\n"
2645 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2646 "\nSend the transaction\n"
2647 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2650 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
2652 // parse hex string from parameter
2653 CTransaction origTx;
2654 if (!DecodeHexTx(origTx, params[0].get_str()))
2655 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2657 CMutableTransaction tx(origTx);
2659 string strFailReason;
2660 int nChangePos = -1;
2661 if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason))
2662 throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2664 UniValue result(UniValue::VOBJ);
2665 result.push_back(Pair("hex", EncodeHexTx(tx)));
2666 result.push_back(Pair("changepos", nChangePos));
2667 result.push_back(Pair("fee", ValueFromAmount(nFee)));
2672 UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
2675 throw runtime_error(
2676 "zcsamplejoinsplit\n"
2678 "Perform a joinsplit and return the JSDescription.\n"
2684 uint256 joinSplitPubKey;
2685 uint256 anchor = SproutMerkleTree().root();
2686 JSDescription samplejoinsplit(true,
2690 {JSInput(), JSInput()},
2691 {JSOutput(), JSOutput()},
2695 CDataStream ss(SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
2696 ss << samplejoinsplit;
2698 return HexStr(ss.begin(), ss.end());
2701 UniValue zc_benchmark(const UniValue& params, bool fHelp)
2703 if (!EnsureWalletIsAvailable(fHelp)) {
2704 return NullUniValue;
2707 if (fHelp || params.size() < 2) {
2708 throw runtime_error(
2709 "zcbenchmark benchmarktype samplecount\n"
2711 "Runs a benchmark of the selected type samplecount times,\n"
2712 "returning the running times of each sample.\n"
2716 " \"runningtime\": runningtime\n"
2719 " \"runningtime\": runningtime\n"
2728 std::string benchmarktype = params[0].get_str();
2729 int samplecount = params[1].get_int();
2731 if (samplecount <= 0) {
2732 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid samplecount");
2735 std::vector<double> sample_times;
2737 JSDescription samplejoinsplit;
2739 if (benchmarktype == "verifyjoinsplit") {
2740 CDataStream ss(ParseHexV(params[2].get_str(), "js"), SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
2741 ss >> samplejoinsplit;
2744 for (int i = 0; i < samplecount; i++) {
2745 if (benchmarktype == "sleep") {
2746 sample_times.push_back(benchmark_sleep());
2747 } else if (benchmarktype == "parameterloading") {
2748 sample_times.push_back(benchmark_parameter_loading());
2749 } else if (benchmarktype == "createjoinsplit") {
2750 if (params.size() < 3) {
2751 sample_times.push_back(benchmark_create_joinsplit());
2753 int nThreads = params[2].get_int();
2754 std::vector<double> vals = benchmark_create_joinsplit_threaded(nThreads);
2755 // Divide by nThreads^2 to get average seconds per JoinSplit because
2756 // we are running one JoinSplit per thread.
2757 sample_times.push_back(std::accumulate(vals.begin(), vals.end(), 0.0) / (nThreads*nThreads));
2759 } else if (benchmarktype == "verifyjoinsplit") {
2760 sample_times.push_back(benchmark_verify_joinsplit(samplejoinsplit));
2761 #ifdef ENABLE_MINING
2762 } else if (benchmarktype == "solveequihash") {
2763 if (params.size() < 3) {
2764 sample_times.push_back(benchmark_solve_equihash());
2766 int nThreads = params[2].get_int();
2767 std::vector<double> vals = benchmark_solve_equihash_threaded(nThreads);
2768 sample_times.insert(sample_times.end(), vals.begin(), vals.end());
2771 } else if (benchmarktype == "verifyequihash") {
2772 sample_times.push_back(benchmark_verify_equihash());
2773 } else if (benchmarktype == "validatelargetx") {
2774 // Number of inputs in the spending transaction that we will simulate
2775 int nInputs = 11130;
2776 if (params.size() >= 3) {
2777 nInputs = params[2].get_int();
2779 sample_times.push_back(benchmark_large_tx(nInputs));
2780 } else if (benchmarktype == "trydecryptnotes") {
2781 int nKeys = params[2].get_int();
2782 sample_times.push_back(benchmark_try_decrypt_sprout_notes(nKeys));
2783 } else if (benchmarktype == "trydecryptsaplingnotes") {
2784 int nKeys = params[2].get_int();
2785 sample_times.push_back(benchmark_try_decrypt_sapling_notes(nKeys));
2786 } else if (benchmarktype == "incnotewitnesses") {
2787 int nTxs = params[2].get_int();
2788 sample_times.push_back(benchmark_increment_sprout_note_witnesses(nTxs));
2789 } else if (benchmarktype == "incsaplingnotewitnesses") {
2790 int nTxs = params[2].get_int();
2791 sample_times.push_back(benchmark_increment_sapling_note_witnesses(nTxs));
2792 } else if (benchmarktype == "connectblockslow") {
2793 if (Params().NetworkIDString() != "regtest") {
2794 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2796 sample_times.push_back(benchmark_connectblock_slow());
2797 } else if (benchmarktype == "sendtoaddress") {
2798 if (Params().NetworkIDString() != "regtest") {
2799 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2801 auto amount = AmountFromValue(params[2]);
2802 sample_times.push_back(benchmark_sendtoaddress(amount));
2803 } else if (benchmarktype == "loadwallet") {
2804 if (Params().NetworkIDString() != "regtest") {
2805 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2807 sample_times.push_back(benchmark_loadwallet());
2808 } else if (benchmarktype == "listunspent") {
2809 sample_times.push_back(benchmark_listunspent());
2810 } else if (benchmarktype == "createsaplingspend") {
2811 sample_times.push_back(benchmark_create_sapling_spend());
2812 } else if (benchmarktype == "createsaplingoutput") {
2813 sample_times.push_back(benchmark_create_sapling_output());
2814 } else if (benchmarktype == "verifysaplingspend") {
2815 sample_times.push_back(benchmark_verify_sapling_spend());
2816 } else if (benchmarktype == "verifysaplingoutput") {
2817 sample_times.push_back(benchmark_verify_sapling_output());
2819 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
2823 UniValue results(UniValue::VARR);
2824 for (auto time : sample_times) {
2825 UniValue result(UniValue::VOBJ);
2826 result.push_back(Pair("runningtime", time));
2827 results.push_back(result);
2833 UniValue zc_raw_receive(const UniValue& params, bool fHelp)
2835 if (!EnsureWalletIsAvailable(fHelp)) {
2836 return NullUniValue;
2839 if (fHelp || params.size() != 2) {
2840 throw runtime_error(
2841 "zcrawreceive zcsecretkey encryptednote\n"
2843 "DEPRECATED. Decrypts encryptednote and checks if the coin commitments\n"
2844 "are in the blockchain as indicated by the \"exists\" result.\n"
2847 " \"amount\": value,\n"
2848 " \"note\": noteplaintext,\n"
2849 " \"exists\": exists\n"
2854 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR));
2858 auto spendingkey = DecodeSpendingKey(params[0].get_str());
2859 if (!IsValidSpendingKey(spendingkey)) {
2860 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
2862 if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
2863 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
2865 SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
2868 unsigned char nonce;
2869 ZCNoteEncryption::Ciphertext ct;
2873 CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
2879 } catch(const std::exception &) {
2880 throw runtime_error(
2881 "encrypted_note could not be decoded"
2886 ZCNoteDecryption decryptor(k.receiving_key());
2888 SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
2895 SproutPaymentAddress payment_addr = k.address();
2896 SproutNote decrypted_note = npt.note(payment_addr);
2898 assert(pwalletMain != NULL);
2899 std::vector<boost::optional<SproutWitness>> witnesses;
2901 uint256 commitment = decrypted_note.cm();
2902 pwalletMain->WitnessNoteCommitment(
2908 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2911 UniValue result(UniValue::VOBJ);
2912 result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value())));
2913 result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
2914 result.push_back(Pair("exists", (bool) witnesses[0]));
2920 UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
2922 if (!EnsureWalletIsAvailable(fHelp)) {
2923 return NullUniValue;
2926 if (fHelp || params.size() != 5) {
2927 throw runtime_error(
2928 "zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
2929 " inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
2930 " outputs: a JSON object mapping {zcaddr: value, ...}\n"
2932 "DEPRECATED. Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
2933 "Outputs are confidential between sender/receiver. The vpub_old and\n"
2934 "vpub_new values are globally public and move transparent value into\n"
2935 "or out of the confidential value store, respectively.\n"
2937 "Note: The caller is responsible for delivering the output enc1 and\n"
2938 "enc2 to the appropriate recipients, as well as signing rawtxout and\n"
2939 "ensuring it is mined. (A future RPC call will deliver the confidential\n"
2940 "payments in-band on the blockchain.)\n"
2943 " \"encryptednote1\": enc1,\n"
2944 " \"encryptednote2\": enc2,\n"
2945 " \"rawtxn\": rawtxout\n"
2953 if (!DecodeHexTx(tx, params[0].get_str()))
2954 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2956 UniValue inputs = params[1].get_obj();
2957 UniValue outputs = params[2].get_obj();
2959 CAmount vpub_old(0);
2960 CAmount vpub_new(0);
2962 if (params[3].get_real() != 0.0)
2963 vpub_old = AmountFromValue(params[3]);
2965 if (params[4].get_real() != 0.0)
2966 vpub_new = AmountFromValue(params[4]);
2968 std::vector<JSInput> vjsin;
2969 std::vector<JSOutput> vjsout;
2970 std::vector<SproutNote> notes;
2971 std::vector<SproutSpendingKey> keys;
2972 std::vector<uint256> commitments;
2974 for (const string& name_ : inputs.getKeys()) {
2975 auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
2976 if (!IsValidSpendingKey(spendingkey)) {
2977 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
2979 if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
2980 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
2982 SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
2986 SproutNotePlaintext npt;
2989 CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
2993 SproutPaymentAddress addr = k.address();
2994 SproutNote note = npt.note(addr);
2995 notes.push_back(note);
2996 commitments.push_back(note.cm());
3000 std::vector<boost::optional<SproutWitness>> witnesses;
3001 pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
3003 assert(witnesses.size() == notes.size());
3004 assert(notes.size() == keys.size());
3007 for (size_t i = 0; i < witnesses.size(); i++) {
3008 if (!witnesses[i]) {
3009 throw runtime_error(
3010 "joinsplit input could not be found in tree"
3014 vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
3018 while (vjsin.size() < ZC_NUM_JS_INPUTS) {
3019 vjsin.push_back(JSInput());
3022 for (const string& name_ : outputs.getKeys()) {
3023 auto addrTo = DecodePaymentAddress(name_);
3024 if (!IsValidPaymentAddress(addrTo)) {
3025 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
3027 if (boost::get<libzcash::SproutPaymentAddress>(&addrTo) == nullptr) {
3028 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout payment addresses");
3030 CAmount nAmount = AmountFromValue(outputs[name_]);
3032 vjsout.push_back(JSOutput(boost::get<libzcash::SproutPaymentAddress>(addrTo), nAmount));
3035 while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
3036 vjsout.push_back(JSOutput());
3040 if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
3041 throw runtime_error("unsupported joinsplit input/output counts");
3044 uint256 joinSplitPubKey;
3045 unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
3046 crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
3048 CMutableTransaction mtx(tx);
3050 mtx.joinSplitPubKey = joinSplitPubKey;
3052 JSDescription jsdesc(false,
3056 {vjsin[0], vjsin[1]},
3057 {vjsout[0], vjsout[1]},
3062 auto verifier = libzcash::ProofVerifier::Strict();
3063 assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
3066 mtx.vjoinsplit.push_back(jsdesc);
3068 // Empty output script.
3070 CTransaction signTx(mtx);
3071 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
3072 uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
3074 // Add the signature
3075 assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
3076 dataToBeSigned.begin(), 32,
3081 assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
3082 dataToBeSigned.begin(), 32,
3083 mtx.joinSplitPubKey.begin()
3086 CTransaction rawTx(mtx);
3088 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3091 std::string encryptedNote1;
3092 std::string encryptedNote2;
3094 CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3095 ss2 << ((unsigned char) 0x00);
3096 ss2 << jsdesc.ephemeralKey;
3097 ss2 << jsdesc.ciphertexts[0];
3098 ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3100 encryptedNote1 = HexStr(ss2.begin(), ss2.end());
3103 CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3104 ss2 << ((unsigned char) 0x01);
3105 ss2 << jsdesc.ephemeralKey;
3106 ss2 << jsdesc.ciphertexts[1];
3107 ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3109 encryptedNote2 = HexStr(ss2.begin(), ss2.end());
3112 UniValue result(UniValue::VOBJ);
3113 result.push_back(Pair("encryptednote1", encryptedNote1));
3114 result.push_back(Pair("encryptednote2", encryptedNote2));
3115 result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
3119 UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
3121 if (!EnsureWalletIsAvailable(fHelp)) {
3122 return NullUniValue;
3125 if (fHelp || params.size() != 0) {
3126 throw runtime_error(
3129 "DEPRECATED. Generate a zcaddr which can send and receive confidential values.\n"
3132 " \"zcaddress\": zcaddr,\n"
3133 " \"zcsecretkey\": zcsecretkey,\n"
3134 " \"zcviewingkey\": zcviewingkey,\n"
3139 auto k = SproutSpendingKey::random();
3140 auto addr = k.address();
3141 auto viewing_key = k.viewing_key();
3143 UniValue result(UniValue::VOBJ);
3144 result.push_back(Pair("zcaddress", EncodePaymentAddress(addr)));
3145 result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k)));
3146 result.push_back(Pair("zcviewingkey", EncodeViewingKey(viewing_key)));
3151 UniValue z_getnewaddress(const UniValue& params, bool fHelp)
3153 if (!EnsureWalletIsAvailable(fHelp))
3154 return NullUniValue;
3156 std::string defaultType = ADDR_TYPE_SAPLING;
3158 if (fHelp || params.size() > 1)
3159 throw runtime_error(
3160 "z_getnewaddress ( type )\n"
3161 "\nReturns a new shielded address for receiving payments.\n"
3162 "\nWith no arguments, returns a Sapling address.\n"
3164 "1. \"type\" (string, optional, default=\"" + defaultType + "\") The type of address. One of [\""
3165 + ADDR_TYPE_SPROUT + "\", \"" + ADDR_TYPE_SAPLING + "\"].\n"
3167 "\"zcashaddress\" (string) The new shielded address.\n"
3169 + HelpExampleCli("z_getnewaddress", "")
3170 + HelpExampleCli("z_getnewaddress", ADDR_TYPE_SAPLING)
3171 + HelpExampleRpc("z_getnewaddress", "")
3174 LOCK2(cs_main, pwalletMain->cs_wallet);
3176 EnsureWalletIsUnlocked();
3178 auto addrType = defaultType;
3179 if (params.size() > 0) {
3180 addrType = params[0].get_str();
3183 if (addrType == ADDR_TYPE_SPROUT) {
3184 return EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey());
3185 } else if (addrType == ADDR_TYPE_SAPLING) {
3186 return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
3188 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");
3193 UniValue z_listaddresses(const UniValue& params, bool fHelp)
3195 if (!EnsureWalletIsAvailable(fHelp))
3196 return NullUniValue;
3198 if (fHelp || params.size() > 1)
3199 throw runtime_error(
3200 "z_listaddresses ( includeWatchonly )\n"
3201 "\nReturns the list of Sprout and Sapling shielded addresses belonging to the wallet.\n"
3203 "1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
3205 "[ (json array of string)\n"
3206 " \"zaddr\" (string) a zaddr belonging to the wallet\n"
3210 + HelpExampleCli("z_listaddresses", "")
3211 + HelpExampleRpc("z_listaddresses", "")
3214 LOCK2(cs_main, pwalletMain->cs_wallet);
3216 bool fIncludeWatchonly = false;
3217 if (params.size() > 0) {
3218 fIncludeWatchonly = params[0].get_bool();
3221 UniValue ret(UniValue::VARR);
3223 std::set<libzcash::SproutPaymentAddress> addresses;
3224 pwalletMain->GetSproutPaymentAddresses(addresses);
3225 for (auto addr : addresses) {
3226 if (fIncludeWatchonly || pwalletMain->HaveSproutSpendingKey(addr)) {
3227 ret.push_back(EncodePaymentAddress(addr));
3232 std::set<libzcash::SaplingPaymentAddress> addresses;
3233 pwalletMain->GetSaplingPaymentAddresses(addresses);
3234 libzcash::SaplingIncomingViewingKey ivk;
3235 libzcash::SaplingFullViewingKey fvk;
3236 for (auto addr : addresses) {
3237 if (fIncludeWatchonly || (
3238 pwalletMain->GetSaplingIncomingViewingKey(addr, ivk) &&
3239 pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
3240 pwalletMain->HaveSaplingSpendingKey(fvk)
3242 ret.push_back(EncodePaymentAddress(addr));
3249 CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
3250 std::set<CTxDestination> destinations;
3251 vector<COutput> vecOutputs;
3252 CAmount balance = 0;
3254 if (transparentAddress.length() > 0) {
3255 CTxDestination taddr = DecodeDestination(transparentAddress);
3256 if (!IsValidDestination(taddr)) {
3257 throw std::runtime_error("invalid transparent address");
3259 destinations.insert(taddr);
3262 LOCK2(cs_main, pwalletMain->cs_wallet);
3264 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
3266 BOOST_FOREACH(const COutput& out, vecOutputs) {
3267 if (out.nDepth < minDepth) {
3271 if (ignoreUnspendable && !out.fSpendable) {
3275 if (destinations.size()) {
3276 CTxDestination address;
3277 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
3281 if (!destinations.count(address)) {
3286 CAmount nValue = out.tx->vout[out.i].nValue;
3292 CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
3293 CAmount balance = 0;
3294 std::vector<CSproutNotePlaintextEntry> sproutEntries;
3295 std::vector<SaplingNoteEntry> saplingEntries;
3296 LOCK2(cs_main, pwalletMain->cs_wallet);
3297 pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, address, minDepth, true, ignoreUnspendable);
3298 for (auto & entry : sproutEntries) {
3299 balance += CAmount(entry.plaintext.value());
3301 for (auto & entry : saplingEntries) {
3302 balance += CAmount(entry.note.value());
3308 UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
3310 if (!EnsureWalletIsAvailable(fHelp))
3311 return NullUniValue;
3313 if (fHelp || params.size()==0 || params.size() >2)
3314 throw runtime_error(
3315 "z_listreceivedbyaddress \"address\" ( minconf )\n"
3316 "\nReturn a list of amounts received by a zaddr belonging to the node's wallet.\n"
3318 "1. \"address\" (string) The private address.\n"
3319 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3322 " \"txid\": \"txid\", (string) the transaction id\n"
3323 " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
3324 " \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n"
3325 " \"jsindex\" (sprout) : n, (numeric) the joinsplit index\n"
3326 " \"jsoutindex\" (sprout) : n, (numeric) the output index of the joinsplit\n"
3327 " \"outindex\" (sapling) : n, (numeric) the output index\n"
3328 " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
3331 + HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3332 + HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3335 LOCK2(cs_main, pwalletMain->cs_wallet);
3338 if (params.size() > 1) {
3339 nMinDepth = params[1].get_int();
3341 if (nMinDepth < 0) {
3342 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3345 // Check that the from address is valid.
3346 auto fromaddress = params[0].get_str();
3348 auto zaddr = DecodePaymentAddress(fromaddress);
3349 if (!IsValidPaymentAddress(zaddr)) {
3350 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
3353 // Visitor to support Sprout and Sapling addrs
3354 if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), zaddr)) {
3355 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
3358 UniValue result(UniValue::VARR);
3359 std::vector<CSproutNotePlaintextEntry> sproutEntries;
3360 std::vector<SaplingNoteEntry> saplingEntries;
3361 pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false);
3363 std::set<std::pair<PaymentAddress, uint256>> nullifierSet;
3364 auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
3365 if (hasSpendingKey) {
3366 nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr});
3369 if (boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr) {
3370 for (CSproutNotePlaintextEntry & entry : sproutEntries) {
3371 UniValue obj(UniValue::VOBJ);
3372 obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
3373 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
3374 std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
3375 obj.push_back(Pair("memo", HexStr(data)));
3376 obj.push_back(Pair("jsindex", entry.jsop.js));
3377 obj.push_back(Pair("jsoutindex", entry.jsop.n));
3378 if (hasSpendingKey) {
3379 obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop)));
3381 result.push_back(obj);
3383 } else if (boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
3384 for (SaplingNoteEntry & entry : saplingEntries) {
3385 UniValue obj(UniValue::VOBJ);
3386 obj.push_back(Pair("txid", entry.op.hash.ToString()));
3387 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value()))));
3388 obj.push_back(Pair("memo", HexStr(entry.memo)));
3389 obj.push_back(Pair("outindex", (int)entry.op.n));
3390 if (hasSpendingKey) {
3391 obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op)));
3393 result.push_back(obj);
3399 UniValue z_getbalance(const UniValue& params, bool fHelp)
3401 if (!EnsureWalletIsAvailable(fHelp))
3402 return NullUniValue;
3404 if (fHelp || params.size()==0 || params.size() >2)
3405 throw runtime_error(
3406 "z_getbalance \"address\" ( minconf )\n"
3407 "\nReturns the balance of a taddr or zaddr belonging to the node's wallet.\n"
3408 "\nCAUTION: If the wallet has only an incoming viewing key for this address, then spends cannot be"
3409 "\ndetected, and so the returned balance may be larger than the actual balance.\n"
3411 "1. \"address\" (string) The selected address. It may be a transparent or private address.\n"
3412 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3414 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this address.\n"
3416 "\nThe total amount received by address \"myaddress\"\n"
3417 + HelpExampleCli("z_getbalance", "\"myaddress\"") +
3418 "\nThe total amount received by address \"myaddress\" at least 5 blocks confirmed\n"
3419 + HelpExampleCli("z_getbalance", "\"myaddress\" 5") +
3420 "\nAs a json rpc call\n"
3421 + HelpExampleRpc("z_getbalance", "\"myaddress\", 5")
3424 LOCK2(cs_main, pwalletMain->cs_wallet);
3427 if (params.size() > 1) {
3428 nMinDepth = params[1].get_int();
3430 if (nMinDepth < 0) {
3431 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3434 // Check that the from address is valid.
3435 auto fromaddress = params[0].get_str();
3436 bool fromTaddr = false;
3437 CTxDestination taddr = DecodeDestination(fromaddress);
3438 fromTaddr = IsValidDestination(taddr);
3440 auto res = DecodePaymentAddress(fromaddress);
3441 if (!IsValidPaymentAddress(res)) {
3442 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3444 if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), res)) {
3445 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, spending key or viewing key not found.");
3449 CAmount nBalance = 0;
3451 nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
3453 nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
3456 return ValueFromAmount(nBalance);
3460 UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
3462 if (!EnsureWalletIsAvailable(fHelp))
3463 return NullUniValue;
3465 if (fHelp || params.size() > 2)
3466 throw runtime_error(
3467 "z_gettotalbalance ( minconf includeWatchonly )\n"
3468 "\nReturn the total value of funds stored in the node's wallet.\n"
3469 "\nCAUTION: If the wallet contains any addresses for which it only has incoming viewing keys,"
3470 "\nthe returned private balance may be larger than the actual balance, because spends cannot"
3471 "\nbe detected with incoming viewing keys.\n"
3473 "1. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
3474 "2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
3477 " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n"
3478 " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n"
3479 " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n"
3482 "\nThe total amount in the wallet\n"
3483 + HelpExampleCli("z_gettotalbalance", "") +
3484 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
3485 + HelpExampleCli("z_gettotalbalance", "5") +
3486 "\nAs a json rpc call\n"
3487 + HelpExampleRpc("z_gettotalbalance", "5")
3490 LOCK2(cs_main, pwalletMain->cs_wallet);
3493 if (params.size() > 0) {
3494 nMinDepth = params[0].get_int();
3496 if (nMinDepth < 0) {
3497 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3500 bool fIncludeWatchonly = false;
3501 if (params.size() > 1) {
3502 fIncludeWatchonly = params[1].get_bool();
3505 // getbalance and "getbalance * 1 true" should return the same number
3506 // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
3507 // pwalletMain->GetBalance() does not accept min depth parameter
3508 // so we use our own method to get balance of utxos.
3509 CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
3510 CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
3511 CAmount nTotalBalance = nBalance + nPrivateBalance;
3512 UniValue result(UniValue::VOBJ);
3513 result.push_back(Pair("transparent", FormatMoney(nBalance)));
3514 result.push_back(Pair("private", FormatMoney(nPrivateBalance)));
3515 result.push_back(Pair("total", FormatMoney(nTotalBalance)));
3519 UniValue z_getoperationresult(const UniValue& params, bool fHelp)
3521 if (!EnsureWalletIsAvailable(fHelp))
3522 return NullUniValue;
3524 if (fHelp || params.size() > 1)
3525 throw runtime_error(
3526 "z_getoperationresult ([\"operationid\", ... ]) \n"
3527 "\nRetrieve the result and status of an operation which has finished, and then remove the operation from memory."
3528 + HelpRequiringPassphrase() + "\n"
3530 "1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
3532 "\" [object, ...]\" (array) A list of JSON objects\n"
3534 + HelpExampleCli("z_getoperationresult", "'[\"operationid\", ... ]'")
3535 + HelpExampleRpc("z_getoperationresult", "'[\"operationid\", ... ]'")
3538 // This call will remove finished operations
3539 return z_getoperationstatus_IMPL(params, true);
3542 UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
3544 if (!EnsureWalletIsAvailable(fHelp))
3545 return NullUniValue;
3547 if (fHelp || params.size() > 1)
3548 throw runtime_error(
3549 "z_getoperationstatus ([\"operationid\", ... ]) \n"
3550 "\nGet operation status and any associated result or error data. The operation will remain in memory."
3551 + HelpRequiringPassphrase() + "\n"
3553 "1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
3555 "\" [object, ...]\" (array) A list of JSON objects\n"
3557 + HelpExampleCli("z_getoperationstatus", "'[\"operationid\", ... ]'")
3558 + HelpExampleRpc("z_getoperationstatus", "'[\"operationid\", ... ]'")
3561 // This call is idempotent so we don't want to remove finished operations
3562 return z_getoperationstatus_IMPL(params, false);
3565 UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedOperations=false)
3567 LOCK2(cs_main, pwalletMain->cs_wallet);
3569 std::set<AsyncRPCOperationId> filter;
3570 if (params.size()==1) {
3571 UniValue ids = params[0].get_array();
3572 for (const UniValue & v : ids.getValues()) {
3573 filter.insert(v.get_str());
3576 bool useFilter = (filter.size()>0);
3578 UniValue ret(UniValue::VARR);
3579 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3580 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
3582 for (auto id : ids) {
3583 if (useFilter && !filter.count(id))
3586 std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
3589 // It's possible that the operation was removed from the internal queue and map during this loop
3590 // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id.");
3593 UniValue obj = operation->getStatus();
3594 std::string s = obj["status"].get_str();
3595 if (fRemoveFinishedOperations) {
3596 // Caller is only interested in retrieving finished results
3597 if ("success"==s || "failed"==s || "cancelled"==s) {
3599 q->popOperationForId(id);
3606 std::vector<UniValue> arrTmp = ret.getValues();
3608 // sort results chronologically by creation_time
3609 std::sort(arrTmp.begin(), arrTmp.end(), [](UniValue a, UniValue b) -> bool {
3610 const int64_t t1 = find_value(a.get_obj(), "creation_time").get_int64();
3611 const int64_t t2 = find_value(b.get_obj(), "creation_time").get_int64();
3617 ret.push_backV(arrTmp);
3623 // JSDescription size depends on the transaction version
3624 #define V3_JS_DESCRIPTION_SIZE (GetSerializeSize(JSDescription(), SER_NETWORK, (OVERWINTER_TX_VERSION | (1 << 31))))
3625 // Here we define the maximum number of zaddr outputs that can be included in a transaction.
3626 // If input notes are small, we might actually require more than one joinsplit per zaddr output.
3627 // For now though, we assume we use one joinsplit per zaddr output (and the second output note is change).
3628 // We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data.
3629 #define Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING ((MAX_TX_SIZE_BEFORE_SAPLING / V3_JS_DESCRIPTION_SIZE) - 1)
3631 // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes
3632 #define CTXIN_SPEND_DUST_SIZE 148
3633 #define CTXOUT_REGULAR_SIZE 34
3635 UniValue z_sendmany(const UniValue& params, bool fHelp)
3637 if (!EnsureWalletIsAvailable(fHelp))
3638 return NullUniValue;
3640 if (fHelp || params.size() < 2 || params.size() > 4)
3641 throw runtime_error(
3642 "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
3643 "\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
3644 "\nChange generated from a taddr flows to a new taddr address, while change generated from a zaddr returns to itself."
3645 "\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
3646 + strprintf("\nBefore Sapling activates, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING)
3647 + HelpRequiringPassphrase() + "\n"
3649 "1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n"
3650 "2. \"amounts\" (array, required) An array of json objects representing the amounts to send.\n"
3652 " \"address\":address (string, required) The address is a taddr or zaddr\n"
3653 " \"amount\":amount (numeric, required) The numeric amount in " + CURRENCY_UNIT + " is the value\n"
3654 " \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
3656 "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
3657 "4. fee (numeric, optional, default="
3658 + strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
3660 "\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
3662 + HelpExampleCli("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
3663 + HelpExampleRpc("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
3666 LOCK2(cs_main, pwalletMain->cs_wallet);
3668 // Check that the from address is valid.
3669 auto fromaddress = params[0].get_str();
3670 bool fromTaddr = false;
3671 bool fromSapling = false;
3672 CTxDestination taddr = DecodeDestination(fromaddress);
3673 fromTaddr = IsValidDestination(taddr);
3675 auto res = DecodePaymentAddress(fromaddress);
3676 if (!IsValidPaymentAddress(res)) {
3678 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3681 // Check that we have the spending key
3682 if (!boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), res)) {
3683 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
3686 // Remember whether this is a Sprout or Sapling address
3687 fromSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
3689 // This logic will need to be updated if we add a new shielded pool
3690 bool fromSprout = !(fromTaddr || fromSapling);
3692 UniValue outputs = params[1].get_array();
3694 if (outputs.size()==0)
3695 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty.");
3697 // Keep track of addresses to spot duplicates
3698 set<std::string> setAddress;
3700 // Track whether we see any Sprout addresses
3701 bool noSproutAddrs = !fromSprout;
3704 std::vector<SendManyRecipient> taddrRecipients;
3705 std::vector<SendManyRecipient> zaddrRecipients;
3706 CAmount nTotalOut = 0;
3708 bool containsSproutOutput = false;
3709 bool containsSaplingOutput = false;
3711 for (const UniValue& o : outputs.getValues()) {
3713 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
3715 // sanity check, report error if unknown key-value pairs
3716 for (const string& name_ : o.getKeys()) {
3717 std::string s = name_;
3718 if (s != "address" && s != "amount" && s!="memo")
3719 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown key: ")+s);
3722 string address = find_value(o, "address").get_str();
3723 bool isZaddr = false;
3724 CTxDestination taddr = DecodeDestination(address);
3725 if (!IsValidDestination(taddr)) {
3726 auto res = DecodePaymentAddress(address);
3727 if (IsValidPaymentAddress(res)) {
3730 bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
3731 bool toSprout = !toSapling;
3732 noSproutAddrs = noSproutAddrs && toSapling;
3734 containsSproutOutput |= toSprout;
3735 containsSaplingOutput |= toSapling;
3737 // Sending to both Sprout and Sapling is currently unsupported using z_sendmany
3738 if (containsSproutOutput && containsSaplingOutput) {
3740 RPC_INVALID_PARAMETER,
3741 "Cannot send to both Sprout and Sapling addresses using z_sendmany");
3744 // If sending between shielded addresses, they must be the same type
3745 if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
3747 RPC_INVALID_PARAMETER,
3748 "Cannot send between Sprout and Sapling addresses using z_sendmany");
3751 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
3755 if (setAddress.count(address))
3756 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address);
3757 setAddress.insert(address);
3759 UniValue memoValue = find_value(o, "memo");
3761 if (!memoValue.isNull()) {
3762 memo = memoValue.get_str();
3764 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo cannot be used with a taddr. It can only be used with a zaddr.");
3765 } else if (!IsHex(memo)) {
3766 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
3768 if (memo.length() > ZC_MEMO_SIZE*2) {
3769 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
3773 UniValue av = find_value(o, "amount");
3774 CAmount nAmount = AmountFromValue( av );
3776 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");
3779 zaddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3781 taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3784 nTotalOut += nAmount;
3787 int nextBlockHeight = chainActive.Height() + 1;
3788 CMutableTransaction mtx;
3789 mtx.fOverwintered = true;
3790 mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
3791 mtx.nVersion = SAPLING_TX_VERSION;
3792 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
3793 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
3794 if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
3795 mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
3796 mtx.nVersion = OVERWINTER_TX_VERSION;
3798 mtx.fOverwintered = false;
3802 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
3804 // Check the number of zaddr outputs does not exceed the limit.
3805 if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING) {
3806 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs");
3810 // If Sapling is not active, do not allow sending from or sending to Sapling addresses.
3811 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
3812 if (fromSapling || containsSaplingOutput) {
3813 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
3817 // As a sanity check, estimate and verify that the size of the transaction will be valid.
3818 // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
3820 for (int i = 0; i < zaddrRecipients.size(); i++) {
3821 auto address = std::get<0>(zaddrRecipients[i]);
3822 auto res = DecodePaymentAddress(address);
3823 bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
3825 mtx.vShieldedOutput.push_back(OutputDescription());
3827 JSDescription jsdesc;
3828 if (mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)) {
3829 jsdesc.proof = GrothProof();
3831 mtx.vjoinsplit.push_back(jsdesc);
3834 CTransaction tx(mtx);
3835 txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
3837 txsize += CTXIN_SPEND_DUST_SIZE;
3838 txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change
3840 txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size();
3841 if (txsize > max_tx_size) {
3842 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", max_tx_size ));
3845 // Minimum confirmations
3847 if (params.size() > 2) {
3848 nMinDepth = params[2].get_int();
3850 if (nMinDepth < 0) {
3851 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3854 // Fee in Zatoshis, not currency format)
3855 CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
3856 CAmount nDefaultFee = nFee;
3858 if (params.size() > 3) {
3859 if (params[3].get_real() == 0.0) {
3862 nFee = AmountFromValue( params[3] );
3865 // Check that the user specified fee is not absurd.
3866 // This allows amount=0 (and all amount < nDefaultFee) transactions to use the default network fee
3867 // or anything less than nDefaultFee instead of being forced to use a custom fee and leak metadata
3868 if (nTotalOut < nDefaultFee) {
3869 if (nFee > nDefaultFee) {
3870 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Small transaction amount %s has fee %s that is greater than the default fee %s", FormatMoney(nTotalOut), FormatMoney(nFee), FormatMoney(nDefaultFee)));
3873 // Check that the user specified fee is not absurd.
3874 if (nFee > nTotalOut) {
3875 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut)));
3880 // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
3881 UniValue o(UniValue::VOBJ);
3882 o.push_back(Pair("fromaddress", params[0]));
3883 o.push_back(Pair("amounts", params[1]));
3884 o.push_back(Pair("minconf", nMinDepth));
3885 o.push_back(Pair("fee", std::stod(FormatMoney(nFee))));
3886 UniValue contextInfo = o;
3888 // Builder (used if Sapling addresses are involved)
3889 boost::optional<TransactionBuilder> builder;
3890 if (noSproutAddrs) {
3891 builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
3894 // Contextual transaction we will build on
3895 // (used if no Sapling addresses are involved)
3896 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
3897 bool isShielded = !fromTaddr || zaddrRecipients.size() > 0;
3898 if (contextualTx.nVersion == 1 && isShielded) {
3899 contextualTx.nVersion = 2; // Tx format should support vjoinsplits
3902 // Create operation and add to global queue
3903 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3904 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(builder, contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
3905 q->addOperation(operation);
3906 AsyncRPCOperationId operationId = operation->getId();
3910 UniValue z_setmigration(const UniValue& params, bool fHelp) {
3911 if (!EnsureWalletIsAvailable(fHelp))
3912 return NullUniValue;
3913 if (fHelp || params.size() != 1)
3914 throw runtime_error(
3915 "z_setmigration enabled\n"
3916 "When enabled the Sprout to Sapling migration will attempt to migrate all funds from this wallet’s\n"
3917 "Sprout addresses to either the address for Sapling account 0 or the address specified by the parameter\n"
3918 "'-migrationdestaddress'.\n"
3920 "This migration is designed to minimize information leakage. As a result for wallets with a significant\n"
3921 "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n"
3922 "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n"
3923 "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n"
3924 "the wallet’s Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n"
3926 "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n"
3928 LOCK(pwalletMain->cs_wallet);
3929 pwalletMain->fSaplingMigrationEnabled = params[0].get_bool();
3930 return NullUniValue;
3933 UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) {
3934 if (!EnsureWalletIsAvailable(fHelp))
3935 return NullUniValue;
3936 if (fHelp || params.size() != 0)
3937 throw runtime_error(
3938 "z_getmigrationstatus\n"
3939 "Returns information about the status of the Sprout to Sapling migration.\n"
3940 "In the result a transactions is defined as finalized if and only if it has\n"
3941 "at least ten confirmations.\n"
3942 "Note: It is possible that manually created transactions involving this wallet\n"
3943 "will be included in the result.\n"
3946 " \"enabled\": true|false, (boolean) Whether or not migration is enabled\n"
3947 " \"destination_address\": \"zaddr\", (string) The Sapling address that will receive Sprout funds\n"
3948 " \"unmigrated_amount\": nnn.n, (numeric) The total amount of unmigrated " + CURRENCY_UNIT +" \n"
3949 " \"unfinalized_migrated_amount\": nnn.n, (numeric) The total amount of unfinalized " + CURRENCY_UNIT + " \n"
3950 " \"finalized_migrated_amount\": nnn.n, (numeric) The total amount of finalized " + CURRENCY_UNIT + " \n"
3951 " \"finalized_migration_transactions\": nnn, (numeric) The number of migration transactions involving this wallet\n"
3952 " \"time_started\": ttt, (numeric, optional) The block time of the first migration transaction as a Unix timestamp\n"
3953 " \"migration_txids\": [txids] (json array of strings) An array of all migration txids involving this wallet\n"
3956 LOCK2(cs_main, pwalletMain->cs_wallet);
3957 UniValue migrationStatus(UniValue::VOBJ);
3958 migrationStatus.push_back(Pair("enabled", pwalletMain->fSaplingMigrationEnabled));
3959 // The "destination_address" field MAY be omitted if the "-migrationdestaddress"
3960 // parameter is not set and no default address has yet been generated.
3961 // Note: The following function may return the default address even if it has not been added to the wallet
3962 auto destinationAddress = AsyncRPCOperation_saplingmigration::getMigrationDestAddress(pwalletMain->GetHDSeedForRPC());
3963 migrationStatus.push_back(Pair("destination_address", EncodePaymentAddress(destinationAddress)));
3964 // The values of "unmigrated_amount" and "migrated_amount" MUST take into
3965 // account failed transactions, that were not mined within their expiration
3968 std::vector<CSproutNotePlaintextEntry> sproutEntries;
3969 std::vector<SaplingNoteEntry> saplingEntries;
3970 std::set<PaymentAddress> noFilter;
3971 // Here we are looking for any and all Sprout notes for which we have the spending key, including those
3972 // which are locked and/or only exist in the mempool, as they should be included in the unmigrated amount.
3973 pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false);
3974 CAmount unmigratedAmount = 0;
3975 for (const auto& sproutEntry : sproutEntries) {
3976 unmigratedAmount += sproutEntry.plaintext.value();
3978 migrationStatus.push_back(Pair("unmigrated_amount", FormatMoney(unmigratedAmount)));
3980 // "migration_txids" is a list of strings representing transaction IDs of all
3981 // known migration transactions involving this wallet, as lowercase hexadecimal
3982 // in RPC byte order.
3983 UniValue migrationTxids(UniValue::VARR);
3984 CAmount unfinalizedMigratedAmount = 0;
3985 CAmount finalizedMigratedAmount = 0;
3986 int numFinalizedMigrationTxs = 0;
3987 uint64_t timeStarted = 0;
3988 for (const auto& txPair : pwalletMain->mapWallet) {
3989 CWalletTx tx = txPair.second;
3990 // A given transaction is defined as a migration transaction iff it has:
3991 // * one or more Sprout JoinSplits with nonzero vpub_new field; and
3992 // * no Sapling Spends, and;
3993 // * one or more Sapling Outputs.
3994 if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) {
3995 bool nonZeroVPubNew = false;
3996 for (const auto& js : tx.vjoinsplit) {
3997 if (js.vpub_new > 0) {
3998 nonZeroVPubNew = true;
4002 if (!nonZeroVPubNew) {
4005 migrationTxids.push_back(txPair.first.ToString());
4006 // A transaction is "finalized" iff it has at least 10 confirmations.
4007 // TODO: subject to change, if the recommended number of confirmations changes.
4008 if (tx.GetDepthInMainChain() >= 10) {
4009 finalizedMigratedAmount -= tx.valueBalance;
4010 ++numFinalizedMigrationTxs;
4012 unfinalizedMigratedAmount -= tx.valueBalance;
4014 // If the transaction is in the mempool it will not be associated with a block yet
4015 if (tx.hashBlock.IsNull() || mapBlockIndex[tx.hashBlock] == nullptr) {
4018 CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock];
4019 // The value of "time_started" is the earliest Unix timestamp of any known
4020 // migration transaction involving this wallet; if there is no such transaction,
4021 // then the field is absent.
4022 if (timeStarted == 0 || timeStarted > blockIndex->GetBlockTime()) {
4023 timeStarted = blockIndex->GetBlockTime();
4027 migrationStatus.push_back(Pair("unfinalized_migrated_amount", FormatMoney(unfinalizedMigratedAmount)));
4028 migrationStatus.push_back(Pair("finalized_migrated_amount", FormatMoney(finalizedMigratedAmount)));
4029 migrationStatus.push_back(Pair("finalized_migration_transactions", numFinalizedMigrationTxs));
4030 if (timeStarted > 0) {
4031 migrationStatus.push_back(Pair("time_started", timeStarted));
4033 migrationStatus.push_back(Pair("migration_txids", migrationTxids));
4034 return migrationStatus;
4038 When estimating the number of coinbase utxos we can shield in a single transaction:
4039 1. Joinsplit description is 1802 bytes.
4040 2. Transaction overhead ~ 100 bytes
4041 3. Spending a typical P2PKH is >=148 bytes, as defined in CTXIN_SPEND_DUST_SIZE.
4042 4. Spending a multi-sig P2SH address can vary greatly:
4043 https://github.com/bitcoin/bitcoin/blob/c3ad56f4e0b587d8d763af03d743fdfc2d180c9b/src/main.cpp#L517
4044 In real-world coinbase utxos, we consider a 3-of-3 multisig, where the size is roughly:
4045 (3*(33+1))+3 = 105 byte redeem script
4046 105 + 1 + 3*(73+1) = 328 bytes of scriptSig, rounded up to 400 based on testnet experiments.
4048 #define CTXIN_SPEND_P2SH_SIZE 400
4050 #define SHIELD_COINBASE_DEFAULT_LIMIT 50
4052 UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
4054 if (!EnsureWalletIsAvailable(fHelp))
4055 return NullUniValue;
4057 if (fHelp || params.size() < 2 || params.size() > 4)
4058 throw runtime_error(
4059 "z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n"
4060 "\nShield transparent coinbase funds by sending to a shielded zaddr. This is an asynchronous operation and utxos"
4061 "\nselected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent`"
4062 "\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding can be limited"
4063 "\nby the caller. If the limit parameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit"
4064 "\noption will determine the number of uxtos. Any limit is constrained by the consensus rule defining a maximum"
4065 "\ntransaction size of "
4066 + strprintf("%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
4067 + HelpRequiringPassphrase() + "\n"
4069 "1. \"fromaddress\" (string, required) The address is a taddr or \"*\" for all taddrs belonging to the wallet.\n"
4070 "2. \"toaddress\" (string, required) The address is a zaddr.\n"
4071 "3. fee (numeric, optional, default="
4072 + strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
4073 "4. limit (numeric, optional, default="
4074 + strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
4077 " \"remainingUTXOs\": xxx (numeric) Number of coinbase utxos still available for shielding.\n"
4078 " \"remainingValue\": xxx (numeric) Value of coinbase utxos still available for shielding.\n"
4079 " \"shieldingUTXOs\": xxx (numeric) Number of coinbase utxos being shielded.\n"
4080 " \"shieldingValue\": xxx (numeric) Value of coinbase utxos being shielded.\n"
4081 " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
4084 + HelpExampleCli("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4085 + HelpExampleRpc("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4088 LOCK2(cs_main, pwalletMain->cs_wallet);
4090 // Validate the from address
4091 auto fromaddress = params[0].get_str();
4092 bool isFromWildcard = fromaddress == "*";
4093 CTxDestination taddr;
4094 if (!isFromWildcard) {
4095 taddr = DecodeDestination(fromaddress);
4096 if (!IsValidDestination(taddr)) {
4097 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
4101 // Validate the destination address
4102 auto destaddress = params[1].get_str();
4103 if (!IsValidPaymentAddressString(destaddress)) {
4104 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
4107 // Convert fee from currency format to zatoshis
4108 CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
4109 if (params.size() > 2) {
4110 if (params[2].get_real() == 0.0) {
4113 nFee = AmountFromValue( params[2] );
4117 int nLimit = SHIELD_COINBASE_DEFAULT_LIMIT;
4118 if (params.size() > 3) {
4119 nLimit = params[3].get_int();
4121 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of utxos cannot be negative");
4125 int nextBlockHeight = chainActive.Height() + 1;
4126 bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
4127 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
4128 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
4129 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
4132 // If Sapling is not active, do not allow sending to a Sapling address.
4133 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
4134 auto res = DecodePaymentAddress(destaddress);
4135 if (IsValidPaymentAddress(res)) {
4136 bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
4138 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
4141 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
4145 // Prepare to get coinbase utxos
4146 std::vector<ShieldCoinbaseUTXO> inputs;
4147 CAmount shieldedValue = 0;
4148 CAmount remainingValue = 0;
4149 size_t estimatedTxSize = 2000; // 1802 joinsplit description + tx overhead + wiggle room
4150 size_t utxoCounter = 0;
4151 bool maxedOutFlag = false;
4152 size_t mempoolLimit = (nLimit != 0) ? nLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
4154 // Set of addresses to filter utxos by
4155 std::set<CTxDestination> destinations = {};
4156 if (!isFromWildcard) {
4157 destinations.insert(taddr);
4160 // Get available utxos
4161 vector<COutput> vecOutputs;
4162 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true);
4164 // Find unspent coinbase utxos and update estimated size
4165 BOOST_FOREACH(const COutput& out, vecOutputs) {
4166 if (!out.fSpendable) {
4170 CTxDestination address;
4171 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
4174 // If taddr is not wildcard "*", filter utxos
4175 if (destinations.size() > 0 && !destinations.count(address)) {
4179 if (!out.tx->IsCoinBase()) {
4184 auto scriptPubKey = out.tx->vout[out.i].scriptPubKey;
4185 CAmount nValue = out.tx->vout[out.i].nValue;
4187 if (!maxedOutFlag) {
4188 size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
4189 if (estimatedTxSize + increase >= max_tx_size ||
4190 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
4192 maxedOutFlag = true;
4194 estimatedTxSize += increase;
4195 ShieldCoinbaseUTXO utxo = {out.tx->GetHash(), out.i, scriptPubKey, nValue};
4196 inputs.push_back(utxo);
4197 shieldedValue += nValue;
4202 remainingValue += nValue;
4206 size_t numUtxos = inputs.size();
4208 if (numUtxos == 0) {
4209 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase funds to shield.");
4212 if (shieldedValue < nFee) {
4213 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
4214 strprintf("Insufficient coinbase funds, have %s, which is less than miners fee %s",
4215 FormatMoney(shieldedValue), FormatMoney(nFee)));
4218 // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
4219 CAmount netAmount = shieldedValue - nFee;
4220 if (nFee > netAmount) {
4221 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
4224 // Keep record of parameters in context object
4225 UniValue contextInfo(UniValue::VOBJ);
4226 contextInfo.push_back(Pair("fromaddress", params[0]));
4227 contextInfo.push_back(Pair("toaddress", params[1]));
4228 contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
4230 // Builder (used if Sapling addresses are involved)
4231 TransactionBuilder builder = TransactionBuilder(
4232 Params().GetConsensus(), nextBlockHeight, pwalletMain);
4234 // Contextual transaction we will build on
4235 // (used if no Sapling addresses are involved)
4236 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
4237 Params().GetConsensus(), nextBlockHeight);
4238 if (contextualTx.nVersion == 1) {
4239 contextualTx.nVersion = 2; // Tx format should support vjoinsplits
4242 // Create operation and add to global queue
4243 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4244 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress, nFee, contextInfo) );
4245 q->addOperation(operation);
4246 AsyncRPCOperationId operationId = operation->getId();
4248 // Return continuation information
4249 UniValue o(UniValue::VOBJ);
4250 o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
4251 o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue)));
4252 o.push_back(Pair("shieldingUTXOs", static_cast<uint64_t>(numUtxos)));
4253 o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
4254 o.push_back(Pair("opid", operationId));
4259 #define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
4260 #define MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT 20
4261 #define MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT 200
4263 #define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)
4264 #define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION)
4265 #define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION)
4267 UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
4269 if (!EnsureWalletIsAvailable(fHelp))
4270 return NullUniValue;
4272 string enableArg = "zmergetoaddress";
4273 auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, false);
4274 std::string strDisabledMsg = "";
4275 if (!fEnableMergeToAddress) {
4276 strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
4279 if (fHelp || params.size() < 2 || params.size() > 6)
4280 throw runtime_error(
4281 "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
4283 "\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
4284 "\nto combine those into a single note."
4285 "\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
4286 "\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
4287 "\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
4288 "\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
4289 "\nnumber of UTXOs. After Overwinter has activated -mempooltxinputlimit is ignored and having a transparent"
4290 "\ninput limit of zero will mean limit the number of UTXOs based on the size of the transaction. Any limit is"
4291 "\nconstrained by the consensus rule defining a maximum transaction size of "
4292 + strprintf("%d bytes before Sapling, and %d", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
4293 + "\nbytes once Sapling activates."
4294 + HelpRequiringPassphrase() + "\n"
4296 "1. fromaddresses (array, required) A JSON array with addresses.\n"
4297 " The following special strings are accepted inside the array:\n"
4298 " - \"ANY_TADDR\": Merge UTXOs from any taddrs belonging to the wallet.\n"
4299 " - \"ANY_SPROUT\": Merge notes from any Sprout zaddrs belonging to the wallet.\n"
4300 " - \"ANY_SAPLING\": Merge notes from any Sapling zaddrs belonging to the wallet.\n"
4301 " If a special string is given, any given addresses of that type will be counted as duplicates and cause an error.\n"
4303 " \"address\" (string) Can be a taddr or a zaddr\n"
4306 "2. \"toaddress\" (string, required) The taddr or zaddr to send the funds to.\n"
4307 "3. fee (numeric, optional, default="
4308 + strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
4309 "4. transparent_limit (numeric, optional, default="
4310 + strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
4311 "5. shielded_limit (numeric, optional, default="
4312 + strprintf("%d Sprout or %d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT, MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
4313 "6. \"memo\" (string, optional) Encoded as hex. When toaddress is a zaddr, this will be stored in the memo field of the new note.\n"
4316 " \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
4317 " \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
4318 " \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
4319 " \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
4320 " \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
4321 " \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
4322 " \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
4323 " \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
4324 " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
4327 + HelpExampleCli("z_mergetoaddress", "'[\"ANY_SAPLING\", \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"]' ztestsapling19rnyu293v44f0kvtmszhx35lpdug574twc0lwyf4s7w0umtkrdq5nfcauxrxcyfmh3m7slemqsj")
4328 + HelpExampleRpc("z_mergetoaddress", "[\"ANY_SAPLING\", \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"], \"ztestsapling19rnyu293v44f0kvtmszhx35lpdug574twc0lwyf4s7w0umtkrdq5nfcauxrxcyfmh3m7slemqsj\"")
4331 if (!fEnableMergeToAddress) {
4332 throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled. Run './zcash-cli help z_mergetoaddress' for instructions on how to enable this feature.");
4335 LOCK2(cs_main, pwalletMain->cs_wallet);
4337 bool useAnyUTXO = false;
4338 bool useAnySprout = false;
4339 bool useAnySapling = false;
4340 std::set<CTxDestination> taddrs = {};
4341 std::set<libzcash::PaymentAddress> zaddrs = {};
4343 UniValue addresses = params[0].get_array();
4344 if (addresses.size()==0)
4345 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
4347 // Keep track of addresses to spot duplicates
4348 std::set<std::string> setAddress;
4351 for (const UniValue& o : addresses.getValues()) {
4353 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
4355 std::string address = o.get_str();
4357 if (address == "ANY_TADDR") {
4359 } else if (address == "ANY_SPROUT") {
4360 useAnySprout = true;
4361 } else if (address == "ANY_SAPLING") {
4362 useAnySapling = true;
4364 CTxDestination taddr = DecodeDestination(address);
4365 if (IsValidDestination(taddr)) {
4366 taddrs.insert(taddr);
4368 auto zaddr = DecodePaymentAddress(address);
4369 if (IsValidPaymentAddress(zaddr)) {
4370 zaddrs.insert(zaddr);
4372 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
4377 if (setAddress.count(address))
4378 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
4379 setAddress.insert(address);
4382 if (useAnyUTXO && taddrs.size() > 0) {
4383 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific taddrs when using \"ANY_TADDR\"");
4385 if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) {
4386 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific zaddrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\"");
4389 const int nextBlockHeight = chainActive.Height() + 1;
4390 const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
4391 const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
4393 // Validate the destination address
4394 auto destaddress = params[1].get_str();
4395 bool isToSproutZaddr = false;
4396 bool isToSaplingZaddr = false;
4397 CTxDestination taddr = DecodeDestination(destaddress);
4398 if (!IsValidDestination(taddr)) {
4399 auto decodeAddr = DecodePaymentAddress(destaddress);
4400 if (IsValidPaymentAddress(decodeAddr)) {
4401 if (boost::get<libzcash::SaplingPaymentAddress>(&decodeAddr) != nullptr) {
4402 isToSaplingZaddr = true;
4403 // If Sapling is not active, do not allow sending to a sapling addresses.
4404 if (!saplingActive) {
4405 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
4408 isToSproutZaddr = true;
4411 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
4415 // Convert fee from currency format to zatoshis
4416 CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
4417 if (params.size() > 2) {
4418 if (params[2].get_real() == 0.0) {
4421 nFee = AmountFromValue( params[2] );
4425 int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
4426 if (params.size() > 3) {
4427 nUTXOLimit = params[3].get_int();
4428 if (nUTXOLimit < 0) {
4429 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
4433 int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT;
4434 int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT;
4435 if (params.size() > 4) {
4436 int nNoteLimit = params[4].get_int();
4437 if (nNoteLimit < 0) {
4438 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
4440 sproutNoteLimit = nNoteLimit;
4441 saplingNoteLimit = nNoteLimit;
4445 if (params.size() > 5) {
4446 memo = params[5].get_str();
4447 if (!(isToSproutZaddr || isToSaplingZaddr)) {
4448 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr.");
4449 } else if (!IsHex(memo)) {
4450 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
4452 if (memo.length() > ZC_MEMO_SIZE*2) {
4453 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
4457 MergeToAddressRecipient recipient(destaddress, memo);
4459 // Prepare to get UTXOs and notes
4460 std::vector<MergeToAddressInputUTXO> utxoInputs;
4461 std::vector<MergeToAddressInputSproutNote> sproutNoteInputs;
4462 std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs;
4463 CAmount mergedUTXOValue = 0;
4464 CAmount mergedNoteValue = 0;
4465 CAmount remainingUTXOValue = 0;
4466 CAmount remainingNoteValue = 0;
4467 size_t utxoCounter = 0;
4468 size_t noteCounter = 0;
4469 bool maxedOutUTXOsFlag = false;
4470 bool maxedOutNotesFlag = false;
4471 size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
4473 unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING;
4474 size_t estimatedTxSize = 200; // tx overhead + wiggle room
4475 if (isToSproutZaddr) {
4476 estimatedTxSize += JOINSPLIT_SIZE;
4477 } else if (isToSaplingZaddr) {
4478 estimatedTxSize += OUTPUTDESCRIPTION_SIZE;
4481 if (useAnyUTXO || taddrs.size() > 0) {
4482 // Get available utxos
4483 vector<COutput> vecOutputs;
4484 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
4486 // Find unspent utxos and update estimated size
4487 for (const COutput& out : vecOutputs) {
4488 if (!out.fSpendable) {
4492 CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey;
4494 CTxDestination address;
4495 if (!ExtractDestination(scriptPubKey, address)) {
4498 // If taddr is not wildcard "*", filter utxos
4499 if (taddrs.size() > 0 && !taddrs.count(address)) {
4504 CAmount nValue = out.tx->vout[out.i].nValue;
4506 if (!maxedOutUTXOsFlag) {
4507 size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
4508 if (estimatedTxSize + increase >= max_tx_size ||
4509 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
4511 maxedOutUTXOsFlag = true;
4513 estimatedTxSize += increase;
4514 COutPoint utxo(out.tx->GetHash(), out.i);
4515 utxoInputs.emplace_back(utxo, nValue, scriptPubKey);
4516 mergedUTXOValue += nValue;
4520 if (maxedOutUTXOsFlag) {
4521 remainingUTXOValue += nValue;
4526 if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
4527 // Get available notes
4528 std::vector<CSproutNotePlaintextEntry> sproutEntries;
4529 std::vector<SaplingNoteEntry> saplingEntries;
4530 pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
4532 // If Sapling is not active, do not allow sending from a sapling addresses.
4533 if (!saplingActive && saplingEntries.size() > 0) {
4534 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
4536 // Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress
4537 if (sproutEntries.size() > 0 && saplingEntries.size() > 0) {
4539 RPC_INVALID_PARAMETER,
4540 "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress");
4542 // If sending between shielded addresses, they must be the same type
4543 if ((saplingEntries.size() > 0 && isToSproutZaddr) || (sproutEntries.size() > 0 && isToSaplingZaddr)) {
4545 RPC_INVALID_PARAMETER,
4546 "Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
4549 // Find unspent notes and update estimated size
4550 for (const CSproutNotePlaintextEntry& entry : sproutEntries) {
4552 CAmount nValue = entry.plaintext.value();
4554 if (!maxedOutNotesFlag) {
4555 // If we haven't added any notes yet and the merge is to a
4556 // z-address, we have already accounted for the first JoinSplit.
4557 size_t increase = (sproutNoteInputs.empty() && !isToSproutZaddr) || (sproutNoteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
4558 if (estimatedTxSize + increase >= max_tx_size ||
4559 (sproutNoteLimit > 0 && noteCounter > sproutNoteLimit))
4561 maxedOutNotesFlag = true;
4563 estimatedTxSize += increase;
4564 auto zaddr = entry.address;
4565 SproutSpendingKey zkey;
4566 pwalletMain->GetSproutSpendingKey(zaddr, zkey);
4567 sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey);
4568 mergedNoteValue += nValue;
4572 if (maxedOutNotesFlag) {
4573 remainingNoteValue += nValue;
4577 for (const SaplingNoteEntry& entry : saplingEntries) {
4579 CAmount nValue = entry.note.value();
4580 if (!maxedOutNotesFlag) {
4581 size_t increase = SPENDDESCRIPTION_SIZE;
4582 if (estimatedTxSize + increase >= max_tx_size ||
4583 (saplingNoteLimit > 0 && noteCounter > saplingNoteLimit))
4585 maxedOutNotesFlag = true;
4587 estimatedTxSize += increase;
4588 libzcash::SaplingExtendedSpendingKey extsk;
4589 if (!pwalletMain->GetSaplingExtendedSpendingKey(entry.address, extsk)) {
4590 throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find spending key for payment address.");
4592 saplingNoteInputs.emplace_back(entry.op, entry.note, nValue, extsk.expsk);
4593 mergedNoteValue += nValue;
4597 if (maxedOutNotesFlag) {
4598 remainingNoteValue += nValue;
4603 size_t numUtxos = utxoInputs.size();
4604 size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
4606 if (numUtxos == 0 && numNotes == 0) {
4607 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
4610 // Sanity check: Don't do anything if:
4611 // - We only have one from address
4612 // - It's equal to toaddress
4613 // - The address only contains a single UTXO or note
4614 if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
4615 throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
4618 CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
4619 if (mergedValue < nFee) {
4620 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
4621 strprintf("Insufficient funds, have %s, which is less than miners fee %s",
4622 FormatMoney(mergedValue), FormatMoney(nFee)));
4625 // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
4626 CAmount netAmount = mergedValue - nFee;
4627 if (nFee > netAmount) {
4628 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
4631 // Keep record of parameters in context object
4632 UniValue contextInfo(UniValue::VOBJ);
4633 contextInfo.push_back(Pair("fromaddresses", params[0]));
4634 contextInfo.push_back(Pair("toaddress", params[1]));
4635 contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
4637 // Contextual transaction we will build on
4638 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
4639 Params().GetConsensus(),
4641 bool isSproutShielded = sproutNoteInputs.size() > 0 || isToSproutZaddr;
4642 if (contextualTx.nVersion == 1 && isSproutShielded) {
4643 contextualTx.nVersion = 2; // Tx format should support vjoinsplit
4646 // Builder (used if Sapling addresses are involved)
4647 boost::optional<TransactionBuilder> builder;
4648 if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
4649 builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
4651 // Create operation and add to global queue
4652 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4653 std::shared_ptr<AsyncRPCOperation> operation(
4654 new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
4655 q->addOperation(operation);
4656 AsyncRPCOperationId operationId = operation->getId();
4658 // Return continuation information
4659 UniValue o(UniValue::VOBJ);
4660 o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
4661 o.push_back(Pair("remainingTransparentValue", ValueFromAmount(remainingUTXOValue)));
4662 o.push_back(Pair("remainingNotes", static_cast<uint64_t>(noteCounter - numNotes)));
4663 o.push_back(Pair("remainingShieldedValue", ValueFromAmount(remainingNoteValue)));
4664 o.push_back(Pair("mergingUTXOs", static_cast<uint64_t>(numUtxos)));
4665 o.push_back(Pair("mergingTransparentValue", ValueFromAmount(mergedUTXOValue)));
4666 o.push_back(Pair("mergingNotes", static_cast<uint64_t>(numNotes)));
4667 o.push_back(Pair("mergingShieldedValue", ValueFromAmount(mergedNoteValue)));
4668 o.push_back(Pair("opid", operationId));
4673 UniValue z_listoperationids(const UniValue& params, bool fHelp)
4675 if (!EnsureWalletIsAvailable(fHelp))
4676 return NullUniValue;
4678 if (fHelp || params.size() > 1)
4679 throw runtime_error(
4680 "z_listoperationids\n"
4681 "\nReturns the list of operation ids currently known to the wallet.\n"
4683 "1. \"status\" (string, optional) Filter result by the operation's state e.g. \"success\".\n"
4685 "[ (json array of string)\n"
4686 " \"operationid\" (string) an operation id belonging to the wallet\n"
4690 + HelpExampleCli("z_listoperationids", "")
4691 + HelpExampleRpc("z_listoperationids", "")
4694 LOCK2(cs_main, pwalletMain->cs_wallet);
4697 bool useFilter = false;
4698 if (params.size()==1) {
4699 filter = params[0].get_str();
4703 UniValue ret(UniValue::VARR);
4704 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4705 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
4706 for (auto id : ids) {
4707 std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
4711 std::string state = operation->getStateAsString();
4712 if (useFilter && filter.compare(state)!=0)
4720 extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
4721 extern UniValue importprivkey(const UniValue& params, bool fHelp);
4722 extern UniValue importaddress(const UniValue& params, bool fHelp);
4723 extern UniValue dumpwallet(const UniValue& params, bool fHelp);
4724 extern UniValue importwallet(const UniValue& params, bool fHelp);
4725 extern UniValue z_exportkey(const UniValue& params, bool fHelp);
4726 extern UniValue z_importkey(const UniValue& params, bool fHelp);
4727 extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp);
4728 extern UniValue z_importviewingkey(const UniValue& params, bool fHelp);
4729 extern UniValue z_exportwallet(const UniValue& params, bool fHelp);
4730 extern UniValue z_importwallet(const UniValue& params, bool fHelp);
4732 extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp
4733 extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp);
4735 static const CRPCCommand commands[] =
4736 { // category name actor (function) okSafeMode
4737 // --------------------- ------------------------ ----------------------- ----------
4738 { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false },
4739 { "hidden", "resendwallettransactions", &resendwallettransactions, true },
4740 { "wallet", "addmultisigaddress", &addmultisigaddress, true },
4741 { "wallet", "backupwallet", &backupwallet, true },
4742 { "wallet", "dumpprivkey", &dumpprivkey, true },
4743 { "wallet", "dumpwallet", &dumpwallet, true },
4744 { "wallet", "encryptwallet", &encryptwallet, true },
4745 { "wallet", "getaccountaddress", &getaccountaddress, true },
4746 { "wallet", "getaccount", &getaccount, true },
4747 { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
4748 { "wallet", "getbalance", &getbalance, false },
4749 { "wallet", "getnewaddress", &getnewaddress, true },
4750 { "wallet", "getrawchangeaddress", &getrawchangeaddress, true },
4751 { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false },
4752 { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false },
4753 { "wallet", "gettransaction", &gettransaction, false },
4754 { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false },
4755 { "wallet", "getwalletinfo", &getwalletinfo, false },
4756 { "wallet", "importprivkey", &importprivkey, true },
4757 { "wallet", "importwallet", &importwallet, true },
4758 { "wallet", "importaddress", &importaddress, true },
4759 { "wallet", "keypoolrefill", &keypoolrefill, true },
4760 { "wallet", "listaccounts", &listaccounts, false },
4761 { "wallet", "listaddressgroupings", &listaddressgroupings, false },
4762 { "wallet", "listlockunspent", &listlockunspent, false },
4763 { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false },
4764 { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false },
4765 { "wallet", "listsinceblock", &listsinceblock, false },
4766 { "wallet", "listtransactions", &listtransactions, false },
4767 { "wallet", "listunspent", &listunspent, false },
4768 { "wallet", "lockunspent", &lockunspent, true },
4769 { "wallet", "move", &movecmd, false },
4770 { "wallet", "sendfrom", &sendfrom, false },
4771 { "wallet", "sendmany", &sendmany, false },
4772 { "wallet", "sendtoaddress", &sendtoaddress, false },
4773 { "wallet", "setaccount", &setaccount, true },
4774 { "wallet", "settxfee", &settxfee, true },
4775 { "wallet", "signmessage", &signmessage, true },
4776 { "wallet", "walletlock", &walletlock, true },
4777 { "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
4778 { "wallet", "walletpassphrase", &walletpassphrase, true },
4779 { "wallet", "zcbenchmark", &zc_benchmark, true },
4780 { "wallet", "zcrawkeygen", &zc_raw_keygen, true },
4781 { "wallet", "zcrawjoinsplit", &zc_raw_joinsplit, true },
4782 { "wallet", "zcrawreceive", &zc_raw_receive, true },
4783 { "wallet", "zcsamplejoinsplit", &zc_sample_joinsplit, true },
4784 { "wallet", "z_listreceivedbyaddress", &z_listreceivedbyaddress, false },
4785 { "wallet", "z_listunspent", &z_listunspent, false },
4786 { "wallet", "z_getbalance", &z_getbalance, false },
4787 { "wallet", "z_gettotalbalance", &z_gettotalbalance, false },
4788 { "wallet", "z_mergetoaddress", &z_mergetoaddress, false },
4789 { "wallet", "z_sendmany", &z_sendmany, false },
4790 { "wallet", "z_setmigration", &z_setmigration, false },
4791 { "wallet", "z_getmigrationstatus", &z_getmigrationstatus, false },
4792 { "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false },
4793 { "wallet", "z_getoperationstatus", &z_getoperationstatus, true },
4794 { "wallet", "z_getoperationresult", &z_getoperationresult, true },
4795 { "wallet", "z_listoperationids", &z_listoperationids, true },
4796 { "wallet", "z_getnewaddress", &z_getnewaddress, true },
4797 { "wallet", "z_listaddresses", &z_listaddresses, true },
4798 { "wallet", "z_exportkey", &z_exportkey, true },
4799 { "wallet", "z_importkey", &z_importkey, true },
4800 { "wallet", "z_exportviewingkey", &z_exportviewingkey, true },
4801 { "wallet", "z_importviewingkey", &z_importviewingkey, true },
4802 { "wallet", "z_exportwallet", &z_exportwallet, true },
4803 { "wallet", "z_importwallet", &z_importwallet, true },
4804 // TODO: rearrange into another category
4805 { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true },
4806 { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true }
4809 void RegisterWalletRPCCommands(CRPCTable &tableRPC)
4811 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
4812 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);