[wallet] getreceivedbyaddress should return error if address is not mine
[bitcoinplatinum.git] / src / wallet / rpcwallet.cpp
blob8abb4c9a25746a51e2651b2154e61a04729978a9
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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.
6 #include "amount.h"
7 #include "base58.h"
8 #include "chain.h"
9 #include "consensus/validation.h"
10 #include "core_io.h"
11 #include "httpserver.h"
12 #include "validation.h"
13 #include "net.h"
14 #include "policy/feerate.h"
15 #include "policy/fees.h"
16 #include "policy/policy.h"
17 #include "policy/rbf.h"
18 #include "rpc/mining.h"
19 #include "rpc/safemode.h"
20 #include "rpc/server.h"
21 #include "script/sign.h"
22 #include "timedata.h"
23 #include "util.h"
24 #include "utilmoneystr.h"
25 #include "wallet/coincontrol.h"
26 #include "wallet/feebumper.h"
27 #include "wallet/wallet.h"
28 #include "wallet/walletdb.h"
30 #include <init.h> // For StartShutdown
32 #include <stdint.h>
34 #include <univalue.h>
36 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
38 CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
40 if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
41 // wallet endpoint was used
42 std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
43 for (CWalletRef pwallet : ::vpwallets) {
44 if (pwallet->GetName() == requestedWallet) {
45 return pwallet;
48 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
50 return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr;
53 std::string HelpRequiringPassphrase(CWallet * const pwallet)
55 return pwallet && pwallet->IsCrypted()
56 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
57 : "";
60 bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
62 if (pwallet) return true;
63 if (avoidException) return false;
64 if (::vpwallets.empty()) {
65 // Note: It isn't currently possible to trigger this error because
66 // wallet RPC methods aren't registered unless a wallet is loaded. But
67 // this error is being kept as a precaution, because it's possible in
68 // the future that wallet RPC methods might get or remain registered
69 // when no wallets are loaded.
70 throw JSONRPCError(
71 RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
73 throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED,
74 "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
77 void EnsureWalletIsUnlocked(CWallet * const pwallet)
79 if (pwallet->IsLocked()) {
80 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
84 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
86 int confirms = wtx.GetDepthInMainChain();
87 entry.push_back(Pair("confirmations", confirms));
88 if (wtx.IsCoinBase())
89 entry.push_back(Pair("generated", true));
90 if (confirms > 0)
92 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
93 entry.push_back(Pair("blockindex", wtx.nIndex));
94 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
95 } else {
96 entry.push_back(Pair("trusted", wtx.IsTrusted()));
98 uint256 hash = wtx.GetHash();
99 entry.push_back(Pair("txid", hash.GetHex()));
100 UniValue conflicts(UniValue::VARR);
101 for (const uint256& conflict : wtx.GetConflicts())
102 conflicts.push_back(conflict.GetHex());
103 entry.push_back(Pair("walletconflicts", conflicts));
104 entry.push_back(Pair("time", wtx.GetTxTime()));
105 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
107 // Add opt-in RBF status
108 std::string rbfStatus = "no";
109 if (confirms <= 0) {
110 LOCK(mempool.cs);
111 RBFTransactionState rbfState = IsRBFOptIn(*wtx.tx, mempool);
112 if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
113 rbfStatus = "unknown";
114 else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
115 rbfStatus = "yes";
117 entry.push_back(Pair("bip125-replaceable", rbfStatus));
119 for (const std::pair<std::string, std::string>& item : wtx.mapValue)
120 entry.push_back(Pair(item.first, item.second));
123 std::string AccountFromValue(const UniValue& value)
125 std::string strAccount = value.get_str();
126 if (strAccount == "*")
127 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
128 return strAccount;
131 UniValue getnewaddress(const JSONRPCRequest& request)
133 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
134 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
135 return NullUniValue;
138 if (request.fHelp || request.params.size() > 1)
139 throw std::runtime_error(
140 "getnewaddress ( \"account\" )\n"
141 "\nReturns a new Bitcoin address for receiving payments.\n"
142 "If 'account' is specified (DEPRECATED), it is added to the address book \n"
143 "so payments received with the address will be credited to 'account'.\n"
144 "\nArguments:\n"
145 "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
146 "\nResult:\n"
147 "\"address\" (string) The new bitcoin address\n"
148 "\nExamples:\n"
149 + HelpExampleCli("getnewaddress", "")
150 + HelpExampleRpc("getnewaddress", "")
153 LOCK2(cs_main, pwallet->cs_wallet);
155 // Parse the account first so we don't generate a key if there's an error
156 std::string strAccount;
157 if (!request.params[0].isNull())
158 strAccount = AccountFromValue(request.params[0]);
160 if (!pwallet->IsLocked()) {
161 pwallet->TopUpKeyPool();
164 // Generate a new key that is added to wallet
165 CPubKey newKey;
166 if (!pwallet->GetKeyFromPool(newKey)) {
167 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
169 CKeyID keyID = newKey.GetID();
171 pwallet->SetAddressBook(keyID, strAccount, "receive");
173 return EncodeDestination(keyID);
177 CTxDestination GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false)
179 CPubKey pubKey;
180 if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
181 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
184 return pubKey.GetID();
187 UniValue getaccountaddress(const JSONRPCRequest& request)
189 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
190 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
191 return NullUniValue;
194 if (request.fHelp || request.params.size() != 1)
195 throw std::runtime_error(
196 "getaccountaddress \"account\"\n"
197 "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
198 "\nArguments:\n"
199 "1. \"account\" (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
200 "\nResult:\n"
201 "\"address\" (string) The account bitcoin address\n"
202 "\nExamples:\n"
203 + HelpExampleCli("getaccountaddress", "")
204 + HelpExampleCli("getaccountaddress", "\"\"")
205 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
206 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
209 LOCK2(cs_main, pwallet->cs_wallet);
211 // Parse the account first so we don't generate a key if there's an error
212 std::string strAccount = AccountFromValue(request.params[0]);
214 UniValue ret(UniValue::VSTR);
216 ret = EncodeDestination(GetAccountAddress(pwallet, strAccount));
217 return ret;
221 UniValue getrawchangeaddress(const JSONRPCRequest& request)
223 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
224 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
225 return NullUniValue;
228 if (request.fHelp || request.params.size() > 0)
229 throw std::runtime_error(
230 "getrawchangeaddress\n"
231 "\nReturns a new Bitcoin address, for receiving change.\n"
232 "This is for use with raw transactions, NOT normal use.\n"
233 "\nResult:\n"
234 "\"address\" (string) The address\n"
235 "\nExamples:\n"
236 + HelpExampleCli("getrawchangeaddress", "")
237 + HelpExampleRpc("getrawchangeaddress", "")
240 LOCK2(cs_main, pwallet->cs_wallet);
242 if (!pwallet->IsLocked()) {
243 pwallet->TopUpKeyPool();
246 CReserveKey reservekey(pwallet);
247 CPubKey vchPubKey;
248 if (!reservekey.GetReservedKey(vchPubKey, true))
249 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
251 reservekey.KeepKey();
253 CKeyID keyID = vchPubKey.GetID();
255 return EncodeDestination(keyID);
259 UniValue setaccount(const JSONRPCRequest& request)
261 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
262 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
263 return NullUniValue;
266 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
267 throw std::runtime_error(
268 "setaccount \"address\" \"account\"\n"
269 "\nDEPRECATED. Sets the account associated with the given address.\n"
270 "\nArguments:\n"
271 "1. \"address\" (string, required) The bitcoin address to be associated with an account.\n"
272 "2. \"account\" (string, required) The account to assign the address to.\n"
273 "\nExamples:\n"
274 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
275 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
278 LOCK2(cs_main, pwallet->cs_wallet);
280 CTxDestination dest = DecodeDestination(request.params[0].get_str());
281 if (!IsValidDestination(dest)) {
282 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
285 std::string strAccount;
286 if (!request.params[1].isNull())
287 strAccount = AccountFromValue(request.params[1]);
289 // Only add the account if the address is yours.
290 if (IsMine(*pwallet, dest)) {
291 // Detect when changing the account of an address that is the 'unused current key' of another account:
292 if (pwallet->mapAddressBook.count(dest)) {
293 std::string strOldAccount = pwallet->mapAddressBook[dest].name;
294 if (dest == GetAccountAddress(pwallet, strOldAccount)) {
295 GetAccountAddress(pwallet, strOldAccount, true);
298 pwallet->SetAddressBook(dest, strAccount, "receive");
300 else
301 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
303 return NullUniValue;
307 UniValue getaccount(const JSONRPCRequest& request)
309 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
310 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
311 return NullUniValue;
314 if (request.fHelp || request.params.size() != 1)
315 throw std::runtime_error(
316 "getaccount \"address\"\n"
317 "\nDEPRECATED. Returns the account associated with the given address.\n"
318 "\nArguments:\n"
319 "1. \"address\" (string, required) The bitcoin address for account lookup.\n"
320 "\nResult:\n"
321 "\"accountname\" (string) the account address\n"
322 "\nExamples:\n"
323 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
324 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
327 LOCK2(cs_main, pwallet->cs_wallet);
329 CTxDestination dest = DecodeDestination(request.params[0].get_str());
330 if (!IsValidDestination(dest)) {
331 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
334 std::string strAccount;
335 std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
336 if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) {
337 strAccount = (*mi).second.name;
339 return strAccount;
343 UniValue getaddressesbyaccount(const JSONRPCRequest& request)
345 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
346 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
347 return NullUniValue;
350 if (request.fHelp || request.params.size() != 1)
351 throw std::runtime_error(
352 "getaddressesbyaccount \"account\"\n"
353 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
354 "\nArguments:\n"
355 "1. \"account\" (string, required) The account name.\n"
356 "\nResult:\n"
357 "[ (json array of string)\n"
358 " \"address\" (string) a bitcoin address associated with the given account\n"
359 " ,...\n"
360 "]\n"
361 "\nExamples:\n"
362 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
363 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
366 LOCK2(cs_main, pwallet->cs_wallet);
368 std::string strAccount = AccountFromValue(request.params[0]);
370 // Find all addresses that have the given account
371 UniValue ret(UniValue::VARR);
372 for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
373 const CTxDestination& dest = item.first;
374 const std::string& strName = item.second.name;
375 if (strName == strAccount) {
376 ret.push_back(EncodeDestination(dest));
379 return ret;
382 static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, const CCoinControl& coin_control)
384 CAmount curBalance = pwallet->GetBalance();
386 // Check amount
387 if (nValue <= 0)
388 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
390 if (nValue > curBalance)
391 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
393 if (pwallet->GetBroadcastTransactions() && !g_connman) {
394 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
397 // Parse Bitcoin address
398 CScript scriptPubKey = GetScriptForDestination(address);
400 // Create and send the transaction
401 CReserveKey reservekey(pwallet);
402 CAmount nFeeRequired;
403 std::string strError;
404 std::vector<CRecipient> vecSend;
405 int nChangePosRet = -1;
406 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
407 vecSend.push_back(recipient);
408 if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
409 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
410 strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
411 throw JSONRPCError(RPC_WALLET_ERROR, strError);
413 CValidationState state;
414 if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
415 strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
416 throw JSONRPCError(RPC_WALLET_ERROR, strError);
420 UniValue sendtoaddress(const JSONRPCRequest& request)
422 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
423 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
424 return NullUniValue;
427 if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
428 throw std::runtime_error(
429 "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount replaceable conf_target \"estimate_mode\")\n"
430 "\nSend an amount to a given address.\n"
431 + HelpRequiringPassphrase(pwallet) +
432 "\nArguments:\n"
433 "1. \"address\" (string, required) The bitcoin address to send to.\n"
434 "2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
435 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
436 " This is not part of the transaction, just kept in your wallet.\n"
437 "4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n"
438 " to which you're sending the transaction. This is not part of the \n"
439 " transaction, just kept in your wallet.\n"
440 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
441 " The recipient will receive less bitcoins than you enter in the amount field.\n"
442 "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
443 "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
444 "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
445 " \"UNSET\"\n"
446 " \"ECONOMICAL\"\n"
447 " \"CONSERVATIVE\"\n"
448 "\nResult:\n"
449 "\"txid\" (string) The transaction id.\n"
450 "\nExamples:\n"
451 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
452 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
453 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
454 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
457 ObserveSafeMode();
458 LOCK2(cs_main, pwallet->cs_wallet);
460 CTxDestination dest = DecodeDestination(request.params[0].get_str());
461 if (!IsValidDestination(dest)) {
462 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
465 // Amount
466 CAmount nAmount = AmountFromValue(request.params[1]);
467 if (nAmount <= 0)
468 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
470 // Wallet comments
471 CWalletTx wtx;
472 if (!request.params[2].isNull() && !request.params[2].get_str().empty())
473 wtx.mapValue["comment"] = request.params[2].get_str();
474 if (!request.params[3].isNull() && !request.params[3].get_str().empty())
475 wtx.mapValue["to"] = request.params[3].get_str();
477 bool fSubtractFeeFromAmount = false;
478 if (!request.params[4].isNull()) {
479 fSubtractFeeFromAmount = request.params[4].get_bool();
482 CCoinControl coin_control;
483 if (!request.params[5].isNull()) {
484 coin_control.signalRbf = request.params[5].get_bool();
487 if (!request.params[6].isNull()) {
488 coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
491 if (!request.params[7].isNull()) {
492 if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
493 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
498 EnsureWalletIsUnlocked(pwallet);
500 SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, wtx, coin_control);
502 return wtx.GetHash().GetHex();
505 UniValue listaddressgroupings(const JSONRPCRequest& request)
507 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
508 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
509 return NullUniValue;
512 if (request.fHelp || request.params.size() != 0)
513 throw std::runtime_error(
514 "listaddressgroupings\n"
515 "\nLists groups of addresses which have had their common ownership\n"
516 "made public by common use as inputs or as the resulting change\n"
517 "in past transactions\n"
518 "\nResult:\n"
519 "[\n"
520 " [\n"
521 " [\n"
522 " \"address\", (string) The bitcoin address\n"
523 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
524 " \"account\" (string, optional) DEPRECATED. The account\n"
525 " ]\n"
526 " ,...\n"
527 " ]\n"
528 " ,...\n"
529 "]\n"
530 "\nExamples:\n"
531 + HelpExampleCli("listaddressgroupings", "")
532 + HelpExampleRpc("listaddressgroupings", "")
535 ObserveSafeMode();
536 LOCK2(cs_main, pwallet->cs_wallet);
538 UniValue jsonGroupings(UniValue::VARR);
539 std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
540 for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
541 UniValue jsonGrouping(UniValue::VARR);
542 for (const CTxDestination& address : grouping)
544 UniValue addressInfo(UniValue::VARR);
545 addressInfo.push_back(EncodeDestination(address));
546 addressInfo.push_back(ValueFromAmount(balances[address]));
548 if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) {
549 addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name);
552 jsonGrouping.push_back(addressInfo);
554 jsonGroupings.push_back(jsonGrouping);
556 return jsonGroupings;
559 UniValue signmessage(const JSONRPCRequest& request)
561 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
562 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
563 return NullUniValue;
566 if (request.fHelp || request.params.size() != 2)
567 throw std::runtime_error(
568 "signmessage \"address\" \"message\"\n"
569 "\nSign a message with the private key of an address"
570 + HelpRequiringPassphrase(pwallet) + "\n"
571 "\nArguments:\n"
572 "1. \"address\" (string, required) The bitcoin address to use for the private key.\n"
573 "2. \"message\" (string, required) The message to create a signature of.\n"
574 "\nResult:\n"
575 "\"signature\" (string) The signature of the message encoded in base 64\n"
576 "\nExamples:\n"
577 "\nUnlock the wallet for 30 seconds\n"
578 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
579 "\nCreate the signature\n"
580 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
581 "\nVerify the signature\n"
582 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
583 "\nAs json rpc\n"
584 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
587 LOCK2(cs_main, pwallet->cs_wallet);
589 EnsureWalletIsUnlocked(pwallet);
591 std::string strAddress = request.params[0].get_str();
592 std::string strMessage = request.params[1].get_str();
594 CTxDestination dest = DecodeDestination(strAddress);
595 if (!IsValidDestination(dest)) {
596 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
599 const CKeyID *keyID = boost::get<CKeyID>(&dest);
600 if (!keyID) {
601 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
604 CKey key;
605 if (!pwallet->GetKey(*keyID, key)) {
606 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
609 CHashWriter ss(SER_GETHASH, 0);
610 ss << strMessageMagic;
611 ss << strMessage;
613 std::vector<unsigned char> vchSig;
614 if (!key.SignCompact(ss.GetHash(), vchSig))
615 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
617 return EncodeBase64(vchSig.data(), vchSig.size());
620 UniValue getreceivedbyaddress(const JSONRPCRequest& request)
622 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
623 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
624 return NullUniValue;
627 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
628 throw std::runtime_error(
629 "getreceivedbyaddress \"address\" ( minconf )\n"
630 "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n"
631 "\nArguments:\n"
632 "1. \"address\" (string, required) The bitcoin address for transactions.\n"
633 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
634 "\nResult:\n"
635 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
636 "\nExamples:\n"
637 "\nThe amount from transactions with at least 1 confirmation\n"
638 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
639 "\nThe amount including unconfirmed transactions, zero confirmations\n"
640 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
641 "\nThe amount with at least 6 confirmations\n"
642 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
643 "\nAs a json rpc call\n"
644 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
647 ObserveSafeMode();
648 LOCK2(cs_main, pwallet->cs_wallet);
650 // Bitcoin address
651 CTxDestination dest = DecodeDestination(request.params[0].get_str());
652 if (!IsValidDestination(dest)) {
653 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
655 CScript scriptPubKey = GetScriptForDestination(dest);
656 if (!IsMine(*pwallet, scriptPubKey)) {
657 throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
660 // Minimum confirmations
661 int nMinDepth = 1;
662 if (!request.params[1].isNull())
663 nMinDepth = request.params[1].get_int();
665 // Tally
666 CAmount nAmount = 0;
667 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
668 const CWalletTx& wtx = pairWtx.second;
669 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
670 continue;
672 for (const CTxOut& txout : wtx.tx->vout)
673 if (txout.scriptPubKey == scriptPubKey)
674 if (wtx.GetDepthInMainChain() >= nMinDepth)
675 nAmount += txout.nValue;
678 return ValueFromAmount(nAmount);
682 UniValue getreceivedbyaccount(const JSONRPCRequest& request)
684 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
685 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
686 return NullUniValue;
689 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
690 throw std::runtime_error(
691 "getreceivedbyaccount \"account\" ( minconf )\n"
692 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
693 "\nArguments:\n"
694 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
695 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
696 "\nResult:\n"
697 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
698 "\nExamples:\n"
699 "\nAmount received by the default account with at least 1 confirmation\n"
700 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
701 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
702 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
703 "\nThe amount with at least 6 confirmations\n"
704 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
705 "\nAs a json rpc call\n"
706 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
709 ObserveSafeMode();
710 LOCK2(cs_main, pwallet->cs_wallet);
712 // Minimum confirmations
713 int nMinDepth = 1;
714 if (!request.params[1].isNull())
715 nMinDepth = request.params[1].get_int();
717 // Get the set of pub keys assigned to account
718 std::string strAccount = AccountFromValue(request.params[0]);
719 std::set<CTxDestination> setAddress = pwallet->GetAccountAddresses(strAccount);
721 // Tally
722 CAmount nAmount = 0;
723 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
724 const CWalletTx& wtx = pairWtx.second;
725 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
726 continue;
728 for (const CTxOut& txout : wtx.tx->vout)
730 CTxDestination address;
731 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
732 if (wtx.GetDepthInMainChain() >= nMinDepth)
733 nAmount += txout.nValue;
738 return ValueFromAmount(nAmount);
742 UniValue getbalance(const JSONRPCRequest& request)
744 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
745 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
746 return NullUniValue;
749 if (request.fHelp || request.params.size() > 3)
750 throw std::runtime_error(
751 "getbalance ( \"account\" minconf include_watchonly )\n"
752 "\nIf account is not specified, returns the server's total available balance.\n"
753 "If account is specified (DEPRECATED), returns the balance in the account.\n"
754 "Note that the account \"\" is not the same as leaving the parameter out.\n"
755 "The server total may be different to the balance in the default \"\" account.\n"
756 "\nArguments:\n"
757 "1. \"account\" (string, optional) DEPRECATED. The account string may be given as a\n"
758 " specific account name to find the balance associated with wallet keys in\n"
759 " a named account, or as the empty string (\"\") to find the balance\n"
760 " associated with wallet keys not in any named account, or as \"*\" to find\n"
761 " the balance associated with all wallet keys regardless of account.\n"
762 " When this option is specified, it calculates the balance in a different\n"
763 " way than when it is not specified, and which can count spends twice when\n"
764 " there are conflicting pending transactions (such as those created by\n"
765 " the bumpfee command), temporarily resulting in low or even negative\n"
766 " balances. In general, account balance calculation is not considered\n"
767 " reliable and has resulted in confusing outcomes, so it is recommended to\n"
768 " avoid passing this argument.\n"
769 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
770 "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n"
771 "\nResult:\n"
772 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
773 "\nExamples:\n"
774 "\nThe total amount in the wallet with 1 or more confirmations\n"
775 + HelpExampleCli("getbalance", "") +
776 "\nThe total amount in the wallet at least 6 blocks confirmed\n"
777 + HelpExampleCli("getbalance", "\"*\" 6") +
778 "\nAs a json rpc call\n"
779 + HelpExampleRpc("getbalance", "\"*\", 6")
782 ObserveSafeMode();
783 LOCK2(cs_main, pwallet->cs_wallet);
785 const UniValue& account_value = request.params[0];
786 const UniValue& minconf = request.params[1];
787 const UniValue& include_watchonly = request.params[2];
789 if (account_value.isNull()) {
790 if (!minconf.isNull()) {
791 throw JSONRPCError(RPC_INVALID_PARAMETER,
792 "getbalance minconf option is only currently supported if an account is specified");
794 if (!include_watchonly.isNull()) {
795 throw JSONRPCError(RPC_INVALID_PARAMETER,
796 "getbalance include_watchonly option is only currently supported if an account is specified");
798 return ValueFromAmount(pwallet->GetBalance());
801 const std::string& account_param = account_value.get_str();
802 const std::string* account = account_param != "*" ? &account_param : nullptr;
804 int nMinDepth = 1;
805 if (!minconf.isNull())
806 nMinDepth = minconf.get_int();
807 isminefilter filter = ISMINE_SPENDABLE;
808 if(!include_watchonly.isNull())
809 if(include_watchonly.get_bool())
810 filter = filter | ISMINE_WATCH_ONLY;
812 return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account));
815 UniValue getunconfirmedbalance(const JSONRPCRequest &request)
817 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
818 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
819 return NullUniValue;
822 if (request.fHelp || request.params.size() > 0)
823 throw std::runtime_error(
824 "getunconfirmedbalance\n"
825 "Returns the server's total unconfirmed balance\n");
827 ObserveSafeMode();
828 LOCK2(cs_main, pwallet->cs_wallet);
830 return ValueFromAmount(pwallet->GetUnconfirmedBalance());
834 UniValue movecmd(const JSONRPCRequest& request)
836 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
837 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
838 return NullUniValue;
841 if (request.fHelp || request.params.size() < 3 || request.params.size() > 5)
842 throw std::runtime_error(
843 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
844 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
845 "\nArguments:\n"
846 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
847 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
848 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
849 "4. (dummy) (numeric, optional) Ignored. Remains for backward compatibility.\n"
850 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
851 "\nResult:\n"
852 "true|false (boolean) true if successful.\n"
853 "\nExamples:\n"
854 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
855 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
856 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
857 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
858 "\nAs a json rpc call\n"
859 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
862 ObserveSafeMode();
863 LOCK2(cs_main, pwallet->cs_wallet);
865 std::string strFrom = AccountFromValue(request.params[0]);
866 std::string strTo = AccountFromValue(request.params[1]);
867 CAmount nAmount = AmountFromValue(request.params[2]);
868 if (nAmount <= 0)
869 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
870 if (!request.params[3].isNull())
871 // unused parameter, used to be nMinDepth, keep type-checking it though
872 (void)request.params[3].get_int();
873 std::string strComment;
874 if (!request.params[4].isNull())
875 strComment = request.params[4].get_str();
877 if (!pwallet->AccountMove(strFrom, strTo, nAmount, strComment)) {
878 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
881 return true;
885 UniValue sendfrom(const JSONRPCRequest& request)
887 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
888 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
889 return NullUniValue;
892 if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
893 throw std::runtime_error(
894 "sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
895 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
896 + HelpRequiringPassphrase(pwallet) + "\n"
897 "\nArguments:\n"
898 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
899 " Specifying an account does not influence coin selection, but it does associate the newly created\n"
900 " transaction with the account, so the account's balance computation and transaction history can reflect\n"
901 " the spend.\n"
902 "2. \"toaddress\" (string, required) The bitcoin address to send funds to.\n"
903 "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
904 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
905 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
906 " This is not part of the transaction, just kept in your wallet.\n"
907 "6. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n"
908 " to which you're sending the transaction. This is not part of the transaction, \n"
909 " it is just kept in your wallet.\n"
910 "\nResult:\n"
911 "\"txid\" (string) The transaction id.\n"
912 "\nExamples:\n"
913 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
914 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
915 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
916 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
917 "\nAs a json rpc call\n"
918 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
921 ObserveSafeMode();
922 LOCK2(cs_main, pwallet->cs_wallet);
924 std::string strAccount = AccountFromValue(request.params[0]);
925 CTxDestination dest = DecodeDestination(request.params[1].get_str());
926 if (!IsValidDestination(dest)) {
927 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
929 CAmount nAmount = AmountFromValue(request.params[2]);
930 if (nAmount <= 0)
931 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
932 int nMinDepth = 1;
933 if (!request.params[3].isNull())
934 nMinDepth = request.params[3].get_int();
936 CWalletTx wtx;
937 wtx.strFromAccount = strAccount;
938 if (!request.params[4].isNull() && !request.params[4].get_str().empty())
939 wtx.mapValue["comment"] = request.params[4].get_str();
940 if (!request.params[5].isNull() && !request.params[5].get_str().empty())
941 wtx.mapValue["to"] = request.params[5].get_str();
943 EnsureWalletIsUnlocked(pwallet);
945 // Check funds
946 CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
947 if (nAmount > nBalance)
948 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
950 CCoinControl no_coin_control; // This is a deprecated API
951 SendMoney(pwallet, dest, nAmount, false, wtx, no_coin_control);
953 return wtx.GetHash().GetHex();
957 UniValue sendmany(const JSONRPCRequest& request)
959 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
960 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
961 return NullUniValue;
964 if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
965 throw std::runtime_error(
966 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n"
967 "\nSend multiple times. Amounts are double-precision floating point numbers."
968 + HelpRequiringPassphrase(pwallet) + "\n"
969 "\nArguments:\n"
970 "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
971 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
972 " {\n"
973 " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
974 " ,...\n"
975 " }\n"
976 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
977 "4. \"comment\" (string, optional) A comment\n"
978 "5. subtractfeefrom (array, optional) A json array with addresses.\n"
979 " The fee will be equally deducted from the amount of each selected address.\n"
980 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
981 " If no addresses are specified here, the sender pays the fee.\n"
982 " [\n"
983 " \"address\" (string) Subtract fee from this address\n"
984 " ,...\n"
985 " ]\n"
986 "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
987 "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
988 "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
989 " \"UNSET\"\n"
990 " \"ECONOMICAL\"\n"
991 " \"CONSERVATIVE\"\n"
992 "\nResult:\n"
993 "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
994 " the number of addresses.\n"
995 "\nExamples:\n"
996 "\nSend two amounts to two different addresses:\n"
997 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
998 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
999 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
1000 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
1001 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
1002 "\nAs a json rpc call\n"
1003 + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
1006 ObserveSafeMode();
1007 LOCK2(cs_main, pwallet->cs_wallet);
1009 if (pwallet->GetBroadcastTransactions() && !g_connman) {
1010 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
1013 std::string strAccount = AccountFromValue(request.params[0]);
1014 UniValue sendTo = request.params[1].get_obj();
1015 int nMinDepth = 1;
1016 if (!request.params[2].isNull())
1017 nMinDepth = request.params[2].get_int();
1019 CWalletTx wtx;
1020 wtx.strFromAccount = strAccount;
1021 if (!request.params[3].isNull() && !request.params[3].get_str().empty())
1022 wtx.mapValue["comment"] = request.params[3].get_str();
1024 UniValue subtractFeeFromAmount(UniValue::VARR);
1025 if (!request.params[4].isNull())
1026 subtractFeeFromAmount = request.params[4].get_array();
1028 CCoinControl coin_control;
1029 if (!request.params[5].isNull()) {
1030 coin_control.signalRbf = request.params[5].get_bool();
1033 if (!request.params[6].isNull()) {
1034 coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
1037 if (!request.params[7].isNull()) {
1038 if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
1039 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
1043 std::set<CTxDestination> destinations;
1044 std::vector<CRecipient> vecSend;
1046 CAmount totalAmount = 0;
1047 std::vector<std::string> keys = sendTo.getKeys();
1048 for (const std::string& name_ : keys) {
1049 CTxDestination dest = DecodeDestination(name_);
1050 if (!IsValidDestination(dest)) {
1051 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
1054 if (destinations.count(dest)) {
1055 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
1057 destinations.insert(dest);
1059 CScript scriptPubKey = GetScriptForDestination(dest);
1060 CAmount nAmount = AmountFromValue(sendTo[name_]);
1061 if (nAmount <= 0)
1062 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1063 totalAmount += nAmount;
1065 bool fSubtractFeeFromAmount = false;
1066 for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1067 const UniValue& addr = subtractFeeFromAmount[idx];
1068 if (addr.get_str() == name_)
1069 fSubtractFeeFromAmount = true;
1072 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1073 vecSend.push_back(recipient);
1076 EnsureWalletIsUnlocked(pwallet);
1078 // Check funds
1079 CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
1080 if (totalAmount > nBalance)
1081 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1083 // Send
1084 CReserveKey keyChange(pwallet);
1085 CAmount nFeeRequired = 0;
1086 int nChangePosRet = -1;
1087 std::string strFailReason;
1088 bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
1089 if (!fCreated)
1090 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1091 CValidationState state;
1092 if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
1093 strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
1094 throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
1097 return wtx.GetHash().GetHex();
1100 // Defined in rpc/misc.cpp
1101 extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params);
1103 UniValue addmultisigaddress(const JSONRPCRequest& request)
1105 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1106 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1107 return NullUniValue;
1110 if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
1112 std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1113 "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
1114 "Each key is a Bitcoin address or hex-encoded public key.\n"
1115 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1117 "\nArguments:\n"
1118 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1119 "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
1120 " [\n"
1121 " \"address\" (string) bitcoin address or hex-encoded public key\n"
1122 " ...,\n"
1123 " ]\n"
1124 "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
1126 "\nResult:\n"
1127 "\"address\" (string) A bitcoin address associated with the keys.\n"
1129 "\nExamples:\n"
1130 "\nAdd a multisig address from 2 addresses\n"
1131 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1132 "\nAs json rpc call\n"
1133 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1135 throw std::runtime_error(msg);
1138 LOCK2(cs_main, pwallet->cs_wallet);
1140 std::string strAccount;
1141 if (!request.params[2].isNull())
1142 strAccount = AccountFromValue(request.params[2]);
1144 // Construct using pay-to-script-hash:
1145 CScript inner = _createmultisig_redeemScript(pwallet, request.params);
1146 CScriptID innerID(inner);
1147 pwallet->AddCScript(inner);
1149 pwallet->SetAddressBook(innerID, strAccount, "send");
1150 return EncodeDestination(innerID);
1153 class Witnessifier : public boost::static_visitor<bool>
1155 public:
1156 CWallet * const pwallet;
1157 CTxDestination result;
1158 bool already_witness;
1160 explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {}
1162 bool operator()(const CKeyID &keyID) {
1163 if (pwallet) {
1164 CScript basescript = GetScriptForDestination(keyID);
1165 CScript witscript = GetScriptForWitness(basescript);
1166 SignatureData sigs;
1167 // This check is to make sure that the script we created can actually be solved for and signed by us
1168 // if we were to have the private keys. This is just to make sure that the script is valid and that,
1169 // if found in a transaction, we would still accept and relay that transaction.
1170 if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1171 !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1172 return false;
1174 return ExtractDestination(witscript, result);
1176 return false;
1179 bool operator()(const CScriptID &scriptID) {
1180 CScript subscript;
1181 if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
1182 int witnessversion;
1183 std::vector<unsigned char> witprog;
1184 if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1185 ExtractDestination(subscript, result);
1186 already_witness = true;
1187 return true;
1189 CScript witscript = GetScriptForWitness(subscript);
1190 SignatureData sigs;
1191 // This check is to make sure that the script we created can actually be solved for and signed by us
1192 // if we were to have the private keys. This is just to make sure that the script is valid and that,
1193 // if found in a transaction, we would still accept and relay that transaction.
1194 if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1195 !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1196 return false;
1198 return ExtractDestination(witscript, result);
1200 return false;
1203 bool operator()(const WitnessV0KeyHash& id)
1205 already_witness = true;
1206 result = id;
1207 return true;
1210 bool operator()(const WitnessV0ScriptHash& id)
1212 already_witness = true;
1213 result = id;
1214 return true;
1217 template<typename T>
1218 bool operator()(const T& dest) { return false; }
1221 UniValue addwitnessaddress(const JSONRPCRequest& request)
1223 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1224 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1225 return NullUniValue;
1228 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
1230 std::string msg = "addwitnessaddress \"address\" ( p2sh )\n"
1231 "\nAdd a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n"
1232 "It returns the witness script.\n"
1234 "\nArguments:\n"
1235 "1. \"address\" (string, required) An address known to the wallet\n"
1236 "2. p2sh (bool, optional, default=true) Embed inside P2SH\n"
1238 "\nResult:\n"
1239 "\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n"
1240 "}\n"
1242 throw std::runtime_error(msg);
1246 LOCK(cs_main);
1247 if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !gArgs.GetBoolArg("-walletprematurewitness", false)) {
1248 throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network");
1252 CTxDestination dest = DecodeDestination(request.params[0].get_str());
1253 if (!IsValidDestination(dest)) {
1254 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
1257 bool p2sh = true;
1258 if (!request.params[1].isNull()) {
1259 p2sh = request.params[1].get_bool();
1262 Witnessifier w(pwallet);
1263 bool ret = boost::apply_visitor(w, dest);
1264 if (!ret) {
1265 throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
1268 CScript witprogram = GetScriptForDestination(w.result);
1270 if (p2sh) {
1271 w.result = CScriptID(witprogram);
1274 if (w.already_witness) {
1275 if (!(dest == w.result)) {
1276 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types");
1278 } else {
1279 pwallet->AddCScript(witprogram);
1280 pwallet->SetAddressBook(w.result, "", "receive");
1283 return EncodeDestination(w.result);
1286 struct tallyitem
1288 CAmount nAmount;
1289 int nConf;
1290 std::vector<uint256> txids;
1291 bool fIsWatchonly;
1292 tallyitem()
1294 nAmount = 0;
1295 nConf = std::numeric_limits<int>::max();
1296 fIsWatchonly = false;
1300 UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByAccounts)
1302 // Minimum confirmations
1303 int nMinDepth = 1;
1304 if (!params[0].isNull())
1305 nMinDepth = params[0].get_int();
1307 // Whether to include empty accounts
1308 bool fIncludeEmpty = false;
1309 if (!params[1].isNull())
1310 fIncludeEmpty = params[1].get_bool();
1312 isminefilter filter = ISMINE_SPENDABLE;
1313 if(!params[2].isNull())
1314 if(params[2].get_bool())
1315 filter = filter | ISMINE_WATCH_ONLY;
1317 // Tally
1318 std::map<CTxDestination, tallyitem> mapTally;
1319 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1320 const CWalletTx& wtx = pairWtx.second;
1322 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
1323 continue;
1325 int nDepth = wtx.GetDepthInMainChain();
1326 if (nDepth < nMinDepth)
1327 continue;
1329 for (const CTxOut& txout : wtx.tx->vout)
1331 CTxDestination address;
1332 if (!ExtractDestination(txout.scriptPubKey, address))
1333 continue;
1335 isminefilter mine = IsMine(*pwallet, address);
1336 if(!(mine & filter))
1337 continue;
1339 tallyitem& item = mapTally[address];
1340 item.nAmount += txout.nValue;
1341 item.nConf = std::min(item.nConf, nDepth);
1342 item.txids.push_back(wtx.GetHash());
1343 if (mine & ISMINE_WATCH_ONLY)
1344 item.fIsWatchonly = true;
1348 // Reply
1349 UniValue ret(UniValue::VARR);
1350 std::map<std::string, tallyitem> mapAccountTally;
1351 for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
1352 const CTxDestination& dest = item.first;
1353 const std::string& strAccount = item.second.name;
1354 std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
1355 if (it == mapTally.end() && !fIncludeEmpty)
1356 continue;
1358 CAmount nAmount = 0;
1359 int nConf = std::numeric_limits<int>::max();
1360 bool fIsWatchonly = false;
1361 if (it != mapTally.end())
1363 nAmount = (*it).second.nAmount;
1364 nConf = (*it).second.nConf;
1365 fIsWatchonly = (*it).second.fIsWatchonly;
1368 if (fByAccounts)
1370 tallyitem& _item = mapAccountTally[strAccount];
1371 _item.nAmount += nAmount;
1372 _item.nConf = std::min(_item.nConf, nConf);
1373 _item.fIsWatchonly = fIsWatchonly;
1375 else
1377 UniValue obj(UniValue::VOBJ);
1378 if(fIsWatchonly)
1379 obj.push_back(Pair("involvesWatchonly", true));
1380 obj.push_back(Pair("address", EncodeDestination(dest)));
1381 obj.push_back(Pair("account", strAccount));
1382 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1383 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1384 if (!fByAccounts)
1385 obj.push_back(Pair("label", strAccount));
1386 UniValue transactions(UniValue::VARR);
1387 if (it != mapTally.end())
1389 for (const uint256& _item : (*it).second.txids)
1391 transactions.push_back(_item.GetHex());
1394 obj.push_back(Pair("txids", transactions));
1395 ret.push_back(obj);
1399 if (fByAccounts)
1401 for (std::map<std::string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1403 CAmount nAmount = (*it).second.nAmount;
1404 int nConf = (*it).second.nConf;
1405 UniValue obj(UniValue::VOBJ);
1406 if((*it).second.fIsWatchonly)
1407 obj.push_back(Pair("involvesWatchonly", true));
1408 obj.push_back(Pair("account", (*it).first));
1409 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1410 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1411 ret.push_back(obj);
1415 return ret;
1418 UniValue listreceivedbyaddress(const JSONRPCRequest& request)
1420 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1421 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1422 return NullUniValue;
1425 if (request.fHelp || request.params.size() > 3)
1426 throw std::runtime_error(
1427 "listreceivedbyaddress ( minconf include_empty include_watchonly)\n"
1428 "\nList balances by receiving address.\n"
1429 "\nArguments:\n"
1430 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1431 "2. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1432 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1434 "\nResult:\n"
1435 "[\n"
1436 " {\n"
1437 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1438 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1439 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1440 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1441 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1442 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
1443 " \"txids\": [\n"
1444 " n, (numeric) The ids of transactions received with the address \n"
1445 " ...\n"
1446 " ]\n"
1447 " }\n"
1448 " ,...\n"
1449 "]\n"
1451 "\nExamples:\n"
1452 + HelpExampleCli("listreceivedbyaddress", "")
1453 + HelpExampleCli("listreceivedbyaddress", "6 true")
1454 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1457 ObserveSafeMode();
1458 LOCK2(cs_main, pwallet->cs_wallet);
1460 return ListReceived(pwallet, request.params, false);
1463 UniValue listreceivedbyaccount(const JSONRPCRequest& request)
1465 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1466 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1467 return NullUniValue;
1470 if (request.fHelp || request.params.size() > 3)
1471 throw std::runtime_error(
1472 "listreceivedbyaccount ( minconf include_empty include_watchonly)\n"
1473 "\nDEPRECATED. List balances by account.\n"
1474 "\nArguments:\n"
1475 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1476 "2. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1477 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1479 "\nResult:\n"
1480 "[\n"
1481 " {\n"
1482 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1483 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1484 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1485 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1486 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1487 " }\n"
1488 " ,...\n"
1489 "]\n"
1491 "\nExamples:\n"
1492 + HelpExampleCli("listreceivedbyaccount", "")
1493 + HelpExampleCli("listreceivedbyaccount", "6 true")
1494 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1497 ObserveSafeMode();
1498 LOCK2(cs_main, pwallet->cs_wallet);
1500 return ListReceived(pwallet, request.params, true);
1503 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1505 if (IsValidDestination(dest)) {
1506 entry.push_back(Pair("address", EncodeDestination(dest)));
1511 * List transactions based on the given criteria.
1513 * @param pwallet The wallet.
1514 * @param wtx The wallet transaction.
1515 * @param strAccount The account, if any, or "*" for all.
1516 * @param nMinDepth The minimum confirmation depth.
1517 * @param fLong Whether to include the JSON version of the transaction.
1518 * @param ret The UniValue into which the result is stored.
1519 * @param filter The "is mine" filter bool.
1521 void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1523 CAmount nFee;
1524 std::string strSentAccount;
1525 std::list<COutputEntry> listReceived;
1526 std::list<COutputEntry> listSent;
1528 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1530 bool fAllAccounts = (strAccount == std::string("*"));
1531 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1533 // Sent
1534 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1536 for (const COutputEntry& s : listSent)
1538 UniValue entry(UniValue::VOBJ);
1539 if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
1540 entry.push_back(Pair("involvesWatchonly", true));
1542 entry.push_back(Pair("account", strSentAccount));
1543 MaybePushAddress(entry, s.destination);
1544 entry.push_back(Pair("category", "send"));
1545 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1546 if (pwallet->mapAddressBook.count(s.destination)) {
1547 entry.push_back(Pair("label", pwallet->mapAddressBook[s.destination].name));
1549 entry.push_back(Pair("vout", s.vout));
1550 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1551 if (fLong)
1552 WalletTxToJSON(wtx, entry);
1553 entry.push_back(Pair("abandoned", wtx.isAbandoned()));
1554 ret.push_back(entry);
1558 // Received
1559 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1561 for (const COutputEntry& r : listReceived)
1563 std::string account;
1564 if (pwallet->mapAddressBook.count(r.destination)) {
1565 account = pwallet->mapAddressBook[r.destination].name;
1567 if (fAllAccounts || (account == strAccount))
1569 UniValue entry(UniValue::VOBJ);
1570 if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
1571 entry.push_back(Pair("involvesWatchonly", true));
1573 entry.push_back(Pair("account", account));
1574 MaybePushAddress(entry, r.destination);
1575 if (wtx.IsCoinBase())
1577 if (wtx.GetDepthInMainChain() < 1)
1578 entry.push_back(Pair("category", "orphan"));
1579 else if (wtx.GetBlocksToMaturity() > 0)
1580 entry.push_back(Pair("category", "immature"));
1581 else
1582 entry.push_back(Pair("category", "generate"));
1584 else
1586 entry.push_back(Pair("category", "receive"));
1588 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1589 if (pwallet->mapAddressBook.count(r.destination)) {
1590 entry.push_back(Pair("label", account));
1592 entry.push_back(Pair("vout", r.vout));
1593 if (fLong)
1594 WalletTxToJSON(wtx, entry);
1595 ret.push_back(entry);
1601 void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccount, UniValue& ret)
1603 bool fAllAccounts = (strAccount == std::string("*"));
1605 if (fAllAccounts || acentry.strAccount == strAccount)
1607 UniValue entry(UniValue::VOBJ);
1608 entry.push_back(Pair("account", acentry.strAccount));
1609 entry.push_back(Pair("category", "move"));
1610 entry.push_back(Pair("time", acentry.nTime));
1611 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1612 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1613 entry.push_back(Pair("comment", acentry.strComment));
1614 ret.push_back(entry);
1618 UniValue listtransactions(const JSONRPCRequest& request)
1620 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1621 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1622 return NullUniValue;
1625 if (request.fHelp || request.params.size() > 4)
1626 throw std::runtime_error(
1627 "listtransactions ( \"account\" count skip include_watchonly)\n"
1628 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1629 "\nArguments:\n"
1630 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1631 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1632 "3. skip (numeric, optional, default=0) The number of transactions to skip\n"
1633 "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
1634 "\nResult:\n"
1635 "[\n"
1636 " {\n"
1637 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1638 " It will be \"\" for the default account.\n"
1639 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for \n"
1640 " move transactions (category = move).\n"
1641 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1642 " transaction between accounts, and not associated with an address,\n"
1643 " transaction id or block. 'send' and 'receive' transactions are \n"
1644 " associated with an address, transaction id and block details\n"
1645 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1646 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1647 " and for the 'move' category for inbound funds.\n"
1648 " \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
1649 " \"vout\": n, (numeric) the vout value\n"
1650 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1651 " 'send' category of transactions.\n"
1652 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1653 " 'receive' category of transactions. Negative confirmations indicate the\n"
1654 " transaction conflicts with the block chain\n"
1655 " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
1656 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1657 " category of transactions.\n"
1658 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
1659 " category of transactions.\n"
1660 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1661 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1662 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1663 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1664 " for 'send' and 'receive' category of transactions.\n"
1665 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1666 " \"otheraccount\": \"accountname\", (string) DEPRECATED. For the 'move' category of transactions, the account the funds came \n"
1667 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1668 " negative amounts).\n"
1669 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1670 " may be unknown for unconfirmed transactions not in the mempool\n"
1671 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1672 " 'send' category of transactions.\n"
1673 " }\n"
1674 "]\n"
1676 "\nExamples:\n"
1677 "\nList the most recent 10 transactions in the systems\n"
1678 + HelpExampleCli("listtransactions", "") +
1679 "\nList transactions 100 to 120\n"
1680 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1681 "\nAs a json rpc call\n"
1682 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1685 ObserveSafeMode();
1686 LOCK2(cs_main, pwallet->cs_wallet);
1688 std::string strAccount = "*";
1689 if (!request.params[0].isNull())
1690 strAccount = request.params[0].get_str();
1691 int nCount = 10;
1692 if (!request.params[1].isNull())
1693 nCount = request.params[1].get_int();
1694 int nFrom = 0;
1695 if (!request.params[2].isNull())
1696 nFrom = request.params[2].get_int();
1697 isminefilter filter = ISMINE_SPENDABLE;
1698 if(!request.params[3].isNull())
1699 if(request.params[3].get_bool())
1700 filter = filter | ISMINE_WATCH_ONLY;
1702 if (nCount < 0)
1703 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1704 if (nFrom < 0)
1705 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1707 UniValue ret(UniValue::VARR);
1709 const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
1711 // iterate backwards until we have nCount items to return:
1712 for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1714 CWalletTx *const pwtx = (*it).second.first;
1715 if (pwtx != nullptr)
1716 ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter);
1717 CAccountingEntry *const pacentry = (*it).second.second;
1718 if (pacentry != nullptr)
1719 AcentryToJSON(*pacentry, strAccount, ret);
1721 if ((int)ret.size() >= (nCount+nFrom)) break;
1723 // ret is newest to oldest
1725 if (nFrom > (int)ret.size())
1726 nFrom = ret.size();
1727 if ((nFrom + nCount) > (int)ret.size())
1728 nCount = ret.size() - nFrom;
1730 std::vector<UniValue> arrTmp = ret.getValues();
1732 std::vector<UniValue>::iterator first = arrTmp.begin();
1733 std::advance(first, nFrom);
1734 std::vector<UniValue>::iterator last = arrTmp.begin();
1735 std::advance(last, nFrom+nCount);
1737 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1738 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1740 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1742 ret.clear();
1743 ret.setArray();
1744 ret.push_backV(arrTmp);
1746 return ret;
1749 UniValue listaccounts(const JSONRPCRequest& request)
1751 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1752 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1753 return NullUniValue;
1756 if (request.fHelp || request.params.size() > 2)
1757 throw std::runtime_error(
1758 "listaccounts ( minconf include_watchonly)\n"
1759 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1760 "\nArguments:\n"
1761 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1762 "2. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n"
1763 "\nResult:\n"
1764 "{ (json object where keys are account names, and values are numeric balances\n"
1765 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1766 " ...\n"
1767 "}\n"
1768 "\nExamples:\n"
1769 "\nList account balances where there at least 1 confirmation\n"
1770 + HelpExampleCli("listaccounts", "") +
1771 "\nList account balances including zero confirmation transactions\n"
1772 + HelpExampleCli("listaccounts", "0") +
1773 "\nList account balances for 6 or more confirmations\n"
1774 + HelpExampleCli("listaccounts", "6") +
1775 "\nAs json rpc call\n"
1776 + HelpExampleRpc("listaccounts", "6")
1779 ObserveSafeMode();
1780 LOCK2(cs_main, pwallet->cs_wallet);
1782 int nMinDepth = 1;
1783 if (!request.params[0].isNull())
1784 nMinDepth = request.params[0].get_int();
1785 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1786 if(!request.params[1].isNull())
1787 if(request.params[1].get_bool())
1788 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1790 std::map<std::string, CAmount> mapAccountBalances;
1791 for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
1792 if (IsMine(*pwallet, entry.first) & includeWatchonly) { // This address belongs to me
1793 mapAccountBalances[entry.second.name] = 0;
1797 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1798 const CWalletTx& wtx = pairWtx.second;
1799 CAmount nFee;
1800 std::string strSentAccount;
1801 std::list<COutputEntry> listReceived;
1802 std::list<COutputEntry> listSent;
1803 int nDepth = wtx.GetDepthInMainChain();
1804 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1805 continue;
1806 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1807 mapAccountBalances[strSentAccount] -= nFee;
1808 for (const COutputEntry& s : listSent)
1809 mapAccountBalances[strSentAccount] -= s.amount;
1810 if (nDepth >= nMinDepth)
1812 for (const COutputEntry& r : listReceived)
1813 if (pwallet->mapAddressBook.count(r.destination)) {
1814 mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount;
1816 else
1817 mapAccountBalances[""] += r.amount;
1821 const std::list<CAccountingEntry>& acentries = pwallet->laccentries;
1822 for (const CAccountingEntry& entry : acentries)
1823 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1825 UniValue ret(UniValue::VOBJ);
1826 for (const std::pair<std::string, CAmount>& accountBalance : mapAccountBalances) {
1827 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1829 return ret;
1832 UniValue listsinceblock(const JSONRPCRequest& request)
1834 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1835 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1836 return NullUniValue;
1839 if (request.fHelp || request.params.size() > 4)
1840 throw std::runtime_error(
1841 "listsinceblock ( \"blockhash\" target_confirmations include_watchonly include_removed )\n"
1842 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
1843 "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
1844 "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n"
1845 "\nArguments:\n"
1846 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1847 "2. target_confirmations: (numeric, optional, default=1) Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value\n"
1848 "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
1849 "4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n"
1850 " (not guaranteed to work on pruned nodes)\n"
1851 "\nResult:\n"
1852 "{\n"
1853 " \"transactions\": [\n"
1854 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1855 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1856 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1857 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1858 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1859 " \"vout\" : n, (numeric) the vout value\n"
1860 " \"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"
1861 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1862 " When it's < 0, it means the transaction conflicted that many blocks ago.\n"
1863 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1864 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
1865 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1866 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1867 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1868 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1869 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1870 " may be unknown for unconfirmed transactions not in the mempool\n"
1871 " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n"
1872 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1873 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1874 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1875 " ],\n"
1876 " \"removed\": [\n"
1877 " <structure is the same as \"transactions\" above, only present if include_removed=true>\n"
1878 " Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n"
1879 " ],\n"
1880 " \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n"
1881 "}\n"
1882 "\nExamples:\n"
1883 + HelpExampleCli("listsinceblock", "")
1884 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1885 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1888 ObserveSafeMode();
1889 LOCK2(cs_main, pwallet->cs_wallet);
1891 const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
1892 const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
1893 int target_confirms = 1;
1894 isminefilter filter = ISMINE_SPENDABLE;
1896 if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
1897 uint256 blockId;
1899 blockId.SetHex(request.params[0].get_str());
1900 BlockMap::iterator it = mapBlockIndex.find(blockId);
1901 if (it == mapBlockIndex.end()) {
1902 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1904 paltindex = pindex = it->second;
1905 if (chainActive[pindex->nHeight] != pindex) {
1906 // the block being asked for is a part of a deactivated chain;
1907 // we don't want to depend on its perceived height in the block
1908 // chain, we want to instead use the last common ancestor
1909 pindex = chainActive.FindFork(pindex);
1913 if (!request.params[1].isNull()) {
1914 target_confirms = request.params[1].get_int();
1916 if (target_confirms < 1) {
1917 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1921 if (!request.params[2].isNull() && request.params[2].get_bool()) {
1922 filter = filter | ISMINE_WATCH_ONLY;
1925 bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
1927 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1929 UniValue transactions(UniValue::VARR);
1931 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1932 CWalletTx tx = pairWtx.second;
1934 if (depth == -1 || tx.GetDepthInMainChain() < depth) {
1935 ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
1939 // when a reorg'd block is requested, we also list any relevant transactions
1940 // in the blocks of the chain that was detached
1941 UniValue removed(UniValue::VARR);
1942 while (include_removed && paltindex && paltindex != pindex) {
1943 CBlock block;
1944 if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus())) {
1945 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
1947 for (const CTransactionRef& tx : block.vtx) {
1948 auto it = pwallet->mapWallet.find(tx->GetHash());
1949 if (it != pwallet->mapWallet.end()) {
1950 // We want all transactions regardless of confirmation count to appear here,
1951 // even negative confirmation ones, hence the big negative.
1952 ListTransactions(pwallet, it->second, "*", -100000000, true, removed, filter);
1955 paltindex = paltindex->pprev;
1958 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1959 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1961 UniValue ret(UniValue::VOBJ);
1962 ret.push_back(Pair("transactions", transactions));
1963 if (include_removed) ret.push_back(Pair("removed", removed));
1964 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1966 return ret;
1969 UniValue gettransaction(const JSONRPCRequest& request)
1971 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1972 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1973 return NullUniValue;
1976 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
1977 throw std::runtime_error(
1978 "gettransaction \"txid\" ( include_watchonly )\n"
1979 "\nGet detailed information about in-wallet transaction <txid>\n"
1980 "\nArguments:\n"
1981 "1. \"txid\" (string, required) The transaction id\n"
1982 "2. \"include_watchonly\" (bool, optional, default=false) Whether to include watch-only addresses in balance calculation and details[]\n"
1983 "\nResult:\n"
1984 "{\n"
1985 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1986 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1987 " 'send' category of transactions.\n"
1988 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1989 " \"blockhash\" : \"hash\", (string) The block hash\n"
1990 " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n"
1991 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1992 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1993 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1994 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1995 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1996 " may be unknown for unconfirmed transactions not in the mempool\n"
1997 " \"details\" : [\n"
1998 " {\n"
1999 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
2000 " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n"
2001 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
2002 " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
2003 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
2004 " \"vout\" : n, (numeric) the vout value\n"
2005 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
2006 " 'send' category of transactions.\n"
2007 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
2008 " 'send' category of transactions.\n"
2009 " }\n"
2010 " ,...\n"
2011 " ],\n"
2012 " \"hex\" : \"data\" (string) Raw data for transaction\n"
2013 "}\n"
2015 "\nExamples:\n"
2016 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2017 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
2018 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2021 ObserveSafeMode();
2022 LOCK2(cs_main, pwallet->cs_wallet);
2024 uint256 hash;
2025 hash.SetHex(request.params[0].get_str());
2027 isminefilter filter = ISMINE_SPENDABLE;
2028 if(!request.params[1].isNull())
2029 if(request.params[1].get_bool())
2030 filter = filter | ISMINE_WATCH_ONLY;
2032 UniValue entry(UniValue::VOBJ);
2033 auto it = pwallet->mapWallet.find(hash);
2034 if (it == pwallet->mapWallet.end()) {
2035 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2037 const CWalletTx& wtx = it->second;
2039 CAmount nCredit = wtx.GetCredit(filter);
2040 CAmount nDebit = wtx.GetDebit(filter);
2041 CAmount nNet = nCredit - nDebit;
2042 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
2044 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
2045 if (wtx.IsFromMe(filter))
2046 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
2048 WalletTxToJSON(wtx, entry);
2050 UniValue details(UniValue::VARR);
2051 ListTransactions(pwallet, wtx, "*", 0, false, details, filter);
2052 entry.push_back(Pair("details", details));
2054 std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags());
2055 entry.push_back(Pair("hex", strHex));
2057 return entry;
2060 UniValue abandontransaction(const JSONRPCRequest& request)
2062 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2063 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2064 return NullUniValue;
2067 if (request.fHelp || request.params.size() != 1)
2068 throw std::runtime_error(
2069 "abandontransaction \"txid\"\n"
2070 "\nMark in-wallet transaction <txid> as abandoned\n"
2071 "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
2072 "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
2073 "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
2074 "It has no effect on transactions which are already conflicted or abandoned.\n"
2075 "\nArguments:\n"
2076 "1. \"txid\" (string, required) The transaction id\n"
2077 "\nResult:\n"
2078 "\nExamples:\n"
2079 + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2080 + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2083 ObserveSafeMode();
2084 LOCK2(cs_main, pwallet->cs_wallet);
2086 uint256 hash;
2087 hash.SetHex(request.params[0].get_str());
2089 if (!pwallet->mapWallet.count(hash)) {
2090 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2092 if (!pwallet->AbandonTransaction(hash)) {
2093 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
2096 return NullUniValue;
2100 UniValue backupwallet(const JSONRPCRequest& request)
2102 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2103 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2104 return NullUniValue;
2107 if (request.fHelp || request.params.size() != 1)
2108 throw std::runtime_error(
2109 "backupwallet \"destination\"\n"
2110 "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
2111 "\nArguments:\n"
2112 "1. \"destination\" (string) The destination directory or file\n"
2113 "\nExamples:\n"
2114 + HelpExampleCli("backupwallet", "\"backup.dat\"")
2115 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
2118 LOCK2(cs_main, pwallet->cs_wallet);
2120 std::string strDest = request.params[0].get_str();
2121 if (!pwallet->BackupWallet(strDest)) {
2122 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
2125 return NullUniValue;
2129 UniValue keypoolrefill(const JSONRPCRequest& request)
2131 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2132 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2133 return NullUniValue;
2136 if (request.fHelp || request.params.size() > 1)
2137 throw std::runtime_error(
2138 "keypoolrefill ( newsize )\n"
2139 "\nFills the keypool."
2140 + HelpRequiringPassphrase(pwallet) + "\n"
2141 "\nArguments\n"
2142 "1. newsize (numeric, optional, default=100) The new keypool size\n"
2143 "\nExamples:\n"
2144 + HelpExampleCli("keypoolrefill", "")
2145 + HelpExampleRpc("keypoolrefill", "")
2148 LOCK2(cs_main, pwallet->cs_wallet);
2150 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
2151 unsigned int kpSize = 0;
2152 if (!request.params[0].isNull()) {
2153 if (request.params[0].get_int() < 0)
2154 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
2155 kpSize = (unsigned int)request.params[0].get_int();
2158 EnsureWalletIsUnlocked(pwallet);
2159 pwallet->TopUpKeyPool(kpSize);
2161 if (pwallet->GetKeyPoolSize() < kpSize) {
2162 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
2165 return NullUniValue;
2169 static void LockWallet(CWallet* pWallet)
2171 LOCK(pWallet->cs_wallet);
2172 pWallet->nRelockTime = 0;
2173 pWallet->Lock();
2176 UniValue walletpassphrase(const JSONRPCRequest& request)
2178 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2179 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2180 return NullUniValue;
2183 if (request.fHelp || request.params.size() != 2) {
2184 throw std::runtime_error(
2185 "walletpassphrase \"passphrase\" timeout\n"
2186 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
2187 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
2188 "\nArguments:\n"
2189 "1. \"passphrase\" (string, required) The wallet passphrase\n"
2190 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
2191 "\nNote:\n"
2192 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
2193 "time that overrides the old one.\n"
2194 "\nExamples:\n"
2195 "\nUnlock the wallet for 60 seconds\n"
2196 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
2197 "\nLock the wallet again (before 60 seconds)\n"
2198 + HelpExampleCli("walletlock", "") +
2199 "\nAs json rpc call\n"
2200 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
2204 LOCK2(cs_main, pwallet->cs_wallet);
2206 if (request.fHelp)
2207 return true;
2208 if (!pwallet->IsCrypted()) {
2209 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
2212 // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
2213 SecureString strWalletPass;
2214 strWalletPass.reserve(100);
2215 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2216 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2217 strWalletPass = request.params[0].get_str().c_str();
2219 if (strWalletPass.length() > 0)
2221 if (!pwallet->Unlock(strWalletPass)) {
2222 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2225 else
2226 throw std::runtime_error(
2227 "walletpassphrase <passphrase> <timeout>\n"
2228 "Stores the wallet decryption key in memory for <timeout> seconds.");
2230 pwallet->TopUpKeyPool();
2232 int64_t nSleepTime = request.params[1].get_int64();
2233 pwallet->nRelockTime = GetTime() + nSleepTime;
2234 RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime);
2236 return NullUniValue;
2240 UniValue walletpassphrasechange(const JSONRPCRequest& request)
2242 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2243 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2244 return NullUniValue;
2247 if (request.fHelp || request.params.size() != 2) {
2248 throw std::runtime_error(
2249 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
2250 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
2251 "\nArguments:\n"
2252 "1. \"oldpassphrase\" (string) The current passphrase\n"
2253 "2. \"newpassphrase\" (string) The new passphrase\n"
2254 "\nExamples:\n"
2255 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
2256 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
2260 LOCK2(cs_main, pwallet->cs_wallet);
2262 if (request.fHelp)
2263 return true;
2264 if (!pwallet->IsCrypted()) {
2265 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
2268 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
2269 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2270 SecureString strOldWalletPass;
2271 strOldWalletPass.reserve(100);
2272 strOldWalletPass = request.params[0].get_str().c_str();
2274 SecureString strNewWalletPass;
2275 strNewWalletPass.reserve(100);
2276 strNewWalletPass = request.params[1].get_str().c_str();
2278 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
2279 throw std::runtime_error(
2280 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
2281 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
2283 if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {
2284 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2287 return NullUniValue;
2291 UniValue walletlock(const JSONRPCRequest& request)
2293 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2294 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2295 return NullUniValue;
2298 if (request.fHelp || request.params.size() != 0) {
2299 throw std::runtime_error(
2300 "walletlock\n"
2301 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2302 "After calling this method, you will need to call walletpassphrase again\n"
2303 "before being able to call any methods which require the wallet to be unlocked.\n"
2304 "\nExamples:\n"
2305 "\nSet the passphrase for 2 minutes to perform a transaction\n"
2306 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2307 "\nPerform a send (requires passphrase set)\n"
2308 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2309 "\nClear the passphrase since we are done before 2 minutes is up\n"
2310 + HelpExampleCli("walletlock", "") +
2311 "\nAs json rpc call\n"
2312 + HelpExampleRpc("walletlock", "")
2316 LOCK2(cs_main, pwallet->cs_wallet);
2318 if (request.fHelp)
2319 return true;
2320 if (!pwallet->IsCrypted()) {
2321 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2324 pwallet->Lock();
2325 pwallet->nRelockTime = 0;
2327 return NullUniValue;
2331 UniValue encryptwallet(const JSONRPCRequest& request)
2333 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2334 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2335 return NullUniValue;
2338 if (request.fHelp || request.params.size() != 1) {
2339 throw std::runtime_error(
2340 "encryptwallet \"passphrase\"\n"
2341 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2342 "After this, any calls that interact with private keys such as sending or signing \n"
2343 "will require the passphrase to be set prior the making these calls.\n"
2344 "Use the walletpassphrase call for this, and then walletlock call.\n"
2345 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2346 "Note that this will shutdown the server.\n"
2347 "\nArguments:\n"
2348 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2349 "\nExamples:\n"
2350 "\nEncrypt your wallet\n"
2351 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2352 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
2353 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2354 "\nNow we can do something like sign\n"
2355 + HelpExampleCli("signmessage", "\"address\" \"test message\"") +
2356 "\nNow lock the wallet again by removing the passphrase\n"
2357 + HelpExampleCli("walletlock", "") +
2358 "\nAs a json rpc call\n"
2359 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2363 LOCK2(cs_main, pwallet->cs_wallet);
2365 if (request.fHelp)
2366 return true;
2367 if (pwallet->IsCrypted()) {
2368 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2371 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2372 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2373 SecureString strWalletPass;
2374 strWalletPass.reserve(100);
2375 strWalletPass = request.params[0].get_str().c_str();
2377 if (strWalletPass.length() < 1)
2378 throw std::runtime_error(
2379 "encryptwallet <passphrase>\n"
2380 "Encrypts the wallet with <passphrase>.");
2382 if (!pwallet->EncryptWallet(strWalletPass)) {
2383 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2386 // BDB seems to have a bad habit of writing old data into
2387 // slack space in .dat files; that is bad if the old data is
2388 // unencrypted private keys. So:
2389 StartShutdown();
2390 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
2393 UniValue lockunspent(const JSONRPCRequest& request)
2395 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2396 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2397 return NullUniValue;
2400 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2401 throw std::runtime_error(
2402 "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
2403 "\nUpdates list of temporarily unspendable outputs.\n"
2404 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2405 "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
2406 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2407 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2408 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2409 "Also see the listunspent call\n"
2410 "\nArguments:\n"
2411 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2412 "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
2413 " [ (json array of json objects)\n"
2414 " {\n"
2415 " \"txid\":\"id\", (string) The transaction id\n"
2416 " \"vout\": n (numeric) The output number\n"
2417 " }\n"
2418 " ,...\n"
2419 " ]\n"
2421 "\nResult:\n"
2422 "true|false (boolean) Whether the command was successful or not\n"
2424 "\nExamples:\n"
2425 "\nList the unspent transactions\n"
2426 + HelpExampleCli("listunspent", "") +
2427 "\nLock an unspent transaction\n"
2428 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2429 "\nList the locked transactions\n"
2430 + HelpExampleCli("listlockunspent", "") +
2431 "\nUnlock the transaction again\n"
2432 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2433 "\nAs a json rpc call\n"
2434 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2437 LOCK2(cs_main, pwallet->cs_wallet);
2439 RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
2441 bool fUnlock = request.params[0].get_bool();
2443 if (request.params[1].isNull()) {
2444 if (fUnlock)
2445 pwallet->UnlockAllCoins();
2446 return true;
2449 RPCTypeCheckArgument(request.params[1], UniValue::VARR);
2451 UniValue outputs = request.params[1].get_array();
2452 for (unsigned int idx = 0; idx < outputs.size(); idx++) {
2453 const UniValue& output = outputs[idx];
2454 if (!output.isObject())
2455 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2456 const UniValue& o = output.get_obj();
2458 RPCTypeCheckObj(o,
2460 {"txid", UniValueType(UniValue::VSTR)},
2461 {"vout", UniValueType(UniValue::VNUM)},
2464 std::string txid = find_value(o, "txid").get_str();
2465 if (!IsHex(txid))
2466 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2468 int nOutput = find_value(o, "vout").get_int();
2469 if (nOutput < 0)
2470 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2472 COutPoint outpt(uint256S(txid), nOutput);
2474 if (fUnlock)
2475 pwallet->UnlockCoin(outpt);
2476 else
2477 pwallet->LockCoin(outpt);
2480 return true;
2483 UniValue listlockunspent(const JSONRPCRequest& request)
2485 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2486 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2487 return NullUniValue;
2490 if (request.fHelp || request.params.size() > 0)
2491 throw std::runtime_error(
2492 "listlockunspent\n"
2493 "\nReturns list of temporarily unspendable outputs.\n"
2494 "See the lockunspent call to lock and unlock transactions for spending.\n"
2495 "\nResult:\n"
2496 "[\n"
2497 " {\n"
2498 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2499 " \"vout\" : n (numeric) The vout value\n"
2500 " }\n"
2501 " ,...\n"
2502 "]\n"
2503 "\nExamples:\n"
2504 "\nList the unspent transactions\n"
2505 + HelpExampleCli("listunspent", "") +
2506 "\nLock an unspent transaction\n"
2507 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2508 "\nList the locked transactions\n"
2509 + HelpExampleCli("listlockunspent", "") +
2510 "\nUnlock the transaction again\n"
2511 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2512 "\nAs a json rpc call\n"
2513 + HelpExampleRpc("listlockunspent", "")
2516 ObserveSafeMode();
2517 LOCK2(cs_main, pwallet->cs_wallet);
2519 std::vector<COutPoint> vOutpts;
2520 pwallet->ListLockedCoins(vOutpts);
2522 UniValue ret(UniValue::VARR);
2524 for (COutPoint &outpt : vOutpts) {
2525 UniValue o(UniValue::VOBJ);
2527 o.push_back(Pair("txid", outpt.hash.GetHex()));
2528 o.push_back(Pair("vout", (int)outpt.n));
2529 ret.push_back(o);
2532 return ret;
2535 UniValue settxfee(const JSONRPCRequest& request)
2537 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2538 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2539 return NullUniValue;
2542 if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
2543 throw std::runtime_error(
2544 "settxfee amount\n"
2545 "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
2546 "\nArguments:\n"
2547 "1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
2548 "\nResult\n"
2549 "true|false (boolean) Returns true if successful\n"
2550 "\nExamples:\n"
2551 + HelpExampleCli("settxfee", "0.00001")
2552 + HelpExampleRpc("settxfee", "0.00001")
2555 LOCK2(cs_main, pwallet->cs_wallet);
2557 // Amount
2558 CAmount nAmount = AmountFromValue(request.params[0]);
2560 payTxFee = CFeeRate(nAmount, 1000);
2561 return true;
2564 UniValue getwalletinfo(const JSONRPCRequest& request)
2566 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2567 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2568 return NullUniValue;
2571 if (request.fHelp || request.params.size() != 0)
2572 throw std::runtime_error(
2573 "getwalletinfo\n"
2574 "Returns an object containing various wallet state info.\n"
2575 "\nResult:\n"
2576 "{\n"
2577 " \"walletname\": xxxxx, (string) the wallet name\n"
2578 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2579 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2580 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2581 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2582 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2583 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
2584 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
2585 " \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n"
2586 " \"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"
2587 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2588 " \"hdmasterkeyid\": \"<hash160>\" (string) the Hash160 of the HD master pubkey\n"
2589 "}\n"
2590 "\nExamples:\n"
2591 + HelpExampleCli("getwalletinfo", "")
2592 + HelpExampleRpc("getwalletinfo", "")
2595 ObserveSafeMode();
2596 LOCK2(cs_main, pwallet->cs_wallet);
2598 UniValue obj(UniValue::VOBJ);
2600 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
2601 obj.push_back(Pair("walletname", pwallet->GetName()));
2602 obj.push_back(Pair("walletversion", pwallet->GetVersion()));
2603 obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
2604 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance())));
2605 obj.push_back(Pair("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance())));
2606 obj.push_back(Pair("txcount", (int)pwallet->mapWallet.size()));
2607 obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
2608 obj.push_back(Pair("keypoolsize", (int64_t)kpExternalSize));
2609 CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
2610 if (!masterKeyID.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2611 obj.push_back(Pair("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize)));
2613 if (pwallet->IsCrypted()) {
2614 obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
2616 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2617 if (!masterKeyID.IsNull())
2618 obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
2619 return obj;
2622 UniValue listwallets(const JSONRPCRequest& request)
2624 if (request.fHelp || request.params.size() != 0)
2625 throw std::runtime_error(
2626 "listwallets\n"
2627 "Returns a list of currently loaded wallets.\n"
2628 "For full information on the wallet, use \"getwalletinfo\"\n"
2629 "\nResult:\n"
2630 "[ (json array of strings)\n"
2631 " \"walletname\" (string) the wallet name\n"
2632 " ...\n"
2633 "]\n"
2634 "\nExamples:\n"
2635 + HelpExampleCli("listwallets", "")
2636 + HelpExampleRpc("listwallets", "")
2639 UniValue obj(UniValue::VARR);
2641 for (CWalletRef pwallet : vpwallets) {
2643 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2644 return NullUniValue;
2647 LOCK(pwallet->cs_wallet);
2649 obj.push_back(pwallet->GetName());
2652 return obj;
2655 UniValue resendwallettransactions(const JSONRPCRequest& request)
2657 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2658 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2659 return NullUniValue;
2662 if (request.fHelp || request.params.size() != 0)
2663 throw std::runtime_error(
2664 "resendwallettransactions\n"
2665 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2666 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2667 "automatically.\n"
2668 "Returns an RPC error if -walletbroadcast is set to false.\n"
2669 "Returns array of transaction ids that were re-broadcast.\n"
2672 if (!g_connman)
2673 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
2675 LOCK2(cs_main, pwallet->cs_wallet);
2677 if (!pwallet->GetBroadcastTransactions()) {
2678 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast");
2681 std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
2682 UniValue result(UniValue::VARR);
2683 for (const uint256& txid : txids)
2685 result.push_back(txid.ToString());
2687 return result;
2690 UniValue listunspent(const JSONRPCRequest& request)
2692 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2693 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2694 return NullUniValue;
2697 if (request.fHelp || request.params.size() > 5)
2698 throw std::runtime_error(
2699 "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n"
2700 "\nReturns array of unspent transaction outputs\n"
2701 "with between minconf and maxconf (inclusive) confirmations.\n"
2702 "Optionally filter to only include txouts paid to specified addresses.\n"
2703 "\nArguments:\n"
2704 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2705 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2706 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2707 " [\n"
2708 " \"address\" (string) bitcoin address\n"
2709 " ,...\n"
2710 " ]\n"
2711 "4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
2712 " See description of \"safe\" attribute below.\n"
2713 "5. query_options (json, optional) JSON with query options\n"
2714 " {\n"
2715 " \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n"
2716 " \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
2717 " \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
2718 " \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
2719 " }\n"
2720 "\nResult\n"
2721 "[ (array of json object)\n"
2722 " {\n"
2723 " \"txid\" : \"txid\", (string) the transaction id \n"
2724 " \"vout\" : n, (numeric) the vout value\n"
2725 " \"address\" : \"address\", (string) the bitcoin address\n"
2726 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2727 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2728 " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
2729 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2730 " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
2731 " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n"
2732 " \"solvable\" : xxx, (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
2733 " \"safe\" : xxx (bool) Whether this output is considered safe to spend. Unconfirmed transactions\n"
2734 " from outside keys and unconfirmed replacement transactions are considered unsafe\n"
2735 " and are not eligible for spending by fundrawtransaction and sendtoaddress.\n"
2736 " }\n"
2737 " ,...\n"
2738 "]\n"
2740 "\nExamples\n"
2741 + HelpExampleCli("listunspent", "")
2742 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2743 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2744 + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
2745 + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
2748 ObserveSafeMode();
2750 int nMinDepth = 1;
2751 if (!request.params[0].isNull()) {
2752 RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
2753 nMinDepth = request.params[0].get_int();
2756 int nMaxDepth = 9999999;
2757 if (!request.params[1].isNull()) {
2758 RPCTypeCheckArgument(request.params[1], UniValue::VNUM);
2759 nMaxDepth = request.params[1].get_int();
2762 std::set<CTxDestination> destinations;
2763 if (!request.params[2].isNull()) {
2764 RPCTypeCheckArgument(request.params[2], UniValue::VARR);
2765 UniValue inputs = request.params[2].get_array();
2766 for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2767 const UniValue& input = inputs[idx];
2768 CTxDestination dest = DecodeDestination(input.get_str());
2769 if (!IsValidDestination(dest)) {
2770 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
2772 if (!destinations.insert(dest).second) {
2773 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
2778 bool include_unsafe = true;
2779 if (!request.params[3].isNull()) {
2780 RPCTypeCheckArgument(request.params[3], UniValue::VBOOL);
2781 include_unsafe = request.params[3].get_bool();
2784 CAmount nMinimumAmount = 0;
2785 CAmount nMaximumAmount = MAX_MONEY;
2786 CAmount nMinimumSumAmount = MAX_MONEY;
2787 uint64_t nMaximumCount = 0;
2789 if (!request.params[4].isNull()) {
2790 const UniValue& options = request.params[4].get_obj();
2792 if (options.exists("minimumAmount"))
2793 nMinimumAmount = AmountFromValue(options["minimumAmount"]);
2795 if (options.exists("maximumAmount"))
2796 nMaximumAmount = AmountFromValue(options["maximumAmount"]);
2798 if (options.exists("minimumSumAmount"))
2799 nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]);
2801 if (options.exists("maximumCount"))
2802 nMaximumCount = options["maximumCount"].get_int64();
2805 UniValue results(UniValue::VARR);
2806 std::vector<COutput> vecOutputs;
2807 assert(pwallet != nullptr);
2808 LOCK2(cs_main, pwallet->cs_wallet);
2810 pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
2811 for (const COutput& out : vecOutputs) {
2812 CTxDestination address;
2813 const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
2814 bool fValidAddress = ExtractDestination(scriptPubKey, address);
2816 if (destinations.size() && (!fValidAddress || !destinations.count(address)))
2817 continue;
2819 UniValue entry(UniValue::VOBJ);
2820 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2821 entry.push_back(Pair("vout", out.i));
2823 if (fValidAddress) {
2824 entry.push_back(Pair("address", EncodeDestination(address)));
2826 if (pwallet->mapAddressBook.count(address)) {
2827 entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
2830 if (scriptPubKey.IsPayToScriptHash()) {
2831 const CScriptID& hash = boost::get<CScriptID>(address);
2832 CScript redeemScript;
2833 if (pwallet->GetCScript(hash, redeemScript)) {
2834 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2839 entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2840 entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue)));
2841 entry.push_back(Pair("confirmations", out.nDepth));
2842 entry.push_back(Pair("spendable", out.fSpendable));
2843 entry.push_back(Pair("solvable", out.fSolvable));
2844 entry.push_back(Pair("safe", out.fSafe));
2845 results.push_back(entry);
2848 return results;
2851 UniValue fundrawtransaction(const JSONRPCRequest& request)
2853 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2854 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2855 return NullUniValue;
2858 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2859 throw std::runtime_error(
2860 "fundrawtransaction \"hexstring\" ( options )\n"
2861 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2862 "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
2863 "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
2864 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2865 "The inputs added will not be signed, use signrawtransaction for that.\n"
2866 "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
2867 "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
2868 "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
2869 "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
2870 "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
2871 "\nArguments:\n"
2872 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
2873 "2. options (object, optional)\n"
2874 " {\n"
2875 " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
2876 " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
2877 " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
2878 " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
2879 " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
2880 " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
2881 " The fee will be equally deducted from the amount of each specified output.\n"
2882 " The outputs are specified by their zero-based index, before any change output is added.\n"
2883 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
2884 " If no outputs are specified here, the sender pays the fee.\n"
2885 " [vout_index,...]\n"
2886 " \"replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n"
2887 " Allows this transaction to be replaced by a transaction with higher fees\n"
2888 " \"conf_target\" (numeric, optional) Confirmation target (in blocks)\n"
2889 " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
2890 " \"UNSET\"\n"
2891 " \"ECONOMICAL\"\n"
2892 " \"CONSERVATIVE\"\n"
2893 " }\n"
2894 " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
2895 "\nResult:\n"
2896 "{\n"
2897 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
2898 " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
2899 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
2900 "}\n"
2901 "\nExamples:\n"
2902 "\nCreate a transaction with no inputs\n"
2903 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2904 "\nAdd sufficient unsigned inputs to meet the output value\n"
2905 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2906 "\nSign the transaction\n"
2907 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2908 "\nSend the transaction\n"
2909 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2912 ObserveSafeMode();
2913 RPCTypeCheck(request.params, {UniValue::VSTR});
2915 CCoinControl coinControl;
2916 int changePosition = -1;
2917 bool lockUnspents = false;
2918 UniValue subtractFeeFromOutputs;
2919 std::set<int> setSubtractFeeFromOutputs;
2921 if (!request.params[1].isNull()) {
2922 if (request.params[1].type() == UniValue::VBOOL) {
2923 // backward compatibility bool only fallback
2924 coinControl.fAllowWatchOnly = request.params[1].get_bool();
2926 else {
2927 RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
2929 UniValue options = request.params[1];
2931 RPCTypeCheckObj(options,
2933 {"changeAddress", UniValueType(UniValue::VSTR)},
2934 {"changePosition", UniValueType(UniValue::VNUM)},
2935 {"includeWatching", UniValueType(UniValue::VBOOL)},
2936 {"lockUnspents", UniValueType(UniValue::VBOOL)},
2937 {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so.
2938 {"feeRate", UniValueType()}, // will be checked below
2939 {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
2940 {"replaceable", UniValueType(UniValue::VBOOL)},
2941 {"conf_target", UniValueType(UniValue::VNUM)},
2942 {"estimate_mode", UniValueType(UniValue::VSTR)},
2944 true, true);
2946 if (options.exists("changeAddress")) {
2947 CTxDestination dest = DecodeDestination(options["changeAddress"].get_str());
2949 if (!IsValidDestination(dest)) {
2950 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
2953 coinControl.destChange = dest;
2956 if (options.exists("changePosition"))
2957 changePosition = options["changePosition"].get_int();
2959 if (options.exists("includeWatching"))
2960 coinControl.fAllowWatchOnly = options["includeWatching"].get_bool();
2962 if (options.exists("lockUnspents"))
2963 lockUnspents = options["lockUnspents"].get_bool();
2965 if (options.exists("feeRate"))
2967 coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"]));
2968 coinControl.fOverrideFeeRate = true;
2971 if (options.exists("subtractFeeFromOutputs"))
2972 subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
2974 if (options.exists("replaceable")) {
2975 coinControl.signalRbf = options["replaceable"].get_bool();
2977 if (options.exists("conf_target")) {
2978 if (options.exists("feeRate")) {
2979 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate");
2981 coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]);
2983 if (options.exists("estimate_mode")) {
2984 if (options.exists("feeRate")) {
2985 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
2987 if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) {
2988 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
2994 // parse hex string from parameter
2995 CMutableTransaction tx;
2996 if (!DecodeHexTx(tx, request.params[0].get_str(), true))
2997 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2999 if (tx.vout.size() == 0)
3000 throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
3002 if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > tx.vout.size()))
3003 throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
3005 for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3006 int pos = subtractFeeFromOutputs[idx].get_int();
3007 if (setSubtractFeeFromOutputs.count(pos))
3008 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
3009 if (pos < 0)
3010 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
3011 if (pos >= int(tx.vout.size()))
3012 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
3013 setSubtractFeeFromOutputs.insert(pos);
3016 CAmount nFeeOut;
3017 std::string strFailReason;
3019 if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
3020 throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
3023 UniValue result(UniValue::VOBJ);
3024 result.push_back(Pair("hex", EncodeHexTx(tx)));
3025 result.push_back(Pair("changepos", changePosition));
3026 result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
3028 return result;
3031 UniValue bumpfee(const JSONRPCRequest& request)
3033 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3035 if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3036 return NullUniValue;
3038 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
3039 throw std::runtime_error(
3040 "bumpfee \"txid\" ( options ) \n"
3041 "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
3042 "An opt-in RBF transaction with the given txid must be in the wallet.\n"
3043 "The command will pay the additional fee by decreasing (or perhaps removing) its change output.\n"
3044 "If the change output is not big enough to cover the increased fee, the command will currently fail\n"
3045 "instead of adding new inputs to compensate. (A future implementation could improve this.)\n"
3046 "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
3047 "By default, the new fee will be calculated automatically using estimatefee.\n"
3048 "The user can specify a confirmation target for estimatefee.\n"
3049 "Alternatively, the user can specify totalFee, or use RPC settxfee to set a higher fee rate.\n"
3050 "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
3051 "returned by getnetworkinfo) to enter the node's mempool.\n"
3052 "\nArguments:\n"
3053 "1. txid (string, required) The txid to be bumped\n"
3054 "2. options (object, optional)\n"
3055 " {\n"
3056 " \"confTarget\" (numeric, optional) Confirmation target (in blocks)\n"
3057 " \"totalFee\" (numeric, optional) Total fee (NOT feerate) to pay, in satoshis.\n"
3058 " In rare cases, the actual fee paid might be slightly higher than the specified\n"
3059 " totalFee if the tx change output has to be removed because it is too close to\n"
3060 " the dust threshold.\n"
3061 " \"replaceable\" (boolean, optional, default true) Whether the new transaction should still be\n"
3062 " marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
3063 " be left unchanged from the original. If false, any input sequence numbers in the\n"
3064 " original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
3065 " so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
3066 " still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
3067 " are replaceable).\n"
3068 " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
3069 " \"UNSET\"\n"
3070 " \"ECONOMICAL\"\n"
3071 " \"CONSERVATIVE\"\n"
3072 " }\n"
3073 "\nResult:\n"
3074 "{\n"
3075 " \"txid\": \"value\", (string) The id of the new transaction\n"
3076 " \"origfee\": n, (numeric) Fee of the replaced transaction\n"
3077 " \"fee\": n, (numeric) Fee of the new transaction\n"
3078 " \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty)\n"
3079 "}\n"
3080 "\nExamples:\n"
3081 "\nBump the fee, get the new transaction\'s txid\n" +
3082 HelpExampleCli("bumpfee", "<txid>"));
3085 RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
3086 uint256 hash;
3087 hash.SetHex(request.params[0].get_str());
3089 // optional parameters
3090 CAmount totalFee = 0;
3091 CCoinControl coin_control;
3092 coin_control.signalRbf = true;
3093 if (!request.params[1].isNull()) {
3094 UniValue options = request.params[1];
3095 RPCTypeCheckObj(options,
3097 {"confTarget", UniValueType(UniValue::VNUM)},
3098 {"totalFee", UniValueType(UniValue::VNUM)},
3099 {"replaceable", UniValueType(UniValue::VBOOL)},
3100 {"estimate_mode", UniValueType(UniValue::VSTR)},
3102 true, true);
3104 if (options.exists("confTarget") && options.exists("totalFee")) {
3105 throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
3106 } else if (options.exists("confTarget")) { // TODO: alias this to conf_target
3107 coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"]);
3108 } else if (options.exists("totalFee")) {
3109 totalFee = options["totalFee"].get_int64();
3110 if (totalFee <= 0) {
3111 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee %s (must be greater than 0)", FormatMoney(totalFee)));
3115 if (options.exists("replaceable")) {
3116 coin_control.signalRbf = options["replaceable"].get_bool();
3118 if (options.exists("estimate_mode")) {
3119 if (!FeeModeFromString(options["estimate_mode"].get_str(), coin_control.m_fee_mode)) {
3120 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
3125 LOCK2(cs_main, pwallet->cs_wallet);
3126 EnsureWalletIsUnlocked(pwallet);
3128 CFeeBumper feeBump(pwallet, hash, coin_control, totalFee);
3129 BumpFeeResult res = feeBump.getResult();
3130 if (res != BumpFeeResult::OK)
3132 switch(res) {
3133 case BumpFeeResult::INVALID_ADDRESS_OR_KEY:
3134 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, feeBump.getErrors()[0]);
3135 break;
3136 case BumpFeeResult::INVALID_REQUEST:
3137 throw JSONRPCError(RPC_INVALID_REQUEST, feeBump.getErrors()[0]);
3138 break;
3139 case BumpFeeResult::INVALID_PARAMETER:
3140 throw JSONRPCError(RPC_INVALID_PARAMETER, feeBump.getErrors()[0]);
3141 break;
3142 case BumpFeeResult::WALLET_ERROR:
3143 throw JSONRPCError(RPC_WALLET_ERROR, feeBump.getErrors()[0]);
3144 break;
3145 default:
3146 throw JSONRPCError(RPC_MISC_ERROR, feeBump.getErrors()[0]);
3147 break;
3151 // sign bumped transaction
3152 if (!feeBump.signTransaction(pwallet)) {
3153 throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
3155 // commit the bumped transaction
3156 if(!feeBump.commit(pwallet)) {
3157 throw JSONRPCError(RPC_WALLET_ERROR, feeBump.getErrors()[0]);
3159 UniValue result(UniValue::VOBJ);
3160 result.push_back(Pair("txid", feeBump.getBumpedTxId().GetHex()));
3161 result.push_back(Pair("origfee", ValueFromAmount(feeBump.getOldFee())));
3162 result.push_back(Pair("fee", ValueFromAmount(feeBump.getNewFee())));
3163 UniValue errors(UniValue::VARR);
3164 for (const std::string& err: feeBump.getErrors())
3165 errors.push_back(err);
3166 result.push_back(Pair("errors", errors));
3168 return result;
3171 UniValue generate(const JSONRPCRequest& request)
3173 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3175 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3176 return NullUniValue;
3179 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
3180 throw std::runtime_error(
3181 "generate nblocks ( maxtries )\n"
3182 "\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n"
3183 "\nArguments:\n"
3184 "1. nblocks (numeric, required) How many blocks are generated immediately.\n"
3185 "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
3186 "\nResult:\n"
3187 "[ blockhashes ] (array) hashes of blocks generated\n"
3188 "\nExamples:\n"
3189 "\nGenerate 11 blocks\n"
3190 + HelpExampleCli("generate", "11")
3194 int num_generate = request.params[0].get_int();
3195 uint64_t max_tries = 1000000;
3196 if (!request.params[1].isNull()) {
3197 max_tries = request.params[1].get_int();
3200 std::shared_ptr<CReserveScript> coinbase_script;
3201 pwallet->GetScriptForMining(coinbase_script);
3203 // If the keypool is exhausted, no script is returned at all. Catch this.
3204 if (!coinbase_script) {
3205 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
3208 //throw an error if no script was provided
3209 if (coinbase_script->reserveScript.empty()) {
3210 throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available");
3213 return generateBlocks(coinbase_script, num_generate, max_tries, true);
3216 UniValue rescanblockchain(const JSONRPCRequest& request)
3218 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3219 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3220 return NullUniValue;
3223 if (request.fHelp || request.params.size() > 2) {
3224 throw std::runtime_error(
3225 "rescanblockchain (\"start_height\") (\"stop_height\")\n"
3226 "\nRescan the local blockchain for wallet related transactions.\n"
3227 "\nArguments:\n"
3228 "1. \"start_height\" (numeric, optional) block height where the rescan should start\n"
3229 "2. \"stop_height\" (numeric, optional) the last block height that should be scanned\n"
3230 "\nResult:\n"
3231 "{\n"
3232 " \"start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
3233 " \"stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
3234 "}\n"
3235 "\nExamples:\n"
3236 + HelpExampleCli("rescanblockchain", "100000 120000")
3237 + HelpExampleRpc("rescanblockchain", "100000, 120000")
3241 LOCK2(cs_main, pwallet->cs_wallet);
3243 CBlockIndex *pindexStart = chainActive.Genesis();
3244 CBlockIndex *pindexStop = nullptr;
3245 if (!request.params[0].isNull()) {
3246 pindexStart = chainActive[request.params[0].get_int()];
3247 if (!pindexStart) {
3248 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
3252 if (!request.params[1].isNull()) {
3253 pindexStop = chainActive[request.params[1].get_int()];
3254 if (!pindexStop) {
3255 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
3257 else if (pindexStop->nHeight < pindexStart->nHeight) {
3258 throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height");
3262 // We can't rescan beyond non-pruned blocks, stop and throw an error
3263 if (fPruneMode) {
3264 CBlockIndex *block = pindexStop ? pindexStop : chainActive.Tip();
3265 while (block && block->nHeight >= pindexStart->nHeight) {
3266 if (!(block->nStatus & BLOCK_HAVE_DATA)) {
3267 throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
3269 block = block->pprev;
3273 CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, true);
3274 if (!stopBlock) {
3275 if (pwallet->IsAbortingRescan()) {
3276 throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
3278 // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
3279 stopBlock = pindexStop ? pindexStop : chainActive.Tip();
3281 else {
3282 throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
3285 UniValue response(UniValue::VOBJ);
3286 response.pushKV("start_height", pindexStart->nHeight);
3287 response.pushKV("stop_height", stopBlock->nHeight);
3288 return response;
3291 extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
3292 extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
3293 extern UniValue importprivkey(const JSONRPCRequest& request);
3294 extern UniValue importaddress(const JSONRPCRequest& request);
3295 extern UniValue importpubkey(const JSONRPCRequest& request);
3296 extern UniValue dumpwallet(const JSONRPCRequest& request);
3297 extern UniValue importwallet(const JSONRPCRequest& request);
3298 extern UniValue importprunedfunds(const JSONRPCRequest& request);
3299 extern UniValue removeprunedfunds(const JSONRPCRequest& request);
3300 extern UniValue importmulti(const JSONRPCRequest& request);
3301 extern UniValue rescanblockchain(const JSONRPCRequest& request);
3303 static const CRPCCommand commands[] =
3304 { // category name actor (function) argNames
3305 // --------------------- ------------------------ ----------------------- ----------
3306 { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} },
3307 { "hidden", "resendwallettransactions", &resendwallettransactions, {} },
3308 { "wallet", "abandontransaction", &abandontransaction, {"txid"} },
3309 { "wallet", "abortrescan", &abortrescan, {} },
3310 { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} },
3311 { "wallet", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
3312 { "wallet", "backupwallet", &backupwallet, {"destination"} },
3313 { "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
3314 { "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
3315 { "wallet", "dumpwallet", &dumpwallet, {"filename"} },
3316 { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
3317 { "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
3318 { "wallet", "getaccount", &getaccount, {"address"} },
3319 { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
3320 { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} },
3321 { "wallet", "getnewaddress", &getnewaddress, {"account"} },
3322 { "wallet", "getrawchangeaddress", &getrawchangeaddress, {} },
3323 { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} },
3324 { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
3325 { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
3326 { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
3327 { "wallet", "getwalletinfo", &getwalletinfo, {} },
3328 { "wallet", "importmulti", &importmulti, {"requests","options"} },
3329 { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
3330 { "wallet", "importwallet", &importwallet, {"filename"} },
3331 { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
3332 { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
3333 { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
3334 { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
3335 { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
3336 { "wallet", "listaddressgroupings", &listaddressgroupings, {} },
3337 { "wallet", "listlockunspent", &listlockunspent, {} },
3338 { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} },
3339 { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly"} },
3340 { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
3341 { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} },
3342 { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
3343 { "wallet", "listwallets", &listwallets, {} },
3344 { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
3345 { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
3346 { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
3347 { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
3348 { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
3349 { "wallet", "setaccount", &setaccount, {"address","account"} },
3350 { "wallet", "settxfee", &settxfee, {"amount"} },
3351 { "wallet", "signmessage", &signmessage, {"address","message"} },
3352 { "wallet", "walletlock", &walletlock, {} },
3353 { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
3354 { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
3355 { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
3356 { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
3358 { "generating", "generate", &generate, {"nblocks","maxtries"} },
3361 void RegisterWalletRPCCommands(CRPCTable &t)
3363 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
3364 t.appendCommand(commands[vcidx].name, &commands[vcidx]);