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 "rpcserver.h"
17 #include "utilmoneystr.h"
20 #include "primitives/transaction.h"
21 #include "zcbenchmarks.h"
22 #include "script/interpreter.h"
25 #include "asyncrpcoperation.h"
26 #include "asyncrpcqueue.h"
27 #include "wallet/asyncrpcoperation_mergetoaddress.h"
28 #include "wallet/asyncrpcoperation_sendmany.h"
29 #include "wallet/asyncrpcoperation_shieldcoinbase.h"
35 #include <boost/assign/list_of.hpp>
43 using namespace libzcash;
45 extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
47 int64_t nWalletUnlockTime;
48 static CCriticalSection cs_nWalletUnlockTime;
51 UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
53 std::string HelpRequiringPassphrase()
55 return pwalletMain && pwalletMain->IsCrypted()
56 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
60 bool EnsureWalletIsAvailable(bool avoidException)
65 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
72 void EnsureWalletIsUnlocked()
74 if (pwalletMain->IsLocked())
75 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
78 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
80 int confirms = wtx.GetDepthInMainChain();
81 entry.push_back(Pair("confirmations", confirms));
83 entry.push_back(Pair("generated", true));
86 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
87 entry.push_back(Pair("blockindex", wtx.nIndex));
88 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
89 entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
91 uint256 hash = wtx.GetHash();
92 entry.push_back(Pair("txid", hash.GetHex()));
93 UniValue conflicts(UniValue::VARR);
94 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
95 conflicts.push_back(conflict.GetHex());
96 entry.push_back(Pair("walletconflicts", conflicts));
97 entry.push_back(Pair("time", wtx.GetTxTime()));
98 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
99 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
100 entry.push_back(Pair(item.first, item.second));
102 entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx)));
105 string AccountFromValue(const UniValue& value)
107 string strAccount = value.get_str();
108 if (strAccount != "")
109 throw JSONRPCError(RPC_WALLET_ACCOUNTS_UNSUPPORTED, "Accounts are unsupported");
113 UniValue getnewaddress(const UniValue& params, bool fHelp)
115 if (!EnsureWalletIsAvailable(fHelp))
118 if (fHelp || params.size() > 1)
120 "getnewaddress ( \"account\" )\n"
121 "\nReturns a new Zcash address for receiving payments.\n"
123 "1. \"account\" (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
125 "\"zcashaddress\" (string) The new Zcash address\n"
127 + HelpExampleCli("getnewaddress", "")
128 + HelpExampleRpc("getnewaddress", "")
131 LOCK2(cs_main, pwalletMain->cs_wallet);
133 // Parse the account first so we don't generate a key if there's an error
135 if (params.size() > 0)
136 strAccount = AccountFromValue(params[0]);
138 if (!pwalletMain->IsLocked())
139 pwalletMain->TopUpKeyPool();
141 // Generate a new key that is added to wallet
143 if (!pwalletMain->GetKeyFromPool(newKey))
144 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
145 CKeyID keyID = newKey.GetID();
147 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
149 return EncodeDestination(keyID);
153 CTxDestination GetAccountAddress(std::string strAccount, bool bForceNew=false)
155 CWalletDB walletdb(pwalletMain->strWalletFile);
158 walletdb.ReadAccount(strAccount, account);
160 bool bKeyUsed = false;
162 // Check if the current key has been used
163 if (account.vchPubKey.IsValid())
165 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
166 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
167 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
170 const CWalletTx& wtx = (*it).second;
171 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
172 if (txout.scriptPubKey == scriptPubKey)
177 // Generate a new key
178 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
180 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
181 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
183 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
184 walletdb.WriteAccount(strAccount, account);
187 return account.vchPubKey.GetID();
190 UniValue getaccountaddress(const UniValue& params, bool fHelp)
192 if (!EnsureWalletIsAvailable(fHelp))
195 if (fHelp || params.size() != 1)
197 "getaccountaddress \"account\"\n"
198 "\nDEPRECATED. Returns the current Zcash address for receiving payments to this account.\n"
200 "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
202 "\"zcashaddress\" (string) The account Zcash address\n"
204 + HelpExampleCli("getaccountaddress", "")
205 + HelpExampleCli("getaccountaddress", "\"\"")
206 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
207 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
210 LOCK2(cs_main, pwalletMain->cs_wallet);
212 // Parse the account first so we don't generate a key if there's an error
213 string strAccount = AccountFromValue(params[0]);
215 UniValue ret(UniValue::VSTR);
217 ret = EncodeDestination(GetAccountAddress(strAccount));
222 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
224 if (!EnsureWalletIsAvailable(fHelp))
227 if (fHelp || params.size() > 1)
229 "getrawchangeaddress\n"
230 "\nReturns a new Zcash address, for receiving change.\n"
231 "This is for use with raw transactions, NOT normal use.\n"
233 "\"address\" (string) The address\n"
235 + HelpExampleCli("getrawchangeaddress", "")
236 + HelpExampleRpc("getrawchangeaddress", "")
239 LOCK2(cs_main, pwalletMain->cs_wallet);
241 if (!pwalletMain->IsLocked())
242 pwalletMain->TopUpKeyPool();
244 CReserveKey reservekey(pwalletMain);
246 if (!reservekey.GetReservedKey(vchPubKey))
247 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
249 reservekey.KeepKey();
251 CKeyID keyID = vchPubKey.GetID();
253 return EncodeDestination(keyID);
257 UniValue setaccount(const UniValue& params, bool fHelp)
259 if (!EnsureWalletIsAvailable(fHelp))
262 if (fHelp || params.size() < 1 || params.size() > 2)
264 "setaccount \"zcashaddress\" \"account\"\n"
265 "\nDEPRECATED. Sets the account associated with the given address.\n"
267 "1. \"zcashaddress\" (string, required) The Zcash address to be associated with an account.\n"
268 "2. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
270 + HelpExampleCli("setaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"tabby\"")
271 + HelpExampleRpc("setaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"tabby\"")
274 LOCK2(cs_main, pwalletMain->cs_wallet);
276 CTxDestination dest = DecodeDestination(params[0].get_str());
277 if (!IsValidDestination(dest)) {
278 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
282 if (params.size() > 1)
283 strAccount = AccountFromValue(params[1]);
285 // Only add the account if the address is yours.
286 if (IsMine(*pwalletMain, dest)) {
287 // Detect when changing the account of an address that is the 'unused current key' of another account:
288 if (pwalletMain->mapAddressBook.count(dest)) {
289 std::string strOldAccount = pwalletMain->mapAddressBook[dest].name;
290 if (dest == GetAccountAddress(strOldAccount)) {
291 GetAccountAddress(strOldAccount, true);
294 pwalletMain->SetAddressBook(dest, strAccount, "receive");
297 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
303 UniValue getaccount(const UniValue& params, bool fHelp)
305 if (!EnsureWalletIsAvailable(fHelp))
308 if (fHelp || params.size() != 1)
310 "getaccount \"zcashaddress\"\n"
311 "\nDEPRECATED. Returns the account associated with the given address.\n"
313 "1. \"zcashaddress\" (string, required) The Zcash address for account lookup.\n"
315 "\"accountname\" (string) the account address\n"
317 + HelpExampleCli("getaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"")
318 + HelpExampleRpc("getaccount", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"")
321 LOCK2(cs_main, pwalletMain->cs_wallet);
323 CTxDestination dest = DecodeDestination(params[0].get_str());
324 if (!IsValidDestination(dest)) {
325 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
328 std::string strAccount;
329 std::map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(dest);
330 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) {
331 strAccount = (*mi).second.name;
337 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
339 if (!EnsureWalletIsAvailable(fHelp))
342 if (fHelp || params.size() != 1)
344 "getaddressesbyaccount \"account\"\n"
345 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
347 "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"
349 "[ (json array of string)\n"
350 " \"zcashaddress\" (string) a Zcash address associated with the given account\n"
354 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
355 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
358 LOCK2(cs_main, pwalletMain->cs_wallet);
360 string strAccount = AccountFromValue(params[0]);
362 // Find all addresses that have the given account
363 UniValue ret(UniValue::VARR);
364 for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
365 const CTxDestination& dest = item.first;
366 const std::string& strName = item.second.name;
367 if (strName == strAccount) {
368 ret.push_back(EncodeDestination(dest));
374 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
376 CAmount curBalance = pwalletMain->GetBalance();
380 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
382 if (nValue > curBalance)
383 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
385 // Parse Zcash address
386 CScript scriptPubKey = GetScriptForDestination(address);
388 // Create and send the transaction
389 CReserveKey reservekey(pwalletMain);
390 CAmount nFeeRequired;
391 std::string strError;
392 vector<CRecipient> vecSend;
393 int nChangePosRet = -1;
394 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
395 vecSend.push_back(recipient);
396 if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
397 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
398 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));
399 throw JSONRPCError(RPC_WALLET_ERROR, strError);
401 if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
402 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.");
405 UniValue sendtoaddress(const UniValue& params, bool fHelp)
407 if (!EnsureWalletIsAvailable(fHelp))
410 if (fHelp || params.size() < 2 || params.size() > 5)
412 "sendtoaddress \"zcashaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
413 "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
414 + HelpRequiringPassphrase() +
416 "1. \"zcashaddress\" (string, required) The Zcash address to send to.\n"
417 "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
418 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
419 " This is not part of the transaction, just kept in your wallet.\n"
420 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
421 " to which you're sending the transaction. This is not part of the \n"
422 " transaction, just kept in your wallet.\n"
423 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
424 " The recipient will receive less Zcash than you enter in the amount field.\n"
426 "\"transactionid\" (string) The transaction id.\n"
428 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
429 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
430 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
431 + HelpExampleRpc("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
434 LOCK2(cs_main, pwalletMain->cs_wallet);
436 CTxDestination dest = DecodeDestination(params[0].get_str());
437 if (!IsValidDestination(dest)) {
438 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
442 CAmount nAmount = AmountFromValue(params[1]);
444 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
448 if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
449 wtx.mapValue["comment"] = params[2].get_str();
450 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
451 wtx.mapValue["to"] = params[3].get_str();
453 bool fSubtractFeeFromAmount = false;
454 if (params.size() > 4)
455 fSubtractFeeFromAmount = params[4].get_bool();
457 EnsureWalletIsUnlocked();
459 SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx);
461 return wtx.GetHash().GetHex();
464 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
466 if (!EnsureWalletIsAvailable(fHelp))
471 "listaddressgroupings\n"
472 "\nLists groups of addresses which have had their common ownership\n"
473 "made public by common use as inputs or as the resulting change\n"
474 "in past transactions\n"
479 " \"zcashaddress\", (string) The zcash address\n"
480 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
481 " \"account\" (string, optional) The account (DEPRECATED)\n"
488 + HelpExampleCli("listaddressgroupings", "")
489 + HelpExampleRpc("listaddressgroupings", "")
492 LOCK2(cs_main, pwalletMain->cs_wallet);
494 UniValue jsonGroupings(UniValue::VARR);
495 std::map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
496 for (const std::set<CTxDestination>& grouping : pwalletMain->GetAddressGroupings()) {
497 UniValue jsonGrouping(UniValue::VARR);
498 for (const CTxDestination& address : grouping)
500 UniValue addressInfo(UniValue::VARR);
501 addressInfo.push_back(EncodeDestination(address));
502 addressInfo.push_back(ValueFromAmount(balances[address]));
504 if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) {
505 addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second.name);
508 jsonGrouping.push_back(addressInfo);
510 jsonGroupings.push_back(jsonGrouping);
512 return jsonGroupings;
515 UniValue signmessage(const UniValue& params, bool fHelp)
517 if (!EnsureWalletIsAvailable(fHelp))
520 if (fHelp || params.size() != 2)
522 "signmessage \"t-addr\" \"message\"\n"
523 "\nSign a message with the private key of a t-addr"
524 + HelpRequiringPassphrase() + "\n"
526 "1. \"t-addr\" (string, required) The transparent address to use for the private key.\n"
527 "2. \"message\" (string, required) The message to create a signature of.\n"
529 "\"signature\" (string) The signature of the message encoded in base 64\n"
531 "\nUnlock the wallet for 30 seconds\n"
532 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
533 "\nCreate the signature\n"
534 + HelpExampleCli("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"my message\"") +
535 "\nVerify the signature\n"
536 + HelpExampleCli("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"signature\" \"my message\"") +
538 + HelpExampleRpc("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"my message\"")
541 LOCK2(cs_main, pwalletMain->cs_wallet);
543 EnsureWalletIsUnlocked();
545 string strAddress = params[0].get_str();
546 string strMessage = params[1].get_str();
548 CTxDestination dest = DecodeDestination(strAddress);
549 if (!IsValidDestination(dest)) {
550 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
553 const CKeyID *keyID = boost::get<CKeyID>(&dest);
555 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
559 if (!pwalletMain->GetKey(*keyID, key)) {
560 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
563 CHashWriter ss(SER_GETHASH, 0);
564 ss << strMessageMagic;
567 vector<unsigned char> vchSig;
568 if (!key.SignCompact(ss.GetHash(), vchSig))
569 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
571 return EncodeBase64(&vchSig[0], vchSig.size());
574 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
576 if (!EnsureWalletIsAvailable(fHelp))
579 if (fHelp || params.size() < 1 || params.size() > 2)
581 "getreceivedbyaddress \"zcashaddress\" ( minconf )\n"
582 "\nReturns the total amount received by the given Zcash address in transactions with at least minconf confirmations.\n"
584 "1. \"zcashaddress\" (string, required) The Zcash address for transactions.\n"
585 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
587 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
589 "\nThe amount from transactions with at least 1 confirmation\n"
590 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"") +
591 "\nThe amount including unconfirmed transactions, zero confirmations\n"
592 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" 0") +
593 "\nThe amount with at least 6 confirmations, very safe\n"
594 + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" 6") +
595 "\nAs a json rpc call\n"
596 + HelpExampleRpc("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", 6")
599 LOCK2(cs_main, pwalletMain->cs_wallet);
602 CTxDestination dest = DecodeDestination(params[0].get_str());
603 if (!IsValidDestination(dest)) {
604 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
606 CScript scriptPubKey = GetScriptForDestination(dest);
607 if (!IsMine(*pwalletMain, scriptPubKey)) {
608 return ValueFromAmount(0);
611 // Minimum confirmations
613 if (params.size() > 1)
614 nMinDepth = params[1].get_int();
618 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
620 const CWalletTx& wtx = (*it).second;
621 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
624 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
625 if (txout.scriptPubKey == scriptPubKey)
626 if (wtx.GetDepthInMainChain() >= nMinDepth)
627 nAmount += txout.nValue;
630 return ValueFromAmount(nAmount);
634 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
636 if (!EnsureWalletIsAvailable(fHelp))
639 if (fHelp || params.size() < 1 || params.size() > 2)
641 "getreceivedbyaccount \"account\" ( minconf )\n"
642 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
644 "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"
645 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
647 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
649 "\nAmount received by the default account with at least 1 confirmation\n"
650 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
651 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
652 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
653 "\nThe amount with at least 6 confirmation, very safe\n"
654 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
655 "\nAs a json rpc call\n"
656 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
659 LOCK2(cs_main, pwalletMain->cs_wallet);
661 // Minimum confirmations
663 if (params.size() > 1)
664 nMinDepth = params[1].get_int();
666 // Get the set of pub keys assigned to account
667 string strAccount = AccountFromValue(params[0]);
668 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
672 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
674 const CWalletTx& wtx = (*it).second;
675 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
678 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
680 CTxDestination address;
681 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
682 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 nAmount += txout.nValue;
687 return ValueFromAmount(nAmount);
691 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
693 CAmount nBalance = 0;
695 // Tally wallet transactions
696 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
698 const CWalletTx& wtx = (*it).second;
699 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
702 CAmount nReceived, nSent, nFee;
703 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
705 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
706 nBalance += nReceived;
707 nBalance -= nSent + nFee;
710 // Tally internal accounting entries
711 nBalance += walletdb.GetAccountCreditDebit(strAccount);
716 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
718 CWalletDB walletdb(pwalletMain->strWalletFile);
719 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
723 UniValue getbalance(const UniValue& params, bool fHelp)
725 if (!EnsureWalletIsAvailable(fHelp))
728 if (fHelp || params.size() > 3)
730 "getbalance ( \"account\" minconf includeWatchonly )\n"
731 "\nReturns the server's total available balance.\n"
733 "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"
734 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
735 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
737 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
739 "\nThe total amount in the wallet\n"
740 + HelpExampleCli("getbalance", "") +
741 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
742 + HelpExampleCli("getbalance", "\"*\" 6") +
743 "\nAs a json rpc call\n"
744 + HelpExampleRpc("getbalance", "\"*\", 6")
747 LOCK2(cs_main, pwalletMain->cs_wallet);
749 if (params.size() == 0)
750 return ValueFromAmount(pwalletMain->GetBalance());
753 if (params.size() > 1)
754 nMinDepth = params[1].get_int();
755 isminefilter filter = ISMINE_SPENDABLE;
756 if(params.size() > 2)
757 if(params[2].get_bool())
758 filter = filter | ISMINE_WATCH_ONLY;
760 if (params[0].get_str() == "*") {
761 // Calculate total balance a different way from GetBalance()
762 // (GetBalance() sums up all unspent TxOuts)
763 // getbalance and "getbalance * 1 true" should return the same number
764 CAmount nBalance = 0;
765 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
767 const CWalletTx& wtx = (*it).second;
768 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
772 string strSentAccount;
773 list<COutputEntry> listReceived;
774 list<COutputEntry> listSent;
775 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
776 if (wtx.GetDepthInMainChain() >= nMinDepth)
778 BOOST_FOREACH(const COutputEntry& r, listReceived)
779 nBalance += r.amount;
781 BOOST_FOREACH(const COutputEntry& s, listSent)
782 nBalance -= s.amount;
785 return ValueFromAmount(nBalance);
788 string strAccount = AccountFromValue(params[0]);
790 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
792 return ValueFromAmount(nBalance);
795 UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp)
797 if (!EnsureWalletIsAvailable(fHelp))
800 if (fHelp || params.size() > 0)
802 "getunconfirmedbalance\n"
803 "Returns the server's total unconfirmed balance\n");
805 LOCK2(cs_main, pwalletMain->cs_wallet);
807 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
811 UniValue movecmd(const UniValue& params, bool fHelp)
813 if (!EnsureWalletIsAvailable(fHelp))
816 if (fHelp || params.size() < 3 || params.size() > 5)
818 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
819 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
821 "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"
822 "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"
823 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
824 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
825 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
827 "true|false (boolean) true if successful.\n"
829 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
830 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
831 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
832 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
833 "\nAs a json rpc call\n"
834 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
837 LOCK2(cs_main, pwalletMain->cs_wallet);
839 string strFrom = AccountFromValue(params[0]);
840 string strTo = AccountFromValue(params[1]);
841 CAmount nAmount = AmountFromValue(params[2]);
843 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
844 if (params.size() > 3)
845 // unused parameter, used to be nMinDepth, keep type-checking it though
846 (void)params[3].get_int();
848 if (params.size() > 4)
849 strComment = params[4].get_str();
851 CWalletDB walletdb(pwalletMain->strWalletFile);
852 if (!walletdb.TxnBegin())
853 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
855 int64_t nNow = GetAdjustedTime();
858 CAccountingEntry debit;
859 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
860 debit.strAccount = strFrom;
861 debit.nCreditDebit = -nAmount;
863 debit.strOtherAccount = strTo;
864 debit.strComment = strComment;
865 walletdb.WriteAccountingEntry(debit);
868 CAccountingEntry credit;
869 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
870 credit.strAccount = strTo;
871 credit.nCreditDebit = nAmount;
873 credit.strOtherAccount = strFrom;
874 credit.strComment = strComment;
875 walletdb.WriteAccountingEntry(credit);
877 if (!walletdb.TxnCommit())
878 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
884 UniValue sendfrom(const UniValue& params, bool fHelp)
886 if (!EnsureWalletIsAvailable(fHelp))
889 if (fHelp || params.size() < 3 || params.size() > 6)
891 "sendfrom \"fromaccount\" \"tozcashaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
892 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a Zcash address.\n"
893 "The amount is a real and is rounded to the nearest 0.00000001."
894 + HelpRequiringPassphrase() + "\n"
896 "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"
897 "2. \"tozcashaddress\" (string, required) The Zcash address to send funds to.\n"
898 "3. amount (numeric, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
899 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
900 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
901 " This is not part of the transaction, just kept in your wallet.\n"
902 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
903 " to which you're sending the transaction. This is not part of the transaction, \n"
904 " it is just kept in your wallet.\n"
906 "\"transactionid\" (string) The transaction id.\n"
908 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
909 + HelpExampleCli("sendfrom", "\"\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
910 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
911 + HelpExampleCli("sendfrom", "\"tabby\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
912 "\nAs a json rpc call\n"
913 + HelpExampleRpc("sendfrom", "\"tabby\", \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
916 LOCK2(cs_main, pwalletMain->cs_wallet);
918 std::string strAccount = AccountFromValue(params[0]);
919 CTxDestination dest = DecodeDestination(params[1].get_str());
920 if (!IsValidDestination(dest)) {
921 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
923 CAmount nAmount = AmountFromValue(params[2]);
925 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
927 if (params.size() > 3)
928 nMinDepth = params[3].get_int();
931 wtx.strFromAccount = strAccount;
932 if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
933 wtx.mapValue["comment"] = params[4].get_str();
934 if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
935 wtx.mapValue["to"] = params[5].get_str();
937 EnsureWalletIsUnlocked();
940 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
941 if (nAmount > nBalance)
942 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
944 SendMoney(dest, nAmount, false, wtx);
946 return wtx.GetHash().GetHex();
950 UniValue sendmany(const UniValue& params, bool fHelp)
952 if (!EnsureWalletIsAvailable(fHelp))
955 if (fHelp || params.size() < 2 || params.size() > 5)
957 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
958 "\nSend multiple times. Amounts are double-precision floating point numbers."
959 + HelpRequiringPassphrase() + "\n"
961 "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"
962 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
964 " \"address\":amount (numeric) The Zcash address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
967 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
968 "4. \"comment\" (string, optional) A comment\n"
969 "5. subtractfeefromamount (string, optional) A json array with addresses.\n"
970 " The fee will be equally deducted from the amount of each selected address.\n"
971 " Those recipients will receive less Zcash than you enter in their corresponding amount field.\n"
972 " If no addresses are specified here, the sender pays the fee.\n"
974 " \"address\" (string) Subtract fee from this address\n"
978 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
979 " the number of addresses.\n"
981 "\nSend two amounts to two different addresses:\n"
982 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
983 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
984 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
985 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
986 + HelpExampleCli("sendmany", "\"\" \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\",\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
987 "\nAs a json rpc call\n"
988 + HelpExampleRpc("sendmany", "\"\", \"{\\\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\\\":0.01,\\\"t1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
991 LOCK2(cs_main, pwalletMain->cs_wallet);
993 string strAccount = AccountFromValue(params[0]);
994 UniValue sendTo = params[1].get_obj();
996 if (params.size() > 2)
997 nMinDepth = params[2].get_int();
1000 wtx.strFromAccount = strAccount;
1001 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
1002 wtx.mapValue["comment"] = params[3].get_str();
1004 UniValue subtractFeeFromAmount(UniValue::VARR);
1005 if (params.size() > 4)
1006 subtractFeeFromAmount = params[4].get_array();
1008 std::set<CTxDestination> destinations;
1009 std::vector<CRecipient> vecSend;
1011 CAmount totalAmount = 0;
1012 std::vector<std::string> keys = sendTo.getKeys();
1013 for (const std::string& name_ : keys) {
1014 CTxDestination dest = DecodeDestination(name_);
1015 if (!IsValidDestination(dest)) {
1016 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
1019 if (destinations.count(dest)) {
1020 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
1022 destinations.insert(dest);
1024 CScript scriptPubKey = GetScriptForDestination(dest);
1025 CAmount nAmount = AmountFromValue(sendTo[name_]);
1027 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1028 totalAmount += nAmount;
1030 bool fSubtractFeeFromAmount = false;
1031 for (size_t idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1032 const UniValue& addr = subtractFeeFromAmount[idx];
1033 if (addr.get_str() == name_)
1034 fSubtractFeeFromAmount = true;
1037 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1038 vecSend.push_back(recipient);
1041 EnsureWalletIsUnlocked();
1044 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1045 if (totalAmount > nBalance)
1046 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1049 CReserveKey keyChange(pwalletMain);
1050 CAmount nFeeRequired = 0;
1051 int nChangePosRet = -1;
1052 string strFailReason;
1053 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1055 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1056 if (!pwalletMain->CommitTransaction(wtx, keyChange))
1057 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
1059 return wtx.GetHash().GetHex();
1062 // Defined in rpcmisc.cpp
1063 extern CScript _createmultisig_redeemScript(const UniValue& params);
1065 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
1067 if (!EnsureWalletIsAvailable(fHelp))
1068 return NullUniValue;
1070 if (fHelp || params.size() < 2 || params.size() > 3)
1072 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1073 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1074 "Each key is a Zcash address or hex-encoded public key.\n"
1075 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1078 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1079 "2. \"keysobject\" (string, required) A json array of Zcash addresses or hex-encoded public keys\n"
1081 " \"address\" (string) Zcash address or hex-encoded public key\n"
1084 "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"
1087 "\"zcashaddress\" (string) A Zcash address associated with the keys.\n"
1090 "\nAdd a multisig address from 2 addresses\n"
1091 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1092 "\nAs json rpc call\n"
1093 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1095 throw runtime_error(msg);
1098 LOCK2(cs_main, pwalletMain->cs_wallet);
1101 if (params.size() > 2)
1102 strAccount = AccountFromValue(params[2]);
1104 // Construct using pay-to-script-hash:
1105 CScript inner = _createmultisig_redeemScript(params);
1106 CScriptID innerID(inner);
1107 pwalletMain->AddCScript(inner);
1109 pwalletMain->SetAddressBook(innerID, strAccount, "send");
1110 return EncodeDestination(innerID);
1118 vector<uint256> txids;
1123 nConf = std::numeric_limits<int>::max();
1124 fIsWatchonly = false;
1128 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1130 // Minimum confirmations
1132 if (params.size() > 0)
1133 nMinDepth = params[0].get_int();
1135 // Whether to include empty accounts
1136 bool fIncludeEmpty = false;
1137 if (params.size() > 1)
1138 fIncludeEmpty = params[1].get_bool();
1140 isminefilter filter = ISMINE_SPENDABLE;
1141 if(params.size() > 2)
1142 if(params[2].get_bool())
1143 filter = filter | ISMINE_WATCH_ONLY;
1146 std::map<CTxDestination, tallyitem> mapTally;
1147 for (const std::pair<uint256, CWalletTx>& pairWtx : pwalletMain->mapWallet) {
1148 const CWalletTx& wtx = pairWtx.second;
1150 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1153 int nDepth = wtx.GetDepthInMainChain();
1154 if (nDepth < nMinDepth)
1157 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1159 CTxDestination address;
1160 if (!ExtractDestination(txout.scriptPubKey, address))
1163 isminefilter mine = IsMine(*pwalletMain, address);
1164 if(!(mine & filter))
1167 tallyitem& item = mapTally[address];
1168 item.nAmount += txout.nValue;
1169 item.nConf = min(item.nConf, nDepth);
1170 item.txids.push_back(wtx.GetHash());
1171 if (mine & ISMINE_WATCH_ONLY)
1172 item.fIsWatchonly = true;
1177 UniValue ret(UniValue::VARR);
1178 std::map<std::string, tallyitem> mapAccountTally;
1179 for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
1180 const CTxDestination& dest = item.first;
1181 const std::string& strAccount = item.second.name;
1182 std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
1183 if (it == mapTally.end() && !fIncludeEmpty)
1186 CAmount nAmount = 0;
1187 int nConf = std::numeric_limits<int>::max();
1188 bool fIsWatchonly = false;
1189 if (it != mapTally.end())
1191 nAmount = (*it).second.nAmount;
1192 nConf = (*it).second.nConf;
1193 fIsWatchonly = (*it).second.fIsWatchonly;
1198 tallyitem& item = mapAccountTally[strAccount];
1199 item.nAmount += nAmount;
1200 item.nConf = min(item.nConf, nConf);
1201 item.fIsWatchonly = fIsWatchonly;
1205 UniValue obj(UniValue::VOBJ);
1207 obj.push_back(Pair("involvesWatchonly", true));
1208 obj.push_back(Pair("address", EncodeDestination(dest)));
1209 obj.push_back(Pair("account", strAccount));
1210 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1211 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1212 UniValue transactions(UniValue::VARR);
1213 if (it != mapTally.end())
1215 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1217 transactions.push_back(item.GetHex());
1220 obj.push_back(Pair("txids", transactions));
1227 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1229 CAmount nAmount = (*it).second.nAmount;
1230 int nConf = (*it).second.nConf;
1231 UniValue obj(UniValue::VOBJ);
1232 if((*it).second.fIsWatchonly)
1233 obj.push_back(Pair("involvesWatchonly", true));
1234 obj.push_back(Pair("account", (*it).first));
1235 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1236 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1244 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1246 if (!EnsureWalletIsAvailable(fHelp))
1247 return NullUniValue;
1249 if (fHelp || params.size() > 3)
1250 throw runtime_error(
1251 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1252 "\nList balances by receiving address.\n"
1254 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1255 "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1256 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1261 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1262 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1263 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1264 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1265 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1271 + HelpExampleCli("listreceivedbyaddress", "")
1272 + HelpExampleCli("listreceivedbyaddress", "6 true")
1273 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1276 LOCK2(cs_main, pwalletMain->cs_wallet);
1278 return ListReceived(params, false);
1281 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
1283 if (!EnsureWalletIsAvailable(fHelp))
1284 return NullUniValue;
1286 if (fHelp || params.size() > 3)
1287 throw runtime_error(
1288 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1289 "\nDEPRECATED. List balances by account.\n"
1291 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1292 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1293 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1298 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1299 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1300 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1301 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1307 + HelpExampleCli("listreceivedbyaccount", "")
1308 + HelpExampleCli("listreceivedbyaccount", "6 true")
1309 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1312 LOCK2(cs_main, pwalletMain->cs_wallet);
1314 return ListReceived(params, true);
1317 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1319 if (IsValidDestination(dest)) {
1320 entry.push_back(Pair("address", EncodeDestination(dest)));
1324 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1327 string strSentAccount;
1328 list<COutputEntry> listReceived;
1329 list<COutputEntry> listSent;
1331 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1333 bool fAllAccounts = (strAccount == string("*"));
1334 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1337 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1339 BOOST_FOREACH(const COutputEntry& s, listSent)
1341 UniValue entry(UniValue::VOBJ);
1342 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1343 entry.push_back(Pair("involvesWatchonly", true));
1344 entry.push_back(Pair("account", strSentAccount));
1345 MaybePushAddress(entry, s.destination);
1346 entry.push_back(Pair("category", "send"));
1347 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1348 entry.push_back(Pair("vout", s.vout));
1349 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1351 WalletTxToJSON(wtx, entry);
1352 entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
1353 ret.push_back(entry);
1358 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1360 BOOST_FOREACH(const COutputEntry& r, listReceived)
1363 if (pwalletMain->mapAddressBook.count(r.destination))
1364 account = pwalletMain->mapAddressBook[r.destination].name;
1365 if (fAllAccounts || (account == strAccount))
1367 UniValue entry(UniValue::VOBJ);
1368 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1369 entry.push_back(Pair("involvesWatchonly", true));
1370 entry.push_back(Pair("account", account));
1371 MaybePushAddress(entry, r.destination);
1372 if (wtx.IsCoinBase())
1374 if (wtx.GetDepthInMainChain() < 1)
1375 entry.push_back(Pair("category", "orphan"));
1376 else if (wtx.GetBlocksToMaturity() > 0)
1377 entry.push_back(Pair("category", "immature"));
1379 entry.push_back(Pair("category", "generate"));
1383 entry.push_back(Pair("category", "receive"));
1385 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1386 entry.push_back(Pair("vout", r.vout));
1388 WalletTxToJSON(wtx, entry);
1389 entry.push_back(Pair("size", static_cast<uint64_t>(GetSerializeSize(static_cast<CTransaction>(wtx), SER_NETWORK, PROTOCOL_VERSION))));
1390 ret.push_back(entry);
1396 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1398 bool fAllAccounts = (strAccount == string("*"));
1400 if (fAllAccounts || acentry.strAccount == strAccount)
1402 UniValue entry(UniValue::VOBJ);
1403 entry.push_back(Pair("account", acentry.strAccount));
1404 entry.push_back(Pair("category", "move"));
1405 entry.push_back(Pair("time", acentry.nTime));
1406 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1407 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1408 entry.push_back(Pair("comment", acentry.strComment));
1409 ret.push_back(entry);
1413 UniValue listtransactions(const UniValue& params, bool fHelp)
1415 if (!EnsureWalletIsAvailable(fHelp))
1416 return NullUniValue;
1418 if (fHelp || params.size() > 4)
1419 throw runtime_error(
1420 "listtransactions ( \"account\" count from includeWatchonly)\n"
1421 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1423 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1424 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1425 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1426 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1430 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1431 " It will be \"\" for the default account.\n"
1432 " \"address\":\"zcashaddress\", (string) The Zcash address of the transaction. Not present for \n"
1433 " move transactions (category = move).\n"
1434 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1435 " transaction between accounts, and not associated with an address,\n"
1436 " transaction id or block. 'send' and 'receive' transactions are \n"
1437 " associated with an address, transaction id and block details\n"
1438 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1439 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1440 " and for the 'move' category for inbound funds.\n"
1441 " \"vout\" : n, (numeric) the vout value\n"
1442 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1443 " 'send' category of transactions.\n"
1444 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1445 " 'receive' category of transactions.\n"
1446 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1447 " category of transactions.\n"
1448 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1449 " category of transactions.\n"
1450 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1451 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1452 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1453 " for 'send' and 'receive' category of transactions.\n"
1454 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1455 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1456 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1457 " negative amounts).\n"
1458 " \"size\": n, (numeric) Transaction size in bytes\n"
1463 "\nList the most recent 10 transactions in the systems\n"
1464 + HelpExampleCli("listtransactions", "") +
1465 "\nList transactions 100 to 120\n"
1466 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1467 "\nAs a json rpc call\n"
1468 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1471 LOCK2(cs_main, pwalletMain->cs_wallet);
1473 string strAccount = "*";
1474 if (params.size() > 0)
1475 strAccount = params[0].get_str();
1477 if (params.size() > 1)
1478 nCount = params[1].get_int();
1480 if (params.size() > 2)
1481 nFrom = params[2].get_int();
1482 isminefilter filter = ISMINE_SPENDABLE;
1483 if(params.size() > 3)
1484 if(params[3].get_bool())
1485 filter = filter | ISMINE_WATCH_ONLY;
1488 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1490 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1492 UniValue ret(UniValue::VARR);
1494 std::list<CAccountingEntry> acentries;
1495 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1497 // iterate backwards until we have nCount items to return:
1498 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1500 CWalletTx *const pwtx = (*it).second.first;
1502 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1503 CAccountingEntry *const pacentry = (*it).second.second;
1505 AcentryToJSON(*pacentry, strAccount, ret);
1507 if ((int)ret.size() >= (nCount+nFrom)) break;
1509 // ret is newest to oldest
1511 if (nFrom > (int)ret.size())
1513 if ((nFrom + nCount) > (int)ret.size())
1514 nCount = ret.size() - nFrom;
1516 vector<UniValue> arrTmp = ret.getValues();
1518 vector<UniValue>::iterator first = arrTmp.begin();
1519 std::advance(first, nFrom);
1520 vector<UniValue>::iterator last = arrTmp.begin();
1521 std::advance(last, nFrom+nCount);
1523 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1524 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1526 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1530 ret.push_backV(arrTmp);
1535 UniValue listaccounts(const UniValue& params, bool fHelp)
1537 if (!EnsureWalletIsAvailable(fHelp))
1538 return NullUniValue;
1540 if (fHelp || params.size() > 2)
1541 throw runtime_error(
1542 "listaccounts ( minconf includeWatchonly)\n"
1543 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1545 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1546 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1548 "{ (json object where keys are account names, and values are numeric balances\n"
1549 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1553 "\nList account balances where there at least 1 confirmation\n"
1554 + HelpExampleCli("listaccounts", "") +
1555 "\nList account balances including zero confirmation transactions\n"
1556 + HelpExampleCli("listaccounts", "0") +
1557 "\nList account balances for 6 or more confirmations\n"
1558 + HelpExampleCli("listaccounts", "6") +
1559 "\nAs json rpc call\n"
1560 + HelpExampleRpc("listaccounts", "6")
1563 LOCK2(cs_main, pwalletMain->cs_wallet);
1566 if (params.size() > 0)
1567 nMinDepth = params[0].get_int();
1568 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1569 if(params.size() > 1)
1570 if(params[1].get_bool())
1571 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1573 map<string, CAmount> mapAccountBalances;
1574 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1575 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1576 mapAccountBalances[entry.second.name] = 0;
1579 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1581 const CWalletTx& wtx = (*it).second;
1583 string strSentAccount;
1584 list<COutputEntry> listReceived;
1585 list<COutputEntry> listSent;
1586 int nDepth = wtx.GetDepthInMainChain();
1587 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1589 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1590 mapAccountBalances[strSentAccount] -= nFee;
1591 BOOST_FOREACH(const COutputEntry& s, listSent)
1592 mapAccountBalances[strSentAccount] -= s.amount;
1593 if (nDepth >= nMinDepth)
1595 BOOST_FOREACH(const COutputEntry& r, listReceived)
1596 if (pwalletMain->mapAddressBook.count(r.destination))
1597 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1599 mapAccountBalances[""] += r.amount;
1603 list<CAccountingEntry> acentries;
1604 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1605 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1606 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1608 UniValue ret(UniValue::VOBJ);
1609 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1610 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1615 UniValue listsinceblock(const UniValue& params, bool fHelp)
1617 if (!EnsureWalletIsAvailable(fHelp))
1618 return NullUniValue;
1621 throw runtime_error(
1622 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1623 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1625 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1626 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1627 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1630 " \"transactions\": [\n"
1631 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1632 " \"address\":\"zcashaddress\", (string) The Zcash address of the transaction. Not present for move transactions (category = move).\n"
1633 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1634 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1635 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1636 " \"vout\" : n, (numeric) the vout value\n"
1637 " \"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"
1638 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1639 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1640 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1641 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1642 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1643 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1644 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1645 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1646 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1648 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1651 + HelpExampleCli("listsinceblock", "")
1652 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1653 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1656 LOCK2(cs_main, pwalletMain->cs_wallet);
1658 CBlockIndex *pindex = NULL;
1659 int target_confirms = 1;
1660 isminefilter filter = ISMINE_SPENDABLE;
1662 if (params.size() > 0)
1666 blockId.SetHex(params[0].get_str());
1667 BlockMap::iterator it = mapBlockIndex.find(blockId);
1668 if (it != mapBlockIndex.end())
1669 pindex = it->second;
1672 if (params.size() > 1)
1674 target_confirms = params[1].get_int();
1676 if (target_confirms < 1)
1677 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1680 if(params.size() > 2)
1681 if(params[2].get_bool())
1682 filter = filter | ISMINE_WATCH_ONLY;
1684 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1686 UniValue transactions(UniValue::VARR);
1688 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1690 CWalletTx tx = (*it).second;
1692 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1693 ListTransactions(tx, "*", 0, true, transactions, filter);
1696 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1697 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1699 UniValue ret(UniValue::VOBJ);
1700 ret.push_back(Pair("transactions", transactions));
1701 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1706 UniValue gettransaction(const UniValue& params, bool fHelp)
1708 if (!EnsureWalletIsAvailable(fHelp))
1709 return NullUniValue;
1711 if (fHelp || params.size() < 1 || params.size() > 2)
1712 throw runtime_error(
1713 "gettransaction \"txid\" ( includeWatchonly )\n"
1714 "\nGet detailed information about in-wallet transaction <txid>\n"
1716 "1. \"txid\" (string, required) The transaction id\n"
1717 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1720 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1721 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1722 " \"blockhash\" : \"hash\", (string) The block hash\n"
1723 " \"blockindex\" : xx, (numeric) The block index\n"
1724 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1725 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1726 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1727 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1728 " \"details\" : [\n"
1730 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
1731 " \"address\" : \"zcashaddress\", (string) The Zcash address involved in the transaction\n"
1732 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1733 " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
1734 " \"vout\" : n, (numeric) the vout value\n"
1738 " \"vjoinsplit\" : [\n"
1740 " \"anchor\" : \"treestateref\", (string) Merkle root of note commitment tree\n"
1741 " \"nullifiers\" : [ string, ... ] (string) Nullifiers of input notes\n"
1742 " \"commitments\" : [ string, ... ] (string) Note commitments for note outputs\n"
1743 " \"macs\" : [ string, ... ] (string) Message authentication tags\n"
1744 " \"vpub_old\" : x.xxx (numeric) The amount removed from the transparent value pool\n"
1745 " \"vpub_new\" : x.xxx, (numeric) The amount added to the transparent value pool\n"
1749 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1753 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1754 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1755 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1758 LOCK2(cs_main, pwalletMain->cs_wallet);
1761 hash.SetHex(params[0].get_str());
1763 isminefilter filter = ISMINE_SPENDABLE;
1764 if(params.size() > 1)
1765 if(params[1].get_bool())
1766 filter = filter | ISMINE_WATCH_ONLY;
1768 UniValue entry(UniValue::VOBJ);
1769 if (!pwalletMain->mapWallet.count(hash))
1770 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1771 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1773 CAmount nCredit = wtx.GetCredit(filter);
1774 CAmount nDebit = wtx.GetDebit(filter);
1775 CAmount nNet = nCredit - nDebit;
1776 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1778 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1779 if (wtx.IsFromMe(filter))
1780 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1782 WalletTxToJSON(wtx, entry);
1784 UniValue details(UniValue::VARR);
1785 ListTransactions(wtx, "*", 0, false, details, filter);
1786 entry.push_back(Pair("details", details));
1788 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1789 entry.push_back(Pair("hex", strHex));
1795 UniValue backupwallet(const UniValue& params, bool fHelp)
1797 if (!EnsureWalletIsAvailable(fHelp))
1798 return NullUniValue;
1800 if (fHelp || params.size() != 1)
1801 throw runtime_error(
1802 "backupwallet \"destination\"\n"
1803 "\nSafely copies wallet.dat to destination filename\n"
1805 "1. \"destination\" (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
1807 "\"path\" (string) The full path of the destination file\n"
1809 + HelpExampleCli("backupwallet", "\"backupdata\"")
1810 + HelpExampleRpc("backupwallet", "\"backupdata\"")
1813 LOCK2(cs_main, pwalletMain->cs_wallet);
1815 boost::filesystem::path exportdir;
1817 exportdir = GetExportDir();
1818 } catch (const std::runtime_error& e) {
1819 throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
1821 if (exportdir.empty()) {
1822 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot backup wallet until the -exportdir option has been set");
1824 std::string unclean = params[0].get_str();
1825 std::string clean = SanitizeFilename(unclean);
1826 if (clean.compare(unclean) != 0) {
1827 throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Filename is invalid as only alphanumeric characters are allowed. Try '%s' instead.", clean));
1829 boost::filesystem::path exportfilepath = exportdir / clean;
1831 if (!BackupWallet(*pwalletMain, exportfilepath.string()))
1832 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1834 return exportfilepath.string();
1838 UniValue keypoolrefill(const UniValue& params, bool fHelp)
1840 if (!EnsureWalletIsAvailable(fHelp))
1841 return NullUniValue;
1843 if (fHelp || params.size() > 1)
1844 throw runtime_error(
1845 "keypoolrefill ( newsize )\n"
1846 "\nFills the keypool."
1847 + HelpRequiringPassphrase() + "\n"
1849 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1851 + HelpExampleCli("keypoolrefill", "")
1852 + HelpExampleRpc("keypoolrefill", "")
1855 LOCK2(cs_main, pwalletMain->cs_wallet);
1857 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1858 unsigned int kpSize = 0;
1859 if (params.size() > 0) {
1860 if (params[0].get_int() < 0)
1861 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1862 kpSize = (unsigned int)params[0].get_int();
1865 EnsureWalletIsUnlocked();
1866 pwalletMain->TopUpKeyPool(kpSize);
1868 if (pwalletMain->GetKeyPoolSize() < kpSize)
1869 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1871 return NullUniValue;
1875 static void LockWallet(CWallet* pWallet)
1877 LOCK(cs_nWalletUnlockTime);
1878 nWalletUnlockTime = 0;
1882 UniValue walletpassphrase(const UniValue& params, bool fHelp)
1884 if (!EnsureWalletIsAvailable(fHelp))
1885 return NullUniValue;
1887 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1888 throw runtime_error(
1889 "walletpassphrase \"passphrase\" timeout\n"
1890 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1891 "This is needed prior to performing transactions related to private keys such as sending Zcash\n"
1893 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1894 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1896 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1897 "time that overrides the old one.\n"
1899 "\nunlock the wallet for 60 seconds\n"
1900 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1901 "\nLock the wallet again (before 60 seconds)\n"
1902 + HelpExampleCli("walletlock", "") +
1903 "\nAs json rpc call\n"
1904 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1907 LOCK2(cs_main, pwalletMain->cs_wallet);
1911 if (!pwalletMain->IsCrypted())
1912 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1914 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1915 SecureString strWalletPass;
1916 strWalletPass.reserve(100);
1917 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1918 // Alternately, find a way to make params[0] mlock()'d to begin with.
1919 strWalletPass = params[0].get_str().c_str();
1921 if (strWalletPass.length() > 0)
1923 if (!pwalletMain->Unlock(strWalletPass))
1924 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1927 throw runtime_error(
1928 "walletpassphrase <passphrase> <timeout>\n"
1929 "Stores the wallet decryption key in memory for <timeout> seconds.");
1931 // No need to check return values, because the wallet was unlocked above
1932 pwalletMain->UpdateNullifierNoteMap();
1933 pwalletMain->TopUpKeyPool();
1935 int64_t nSleepTime = params[1].get_int64();
1936 LOCK(cs_nWalletUnlockTime);
1937 nWalletUnlockTime = GetTime() + nSleepTime;
1938 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1940 return NullUniValue;
1944 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
1946 if (!EnsureWalletIsAvailable(fHelp))
1947 return NullUniValue;
1949 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1950 throw runtime_error(
1951 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1952 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1954 "1. \"oldpassphrase\" (string) The current passphrase\n"
1955 "2. \"newpassphrase\" (string) The new passphrase\n"
1957 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1958 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1961 LOCK2(cs_main, pwalletMain->cs_wallet);
1965 if (!pwalletMain->IsCrypted())
1966 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1968 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1969 // Alternately, find a way to make params[0] mlock()'d to begin with.
1970 SecureString strOldWalletPass;
1971 strOldWalletPass.reserve(100);
1972 strOldWalletPass = params[0].get_str().c_str();
1974 SecureString strNewWalletPass;
1975 strNewWalletPass.reserve(100);
1976 strNewWalletPass = params[1].get_str().c_str();
1978 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1979 throw runtime_error(
1980 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1981 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1983 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1984 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1986 return NullUniValue;
1990 UniValue walletlock(const UniValue& params, bool fHelp)
1992 if (!EnsureWalletIsAvailable(fHelp))
1993 return NullUniValue;
1995 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1996 throw runtime_error(
1998 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1999 "After calling this method, you will need to call walletpassphrase again\n"
2000 "before being able to call any methods which require the wallet to be unlocked.\n"
2002 "\nSet the passphrase for 2 minutes to perform a transaction\n"
2003 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2004 "\nPerform a send (requires passphrase set)\n"
2005 + HelpExampleCli("sendtoaddress", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2006 "\nClear the passphrase since we are done before 2 minutes is up\n"
2007 + HelpExampleCli("walletlock", "") +
2008 "\nAs json rpc call\n"
2009 + HelpExampleRpc("walletlock", "")
2012 LOCK2(cs_main, pwalletMain->cs_wallet);
2016 if (!pwalletMain->IsCrypted())
2017 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2020 LOCK(cs_nWalletUnlockTime);
2021 pwalletMain->Lock();
2022 nWalletUnlockTime = 0;
2025 return NullUniValue;
2029 UniValue encryptwallet(const UniValue& params, bool fHelp)
2031 if (!EnsureWalletIsAvailable(fHelp))
2032 return NullUniValue;
2034 string enableArg = "developerencryptwallet";
2035 auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, false);
2037 std::string strWalletEncryptionDisabledMsg = "";
2038 if (!fEnableWalletEncryption) {
2039 strWalletEncryptionDisabledMsg = experimentalDisabledHelpMsg("encryptwallet", enableArg);
2042 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2043 throw runtime_error(
2044 "encryptwallet \"passphrase\"\n"
2045 + strWalletEncryptionDisabledMsg +
2046 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2047 "After this, any calls that interact with private keys such as sending or signing \n"
2048 "will require the passphrase to be set prior the making these calls.\n"
2049 "Use the walletpassphrase call for this, and then walletlock call.\n"
2050 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2051 "Note that this will shutdown the server.\n"
2053 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2055 "\nEncrypt you wallet\n"
2056 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2057 "\nNow set the passphrase to use the wallet, such as for signing or sending Zcash\n"
2058 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2059 "\nNow we can so something like sign\n"
2060 + HelpExampleCli("signmessage", "\"zcashaddress\" \"test message\"") +
2061 "\nNow lock the wallet again by removing the passphrase\n"
2062 + HelpExampleCli("walletlock", "") +
2063 "\nAs a json rpc call\n"
2064 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2067 LOCK2(cs_main, pwalletMain->cs_wallet);
2071 if (!fEnableWalletEncryption) {
2072 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
2074 if (pwalletMain->IsCrypted())
2075 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2077 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2078 // Alternately, find a way to make params[0] mlock()'d to begin with.
2079 SecureString strWalletPass;
2080 strWalletPass.reserve(100);
2081 strWalletPass = params[0].get_str().c_str();
2083 if (strWalletPass.length() < 1)
2084 throw runtime_error(
2085 "encryptwallet <passphrase>\n"
2086 "Encrypts the wallet with <passphrase>.");
2088 if (!pwalletMain->EncryptWallet(strWalletPass))
2089 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2091 // BDB seems to have a bad habit of writing old data into
2092 // slack space in .dat files; that is bad if the old data is
2093 // unencrypted private keys. So:
2095 return "wallet encrypted; Zcash server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
2098 UniValue lockunspent(const UniValue& params, bool fHelp)
2100 if (!EnsureWalletIsAvailable(fHelp))
2101 return NullUniValue;
2103 if (fHelp || params.size() < 1 || params.size() > 2)
2104 throw runtime_error(
2105 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2106 "\nUpdates list of temporarily unspendable outputs.\n"
2107 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2108 "A locked transaction output will not be chosen by automatic coin selection, when spending Zcash.\n"
2109 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2110 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2111 "Also see the listunspent call\n"
2113 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2114 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2115 " [ (json array of json objects)\n"
2117 " \"txid\":\"id\", (string) The transaction id\n"
2118 " \"vout\": n (numeric) The output number\n"
2124 "true|false (boolean) Whether the command was successful or not\n"
2127 "\nList the unspent transactions\n"
2128 + HelpExampleCli("listunspent", "") +
2129 "\nLock an unspent transaction\n"
2130 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2131 "\nList the locked transactions\n"
2132 + HelpExampleCli("listlockunspent", "") +
2133 "\nUnlock the transaction again\n"
2134 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2135 "\nAs a json rpc call\n"
2136 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2139 LOCK2(cs_main, pwalletMain->cs_wallet);
2141 if (params.size() == 1)
2142 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2144 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2146 bool fUnlock = params[0].get_bool();
2148 if (params.size() == 1) {
2150 pwalletMain->UnlockAllCoins();
2154 UniValue outputs = params[1].get_array();
2155 for (size_t idx = 0; idx < outputs.size(); idx++) {
2156 const UniValue& output = outputs[idx];
2157 if (!output.isObject())
2158 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2159 const UniValue& o = output.get_obj();
2161 RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
2163 string txid = find_value(o, "txid").get_str();
2165 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2167 int nOutput = find_value(o, "vout").get_int();
2169 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2171 COutPoint outpt(uint256S(txid), nOutput);
2174 pwalletMain->UnlockCoin(outpt);
2176 pwalletMain->LockCoin(outpt);
2182 UniValue listlockunspent(const UniValue& params, bool fHelp)
2184 if (!EnsureWalletIsAvailable(fHelp))
2185 return NullUniValue;
2187 if (fHelp || params.size() > 0)
2188 throw runtime_error(
2190 "\nReturns list of temporarily unspendable outputs.\n"
2191 "See the lockunspent call to lock and unlock transactions for spending.\n"
2195 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2196 " \"vout\" : n (numeric) The vout value\n"
2201 "\nList the unspent transactions\n"
2202 + HelpExampleCli("listunspent", "") +
2203 "\nLock an unspent transaction\n"
2204 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2205 "\nList the locked transactions\n"
2206 + HelpExampleCli("listlockunspent", "") +
2207 "\nUnlock the transaction again\n"
2208 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2209 "\nAs a json rpc call\n"
2210 + HelpExampleRpc("listlockunspent", "")
2213 LOCK2(cs_main, pwalletMain->cs_wallet);
2215 vector<COutPoint> vOutpts;
2216 pwalletMain->ListLockedCoins(vOutpts);
2218 UniValue ret(UniValue::VARR);
2220 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2221 UniValue o(UniValue::VOBJ);
2223 o.push_back(Pair("txid", outpt.hash.GetHex()));
2224 o.push_back(Pair("vout", (int)outpt.n));
2231 UniValue settxfee(const UniValue& params, bool fHelp)
2233 if (!EnsureWalletIsAvailable(fHelp))
2234 return NullUniValue;
2236 if (fHelp || params.size() < 1 || params.size() > 1)
2237 throw runtime_error(
2239 "\nSet the transaction fee per kB.\n"
2241 "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n"
2243 "true|false (boolean) Returns true if successful\n"
2245 + HelpExampleCli("settxfee", "0.00001")
2246 + HelpExampleRpc("settxfee", "0.00001")
2249 LOCK2(cs_main, pwalletMain->cs_wallet);
2252 CAmount nAmount = AmountFromValue(params[0]);
2254 payTxFee = CFeeRate(nAmount, 1000);
2258 UniValue getwalletinfo(const UniValue& params, bool fHelp)
2260 if (!EnsureWalletIsAvailable(fHelp))
2261 return NullUniValue;
2263 if (fHelp || params.size() != 0)
2264 throw runtime_error(
2266 "Returns an object containing various wallet state info.\n"
2269 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2270 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2271 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2272 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2273 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2274 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
2275 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
2276 " \"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"
2277 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2280 + HelpExampleCli("getwalletinfo", "")
2281 + HelpExampleRpc("getwalletinfo", "")
2284 LOCK2(cs_main, pwalletMain->cs_wallet);
2286 UniValue obj(UniValue::VOBJ);
2287 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2288 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
2289 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2290 obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
2291 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
2292 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2293 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2294 if (pwalletMain->IsCrypted())
2295 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2296 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2300 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
2302 if (!EnsureWalletIsAvailable(fHelp))
2303 return NullUniValue;
2305 if (fHelp || params.size() != 0)
2306 throw runtime_error(
2307 "resendwallettransactions\n"
2308 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2309 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2311 "Returns array of transaction ids that were re-broadcast.\n"
2314 LOCK2(cs_main, pwalletMain->cs_wallet);
2316 std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2317 UniValue result(UniValue::VARR);
2318 BOOST_FOREACH(const uint256& txid, txids)
2320 result.push_back(txid.ToString());
2325 UniValue listunspent(const UniValue& params, bool fHelp)
2327 if (!EnsureWalletIsAvailable(fHelp))
2328 return NullUniValue;
2330 if (fHelp || params.size() > 3)
2331 throw runtime_error(
2332 "listunspent ( minconf maxconf [\"address\",...] )\n"
2333 "\nReturns array of unspent transaction outputs\n"
2334 "with between minconf and maxconf (inclusive) confirmations.\n"
2335 "Optionally filter to only include txouts paid to specified addresses.\n"
2336 "Results are an array of Objects, each of which has:\n"
2337 "{txid, vout, scriptPubKey, amount, confirmations}\n"
2339 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2340 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2341 "3. \"addresses\" (string) A json array of Zcash addresses to filter\n"
2343 " \"address\" (string) Zcash address\n"
2347 "[ (array of json object)\n"
2349 " \"txid\" : \"txid\", (string) the transaction id \n"
2350 " \"vout\" : n, (numeric) the vout value\n"
2351 " \"generated\" : true|false (boolean) true if txout is a coinbase transaction output\n"
2352 " \"address\" : \"address\", (string) the Zcash address\n"
2353 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2354 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2355 " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n"
2356 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2357 " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
2358 " \"spendable\" : xxx (bool) Whether we have the private keys to spend this output\n"
2364 + HelpExampleCli("listunspent", "")
2365 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"t1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"t1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2366 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"t1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"t1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2369 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
2372 if (params.size() > 0)
2373 nMinDepth = params[0].get_int();
2375 int nMaxDepth = 9999999;
2376 if (params.size() > 1)
2377 nMaxDepth = params[1].get_int();
2379 std::set<CTxDestination> destinations;
2380 if (params.size() > 2) {
2381 UniValue inputs = params[2].get_array();
2382 for (size_t idx = 0; idx < inputs.size(); idx++) {
2383 const UniValue& input = inputs[idx];
2384 CTxDestination dest = DecodeDestination(input.get_str());
2385 if (!IsValidDestination(dest)) {
2386 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + input.get_str());
2388 if (!destinations.insert(dest).second) {
2389 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
2394 UniValue results(UniValue::VARR);
2395 vector<COutput> vecOutputs;
2396 assert(pwalletMain != NULL);
2397 LOCK2(cs_main, pwalletMain->cs_wallet);
2398 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2399 BOOST_FOREACH(const COutput& out, vecOutputs) {
2400 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2403 CTxDestination address;
2404 const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
2405 bool fValidAddress = ExtractDestination(scriptPubKey, address);
2407 if (destinations.size() && (!fValidAddress || !destinations.count(address)))
2410 UniValue entry(UniValue::VOBJ);
2411 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2412 entry.push_back(Pair("vout", out.i));
2413 entry.push_back(Pair("generated", out.tx->IsCoinBase()));
2415 if (fValidAddress) {
2416 entry.push_back(Pair("address", EncodeDestination(address)));
2418 if (pwalletMain->mapAddressBook.count(address))
2419 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2421 if (scriptPubKey.IsPayToScriptHash()) {
2422 const CScriptID& hash = boost::get<CScriptID>(address);
2423 CScript redeemScript;
2424 if (pwalletMain->GetCScript(hash, redeemScript))
2425 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2429 entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2430 entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue)));
2431 entry.push_back(Pair("confirmations", out.nDepth));
2432 entry.push_back(Pair("spendable", out.fSpendable));
2433 results.push_back(entry);
2440 UniValue z_listunspent(const UniValue& params, bool fHelp)
2442 if (!EnsureWalletIsAvailable(fHelp))
2443 return NullUniValue;
2445 if (fHelp || params.size() > 4)
2446 throw runtime_error(
2447 "z_listunspent ( minconf maxconf includeWatchonly [\"zaddr\",...] )\n"
2448 "\nReturns array of unspent shielded notes with between minconf and maxconf (inclusive) confirmations.\n"
2449 "Optionally filter to only include notes sent to specified addresses.\n"
2450 "When minconf is 0, unspent notes with zero confirmations are returned, even though they are not immediately spendable.\n"
2451 "Results are an array of Objects, each of which has:\n"
2452 "{txid, jsindex, jsoutindex, confirmations, address, amount, memo}\n"
2454 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2455 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2456 "3. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
2457 "4. \"addresses\" (string) A json array of zaddrs to filter on. Duplicate addresses not allowed.\n"
2459 " \"address\" (string) zaddr\n"
2463 "[ (array of json object)\n"
2465 " \"txid\" : \"txid\", (string) the transaction id \n"
2466 " \"jsindex\" : n (numeric) the joinsplit index\n"
2467 " \"jsoutindex\" : n (numeric) the output index of the joinsplit\n"
2468 " \"confirmations\" : n (numeric) the number of confirmations\n"
2469 " \"spendable\" : true|false (boolean) true if note can be spent by wallet, false if note has zero confirmations, false if address is watchonly\n"
2470 " \"address\" : \"address\", (string) the shielded address\n"
2471 " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
2472 " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
2473 " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
2479 + HelpExampleCli("z_listunspent", "")
2480 + HelpExampleCli("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
2481 + HelpExampleRpc("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
2484 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VBOOL)(UniValue::VARR));
2487 if (params.size() > 0) {
2488 nMinDepth = params[0].get_int();
2490 if (nMinDepth < 0) {
2491 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
2494 int nMaxDepth = 9999999;
2495 if (params.size() > 1) {
2496 nMaxDepth = params[1].get_int();
2498 if (nMaxDepth < nMinDepth) {
2499 throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum number of confirmations must be greater or equal to the minimum number of confirmations");
2502 std::set<libzcash::PaymentAddress> zaddrs = {};
2504 bool fIncludeWatchonly = false;
2505 if (params.size() > 2) {
2506 fIncludeWatchonly = params[2].get_bool();
2509 LOCK2(cs_main, pwalletMain->cs_wallet);
2511 // User has supplied zaddrs to filter on
2512 if (params.size() > 3) {
2513 UniValue addresses = params[3].get_array();
2514 if (addresses.size()==0)
2515 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, addresses array is empty.");
2517 // Keep track of addresses to spot duplicates
2518 set<std::string> setAddress;
2521 for (const UniValue& o : addresses.getValues()) {
2523 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
2525 string address = o.get_str();
2526 auto zaddr = DecodePaymentAddress(address);
2527 if (IsValidPaymentAddress(zaddr)) {
2528 // TODO: Add Sapling support. For now, ensure we can freely convert.
2529 assert(boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr);
2530 libzcash::SproutPaymentAddress addr = boost::get<libzcash::SproutPaymentAddress>(zaddr);
2531 if (!fIncludeWatchonly && !pwalletMain->HaveSpendingKey(addr)) {
2532 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
2534 zaddrs.insert(addr);
2536 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address);
2539 if (setAddress.count(address)) {
2540 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
2542 setAddress.insert(address);
2546 // User did not provide zaddrs, so use default i.e. all addresses
2547 // TODO: Add Sapling support
2548 std::set<libzcash::SproutPaymentAddress> sproutzaddrs = {};
2549 pwalletMain->GetPaymentAddresses(sproutzaddrs);
2550 zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end());
2553 UniValue results(UniValue::VARR);
2555 if (zaddrs.size() > 0) {
2556 std::vector<CUnspentSproutNotePlaintextEntry> entries;
2557 pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly);
2558 std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
2559 for (CUnspentSproutNotePlaintextEntry & entry : entries) {
2560 UniValue obj(UniValue::VOBJ);
2561 obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
2562 obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
2563 obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
2564 obj.push_back(Pair("confirmations", entry.nHeight));
2565 obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(boost::get<libzcash::SproutPaymentAddress>(entry.address))));
2566 obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
2567 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
2568 std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
2569 obj.push_back(Pair("memo", HexStr(data)));
2570 obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
2571 results.push_back(obj);
2579 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
2581 if (!EnsureWalletIsAvailable(fHelp))
2582 return NullUniValue;
2584 if (fHelp || params.size() != 1)
2585 throw runtime_error(
2586 "fundrawtransaction \"hexstring\"\n"
2587 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2588 "This will not modify existing inputs, and will add one change output to the outputs.\n"
2589 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2590 "The inputs added will not be signed, use signrawtransaction for that.\n"
2592 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
2595 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
2596 " \"fee\": n, (numeric) The fee added to the transaction\n"
2597 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
2601 "\nCreate a transaction with no inputs\n"
2602 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2603 "\nAdd sufficient unsigned inputs to meet the output value\n"
2604 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2605 "\nSign the transaction\n"
2606 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2607 "\nSend the transaction\n"
2608 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2611 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
2613 // parse hex string from parameter
2614 CTransaction origTx;
2615 if (!DecodeHexTx(origTx, params[0].get_str()))
2616 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2618 CMutableTransaction tx(origTx);
2620 string strFailReason;
2621 int nChangePos = -1;
2622 if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason))
2623 throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2625 UniValue result(UniValue::VOBJ);
2626 result.push_back(Pair("hex", EncodeHexTx(tx)));
2627 result.push_back(Pair("changepos", nChangePos));
2628 result.push_back(Pair("fee", ValueFromAmount(nFee)));
2633 UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
2636 throw runtime_error(
2637 "zcsamplejoinsplit\n"
2639 "Perform a joinsplit and return the JSDescription.\n"
2645 uint256 joinSplitPubKey;
2646 uint256 anchor = ZCIncrementalMerkleTree().root();
2647 JSDescription samplejoinsplit(true,
2651 {JSInput(), JSInput()},
2652 {JSOutput(), JSOutput()},
2656 CDataStream ss(SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
2657 ss << samplejoinsplit;
2659 return HexStr(ss.begin(), ss.end());
2662 UniValue zc_benchmark(const UniValue& params, bool fHelp)
2664 if (!EnsureWalletIsAvailable(fHelp)) {
2665 return NullUniValue;
2668 if (fHelp || params.size() < 2) {
2669 throw runtime_error(
2670 "zcbenchmark benchmarktype samplecount\n"
2672 "Runs a benchmark of the selected type samplecount times,\n"
2673 "returning the running times of each sample.\n"
2677 " \"runningtime\": runningtime\n"
2680 " \"runningtime\": runningtime\n"
2689 std::string benchmarktype = params[0].get_str();
2690 int samplecount = params[1].get_int();
2692 if (samplecount <= 0) {
2693 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid samplecount");
2696 std::vector<double> sample_times;
2698 JSDescription samplejoinsplit;
2700 if (benchmarktype == "verifyjoinsplit") {
2701 CDataStream ss(ParseHexV(params[2].get_str(), "js"), SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
2702 ss >> samplejoinsplit;
2705 for (int i = 0; i < samplecount; i++) {
2706 if (benchmarktype == "sleep") {
2707 sample_times.push_back(benchmark_sleep());
2708 } else if (benchmarktype == "parameterloading") {
2709 sample_times.push_back(benchmark_parameter_loading());
2710 } else if (benchmarktype == "createjoinsplit") {
2711 if (params.size() < 3) {
2712 sample_times.push_back(benchmark_create_joinsplit());
2714 int nThreads = params[2].get_int();
2715 std::vector<double> vals = benchmark_create_joinsplit_threaded(nThreads);
2716 // Divide by nThreads^2 to get average seconds per JoinSplit because
2717 // we are running one JoinSplit per thread.
2718 sample_times.push_back(std::accumulate(vals.begin(), vals.end(), 0.0) / (nThreads*nThreads));
2720 } else if (benchmarktype == "verifyjoinsplit") {
2721 sample_times.push_back(benchmark_verify_joinsplit(samplejoinsplit));
2722 #ifdef ENABLE_MINING
2723 } else if (benchmarktype == "solveequihash") {
2724 if (params.size() < 3) {
2725 sample_times.push_back(benchmark_solve_equihash());
2727 int nThreads = params[2].get_int();
2728 std::vector<double> vals = benchmark_solve_equihash_threaded(nThreads);
2729 sample_times.insert(sample_times.end(), vals.begin(), vals.end());
2732 } else if (benchmarktype == "verifyequihash") {
2733 sample_times.push_back(benchmark_verify_equihash());
2734 } else if (benchmarktype == "validatelargetx") {
2735 // Number of inputs in the spending transaction that we will simulate
2736 int nInputs = 11130;
2737 if (params.size() >= 3) {
2738 nInputs = params[2].get_int();
2740 sample_times.push_back(benchmark_large_tx(nInputs));
2741 } else if (benchmarktype == "trydecryptnotes") {
2742 int nAddrs = params[2].get_int();
2743 sample_times.push_back(benchmark_try_decrypt_notes(nAddrs));
2744 } else if (benchmarktype == "incnotewitnesses") {
2745 int nTxs = params[2].get_int();
2746 sample_times.push_back(benchmark_increment_note_witnesses(nTxs));
2747 } else if (benchmarktype == "connectblockslow") {
2748 if (Params().NetworkIDString() != "regtest") {
2749 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2751 sample_times.push_back(benchmark_connectblock_slow());
2752 } else if (benchmarktype == "sendtoaddress") {
2753 if (Params().NetworkIDString() != "regtest") {
2754 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2756 auto amount = AmountFromValue(params[2]);
2757 sample_times.push_back(benchmark_sendtoaddress(amount));
2758 } else if (benchmarktype == "loadwallet") {
2759 if (Params().NetworkIDString() != "regtest") {
2760 throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
2762 sample_times.push_back(benchmark_loadwallet());
2763 } else if (benchmarktype == "listunspent") {
2764 sample_times.push_back(benchmark_listunspent());
2766 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
2770 UniValue results(UniValue::VARR);
2771 for (auto time : sample_times) {
2772 UniValue result(UniValue::VOBJ);
2773 result.push_back(Pair("runningtime", time));
2774 results.push_back(result);
2780 UniValue zc_raw_receive(const UniValue& params, bool fHelp)
2782 if (!EnsureWalletIsAvailable(fHelp)) {
2783 return NullUniValue;
2786 if (fHelp || params.size() != 2) {
2787 throw runtime_error(
2788 "zcrawreceive zcsecretkey encryptednote\n"
2790 "DEPRECATED. Decrypts encryptednote and checks if the coin commitments\n"
2791 "are in the blockchain as indicated by the \"exists\" result.\n"
2794 " \"amount\": value,\n"
2795 " \"note\": noteplaintext,\n"
2796 " \"exists\": exists\n"
2801 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR));
2805 auto spendingkey = DecodeSpendingKey(params[0].get_str());
2806 if (!IsValidSpendingKey(spendingkey)) {
2807 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
2809 if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
2810 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
2812 SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
2815 unsigned char nonce;
2816 ZCNoteEncryption::Ciphertext ct;
2820 CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
2826 } catch(const std::exception &) {
2827 throw runtime_error(
2828 "encrypted_note could not be decoded"
2833 ZCNoteDecryption decryptor(k.receiving_key());
2835 SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
2842 SproutPaymentAddress payment_addr = k.address();
2843 SproutNote decrypted_note = npt.note(payment_addr);
2845 assert(pwalletMain != NULL);
2846 std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
2848 uint256 commitment = decrypted_note.cm();
2849 pwalletMain->WitnessNoteCommitment(
2855 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2858 UniValue result(UniValue::VOBJ);
2859 result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value())));
2860 result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
2861 result.push_back(Pair("exists", (bool) witnesses[0]));
2867 UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
2869 if (!EnsureWalletIsAvailable(fHelp)) {
2870 return NullUniValue;
2873 if (fHelp || params.size() != 5) {
2874 throw runtime_error(
2875 "zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
2876 " inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
2877 " outputs: a JSON object mapping {zcaddr: value, ...}\n"
2879 "DEPRECATED. Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
2880 "Outputs are confidential between sender/receiver. The vpub_old and\n"
2881 "vpub_new values are globally public and move transparent value into\n"
2882 "or out of the confidential value store, respectively.\n"
2884 "Note: The caller is responsible for delivering the output enc1 and\n"
2885 "enc2 to the appropriate recipients, as well as signing rawtxout and\n"
2886 "ensuring it is mined. (A future RPC call will deliver the confidential\n"
2887 "payments in-band on the blockchain.)\n"
2890 " \"encryptednote1\": enc1,\n"
2891 " \"encryptednote2\": enc2,\n"
2892 " \"rawtxn\": rawtxout\n"
2900 if (!DecodeHexTx(tx, params[0].get_str()))
2901 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2903 UniValue inputs = params[1].get_obj();
2904 UniValue outputs = params[2].get_obj();
2906 CAmount vpub_old(0);
2907 CAmount vpub_new(0);
2909 if (params[3].get_real() != 0.0)
2910 vpub_old = AmountFromValue(params[3]);
2912 if (params[4].get_real() != 0.0)
2913 vpub_new = AmountFromValue(params[4]);
2915 std::vector<JSInput> vjsin;
2916 std::vector<JSOutput> vjsout;
2917 std::vector<SproutNote> notes;
2918 std::vector<SproutSpendingKey> keys;
2919 std::vector<uint256> commitments;
2921 for (const string& name_ : inputs.getKeys()) {
2922 auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
2923 if (!IsValidSpendingKey(spendingkey)) {
2924 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
2926 if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
2927 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
2929 SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
2933 SproutNotePlaintext npt;
2936 CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
2940 SproutPaymentAddress addr = k.address();
2941 SproutNote note = npt.note(addr);
2942 notes.push_back(note);
2943 commitments.push_back(note.cm());
2947 std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
2948 pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
2950 assert(witnesses.size() == notes.size());
2951 assert(notes.size() == keys.size());
2954 for (size_t i = 0; i < witnesses.size(); i++) {
2955 if (!witnesses[i]) {
2956 throw runtime_error(
2957 "joinsplit input could not be found in tree"
2961 vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
2965 while (vjsin.size() < ZC_NUM_JS_INPUTS) {
2966 vjsin.push_back(JSInput());
2969 for (const string& name_ : outputs.getKeys()) {
2970 auto addrTo = DecodePaymentAddress(name_);
2971 if (!IsValidPaymentAddress(addrTo)) {
2972 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
2974 if (boost::get<libzcash::SproutPaymentAddress>(&addrTo) == nullptr) {
2975 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout payment addresses");
2977 CAmount nAmount = AmountFromValue(outputs[name_]);
2979 vjsout.push_back(JSOutput(boost::get<libzcash::SproutPaymentAddress>(addrTo), nAmount));
2982 while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
2983 vjsout.push_back(JSOutput());
2987 if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
2988 throw runtime_error("unsupported joinsplit input/output counts");
2991 uint256 joinSplitPubKey;
2992 unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
2993 crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
2995 CMutableTransaction mtx(tx);
2997 mtx.joinSplitPubKey = joinSplitPubKey;
2999 JSDescription jsdesc(false,
3003 {vjsin[0], vjsin[1]},
3004 {vjsout[0], vjsout[1]},
3009 auto verifier = libzcash::ProofVerifier::Strict();
3010 assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
3013 mtx.vjoinsplit.push_back(jsdesc);
3015 // Empty output script.
3017 CTransaction signTx(mtx);
3018 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
3019 uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
3021 // Add the signature
3022 assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
3023 dataToBeSigned.begin(), 32,
3028 assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
3029 dataToBeSigned.begin(), 32,
3030 mtx.joinSplitPubKey.begin()
3033 CTransaction rawTx(mtx);
3035 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3038 std::string encryptedNote1;
3039 std::string encryptedNote2;
3041 CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3042 ss2 << ((unsigned char) 0x00);
3043 ss2 << jsdesc.ephemeralKey;
3044 ss2 << jsdesc.ciphertexts[0];
3045 ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3047 encryptedNote1 = HexStr(ss2.begin(), ss2.end());
3050 CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
3051 ss2 << ((unsigned char) 0x01);
3052 ss2 << jsdesc.ephemeralKey;
3053 ss2 << jsdesc.ciphertexts[1];
3054 ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
3056 encryptedNote2 = HexStr(ss2.begin(), ss2.end());
3059 UniValue result(UniValue::VOBJ);
3060 result.push_back(Pair("encryptednote1", encryptedNote1));
3061 result.push_back(Pair("encryptednote2", encryptedNote2));
3062 result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
3066 UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
3068 if (!EnsureWalletIsAvailable(fHelp)) {
3069 return NullUniValue;
3072 if (fHelp || params.size() != 0) {
3073 throw runtime_error(
3076 "DEPRECATED. Generate a zcaddr which can send and receive confidential values.\n"
3079 " \"zcaddress\": zcaddr,\n"
3080 " \"zcsecretkey\": zcsecretkey,\n"
3081 " \"zcviewingkey\": zcviewingkey,\n"
3086 auto k = SproutSpendingKey::random();
3087 auto addr = k.address();
3088 auto viewing_key = k.viewing_key();
3090 UniValue result(UniValue::VOBJ);
3091 result.push_back(Pair("zcaddress", EncodePaymentAddress(addr)));
3092 result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k)));
3093 result.push_back(Pair("zcviewingkey", EncodeViewingKey(viewing_key)));
3098 UniValue z_getnewaddress(const UniValue& params, bool fHelp)
3100 if (!EnsureWalletIsAvailable(fHelp))
3101 return NullUniValue;
3103 if (fHelp || params.size() > 0)
3104 throw runtime_error(
3106 "\nReturns a new zaddr for receiving payments.\n"
3109 "\"zcashaddress\" (string) The new zaddr\n"
3111 + HelpExampleCli("z_getnewaddress", "")
3112 + HelpExampleRpc("z_getnewaddress", "")
3115 LOCK2(cs_main, pwalletMain->cs_wallet);
3117 EnsureWalletIsUnlocked();
3119 auto zaddr = pwalletMain->GenerateNewZKey();
3120 return EncodePaymentAddress(zaddr);
3124 UniValue z_listaddresses(const UniValue& params, bool fHelp)
3126 if (!EnsureWalletIsAvailable(fHelp))
3127 return NullUniValue;
3129 if (fHelp || params.size() > 1)
3130 throw runtime_error(
3131 "z_listaddresses ( includeWatchonly )\n"
3132 "\nReturns the list of zaddr belonging to the wallet.\n"
3134 "1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
3136 "[ (json array of string)\n"
3137 " \"zaddr\" (string) a zaddr belonging to the wallet\n"
3141 + HelpExampleCli("z_listaddresses", "")
3142 + HelpExampleRpc("z_listaddresses", "")
3145 LOCK2(cs_main, pwalletMain->cs_wallet);
3147 bool fIncludeWatchonly = false;
3148 if (params.size() > 0) {
3149 fIncludeWatchonly = params[0].get_bool();
3152 UniValue ret(UniValue::VARR);
3153 // TODO: Add Sapling support
3154 std::set<libzcash::SproutPaymentAddress> addresses;
3155 pwalletMain->GetPaymentAddresses(addresses);
3156 for (auto addr : addresses ) {
3157 if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
3158 ret.push_back(EncodePaymentAddress(addr));
3164 CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
3165 std::set<CTxDestination> destinations;
3166 vector<COutput> vecOutputs;
3167 CAmount balance = 0;
3169 if (transparentAddress.length() > 0) {
3170 CTxDestination taddr = DecodeDestination(transparentAddress);
3171 if (!IsValidDestination(taddr)) {
3172 throw std::runtime_error("invalid transparent address");
3174 destinations.insert(taddr);
3177 LOCK2(cs_main, pwalletMain->cs_wallet);
3179 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
3181 BOOST_FOREACH(const COutput& out, vecOutputs) {
3182 if (out.nDepth < minDepth) {
3186 if (ignoreUnspendable && !out.fSpendable) {
3190 if (destinations.size()) {
3191 CTxDestination address;
3192 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
3196 if (!destinations.count(address)) {
3201 CAmount nValue = out.tx->vout[out.i].nValue;
3207 CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
3208 CAmount balance = 0;
3209 std::vector<CSproutNotePlaintextEntry> entries;
3210 LOCK2(cs_main, pwalletMain->cs_wallet);
3211 pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
3212 for (auto & entry : entries) {
3213 balance += CAmount(entry.plaintext.value());
3219 UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
3221 if (!EnsureWalletIsAvailable(fHelp))
3222 return NullUniValue;
3224 if (fHelp || params.size()==0 || params.size() >2)
3225 throw runtime_error(
3226 "z_listreceivedbyaddress \"address\" ( minconf )\n"
3227 "\nReturn a list of amounts received by a zaddr belonging to the node’s wallet.\n"
3229 "1. \"address\" (string) The private address.\n"
3230 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3233 " \"txid\": xxxxx, (string) the transaction id\n"
3234 " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
3235 " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
3236 " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
3239 + HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3240 + HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3243 LOCK2(cs_main, pwalletMain->cs_wallet);
3246 if (params.size() > 1) {
3247 nMinDepth = params[1].get_int();
3249 if (nMinDepth < 0) {
3250 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3253 // Check that the from address is valid.
3254 auto fromaddress = params[0].get_str();
3256 auto zaddr = DecodePaymentAddress(fromaddress);
3257 if (!IsValidPaymentAddress(zaddr)) {
3258 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
3260 // TODO: Add Sapling support. For now, ensure we can freely convert.
3261 assert(boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr);
3262 auto sproutzaddr = boost::get<libzcash::SproutPaymentAddress>(zaddr);
3264 if (!(pwalletMain->HaveSpendingKey(sproutzaddr) || pwalletMain->HaveViewingKey(sproutzaddr))) {
3265 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
3269 UniValue result(UniValue::VARR);
3270 std::vector<CSproutNotePlaintextEntry> entries;
3271 pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
3272 std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr});
3273 for (CSproutNotePlaintextEntry & entry : entries) {
3274 UniValue obj(UniValue::VOBJ);
3275 obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
3276 obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
3277 std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
3278 obj.push_back(Pair("memo", HexStr(data)));
3279 // (txid, jsindex, jsoutindex) is needed to globally identify a note
3280 obj.push_back(Pair("jsindex", entry.jsop.js));
3281 obj.push_back(Pair("jsoutindex", entry.jsop.n));
3282 obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
3283 result.push_back(obj);
3288 UniValue z_getbalance(const UniValue& params, bool fHelp)
3290 if (!EnsureWalletIsAvailable(fHelp))
3291 return NullUniValue;
3293 if (fHelp || params.size()==0 || params.size() >2)
3294 throw runtime_error(
3295 "z_getbalance \"address\" ( minconf )\n"
3296 "\nReturns the balance of a taddr or zaddr belonging to the node’s wallet.\n"
3297 "\nCAUTION: If address is a watch-only zaddr, the returned balance may be larger than the actual balance,"
3298 "\nbecause spends cannot be detected with incoming viewing keys.\n"
3300 "1. \"address\" (string) The selected address. It may be a transparent or private address.\n"
3301 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
3303 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this address.\n"
3305 "\nThe total amount received by address \"myaddress\"\n"
3306 + HelpExampleCli("z_getbalance", "\"myaddress\"") +
3307 "\nThe total amount received by address \"myaddress\" at least 5 blocks confirmed\n"
3308 + HelpExampleCli("z_getbalance", "\"myaddress\" 5") +
3309 "\nAs a json rpc call\n"
3310 + HelpExampleRpc("z_getbalance", "\"myaddress\", 5")
3313 LOCK2(cs_main, pwalletMain->cs_wallet);
3316 if (params.size() > 1) {
3317 nMinDepth = params[1].get_int();
3319 if (nMinDepth < 0) {
3320 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3323 // Check that the from address is valid.
3324 auto fromaddress = params[0].get_str();
3325 bool fromTaddr = false;
3326 CTxDestination taddr = DecodeDestination(fromaddress);
3327 fromTaddr = IsValidDestination(taddr);
3329 auto res = DecodePaymentAddress(fromaddress);
3330 if (!IsValidPaymentAddress(res)) {
3331 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3333 // TODO: Add Sapling support. For now, ensure we can freely convert.
3334 assert(boost::get<libzcash::SproutPaymentAddress>(&res) != nullptr);
3335 auto zaddr = boost::get<libzcash::SproutPaymentAddress>(res);
3336 if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
3337 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
3341 CAmount nBalance = 0;
3343 nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
3345 nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
3348 return ValueFromAmount(nBalance);
3352 UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
3354 if (!EnsureWalletIsAvailable(fHelp))
3355 return NullUniValue;
3357 if (fHelp || params.size() > 2)
3358 throw runtime_error(
3359 "z_gettotalbalance ( minconf includeWatchonly )\n"
3360 "\nReturn the total value of funds stored in the node’s wallet.\n"
3361 "\nCAUTION: If the wallet contains watch-only zaddrs, the returned private balance may be larger than the actual balance,"
3362 "\nbecause spends cannot be detected with incoming viewing keys.\n"
3364 "1. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
3365 "2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
3368 " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n"
3369 " \"private\": xxxxx, (numeric) the total balance of private funds\n"
3370 " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n"
3373 "\nThe total amount in the wallet\n"
3374 + HelpExampleCli("z_gettotalbalance", "") +
3375 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
3376 + HelpExampleCli("z_gettotalbalance", "5") +
3377 "\nAs a json rpc call\n"
3378 + HelpExampleRpc("z_gettotalbalance", "5")
3381 LOCK2(cs_main, pwalletMain->cs_wallet);
3384 if (params.size() > 0) {
3385 nMinDepth = params[0].get_int();
3387 if (nMinDepth < 0) {
3388 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3391 bool fIncludeWatchonly = false;
3392 if (params.size() > 1) {
3393 fIncludeWatchonly = params[1].get_bool();
3396 // getbalance and "getbalance * 1 true" should return the same number
3397 // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
3398 // pwalletMain->GetBalance() does not accept min depth parameter
3399 // so we use our own method to get balance of utxos.
3400 CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
3401 CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
3402 CAmount nTotalBalance = nBalance + nPrivateBalance;
3403 UniValue result(UniValue::VOBJ);
3404 result.push_back(Pair("transparent", FormatMoney(nBalance)));
3405 result.push_back(Pair("private", FormatMoney(nPrivateBalance)));
3406 result.push_back(Pair("total", FormatMoney(nTotalBalance)));
3410 UniValue z_getoperationresult(const UniValue& params, bool fHelp)
3412 if (!EnsureWalletIsAvailable(fHelp))
3413 return NullUniValue;
3415 if (fHelp || params.size() > 1)
3416 throw runtime_error(
3417 "z_getoperationresult ([\"operationid\", ... ]) \n"
3418 "\nRetrieve the result and status of an operation which has finished, and then remove the operation from memory."
3419 + HelpRequiringPassphrase() + "\n"
3421 "1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
3423 "\" [object, ...]\" (array) A list of JSON objects\n"
3425 + HelpExampleCli("z_getoperationresult", "'[\"operationid\", ... ]'")
3426 + HelpExampleRpc("z_getoperationresult", "'[\"operationid\", ... ]'")
3429 // This call will remove finished operations
3430 return z_getoperationstatus_IMPL(params, true);
3433 UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
3435 if (!EnsureWalletIsAvailable(fHelp))
3436 return NullUniValue;
3438 if (fHelp || params.size() > 1)
3439 throw runtime_error(
3440 "z_getoperationstatus ([\"operationid\", ... ]) \n"
3441 "\nGet operation status and any associated result or error data. The operation will remain in memory."
3442 + HelpRequiringPassphrase() + "\n"
3444 "1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
3446 "\" [object, ...]\" (array) A list of JSON objects\n"
3448 + HelpExampleCli("z_getoperationstatus", "'[\"operationid\", ... ]'")
3449 + HelpExampleRpc("z_getoperationstatus", "'[\"operationid\", ... ]'")
3452 // This call is idempotent so we don't want to remove finished operations
3453 return z_getoperationstatus_IMPL(params, false);
3456 UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedOperations=false)
3458 LOCK2(cs_main, pwalletMain->cs_wallet);
3460 std::set<AsyncRPCOperationId> filter;
3461 if (params.size()==1) {
3462 UniValue ids = params[0].get_array();
3463 for (const UniValue & v : ids.getValues()) {
3464 filter.insert(v.get_str());
3467 bool useFilter = (filter.size()>0);
3469 UniValue ret(UniValue::VARR);
3470 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3471 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
3473 for (auto id : ids) {
3474 if (useFilter && !filter.count(id))
3477 std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
3480 // It's possible that the operation was removed from the internal queue and map during this loop
3481 // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id.");
3484 UniValue obj = operation->getStatus();
3485 std::string s = obj["status"].get_str();
3486 if (fRemoveFinishedOperations) {
3487 // Caller is only interested in retrieving finished results
3488 if ("success"==s || "failed"==s || "cancelled"==s) {
3490 q->popOperationForId(id);
3497 std::vector<UniValue> arrTmp = ret.getValues();
3499 // sort results chronologically by creation_time
3500 std::sort(arrTmp.begin(), arrTmp.end(), [](UniValue a, UniValue b) -> bool {
3501 const int64_t t1 = find_value(a.get_obj(), "creation_time").get_int64();
3502 const int64_t t2 = find_value(b.get_obj(), "creation_time").get_int64();
3508 ret.push_backV(arrTmp);
3514 // JSDescription size depends on the transaction version
3515 #define V3_JS_DESCRIPTION_SIZE (GetSerializeSize(JSDescription(), SER_NETWORK, (OVERWINTER_TX_VERSION | (1 << 31))))
3516 // Here we define the maximum number of zaddr outputs that can be included in a transaction.
3517 // If input notes are small, we might actually require more than one joinsplit per zaddr output.
3518 // For now though, we assume we use one joinsplit per zaddr output (and the second output note is change).
3519 // We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data.
3520 #define Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING ((MAX_TX_SIZE_BEFORE_SAPLING / V3_JS_DESCRIPTION_SIZE) - 1)
3522 // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes
3523 #define CTXIN_SPEND_DUST_SIZE 148
3524 #define CTXOUT_REGULAR_SIZE 34
3526 UniValue z_sendmany(const UniValue& params, bool fHelp)
3528 if (!EnsureWalletIsAvailable(fHelp))
3529 return NullUniValue;
3531 if (fHelp || params.size() < 2 || params.size() > 4)
3532 throw runtime_error(
3533 "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
3534 "\nSend multiple times. Amounts are double-precision floating point numbers."
3535 "\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself."
3536 "\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
3537 + 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)
3538 + HelpRequiringPassphrase() + "\n"
3540 "1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n"
3541 "2. \"amounts\" (array, required) An array of json objects representing the amounts to send.\n"
3543 " \"address\":address (string, required) The address is a taddr or zaddr\n"
3544 " \"amount\":amount (numeric, required) The numeric amount in " + CURRENCY_UNIT + " is the value\n"
3545 " \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
3547 "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
3548 "4. fee (numeric, optional, default="
3549 + strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
3551 "\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
3553 + HelpExampleCli("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
3554 + HelpExampleRpc("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
3557 LOCK2(cs_main, pwalletMain->cs_wallet);
3559 // Check that the from address is valid.
3560 auto fromaddress = params[0].get_str();
3561 bool fromTaddr = false;
3562 CTxDestination taddr = DecodeDestination(fromaddress);
3563 fromTaddr = IsValidDestination(taddr);
3564 libzcash::SproutPaymentAddress zaddr;
3566 auto res = DecodePaymentAddress(fromaddress);
3567 if (!IsValidPaymentAddress(res)) {
3569 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
3571 // TODO: Add Sapling support. For now, ensure we can freely convert.
3572 assert(boost::get<libzcash::SproutPaymentAddress>(&res) != nullptr);
3573 zaddr = boost::get<libzcash::SproutPaymentAddress>(res);
3576 // Check that we have the spending key
3578 if (!pwalletMain->HaveSpendingKey(zaddr)) {
3579 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
3583 UniValue outputs = params[1].get_array();
3585 if (outputs.size()==0)
3586 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty.");
3588 // Keep track of addresses to spot duplicates
3589 set<std::string> setAddress;
3592 std::vector<SendManyRecipient> taddrRecipients;
3593 std::vector<SendManyRecipient> zaddrRecipients;
3594 CAmount nTotalOut = 0;
3596 for (const UniValue& o : outputs.getValues()) {
3598 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
3600 // sanity check, report error if unknown key-value pairs
3601 for (const string& name_ : o.getKeys()) {
3602 std::string s = name_;
3603 if (s != "address" && s != "amount" && s!="memo")
3604 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown key: ")+s);
3607 string address = find_value(o, "address").get_str();
3608 bool isZaddr = false;
3609 CTxDestination taddr = DecodeDestination(address);
3610 if (!IsValidDestination(taddr)) {
3611 if (IsValidPaymentAddressString(address)) {
3614 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
3618 if (setAddress.count(address))
3619 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+address);
3620 setAddress.insert(address);
3622 UniValue memoValue = find_value(o, "memo");
3624 if (!memoValue.isNull()) {
3625 memo = memoValue.get_str();
3627 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo cannot be used with a taddr. It can only be used with a zaddr.");
3628 } else if (!IsHex(memo)) {
3629 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
3631 if (memo.length() > ZC_MEMO_SIZE*2) {
3632 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
3636 UniValue av = find_value(o, "amount");
3637 CAmount nAmount = AmountFromValue( av );
3639 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");
3642 zaddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3644 taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
3647 nTotalOut += nAmount;
3650 int nextBlockHeight = chainActive.Height() + 1;
3651 CMutableTransaction mtx;
3652 mtx.fOverwintered = true;
3653 mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
3654 mtx.nVersion = SAPLING_TX_VERSION;
3655 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
3656 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
3657 if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
3658 mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
3659 mtx.nVersion = OVERWINTER_TX_VERSION;
3661 mtx.fOverwintered = false;
3665 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
3667 // Check the number of zaddr outputs does not exceed the limit.
3668 if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING) {
3669 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs");
3673 // As a sanity check, estimate and verify that the size of the transaction will be valid.
3674 // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
3676 for (int i = 0; i < zaddrRecipients.size(); i++) {
3677 // TODO Check whether the recipient is a Sprout or Sapling address
3678 JSDescription jsdesc;
3680 if (mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)) {
3681 jsdesc.proof = GrothProof();
3684 mtx.vjoinsplit.push_back(jsdesc);
3686 CTransaction tx(mtx);
3687 txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
3689 txsize += CTXIN_SPEND_DUST_SIZE;
3690 txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change
3692 txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size();
3693 if (txsize > max_tx_size) {
3694 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", max_tx_size ));
3697 // Minimum confirmations
3699 if (params.size() > 2) {
3700 nMinDepth = params[2].get_int();
3702 if (nMinDepth < 0) {
3703 throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
3706 // Fee in Zatoshis, not currency format)
3707 CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
3708 CAmount nDefaultFee = nFee;
3710 if (params.size() > 3) {
3711 if (params[3].get_real() == 0.0) {
3714 nFee = AmountFromValue( params[3] );
3717 // Check that the user specified fee is not absurd.
3718 // This allows amount=0 (and all amount < nDefaultFee) transactions to use the default network fee
3719 // or anything less than nDefaultFee instead of being forced to use a custom fee and leak metadata
3720 if (nTotalOut < nDefaultFee) {
3721 if (nFee > nDefaultFee) {
3722 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)));
3725 // Check that the user specified fee is not absurd.
3726 if (nFee > nTotalOut) {
3727 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)));
3732 // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
3733 UniValue o(UniValue::VOBJ);
3734 o.push_back(Pair("fromaddress", params[0]));
3735 o.push_back(Pair("amounts", params[1]));
3736 o.push_back(Pair("minconf", nMinDepth));
3737 o.push_back(Pair("fee", std::stod(FormatMoney(nFee))));
3738 UniValue contextInfo = o;
3740 // Contextual transaction we will build on
3741 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
3742 bool isShielded = !fromTaddr || zaddrRecipients.size() > 0;
3743 if (contextualTx.nVersion == 1 && isShielded) {
3744 contextualTx.nVersion = 2; // Tx format should support vjoinsplits
3747 // Create operation and add to global queue
3748 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3749 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
3750 q->addOperation(operation);
3751 AsyncRPCOperationId operationId = operation->getId();
3757 When estimating the number of coinbase utxos we can shield in a single transaction:
3758 1. Joinsplit description is 1802 bytes.
3759 2. Transaction overhead ~ 100 bytes
3760 3. Spending a typical P2PKH is >=148 bytes, as defined in CTXIN_SPEND_DUST_SIZE.
3761 4. Spending a multi-sig P2SH address can vary greatly:
3762 https://github.com/bitcoin/bitcoin/blob/c3ad56f4e0b587d8d763af03d743fdfc2d180c9b/src/main.cpp#L517
3763 In real-world coinbase utxos, we consider a 3-of-3 multisig, where the size is roughly:
3764 (3*(33+1))+3 = 105 byte redeem script
3765 105 + 1 + 3*(73+1) = 328 bytes of scriptSig, rounded up to 400 based on testnet experiments.
3767 #define CTXIN_SPEND_P2SH_SIZE 400
3769 #define SHIELD_COINBASE_DEFAULT_LIMIT 50
3771 UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
3773 if (!EnsureWalletIsAvailable(fHelp))
3774 return NullUniValue;
3776 if (fHelp || params.size() < 2 || params.size() > 4)
3777 throw runtime_error(
3778 "z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n"
3779 "\nShield transparent coinbase funds by sending to a shielded zaddr. This is an asynchronous operation and utxos"
3780 "\nselected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent`"
3781 "\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding can be limited"
3782 "\nby the caller. If the limit parameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit"
3783 "\noption will determine the number of uxtos. Any limit is constrained by the consensus rule defining a maximum"
3784 "\ntransaction size of "
3785 + strprintf("%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
3786 + HelpRequiringPassphrase() + "\n"
3788 "1. \"fromaddress\" (string, required) The address is a taddr or \"*\" for all taddrs belonging to the wallet.\n"
3789 "2. \"toaddress\" (string, required) The address is a zaddr.\n"
3790 "3. fee (numeric, optional, default="
3791 + strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
3792 "4. limit (numeric, optional, default="
3793 + 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"
3796 " \"remainingUTXOs\": xxx (numeric) Number of coinbase utxos still available for shielding.\n"
3797 " \"remainingValue\": xxx (numeric) Value of coinbase utxos still available for shielding.\n"
3798 " \"shieldingUTXOs\": xxx (numeric) Number of coinbase utxos being shielded.\n"
3799 " \"shieldingValue\": xxx (numeric) Value of coinbase utxos being shielded.\n"
3800 " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
3803 + HelpExampleCli("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3804 + HelpExampleRpc("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
3807 LOCK2(cs_main, pwalletMain->cs_wallet);
3809 // Validate the from address
3810 auto fromaddress = params[0].get_str();
3811 bool isFromWildcard = fromaddress == "*";
3812 CTxDestination taddr;
3813 if (!isFromWildcard) {
3814 taddr = DecodeDestination(fromaddress);
3815 if (!IsValidDestination(taddr)) {
3816 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
3820 // Validate the destination address
3821 auto destaddress = params[1].get_str();
3822 if (!IsValidPaymentAddressString(destaddress)) {
3823 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
3826 // Convert fee from currency format to zatoshis
3827 CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
3828 if (params.size() > 2) {
3829 if (params[2].get_real() == 0.0) {
3832 nFee = AmountFromValue( params[2] );
3836 int nLimit = SHIELD_COINBASE_DEFAULT_LIMIT;
3837 if (params.size() > 3) {
3838 nLimit = params[3].get_int();
3840 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of utxos cannot be negative");
3844 int nextBlockHeight = chainActive.Height() + 1;
3845 bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
3846 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
3847 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
3848 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
3851 // Prepare to get coinbase utxos
3852 std::vector<ShieldCoinbaseUTXO> inputs;
3853 CAmount shieldedValue = 0;
3854 CAmount remainingValue = 0;
3855 size_t estimatedTxSize = 2000; // 1802 joinsplit description + tx overhead + wiggle room
3856 size_t utxoCounter = 0;
3857 bool maxedOutFlag = false;
3858 size_t mempoolLimit = (nLimit != 0) ? nLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
3860 // Set of addresses to filter utxos by
3861 std::set<CTxDestination> destinations = {};
3862 if (!isFromWildcard) {
3863 destinations.insert(taddr);
3866 // Get available utxos
3867 vector<COutput> vecOutputs;
3868 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true);
3870 // Find unspent coinbase utxos and update estimated size
3871 BOOST_FOREACH(const COutput& out, vecOutputs) {
3872 if (!out.fSpendable) {
3876 CTxDestination address;
3877 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
3880 // If taddr is not wildcard "*", filter utxos
3881 if (destinations.size() > 0 && !destinations.count(address)) {
3885 if (!out.tx->IsCoinBase()) {
3890 CAmount nValue = out.tx->vout[out.i].nValue;
3892 if (!maxedOutFlag) {
3893 size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
3894 if (estimatedTxSize + increase >= max_tx_size ||
3895 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
3897 maxedOutFlag = true;
3899 estimatedTxSize += increase;
3900 ShieldCoinbaseUTXO utxo = {out.tx->GetHash(), out.i, nValue};
3901 inputs.push_back(utxo);
3902 shieldedValue += nValue;
3907 remainingValue += nValue;
3911 size_t numUtxos = inputs.size();
3913 if (numUtxos == 0) {
3914 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase funds to shield.");
3917 if (shieldedValue < nFee) {
3918 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
3919 strprintf("Insufficient coinbase funds, have %s, which is less than miners fee %s",
3920 FormatMoney(shieldedValue), FormatMoney(nFee)));
3923 // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
3924 CAmount netAmount = shieldedValue - nFee;
3925 if (nFee > netAmount) {
3926 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
3929 // Keep record of parameters in context object
3930 UniValue contextInfo(UniValue::VOBJ);
3931 contextInfo.push_back(Pair("fromaddress", params[0]));
3932 contextInfo.push_back(Pair("toaddress", params[1]));
3933 contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
3935 // Contextual transaction we will build on
3936 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
3937 Params().GetConsensus(), nextBlockHeight);
3938 if (contextualTx.nVersion == 1) {
3939 contextualTx.nVersion = 2; // Tx format should support vjoinsplits
3942 // Create operation and add to global queue
3943 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
3944 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(contextualTx, inputs, destaddress, nFee, contextInfo) );
3945 q->addOperation(operation);
3946 AsyncRPCOperationId operationId = operation->getId();
3948 // Return continuation information
3949 UniValue o(UniValue::VOBJ);
3950 o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
3951 o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue)));
3952 o.push_back(Pair("shieldingUTXOs", static_cast<uint64_t>(numUtxos)));
3953 o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
3954 o.push_back(Pair("opid", operationId));
3959 #define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
3960 #define MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT 10
3962 #define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)
3964 UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
3966 if (!EnsureWalletIsAvailable(fHelp))
3967 return NullUniValue;
3969 string enableArg = "zmergetoaddress";
3970 auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, false);
3971 std::string strDisabledMsg = "";
3972 if (!fEnableMergeToAddress) {
3973 strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
3976 if (fHelp || params.size() < 2 || params.size() > 6)
3977 throw runtime_error(
3978 "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
3980 "\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
3981 "\nto combine those into a single note."
3982 "\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
3983 "\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
3984 "\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
3985 "\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
3986 "\nnumber of UTXOs. Any limit is constrained by the consensus rule defining a maximum transaction size of"
3987 + strprintf("\n%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
3988 + HelpRequiringPassphrase() + "\n"
3990 "1. fromaddresses (string, required) A JSON array with addresses.\n"
3991 " The following special strings are accepted inside the array:\n"
3992 " - \"*\": Merge both UTXOs and notes from all addresses belonging to the wallet.\n"
3993 " - \"ANY_TADDR\": Merge UTXOs from all t-addrs belonging to the wallet.\n"
3994 " - \"ANY_ZADDR\": Merge notes from all z-addrs belonging to the wallet.\n"
3995 " If a special string is given, any given addresses of that type will be ignored.\n"
3997 " \"address\" (string) Can be a t-addr or a z-addr\n"
4000 "2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
4001 "3. fee (numeric, optional, default="
4002 + strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
4003 "4. transparent_limit (numeric, optional, default="
4004 + 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"
4005 "4. shielded_limit (numeric, optional, default="
4006 + strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
4007 "5. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
4010 " \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
4011 " \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
4012 " \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
4013 " \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
4014 " \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
4015 " \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
4016 " \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
4017 " \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
4018 " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
4021 + HelpExampleCli("z_mergetoaddress", "'[\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
4022 + HelpExampleRpc("z_mergetoaddress", "[\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
4025 if (!fEnableMergeToAddress) {
4026 throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
4029 LOCK2(cs_main, pwalletMain->cs_wallet);
4031 bool useAny = false;
4032 bool useAnyUTXO = false;
4033 bool useAnyNote = false;
4034 std::set<CTxDestination> taddrs = {};
4035 std::set<libzcash::PaymentAddress> zaddrs = {};
4037 UniValue addresses = params[0].get_array();
4038 if (addresses.size()==0)
4039 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
4041 // Keep track of addresses to spot duplicates
4042 std::set<std::string> setAddress;
4045 for (const UniValue& o : addresses.getValues()) {
4047 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
4049 std::string address = o.get_str();
4050 if (address == "*") {
4052 } else if (address == "ANY_TADDR") {
4054 } else if (address == "ANY_ZADDR") {
4057 CTxDestination taddr = DecodeDestination(address);
4058 if (IsValidDestination(taddr)) {
4059 // Ignore any listed t-addrs if we are using all of them
4060 if (!(useAny || useAnyUTXO)) {
4061 taddrs.insert(taddr);
4064 auto zaddr = DecodePaymentAddress(address);
4065 if (IsValidPaymentAddress(zaddr)) {
4066 // Ignore listed z-addrs if we are using all of them
4067 if (!(useAny || useAnyNote)) {
4068 zaddrs.insert(zaddr);
4072 RPC_INVALID_PARAMETER,
4073 string("Invalid parameter, unknown address format: ") + address);
4078 if (setAddress.count(address))
4079 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
4080 setAddress.insert(address);
4083 // Validate the destination address
4084 auto destaddress = params[1].get_str();
4085 bool isToZaddr = false;
4086 CTxDestination taddr = DecodeDestination(destaddress);
4087 if (!IsValidDestination(taddr)) {
4088 if (IsValidPaymentAddressString(destaddress)) {
4091 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
4095 // Convert fee from currency format to zatoshis
4096 CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
4097 if (params.size() > 2) {
4098 if (params[2].get_real() == 0.0) {
4101 nFee = AmountFromValue( params[2] );
4105 int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
4106 if (params.size() > 3) {
4107 nUTXOLimit = params[3].get_int();
4108 if (nUTXOLimit < 0) {
4109 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
4113 int nNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT;
4114 if (params.size() > 4) {
4115 nNoteLimit = params[4].get_int();
4116 if (nNoteLimit < 0) {
4117 throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
4122 if (params.size() > 5) {
4123 memo = params[5].get_str();
4125 throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr.");
4126 } else if (!IsHex(memo)) {
4127 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
4129 if (memo.length() > ZC_MEMO_SIZE*2) {
4130 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
4134 MergeToAddressRecipient recipient(destaddress, memo);
4136 int nextBlockHeight = chainActive.Height() + 1;
4137 bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
4138 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
4139 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
4140 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
4143 // Prepare to get UTXOs and notes
4144 std::vector<MergeToAddressInputUTXO> utxoInputs;
4145 std::vector<MergeToAddressInputNote> noteInputs;
4146 CAmount mergedUTXOValue = 0;
4147 CAmount mergedNoteValue = 0;
4148 CAmount remainingUTXOValue = 0;
4149 CAmount remainingNoteValue = 0;
4150 size_t utxoCounter = 0;
4151 size_t noteCounter = 0;
4152 bool maxedOutUTXOsFlag = false;
4153 bool maxedOutNotesFlag = false;
4154 size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
4156 size_t estimatedTxSize = 200; // tx overhead + wiggle room
4158 estimatedTxSize += JOINSPLIT_SIZE;
4161 if (useAny || useAnyUTXO || taddrs.size() > 0) {
4162 // Get available utxos
4163 vector<COutput> vecOutputs;
4164 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
4166 // Find unspent utxos and update estimated size
4167 for (const COutput& out : vecOutputs) {
4168 if (!out.fSpendable) {
4172 CTxDestination address;
4173 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
4176 // If taddr is not wildcard "*", filter utxos
4177 if (taddrs.size() > 0 && !taddrs.count(address)) {
4182 CAmount nValue = out.tx->vout[out.i].nValue;
4184 if (!maxedOutUTXOsFlag) {
4185 size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
4186 if (estimatedTxSize + increase >= max_tx_size ||
4187 (mempoolLimit > 0 && utxoCounter > mempoolLimit))
4189 maxedOutUTXOsFlag = true;
4191 estimatedTxSize += increase;
4192 COutPoint utxo(out.tx->GetHash(), out.i);
4193 utxoInputs.emplace_back(utxo, nValue);
4194 mergedUTXOValue += nValue;
4198 if (maxedOutUTXOsFlag) {
4199 remainingUTXOValue += nValue;
4204 if (useAny || useAnyNote || zaddrs.size() > 0) {
4205 // Get available notes
4206 std::vector<CSproutNotePlaintextEntry> entries;
4207 pwalletMain->GetFilteredNotes(entries, zaddrs);
4209 // Find unspent notes and update estimated size
4210 for (CSproutNotePlaintextEntry& entry : entries) {
4212 CAmount nValue = entry.plaintext.value();
4214 if (!maxedOutNotesFlag) {
4215 // If we haven't added any notes yet and the merge is to a
4216 // z-address, we have already accounted for the first JoinSplit.
4217 size_t increase = (noteInputs.empty() && !isToZaddr) || (noteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
4218 if (estimatedTxSize + increase >= max_tx_size ||
4219 (nNoteLimit > 0 && noteCounter > nNoteLimit))
4221 maxedOutNotesFlag = true;
4223 estimatedTxSize += increase;
4224 // TODO: Add Sapling support
4225 auto zaddr = boost::get<SproutPaymentAddress>(entry.address);
4226 SproutSpendingKey zkey;
4227 pwalletMain->GetSpendingKey(zaddr, zkey);
4228 noteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey);
4229 mergedNoteValue += nValue;
4233 if (maxedOutNotesFlag) {
4234 remainingNoteValue += nValue;
4239 size_t numUtxos = utxoInputs.size();
4240 size_t numNotes = noteInputs.size();
4242 if (numUtxos == 0 && numNotes == 0) {
4243 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
4246 // Sanity check: Don't do anything if:
4247 // - We only have one from address
4248 // - It's equal to toaddress
4249 // - The address only contains a single UTXO or note
4250 if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
4251 throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
4254 CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
4255 if (mergedValue < nFee) {
4256 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
4257 strprintf("Insufficient funds, have %s, which is less than miners fee %s",
4258 FormatMoney(mergedValue), FormatMoney(nFee)));
4261 // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
4262 CAmount netAmount = mergedValue - nFee;
4263 if (nFee > netAmount) {
4264 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
4267 // Keep record of parameters in context object
4268 UniValue contextInfo(UniValue::VOBJ);
4269 contextInfo.push_back(Pair("fromaddresses", params[0]));
4270 contextInfo.push_back(Pair("toaddress", params[1]));
4271 contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
4273 // Contextual transaction we will build on
4274 CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
4275 Params().GetConsensus(),
4277 bool isShielded = numNotes > 0 || isToZaddr;
4278 if (contextualTx.nVersion == 1 && isShielded) {
4279 contextualTx.nVersion = 2; // Tx format should support vjoinsplit
4282 // Create operation and add to global queue
4283 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4284 std::shared_ptr<AsyncRPCOperation> operation(
4285 new AsyncRPCOperation_mergetoaddress(contextualTx, utxoInputs, noteInputs, recipient, nFee, contextInfo) );
4286 q->addOperation(operation);
4287 AsyncRPCOperationId operationId = operation->getId();
4289 // Return continuation information
4290 UniValue o(UniValue::VOBJ);
4291 o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
4292 o.push_back(Pair("remainingTransparentValue", ValueFromAmount(remainingUTXOValue)));
4293 o.push_back(Pair("remainingNotes", static_cast<uint64_t>(noteCounter - numNotes)));
4294 o.push_back(Pair("remainingShieldedValue", ValueFromAmount(remainingNoteValue)));
4295 o.push_back(Pair("mergingUTXOs", static_cast<uint64_t>(numUtxos)));
4296 o.push_back(Pair("mergingTransparentValue", ValueFromAmount(mergedUTXOValue)));
4297 o.push_back(Pair("mergingNotes", static_cast<uint64_t>(numNotes)));
4298 o.push_back(Pair("mergingShieldedValue", ValueFromAmount(mergedNoteValue)));
4299 o.push_back(Pair("opid", operationId));
4304 UniValue z_listoperationids(const UniValue& params, bool fHelp)
4306 if (!EnsureWalletIsAvailable(fHelp))
4307 return NullUniValue;
4309 if (fHelp || params.size() > 1)
4310 throw runtime_error(
4311 "z_listoperationids\n"
4312 "\nReturns the list of operation ids currently known to the wallet.\n"
4314 "1. \"status\" (string, optional) Filter result by the operation's state e.g. \"success\".\n"
4316 "[ (json array of string)\n"
4317 " \"operationid\" (string) an operation id belonging to the wallet\n"
4321 + HelpExampleCli("z_listoperationids", "")
4322 + HelpExampleRpc("z_listoperationids", "")
4325 LOCK2(cs_main, pwalletMain->cs_wallet);
4328 bool useFilter = false;
4329 if (params.size()==1) {
4330 filter = params[0].get_str();
4334 UniValue ret(UniValue::VARR);
4335 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
4336 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
4337 for (auto id : ids) {
4338 std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
4342 std::string state = operation->getStateAsString();
4343 if (useFilter && filter.compare(state)!=0)