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