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