]> Git Repo - VerusCoin.git/blame - src/wallet/rpcwallet.cpp
Add symlinks to the params files for testnet3.
[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"
19
20#include <stdint.h>
21
22#include <boost/assign/list_of.hpp>
25cf6f3d 23
51ed9ec9
BD
24#include "json/json_spirit_utils.h"
25#include "json/json_spirit_value.h"
e3bc5698 26
e3bc5698 27using namespace std;
fdbb537d 28using namespace json_spirit;
e3bc5698 29
51ed9ec9 30int64_t nWalletUnlockTime;
e3bc5698
JG
31static CCriticalSection cs_nWalletUnlockTime;
32
bdab0cf5 33std::string HelpRequiringPassphrase()
e3bc5698 34{
b0730874 35 return pwalletMain && pwalletMain->IsCrypted()
a6099ef3 36 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
e3bc5698
JG
37 : "";
38}
39
b9fb692d
JS
40bool EnsureWalletIsAvailable(bool avoidException)
41{
42 if (!pwalletMain)
43 {
44 if (!avoidException)
45 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
46 else
47 return false;
48 }
49 return true;
50}
51
bdab0cf5 52void EnsureWalletIsUnlocked()
e3bc5698
JG
53{
54 if (pwalletMain->IsLocked())
738835d7 55 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
e3bc5698
JG
56}
57
58void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
59{
60 int confirms = wtx.GetDepthInMainChain();
61 entry.push_back(Pair("confirmations", confirms));
e07c8e91
LD
62 if (wtx.IsCoinBase())
63 entry.push_back(Pair("generated", true));
2b72d46f 64 if (confirms > 0)
e3bc5698
JG
65 {
66 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
67 entry.push_back(Pair("blockindex", wtx.nIndex));
209377a7 68 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
e3bc5698 69 }
731b89b8
GA
70 uint256 hash = wtx.GetHash();
71 entry.push_back(Pair("txid", hash.GetHex()));
72 Array conflicts;
73 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
74 conflicts.push_back(conflict.GetHex());
75 entry.push_back(Pair("walletconflicts", conflicts));
d56e30ca 76 entry.push_back(Pair("time", wtx.GetTxTime()));
4b61a6a4 77 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
e3bc5698
JG
78 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
79 entry.push_back(Pair(item.first, item.second));
80}
81
82string AccountFromValue(const Value& value)
83{
84 string strAccount = value.get_str();
85 if (strAccount == "*")
738835d7 86 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
e3bc5698
JG
87 return strAccount;
88}
89
90Value getnewaddress(const Array& params, bool fHelp)
91{
b9fb692d
JS
92 if (!EnsureWalletIsAvailable(fHelp))
93 return Value::null;
94
e3bc5698
JG
95 if (fHelp || params.size() > 1)
96 throw runtime_error(
a6099ef3 97 "getnewaddress ( \"account\" )\n"
98 "\nReturns a new Bitcoin address for receiving payments.\n"
7b782f5b 99 "If 'account' is specified (DEPRECATED), it is added to the address book \n"
a6099ef3 100 "so payments received with the address will be credited to 'account'.\n"
101 "\nArguments:\n"
91a9fe09 102 "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
a6099ef3 103 "\nResult:\n"
104 "\"bitcoinaddress\" (string) The new bitcoin address\n"
105 "\nExamples:\n"
106 + HelpExampleCli("getnewaddress", "")
7b782f5b 107 + HelpExampleRpc("getnewaddress", "")
a6099ef3 108 );
e3bc5698 109
4401b2d7
EL
110 LOCK2(cs_main, pwalletMain->cs_wallet);
111
e3bc5698
JG
112 // Parse the account first so we don't generate a key if there's an error
113 string strAccount;
114 if (params.size() > 0)
115 strAccount = AccountFromValue(params[0]);
116
117 if (!pwalletMain->IsLocked())
118 pwalletMain->TopUpKeyPool();
119
120 // Generate a new key that is added to wallet
121 CPubKey newKey;
71ac5052 122 if (!pwalletMain->GetKeyFromPool(newKey))
738835d7 123 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
e3bc5698
JG
124 CKeyID keyID = newKey.GetID();
125
a41d5fe0 126 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
e3bc5698
JG
127
128 return CBitcoinAddress(keyID).ToString();
129}
130
131
132CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
133{
134 CWalletDB walletdb(pwalletMain->strWalletFile);
135
136 CAccount account;
137 walletdb.ReadAccount(strAccount, account);
138
139 bool bKeyUsed = false;
140
141 // Check if the current key has been used
142 if (account.vchPubKey.IsValid())
143 {
0be990ba 144 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
e3bc5698
JG
145 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
146 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
147 ++it)
148 {
149 const CWalletTx& wtx = (*it).second;
150 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
151 if (txout.scriptPubKey == scriptPubKey)
152 bKeyUsed = true;
153 }
154 }
155
156 // Generate a new key
157 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
158 {
71ac5052 159 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
738835d7 160 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
e3bc5698 161
a41d5fe0 162 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
e3bc5698
JG
163 walletdb.WriteAccount(strAccount, account);
164 }
165
166 return CBitcoinAddress(account.vchPubKey.GetID());
167}
168
169Value getaccountaddress(const Array& params, bool fHelp)
170{
b9fb692d
JS
171 if (!EnsureWalletIsAvailable(fHelp))
172 return Value::null;
173
e3bc5698
JG
174 if (fHelp || params.size() != 1)
175 throw runtime_error(
a6099ef3 176 "getaccountaddress \"account\"\n"
7b782f5b 177 "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
a6099ef3 178 "\nArguments:\n"
179 "1. \"account\" (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
180 "\nResult:\n"
181 "\"bitcoinaddress\" (string) The account bitcoin address\n"
182 "\nExamples:\n"
183 + HelpExampleCli("getaccountaddress", "")
184 + HelpExampleCli("getaccountaddress", "\"\"")
185 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
186 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
187 );
e3bc5698 188
4401b2d7
EL
189 LOCK2(cs_main, pwalletMain->cs_wallet);
190
e3bc5698
JG
191 // Parse the account first so we don't generate a key if there's an error
192 string strAccount = AccountFromValue(params[0]);
193
194 Value ret;
195
196 ret = GetAccountAddress(strAccount).ToString();
e3bc5698
JG
197 return ret;
198}
199
200
e5e9904c
JG
201Value getrawchangeaddress(const Array& params, bool fHelp)
202{
b9fb692d
JS
203 if (!EnsureWalletIsAvailable(fHelp))
204 return Value::null;
205
e5e9904c
JG
206 if (fHelp || params.size() > 1)
207 throw runtime_error(
208 "getrawchangeaddress\n"
a6099ef3 209 "\nReturns a new Bitcoin address, for receiving change.\n"
210 "This is for use with raw transactions, NOT normal use.\n"
211 "\nResult:\n"
212 "\"address\" (string) The address\n"
213 "\nExamples:\n"
214 + HelpExampleCli("getrawchangeaddress", "")
215 + HelpExampleRpc("getrawchangeaddress", "")
216 );
e5e9904c 217
4401b2d7
EL
218 LOCK2(cs_main, pwalletMain->cs_wallet);
219
e5e9904c
JG
220 if (!pwalletMain->IsLocked())
221 pwalletMain->TopUpKeyPool();
222
223 CReserveKey reservekey(pwalletMain);
224 CPubKey vchPubKey;
225 if (!reservekey.GetReservedKey(vchPubKey))
6c37f7fd 226 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
e5e9904c
JG
227
228 reservekey.KeepKey();
229
230 CKeyID keyID = vchPubKey.GetID();
231
232 return CBitcoinAddress(keyID).ToString();
233}
234
e3bc5698
JG
235
236Value setaccount(const Array& params, bool fHelp)
237{
b9fb692d
JS
238 if (!EnsureWalletIsAvailable(fHelp))
239 return Value::null;
240
e3bc5698
JG
241 if (fHelp || params.size() < 1 || params.size() > 2)
242 throw runtime_error(
a6099ef3 243 "setaccount \"bitcoinaddress\" \"account\"\n"
7b782f5b 244 "\nDEPRECATED. Sets the account associated with the given address.\n"
a6099ef3 245 "\nArguments:\n"
246 "1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
247 "2. \"account\" (string, required) The account to assign the address to.\n"
248 "\nExamples:\n"
249 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
250 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
251 );
e3bc5698 252
4401b2d7
EL
253 LOCK2(cs_main, pwalletMain->cs_wallet);
254
e3bc5698
JG
255 CBitcoinAddress address(params[0].get_str());
256 if (!address.IsValid())
738835d7 257 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
e3bc5698 258
e3bc5698
JG
259 string strAccount;
260 if (params.size() > 1)
261 strAccount = AccountFromValue(params[1]);
262
31d6390f
ES
263 // Only add the account if the address is yours.
264 if (IsMine(*pwalletMain, address.Get()))
e3bc5698 265 {
31d6390f
ES
266 // Detect when changing the account of an address that is the 'unused current key' of another account:
267 if (pwalletMain->mapAddressBook.count(address.Get()))
268 {
269 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
270 if (address == GetAccountAddress(strOldAccount))
271 GetAccountAddress(strOldAccount, true);
272 }
273 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
e3bc5698 274 }
31d6390f
ES
275 else
276 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
e3bc5698
JG
277
278 return Value::null;
279}
280
281
282Value getaccount(const Array& params, bool fHelp)
283{
b9fb692d
JS
284 if (!EnsureWalletIsAvailable(fHelp))
285 return Value::null;
286
e3bc5698
JG
287 if (fHelp || params.size() != 1)
288 throw runtime_error(
a6099ef3 289 "getaccount \"bitcoinaddress\"\n"
7b782f5b 290 "\nDEPRECATED. Returns the account associated with the given address.\n"
a6099ef3 291 "\nArguments:\n"
292 "1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
293 "\nResult:\n"
294 "\"accountname\" (string) the account address\n"
295 "\nExamples:\n"
296 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
297 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
298 );
e3bc5698 299
4401b2d7
EL
300 LOCK2(cs_main, pwalletMain->cs_wallet);
301
e3bc5698
JG
302 CBitcoinAddress address(params[0].get_str());
303 if (!address.IsValid())
738835d7 304 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
e3bc5698
JG
305
306 string strAccount;
61885513
GA
307 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
308 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
309 strAccount = (*mi).second.name;
e3bc5698
JG
310 return strAccount;
311}
312
313
314Value getaddressesbyaccount(const Array& params, bool fHelp)
315{
b9fb692d
JS
316 if (!EnsureWalletIsAvailable(fHelp))
317 return Value::null;
318
e3bc5698
JG
319 if (fHelp || params.size() != 1)
320 throw runtime_error(
a6099ef3 321 "getaddressesbyaccount \"account\"\n"
7b782f5b 322 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
a6099ef3 323 "\nArguments:\n"
324 "1. \"account\" (string, required) The account name.\n"
325 "\nResult:\n"
326 "[ (json array of string)\n"
327 " \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
328 " ,...\n"
329 "]\n"
330 "\nExamples:\n"
331 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
332 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
333 );
e3bc5698 334
4401b2d7
EL
335 LOCK2(cs_main, pwalletMain->cs_wallet);
336
e3bc5698
JG
337 string strAccount = AccountFromValue(params[0]);
338
339 // Find all addresses that have the given account
340 Array ret;
61885513 341 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
e3bc5698
JG
342 {
343 const CBitcoinAddress& address = item.first;
61885513 344 const string& strName = item.second.name;
e3bc5698
JG
345 if (strName == strAccount)
346 ret.push_back(address.ToString());
347 }
348 return ret;
349}
350
292623ad 351static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
b93173de 352{
25cf6f3d
PK
353 CAmount curBalance = pwalletMain->GetBalance();
354
b93173de
PJ
355 // Check amount
356 if (nValue <= 0)
4be639ea 357 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
b93173de 358
25cf6f3d 359 if (nValue > curBalance)
b93173de
PJ
360 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
361
b93173de
PJ
362 // Parse Bitcoin address
363 CScript scriptPubKey = GetScriptForDestination(address);
364
365 // Create and send the transaction
366 CReserveKey reservekey(pwalletMain);
367 CAmount nFeeRequired;
25cf6f3d 368 std::string strError;
292623ad
CL
369 vector<CRecipient> vecSend;
370 int nChangePosRet = -1;
371 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
372 vecSend.push_back(recipient);
373 if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
374 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
375 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));
376 throw JSONRPCError(RPC_WALLET_ERROR, strError);
b93173de
PJ
377 }
378 if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
379 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
380}
381
e3bc5698
JG
382Value sendtoaddress(const Array& params, bool fHelp)
383{
b9fb692d
JS
384 if (!EnsureWalletIsAvailable(fHelp))
385 return Value::null;
386
292623ad 387 if (fHelp || params.size() < 2 || params.size() > 5)
e3bc5698 388 throw runtime_error(
292623ad 389 "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
e743678d 390 "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
a6099ef3 391 + HelpRequiringPassphrase() +
392 "\nArguments:\n"
393 "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
394 "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n"
395 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
396 " This is not part of the transaction, just kept in your wallet.\n"
397 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
398 " to which you're sending the transaction. This is not part of the \n"
399 " transaction, just kept in your wallet.\n"
292623ad
CL
400 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
401 " The recipient will receive less bitcoins than you enter in the amount field.\n"
a6099ef3 402 "\nResult:\n"
b5ef85c7 403 "\"transactionid\" (string) The transaction id.\n"
a6099ef3 404 "\nExamples:\n"
405 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
406 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
292623ad 407 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
a6099ef3 408 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
409 );
e3bc5698 410
4401b2d7
EL
411 LOCK2(cs_main, pwalletMain->cs_wallet);
412
e3bc5698
JG
413 CBitcoinAddress address(params[0].get_str());
414 if (!address.IsValid())
738835d7 415 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
e3bc5698
JG
416
417 // Amount
a372168e 418 CAmount nAmount = AmountFromValue(params[1]);
e3bc5698
JG
419
420 // Wallet comments
421 CWalletTx wtx;
422 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
423 wtx.mapValue["comment"] = params[2].get_str();
424 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
425 wtx.mapValue["to"] = params[3].get_str();
426
292623ad
CL
427 bool fSubtractFeeFromAmount = false;
428 if (params.size() > 4)
429 fSubtractFeeFromAmount = params[4].get_bool();
430
f914c7a1 431 EnsureWalletIsUnlocked();
e3bc5698 432
292623ad 433 SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
e3bc5698
JG
434
435 return wtx.GetHash().GetHex();
436}
437
22dfd735 438Value listaddressgroupings(const Array& params, bool fHelp)
439{
b9fb692d
JS
440 if (!EnsureWalletIsAvailable(fHelp))
441 return Value::null;
442
22dfd735 443 if (fHelp)
b1093efa
GM
444 throw runtime_error(
445 "listaddressgroupings\n"
a6099ef3 446 "\nLists groups of addresses which have had their common ownership\n"
b1093efa 447 "made public by common use as inputs or as the resulting change\n"
a6099ef3 448 "in past transactions\n"
449 "\nResult:\n"
450 "[\n"
451 " [\n"
452 " [\n"
453 " \"bitcoinaddress\", (string) The bitcoin address\n"
454 " amount, (numeric) The amount in btc\n"
7b782f5b 455 " \"account\" (string, optional) The account (DEPRECATED)\n"
a6099ef3 456 " ]\n"
457 " ,...\n"
458 " ]\n"
459 " ,...\n"
460 "]\n"
461 "\nExamples:\n"
462 + HelpExampleCli("listaddressgroupings", "")
463 + HelpExampleRpc("listaddressgroupings", "")
464 );
22dfd735 465
4401b2d7
EL
466 LOCK2(cs_main, pwalletMain->cs_wallet);
467
22dfd735 468 Array jsonGroupings;
a372168e 469 map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
b1093efa 470 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
22dfd735 471 {
472 Array jsonGrouping;
b1093efa 473 BOOST_FOREACH(CTxDestination address, grouping)
22dfd735 474 {
475 Array addressInfo;
b1093efa 476 addressInfo.push_back(CBitcoinAddress(address).ToString());
22dfd735 477 addressInfo.push_back(ValueFromAmount(balances[address]));
478 {
22dfd735 479 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
61885513 480 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
22dfd735 481 }
482 jsonGrouping.push_back(addressInfo);
483 }
484 jsonGroupings.push_back(jsonGrouping);
485 }
486 return jsonGroupings;
487}
488
e3bc5698
JG
489Value signmessage(const Array& params, bool fHelp)
490{
b9fb692d
JS
491 if (!EnsureWalletIsAvailable(fHelp))
492 return Value::null;
493
e3bc5698
JG
494 if (fHelp || params.size() != 2)
495 throw runtime_error(
a6099ef3 496 "signmessage \"bitcoinaddress\" \"message\"\n"
497 "\nSign a message with the private key of an address"
498 + HelpRequiringPassphrase() + "\n"
499 "\nArguments:\n"
500 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
501 "2. \"message\" (string, required) The message to create a signature of.\n"
502 "\nResult:\n"
503 "\"signature\" (string) The signature of the message encoded in base 64\n"
504 "\nExamples:\n"
505 "\nUnlock the wallet for 30 seconds\n"
506 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
507 "\nCreate the signature\n"
508 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
509 "\nVerify the signature\n"
510 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
511 "\nAs json rpc\n"
512 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
513 );
e3bc5698 514
4401b2d7
EL
515 LOCK2(cs_main, pwalletMain->cs_wallet);
516
e3bc5698
JG
517 EnsureWalletIsUnlocked();
518
519 string strAddress = params[0].get_str();
520 string strMessage = params[1].get_str();
521
522 CBitcoinAddress addr(strAddress);
523 if (!addr.IsValid())
738835d7 524 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
e3bc5698
JG
525
526 CKeyID keyID;
527 if (!addr.GetKeyID(keyID))
738835d7 528 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
e3bc5698
JG
529
530 CKey key;
531 if (!pwalletMain->GetKey(keyID, key))
738835d7 532 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
e3bc5698 533
8980a509 534 CHashWriter ss(SER_GETHASH, 0);
e3bc5698
JG
535 ss << strMessageMagic;
536 ss << strMessage;
537
538 vector<unsigned char> vchSig;
8980a509 539 if (!key.SignCompact(ss.GetHash(), vchSig))
738835d7 540 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
e3bc5698
JG
541
542 return EncodeBase64(&vchSig[0], vchSig.size());
543}
544
e3bc5698
JG
545Value getreceivedbyaddress(const Array& params, bool fHelp)
546{
b9fb692d
JS
547 if (!EnsureWalletIsAvailable(fHelp))
548 return Value::null;
549
e3bc5698
JG
550 if (fHelp || params.size() < 1 || params.size() > 2)
551 throw runtime_error(
a6099ef3 552 "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
553 "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
554 "\nArguments:\n"
555 "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
556 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
557 "\nResult:\n"
558 "amount (numeric) The total amount in btc received at this address.\n"
559 "\nExamples:\n"
560 "\nThe amount from transactions with at least 1 confirmation\n"
561 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
562 "\nThe amount including unconfirmed transactions, zero confirmations\n"
563 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
564 "\nThe amount with at least 6 confirmation, very safe\n"
565 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
566 "\nAs a json rpc call\n"
567 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
568 );
e3bc5698 569
4401b2d7
EL
570 LOCK2(cs_main, pwalletMain->cs_wallet);
571
e3bc5698
JG
572 // Bitcoin address
573 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
e3bc5698 574 if (!address.IsValid())
738835d7 575 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
0be990ba 576 CScript scriptPubKey = GetScriptForDestination(address.Get());
e3bc5698
JG
577 if (!IsMine(*pwalletMain,scriptPubKey))
578 return (double)0.0;
579
580 // Minimum confirmations
581 int nMinDepth = 1;
582 if (params.size() > 1)
583 nMinDepth = params[1].get_int();
584
585 // Tally
a372168e 586 CAmount nAmount = 0;
e3bc5698
JG
587 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
588 {
589 const CWalletTx& wtx = (*it).second;
75a4d512 590 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
e3bc5698
JG
591 continue;
592
593 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
594 if (txout.scriptPubKey == scriptPubKey)
595 if (wtx.GetDepthInMainChain() >= nMinDepth)
596 nAmount += txout.nValue;
597 }
598
599 return ValueFromAmount(nAmount);
600}
601
602
e3bc5698
JG
603Value getreceivedbyaccount(const Array& params, bool fHelp)
604{
b9fb692d
JS
605 if (!EnsureWalletIsAvailable(fHelp))
606 return Value::null;
607
e3bc5698
JG
608 if (fHelp || params.size() < 1 || params.size() > 2)
609 throw runtime_error(
a6099ef3 610 "getreceivedbyaccount \"account\" ( minconf )\n"
7b782f5b 611 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
a6099ef3 612 "\nArguments:\n"
613 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
614 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
615 "\nResult:\n"
616 "amount (numeric) The total amount in btc received for this account.\n"
617 "\nExamples:\n"
618 "\nAmount received by the default account with at least 1 confirmation\n"
619 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
620 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
621 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
622 "\nThe amount with at least 6 confirmation, very safe\n"
623 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
624 "\nAs a json rpc call\n"
625 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
626 );
e3bc5698 627
4401b2d7
EL
628 LOCK2(cs_main, pwalletMain->cs_wallet);
629
e3bc5698
JG
630 // Minimum confirmations
631 int nMinDepth = 1;
632 if (params.size() > 1)
633 nMinDepth = params[1].get_int();
634
635 // Get the set of pub keys assigned to account
636 string strAccount = AccountFromValue(params[0]);
3624356e 637 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
e3bc5698
JG
638
639 // Tally
a372168e 640 CAmount nAmount = 0;
e3bc5698
JG
641 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
642 {
643 const CWalletTx& wtx = (*it).second;
75a4d512 644 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
e3bc5698
JG
645 continue;
646
647 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
648 {
649 CTxDestination address;
650 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
651 if (wtx.GetDepthInMainChain() >= nMinDepth)
652 nAmount += txout.nValue;
653 }
654 }
655
656 return (double)nAmount / (double)COIN;
657}
658
659
a372168e 660CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
e3bc5698 661{
a372168e 662 CAmount nBalance = 0;
e3bc5698
JG
663
664 // Tally wallet transactions
665 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
666 {
667 const CWalletTx& wtx = (*it).second;
75a4d512 668 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
e3bc5698
JG
669 continue;
670
a372168e 671 CAmount nReceived, nSent, nFee;
d4640d7d 672 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
e3bc5698
JG
673
674 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
675 nBalance += nReceived;
e07c8e91 676 nBalance -= nSent + nFee;
e3bc5698
JG
677 }
678
679 // Tally internal accounting entries
680 nBalance += walletdb.GetAccountCreditDebit(strAccount);
681
682 return nBalance;
683}
684
a372168e 685CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
e3bc5698
JG
686{
687 CWalletDB walletdb(pwalletMain->strWalletFile);
d4640d7d 688 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
e3bc5698
JG
689}
690
691
692Value getbalance(const Array& params, bool fHelp)
693{
b9fb692d
JS
694 if (!EnsureWalletIsAvailable(fHelp))
695 return Value::null;
696
d4640d7d 697 if (fHelp || params.size() > 3)
e3bc5698 698 throw runtime_error(
d4640d7d 699 "getbalance ( \"account\" minconf includeWatchonly )\n"
a6099ef3 700 "\nIf account is not specified, returns the server's total available balance.\n"
7b782f5b 701 "If account is specified (DEPRECATED), returns the balance in the account.\n"
a6099ef3 702 "Note that the account \"\" is not the same as leaving the parameter out.\n"
703 "The server total may be different to the balance in the default \"\" account.\n"
704 "\nArguments:\n"
7b782f5b 705 "1. \"account\" (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
a6099ef3 706 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
d4640d7d 707 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
a6099ef3 708 "\nResult:\n"
709 "amount (numeric) The total amount in btc received for this account.\n"
710 "\nExamples:\n"
7b782f5b 711 "\nThe total amount in the wallet\n"
a6099ef3 712 + HelpExampleCli("getbalance", "") +
7b782f5b 713 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
3cf1f436 714 + HelpExampleCli("getbalance", "\"*\" 6") +
a6099ef3 715 "\nAs a json rpc call\n"
7b782f5b 716 + HelpExampleRpc("getbalance", "\"*\", 6")
a6099ef3 717 );
e3bc5698 718
4401b2d7
EL
719 LOCK2(cs_main, pwalletMain->cs_wallet);
720
e3bc5698
JG
721 if (params.size() == 0)
722 return ValueFromAmount(pwalletMain->GetBalance());
723
724 int nMinDepth = 1;
725 if (params.size() > 1)
726 nMinDepth = params[1].get_int();
a3e192a3 727 isminefilter filter = ISMINE_SPENDABLE;
a5c6c5d6
J
728 if(params.size() > 2)
729 if(params[2].get_bool())
a3e192a3 730 filter = filter | ISMINE_WATCH_ONLY;
e3bc5698
JG
731
732 if (params[0].get_str() == "*") {
733 // Calculate total balance a different way from GetBalance()
734 // (GetBalance() sums up all unspent TxOuts)
c9fd9078 735 // getbalance and "getbalance * 1 true" should return the same number
a372168e 736 CAmount nBalance = 0;
e3bc5698
JG
737 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
738 {
739 const CWalletTx& wtx = (*it).second;
c9fd9078 740 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
e3bc5698
JG
741 continue;
742
a372168e 743 CAmount allFee;
e3bc5698 744 string strSentAccount;
1b4568cb
CL
745 list<COutputEntry> listReceived;
746 list<COutputEntry> listSent;
d4640d7d 747 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
e3bc5698
JG
748 if (wtx.GetDepthInMainChain() >= nMinDepth)
749 {
1b4568cb
CL
750 BOOST_FOREACH(const COutputEntry& r, listReceived)
751 nBalance += r.amount;
e3bc5698 752 }
1b4568cb
CL
753 BOOST_FOREACH(const COutputEntry& s, listSent)
754 nBalance -= s.amount;
e3bc5698 755 nBalance -= allFee;
e3bc5698
JG
756 }
757 return ValueFromAmount(nBalance);
758 }
759
760 string strAccount = AccountFromValue(params[0]);
761
a372168e 762 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
e3bc5698
JG
763
764 return ValueFromAmount(nBalance);
765}
766
6027b460
MB
767Value getunconfirmedbalance(const Array &params, bool fHelp)
768{
b9fb692d
JS
769 if (!EnsureWalletIsAvailable(fHelp))
770 return Value::null;
771
6027b460
MB
772 if (fHelp || params.size() > 0)
773 throw runtime_error(
774 "getunconfirmedbalance\n"
775 "Returns the server's total unconfirmed balance\n");
4401b2d7
EL
776
777 LOCK2(cs_main, pwalletMain->cs_wallet);
778
6027b460
MB
779 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
780}
781
e3bc5698
JG
782
783Value movecmd(const Array& params, bool fHelp)
784{
b9fb692d
JS
785 if (!EnsureWalletIsAvailable(fHelp))
786 return Value::null;
787
e3bc5698
JG
788 if (fHelp || params.size() < 3 || params.size() > 5)
789 throw runtime_error(
a6099ef3 790 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
7b782f5b 791 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
a6099ef3 792 "\nArguments:\n"
793 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
794 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
795 "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
796 "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
797 "\nResult:\n"
45bfa137 798 "true|false (boolean) true if successful.\n"
a6099ef3 799 "\nExamples:\n"
800 "\nMove 0.01 btc from the default account to the account named tabby\n"
801 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
802 "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
803 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
804 "\nAs a json rpc call\n"
805 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
806 );
e3bc5698 807
4401b2d7
EL
808 LOCK2(cs_main, pwalletMain->cs_wallet);
809
e3bc5698
JG
810 string strFrom = AccountFromValue(params[0]);
811 string strTo = AccountFromValue(params[1]);
a372168e 812 CAmount nAmount = AmountFromValue(params[2]);
e3bc5698
JG
813 if (params.size() > 3)
814 // unused parameter, used to be nMinDepth, keep type-checking it though
815 (void)params[3].get_int();
816 string strComment;
817 if (params.size() > 4)
818 strComment = params[4].get_str();
819
820 CWalletDB walletdb(pwalletMain->strWalletFile);
821 if (!walletdb.TxnBegin())
738835d7 822 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
e3bc5698 823
51ed9ec9 824 int64_t nNow = GetAdjustedTime();
e3bc5698
JG
825
826 // Debit
827 CAccountingEntry debit;
4291e8fe 828 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
e3bc5698
JG
829 debit.strAccount = strFrom;
830 debit.nCreditDebit = -nAmount;
831 debit.nTime = nNow;
832 debit.strOtherAccount = strTo;
833 debit.strComment = strComment;
834 walletdb.WriteAccountingEntry(debit);
835
836 // Credit
837 CAccountingEntry credit;
4291e8fe 838 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
e3bc5698
JG
839 credit.strAccount = strTo;
840 credit.nCreditDebit = nAmount;
841 credit.nTime = nNow;
842 credit.strOtherAccount = strFrom;
843 credit.strComment = strComment;
844 walletdb.WriteAccountingEntry(credit);
845
846 if (!walletdb.TxnCommit())
738835d7 847 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
e3bc5698
JG
848
849 return true;
850}
851
852
853Value sendfrom(const Array& params, bool fHelp)
854{
b9fb692d
JS
855 if (!EnsureWalletIsAvailable(fHelp))
856 return Value::null;
857
e3bc5698
JG
858 if (fHelp || params.size() < 3 || params.size() > 6)
859 throw runtime_error(
a6099ef3 860 "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
7b782f5b 861 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
a6099ef3 862 "The amount is a real and is rounded to the nearest 0.00000001."
863 + HelpRequiringPassphrase() + "\n"
864 "\nArguments:\n"
865 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
866 "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
867 "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n"
868 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
869 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
870 " This is not part of the transaction, just kept in your wallet.\n"
871 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
872 " to which you're sending the transaction. This is not part of the transaction, \n"
873 " it is just kept in your wallet.\n"
874 "\nResult:\n"
b5ef85c7 875 "\"transactionid\" (string) The transaction id.\n"
a6099ef3 876 "\nExamples:\n"
877 "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
878 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
879 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
880 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
881 "\nAs a json rpc call\n"
882 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
883 );
e3bc5698 884
4401b2d7
EL
885 LOCK2(cs_main, pwalletMain->cs_wallet);
886
e3bc5698
JG
887 string strAccount = AccountFromValue(params[0]);
888 CBitcoinAddress address(params[1].get_str());
889 if (!address.IsValid())
738835d7 890 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
a372168e 891 CAmount nAmount = AmountFromValue(params[2]);
e3bc5698
JG
892 int nMinDepth = 1;
893 if (params.size() > 3)
894 nMinDepth = params[3].get_int();
895
896 CWalletTx wtx;
897 wtx.strFromAccount = strAccount;
898 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
899 wtx.mapValue["comment"] = params[4].get_str();
900 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
901 wtx.mapValue["to"] = params[5].get_str();
902
903 EnsureWalletIsUnlocked();
904
905 // Check funds
a372168e 906 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
e3bc5698 907 if (nAmount > nBalance)
738835d7 908 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
e3bc5698 909
292623ad 910 SendMoney(address.Get(), nAmount, false, wtx);
e3bc5698
JG
911
912 return wtx.GetHash().GetHex();
913}
914
915
916Value sendmany(const Array& params, bool fHelp)
917{
b9fb692d
JS
918 if (!EnsureWalletIsAvailable(fHelp))
919 return Value::null;
920
292623ad 921 if (fHelp || params.size() < 2 || params.size() > 5)
e3bc5698 922 throw runtime_error(
40a75733 923 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
a6099ef3 924 "\nSend multiple times. Amounts are double-precision floating point numbers."
925 + HelpRequiringPassphrase() + "\n"
926 "\nArguments:\n"
7b782f5b 927 "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
a6099ef3 928 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
929 " {\n"
930 " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
931 " ,...\n"
932 " }\n"
933 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
934 "4. \"comment\" (string, optional) A comment\n"
40a75733 935 "5. subtractfeefromamount (string, optional) A json array with addresses.\n"
292623ad
CL
936 " The fee will be equally deducted from the amount of each selected address.\n"
937 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
40a75733
LD
938 " If no addresses are specified here, the sender pays the fee.\n"
939 " [\n"
940 " \"address\" (string) Subtract fee from this address\n"
292623ad 941 " ,...\n"
40a75733 942 " ]\n"
a6099ef3 943 "\nResult:\n"
944 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
b5ef85c7 945 " the number of addresses.\n"
a6099ef3 946 "\nExamples:\n"
947 "\nSend two amounts to two different addresses:\n"
7b782f5b 948 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
a6099ef3 949 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
7b782f5b 950 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
292623ad 951 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
40a75733 952 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
a6099ef3 953 "\nAs a json rpc call\n"
7b782f5b 954 + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
a6099ef3 955 );
e3bc5698 956
4401b2d7
EL
957 LOCK2(cs_main, pwalletMain->cs_wallet);
958
e3bc5698
JG
959 string strAccount = AccountFromValue(params[0]);
960 Object sendTo = params[1].get_obj();
961 int nMinDepth = 1;
962 if (params.size() > 2)
963 nMinDepth = params[2].get_int();
964
965 CWalletTx wtx;
966 wtx.strFromAccount = strAccount;
967 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
968 wtx.mapValue["comment"] = params[3].get_str();
969
40a75733 970 Array subtractFeeFromAmount;
292623ad 971 if (params.size() > 4)
40a75733 972 subtractFeeFromAmount = params[4].get_array();
292623ad 973
e3bc5698 974 set<CBitcoinAddress> setAddress;
292623ad 975 vector<CRecipient> vecSend;
e3bc5698 976
a372168e 977 CAmount totalAmount = 0;
e3bc5698
JG
978 BOOST_FOREACH(const Pair& s, sendTo)
979 {
980 CBitcoinAddress address(s.name_);
981 if (!address.IsValid())
738835d7 982 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
e3bc5698
JG
983
984 if (setAddress.count(address))
738835d7 985 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
e3bc5698
JG
986 setAddress.insert(address);
987
0be990ba 988 CScript scriptPubKey = GetScriptForDestination(address.Get());
a372168e 989 CAmount nAmount = AmountFromValue(s.value_);
e3bc5698
JG
990 totalAmount += nAmount;
991
292623ad 992 bool fSubtractFeeFromAmount = false;
40a75733
LD
993 BOOST_FOREACH(const Value& addr, subtractFeeFromAmount)
994 if (addr.get_str() == s.name_)
292623ad
CL
995 fSubtractFeeFromAmount = true;
996
997 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
998 vecSend.push_back(recipient);
e3bc5698
JG
999 }
1000
1001 EnsureWalletIsUnlocked();
1002
1003 // Check funds
a372168e 1004 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
e3bc5698 1005 if (totalAmount > nBalance)
738835d7 1006 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
e3bc5698
JG
1007
1008 // Send
1009 CReserveKey keyChange(pwalletMain);
a372168e 1010 CAmount nFeeRequired = 0;
292623ad 1011 int nChangePosRet = -1;
1f00f4e9 1012 string strFailReason;
292623ad 1013 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
e3bc5698 1014 if (!fCreated)
1f00f4e9 1015 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
e3bc5698 1016 if (!pwalletMain->CommitTransaction(wtx, keyChange))
738835d7 1017 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
e3bc5698
JG
1018
1019 return wtx.GetHash().GetHex();
1020}
1021
723a03d2 1022// Defined in rpcmisc.cpp
787ee0c9 1023extern CScript _createmultisig_redeemScript(const Array& params);
34226be7
GA
1024
1025Value addmultisigaddress(const Array& params, bool fHelp)
1026{
b9fb692d
JS
1027 if (!EnsureWalletIsAvailable(fHelp))
1028 return Value::null;
1029
34226be7
GA
1030 if (fHelp || params.size() < 2 || params.size() > 3)
1031 {
a6099ef3 1032 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1033 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1034 "Each key is a Bitcoin address or hex-encoded public key.\n"
7b782f5b 1035 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
a6099ef3 1036
1037 "\nArguments:\n"
1038 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1039 "2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
1040 " [\n"
1041 " \"address\" (string) bitcoin address or hex-encoded public key\n"
1042 " ...,\n"
1043 " ]\n"
7b782f5b 1044 "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
a6099ef3 1045
1046 "\nResult:\n"
1047 "\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
1048
1049 "\nExamples:\n"
1050 "\nAdd a multisig address from 2 addresses\n"
1051 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1052 "\nAs json rpc call\n"
1053 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1054 ;
34226be7
GA
1055 throw runtime_error(msg);
1056 }
1057
4401b2d7
EL
1058 LOCK2(cs_main, pwalletMain->cs_wallet);
1059
34226be7
GA
1060 string strAccount;
1061 if (params.size() > 2)
1062 strAccount = AccountFromValue(params[2]);
e3bc5698
JG
1063
1064 // Construct using pay-to-script-hash:
787ee0c9 1065 CScript inner = _createmultisig_redeemScript(params);
066e2a14 1066 CScriptID innerID(inner);
e3bc5698
JG
1067 pwalletMain->AddCScript(inner);
1068
a41d5fe0 1069 pwalletMain->SetAddressBook(innerID, strAccount, "send");
e3bc5698
JG
1070 return CBitcoinAddress(innerID).ToString();
1071}
1072
1073
1074struct tallyitem
1075{
a372168e 1076 CAmount nAmount;
e3bc5698 1077 int nConf;
62c9b115 1078 vector<uint256> txids;
0fa2f889 1079 bool fIsWatchonly;
e3bc5698
JG
1080 tallyitem()
1081 {
1082 nAmount = 0;
1083 nConf = std::numeric_limits<int>::max();
0fa2f889 1084 fIsWatchonly = false;
e3bc5698
JG
1085 }
1086};
1087
1088Value ListReceived(const Array& params, bool fByAccounts)
1089{
1090 // Minimum confirmations
1091 int nMinDepth = 1;
1092 if (params.size() > 0)
1093 nMinDepth = params[0].get_int();
1094
1095 // Whether to include empty accounts
1096 bool fIncludeEmpty = false;
1097 if (params.size() > 1)
1098 fIncludeEmpty = params[1].get_bool();
1099
a3e192a3 1100 isminefilter filter = ISMINE_SPENDABLE;
0fa2f889
J
1101 if(params.size() > 2)
1102 if(params[2].get_bool())
a3e192a3 1103 filter = filter | ISMINE_WATCH_ONLY;
0fa2f889 1104
e3bc5698
JG
1105 // Tally
1106 map<CBitcoinAddress, tallyitem> mapTally;
1107 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1108 {
1109 const CWalletTx& wtx = (*it).second;
1110
75a4d512 1111 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
e3bc5698
JG
1112 continue;
1113
1114 int nDepth = wtx.GetDepthInMainChain();
1115 if (nDepth < nMinDepth)
1116 continue;
1117
1118 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1119 {
1120 CTxDestination address;
0fa2f889
J
1121 if (!ExtractDestination(txout.scriptPubKey, address))
1122 continue;
1123
1124 isminefilter mine = IsMine(*pwalletMain, address);
f28707a8 1125 if(!(mine & filter))
e3bc5698
JG
1126 continue;
1127
1128 tallyitem& item = mapTally[address];
1129 item.nAmount += txout.nValue;
1130 item.nConf = min(item.nConf, nDepth);
62c9b115 1131 item.txids.push_back(wtx.GetHash());
a3e192a3 1132 if (mine & ISMINE_WATCH_ONLY)
0fa2f889 1133 item.fIsWatchonly = true;
e3bc5698
JG
1134 }
1135 }
1136
1137 // Reply
1138 Array ret;
1139 map<string, tallyitem> mapAccountTally;
61885513 1140 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
e3bc5698
JG
1141 {
1142 const CBitcoinAddress& address = item.first;
61885513 1143 const string& strAccount = item.second.name;
e3bc5698
JG
1144 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1145 if (it == mapTally.end() && !fIncludeEmpty)
1146 continue;
1147
a372168e 1148 CAmount nAmount = 0;
e3bc5698 1149 int nConf = std::numeric_limits<int>::max();
0fa2f889 1150 bool fIsWatchonly = false;
e3bc5698
JG
1151 if (it != mapTally.end())
1152 {
1153 nAmount = (*it).second.nAmount;
1154 nConf = (*it).second.nConf;
0fa2f889 1155 fIsWatchonly = (*it).second.fIsWatchonly;
e3bc5698
JG
1156 }
1157
1158 if (fByAccounts)
1159 {
1160 tallyitem& item = mapAccountTally[strAccount];
1161 item.nAmount += nAmount;
1162 item.nConf = min(item.nConf, nConf);
0fa2f889 1163 item.fIsWatchonly = fIsWatchonly;
e3bc5698
JG
1164 }
1165 else
1166 {
1167 Object obj;
0fa2f889
J
1168 if(fIsWatchonly)
1169 obj.push_back(Pair("involvesWatchonly", true));
e3bc5698
JG
1170 obj.push_back(Pair("address", address.ToString()));
1171 obj.push_back(Pair("account", strAccount));
1172 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1173 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
62c9b115 1174 Array transactions;
1a204694 1175 if (it != mapTally.end())
62c9b115 1176 {
1a204694
A
1177 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1178 {
1179 transactions.push_back(item.GetHex());
1180 }
62c9b115
A
1181 }
1182 obj.push_back(Pair("txids", transactions));
e3bc5698
JG
1183 ret.push_back(obj);
1184 }
1185 }
1186
1187 if (fByAccounts)
1188 {
1189 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1190 {
a372168e 1191 CAmount nAmount = (*it).second.nAmount;
e3bc5698
JG
1192 int nConf = (*it).second.nConf;
1193 Object obj;
0fa2f889
J
1194 if((*it).second.fIsWatchonly)
1195 obj.push_back(Pair("involvesWatchonly", true));
e3bc5698
JG
1196 obj.push_back(Pair("account", (*it).first));
1197 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1198 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1199 ret.push_back(obj);
1200 }
1201 }
1202
1203 return ret;
1204}
1205
1206Value listreceivedbyaddress(const Array& params, bool fHelp)
1207{
b9fb692d
JS
1208 if (!EnsureWalletIsAvailable(fHelp))
1209 return Value::null;
1210
0fa2f889 1211 if (fHelp || params.size() > 3)
e3bc5698 1212 throw runtime_error(
0fa2f889 1213 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
a6099ef3 1214 "\nList balances by receiving address.\n"
1215 "\nArguments:\n"
1216 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
5617267c 1217 "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
0fa2f889 1218 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
a6099ef3 1219
1220 "\nResult:\n"
1221 "[\n"
1222 " {\n"
8f6860a0 1223 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
a6099ef3 1224 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
7b782f5b 1225 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
a6099ef3 1226 " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n"
1227 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1228 " }\n"
1229 " ,...\n"
1230 "]\n"
1231
1232 "\nExamples:\n"
1233 + HelpExampleCli("listreceivedbyaddress", "")
1234 + HelpExampleCli("listreceivedbyaddress", "6 true")
0fa2f889 1235 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
a6099ef3 1236 );
e3bc5698 1237
4401b2d7
EL
1238 LOCK2(cs_main, pwalletMain->cs_wallet);
1239
e3bc5698
JG
1240 return ListReceived(params, false);
1241}
1242
1243Value listreceivedbyaccount(const Array& params, bool fHelp)
1244{
b9fb692d
JS
1245 if (!EnsureWalletIsAvailable(fHelp))
1246 return Value::null;
1247
0fa2f889 1248 if (fHelp || params.size() > 3)
e3bc5698 1249 throw runtime_error(
0fa2f889 1250 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
7b782f5b 1251 "\nDEPRECATED. List balances by account.\n"
a6099ef3 1252 "\nArguments:\n"
1253 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1254 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
0fa2f889 1255 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
a6099ef3 1256
1257 "\nResult:\n"
1258 "[\n"
1259 " {\n"
8f6860a0 1260 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
a6099ef3 1261 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1262 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1263 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1264 " }\n"
1265 " ,...\n"
1266 "]\n"
1267
1268 "\nExamples:\n"
1269 + HelpExampleCli("listreceivedbyaccount", "")
1270 + HelpExampleCli("listreceivedbyaccount", "6 true")
0fa2f889 1271 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
a6099ef3 1272 );
e3bc5698 1273
4401b2d7
EL
1274 LOCK2(cs_main, pwalletMain->cs_wallet);
1275
e3bc5698
JG
1276 return ListReceived(params, true);
1277}
1278
cc6cfab3
LD
1279static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1280{
1281 CBitcoinAddress addr;
1282 if (addr.Set(dest))
1283 entry.push_back(Pair("address", addr.ToString()));
1284}
1285
80dda36a 1286void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
e3bc5698 1287{
a372168e 1288 CAmount nFee;
e3bc5698 1289 string strSentAccount;
1b4568cb
CL
1290 list<COutputEntry> listReceived;
1291 list<COutputEntry> listSent;
e3bc5698 1292
d7d5d23b 1293 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
e3bc5698
JG
1294
1295 bool fAllAccounts = (strAccount == string("*"));
a3e192a3 1296 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
e3bc5698 1297
e3bc5698
JG
1298 // Sent
1299 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1300 {
1b4568cb 1301 BOOST_FOREACH(const COutputEntry& s, listSent)
e3bc5698
JG
1302 {
1303 Object entry;
1b4568cb 1304 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
952877e0 1305 entry.push_back(Pair("involvesWatchonly", true));
e3bc5698 1306 entry.push_back(Pair("account", strSentAccount));
1b4568cb 1307 MaybePushAddress(entry, s.destination);
b96f6a77 1308 entry.push_back(Pair("category", "send"));
1b4568cb
CL
1309 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1310 entry.push_back(Pair("vout", s.vout));
e3bc5698
JG
1311 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1312 if (fLong)
1313 WalletTxToJSON(wtx, entry);
1314 ret.push_back(entry);
1315 }
1316 }
1317
1318 // Received
1319 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1320 {
1b4568cb 1321 BOOST_FOREACH(const COutputEntry& r, listReceived)
e3bc5698
JG
1322 {
1323 string account;
1b4568cb
CL
1324 if (pwalletMain->mapAddressBook.count(r.destination))
1325 account = pwalletMain->mapAddressBook[r.destination].name;
e3bc5698
JG
1326 if (fAllAccounts || (account == strAccount))
1327 {
1328 Object entry;
1b4568cb 1329 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
952877e0 1330 entry.push_back(Pair("involvesWatchonly", true));
e3bc5698 1331 entry.push_back(Pair("account", account));
1b4568cb 1332 MaybePushAddress(entry, r.destination);
e07c8e91
LD
1333 if (wtx.IsCoinBase())
1334 {
1335 if (wtx.GetDepthInMainChain() < 1)
1336 entry.push_back(Pair("category", "orphan"));
1337 else if (wtx.GetBlocksToMaturity() > 0)
1338 entry.push_back(Pair("category", "immature"));
1339 else
1340 entry.push_back(Pair("category", "generate"));
1341 }
1342 else
2b72d46f 1343 {
b96f6a77 1344 entry.push_back(Pair("category", "receive"));
2b72d46f 1345 }
1b4568cb
CL
1346 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1347 entry.push_back(Pair("vout", r.vout));
e3bc5698
JG
1348 if (fLong)
1349 WalletTxToJSON(wtx, entry);
1350 ret.push_back(entry);
1351 }
1352 }
1353 }
1354}
1355
1356void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1357{
1358 bool fAllAccounts = (strAccount == string("*"));
1359
1360 if (fAllAccounts || acentry.strAccount == strAccount)
1361 {
1362 Object entry;
1363 entry.push_back(Pair("account", acentry.strAccount));
1364 entry.push_back(Pair("category", "move"));
d56e30ca 1365 entry.push_back(Pair("time", acentry.nTime));
e3bc5698
JG
1366 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1367 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1368 entry.push_back(Pair("comment", acentry.strComment));
1369 ret.push_back(entry);
1370 }
1371}
1372
1373Value listtransactions(const Array& params, bool fHelp)
1374{
b9fb692d
JS
1375 if (!EnsureWalletIsAvailable(fHelp))
1376 return Value::null;
1377
d7d5d23b 1378 if (fHelp || params.size() > 4)
e3bc5698 1379 throw runtime_error(
d7d5d23b 1380 "listtransactions ( \"account\" count from includeWatchonly)\n"
a6099ef3 1381 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1382 "\nArguments:\n"
7b782f5b 1383 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
a6099ef3 1384 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1385 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
d7d5d23b 1386 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
a6099ef3 1387 "\nResult:\n"
1388 "[\n"
1389 " {\n"
7b782f5b 1390 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
a6099ef3 1391 " It will be \"\" for the default account.\n"
1392 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
1393 " move transactions (category = move).\n"
1394 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1395 " transaction between accounts, and not associated with an address,\n"
1396 " transaction id or block. 'send' and 'receive' transactions are \n"
1397 " associated with an address, transaction id and block details\n"
1398 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1399 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1400 " and for the 'move' category for inbound funds.\n"
1b4568cb 1401 " \"vout\" : n, (numeric) the vout value\n"
a6099ef3 1402 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1403 " 'send' category of transactions.\n"
1404 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1405 " 'receive' category of transactions.\n"
1406 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1407 " category of transactions.\n"
1408 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1409 " category of transactions.\n"
b5ef85c7 1410 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
a6099ef3 1411 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1412 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1413 " for 'send' and 'receive' category of transactions.\n"
1414 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1415 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1416 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1417 " negative amounts).\n"
1418 " }\n"
1419 "]\n"
1420
1421 "\nExamples:\n"
1422 "\nList the most recent 10 transactions in the systems\n"
1423 + HelpExampleCli("listtransactions", "") +
7b782f5b
LD
1424 "\nList transactions 100 to 120\n"
1425 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
a6099ef3 1426 "\nAs a json rpc call\n"
7b782f5b 1427 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
a6099ef3 1428 );
e3bc5698 1429
4401b2d7
EL
1430 LOCK2(cs_main, pwalletMain->cs_wallet);
1431
e3bc5698
JG
1432 string strAccount = "*";
1433 if (params.size() > 0)
1434 strAccount = params[0].get_str();
1435 int nCount = 10;
1436 if (params.size() > 1)
1437 nCount = params[1].get_int();
1438 int nFrom = 0;
1439 if (params.size() > 2)
1440 nFrom = params[2].get_int();
a3e192a3 1441 isminefilter filter = ISMINE_SPENDABLE;
a5c6c5d6
J
1442 if(params.size() > 3)
1443 if(params[3].get_bool())
a3e192a3 1444 filter = filter | ISMINE_WATCH_ONLY;
e3bc5698
JG
1445
1446 if (nCount < 0)
738835d7 1447 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
e3bc5698 1448 if (nFrom < 0)
738835d7 1449 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
e3bc5698
JG
1450
1451 Array ret;
e3bc5698 1452
ddb709e9
LD
1453 std::list<CAccountingEntry> acentries;
1454 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
e3bc5698
JG
1455
1456 // iterate backwards until we have nCount items to return:
c3f95ef1 1457 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
e3bc5698
JG
1458 {
1459 CWalletTx *const pwtx = (*it).second.first;
1460 if (pwtx != 0)
d7d5d23b 1461 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
e3bc5698
JG
1462 CAccountingEntry *const pacentry = (*it).second.second;
1463 if (pacentry != 0)
1464 AcentryToJSON(*pacentry, strAccount, ret);
1465
1466 if ((int)ret.size() >= (nCount+nFrom)) break;
1467 }
1468 // ret is newest to oldest
1469
1470 if (nFrom > (int)ret.size())
1471 nFrom = ret.size();
1472 if ((nFrom + nCount) > (int)ret.size())
1473 nCount = ret.size() - nFrom;
1474 Array::iterator first = ret.begin();
1475 std::advance(first, nFrom);
1476 Array::iterator last = ret.begin();
1477 std::advance(last, nFrom+nCount);
1478
1479 if (last != ret.end()) ret.erase(last, ret.end());
1480 if (first != ret.begin()) ret.erase(ret.begin(), first);
1481
1482 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1483
1484 return ret;
1485}
1486
1487Value listaccounts(const Array& params, bool fHelp)
1488{
b9fb692d
JS
1489 if (!EnsureWalletIsAvailable(fHelp))
1490 return Value::null;
1491
83f3543f 1492 if (fHelp || params.size() > 2)
e3bc5698 1493 throw runtime_error(
83f3543f 1494 "listaccounts ( minconf includeWatchonly)\n"
7b782f5b 1495 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
a6099ef3 1496 "\nArguments:\n"
5617267c 1497 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
83f3543f 1498 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
a6099ef3 1499 "\nResult:\n"
1500 "{ (json object where keys are account names, and values are numeric balances\n"
1501 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1502 " ...\n"
1503 "}\n"
1504 "\nExamples:\n"
1505 "\nList account balances where there at least 1 confirmation\n"
1506 + HelpExampleCli("listaccounts", "") +
1507 "\nList account balances including zero confirmation transactions\n"
1508 + HelpExampleCli("listaccounts", "0") +
1509 "\nList account balances for 6 or more confirmations\n"
1510 + HelpExampleCli("listaccounts", "6") +
1511 "\nAs json rpc call\n"
1512 + HelpExampleRpc("listaccounts", "6")
1513 );
e3bc5698 1514
4401b2d7
EL
1515 LOCK2(cs_main, pwalletMain->cs_wallet);
1516
e3bc5698
JG
1517 int nMinDepth = 1;
1518 if (params.size() > 0)
1519 nMinDepth = params[0].get_int();
a3e192a3 1520 isminefilter includeWatchonly = ISMINE_SPENDABLE;
a5c6c5d6
J
1521 if(params.size() > 1)
1522 if(params[1].get_bool())
a3e192a3 1523 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
e3bc5698 1524
a372168e 1525 map<string, CAmount> mapAccountBalances;
61885513 1526 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
83f3543f 1527 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
61885513 1528 mapAccountBalances[entry.second.name] = 0;
e3bc5698
JG
1529 }
1530
1531 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1532 {
1533 const CWalletTx& wtx = (*it).second;
a372168e 1534 CAmount nFee;
e3bc5698 1535 string strSentAccount;
1b4568cb
CL
1536 list<COutputEntry> listReceived;
1537 list<COutputEntry> listSent;
93a18a36
GA
1538 int nDepth = wtx.GetDepthInMainChain();
1539 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
731b89b8 1540 continue;
83f3543f 1541 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
e3bc5698 1542 mapAccountBalances[strSentAccount] -= nFee;
1b4568cb
CL
1543 BOOST_FOREACH(const COutputEntry& s, listSent)
1544 mapAccountBalances[strSentAccount] -= s.amount;
93a18a36 1545 if (nDepth >= nMinDepth)
e3bc5698 1546 {
1b4568cb
CL
1547 BOOST_FOREACH(const COutputEntry& r, listReceived)
1548 if (pwalletMain->mapAddressBook.count(r.destination))
1549 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
e3bc5698 1550 else
1b4568cb 1551 mapAccountBalances[""] += r.amount;
e3bc5698
JG
1552 }
1553 }
1554
1555 list<CAccountingEntry> acentries;
1556 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1557 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1558 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1559
1560 Object ret;
a372168e 1561 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
e3bc5698
JG
1562 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1563 }
1564 return ret;
1565}
1566
1567Value listsinceblock(const Array& params, bool fHelp)
1568{
b9fb692d
JS
1569 if (!EnsureWalletIsAvailable(fHelp))
1570 return Value::null;
1571
e3bc5698
JG
1572 if (fHelp)
1573 throw runtime_error(
d7d5d23b 1574 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
a6099ef3 1575 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1576 "\nArguments:\n"
1577 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1578 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
d7d5d23b 1579 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
a6099ef3 1580 "\nResult:\n"
1581 "{\n"
1582 " \"transactions\": [\n"
7b782f5b 1583 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
a6099ef3 1584 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1585 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1586 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1587 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1b4568cb 1588 " \"vout\" : n, (numeric) the vout value\n"
a6099ef3 1589 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1590 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1591 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1592 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1593 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
b5ef85c7 1594 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
a6099ef3 1595 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1596 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1597 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1598 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1599 " ],\n"
1600 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1601 "}\n"
1602 "\nExamples:\n"
1603 + HelpExampleCli("listsinceblock", "")
1604 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1605 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1606 );
e3bc5698 1607
4401b2d7
EL
1608 LOCK2(cs_main, pwalletMain->cs_wallet);
1609
e3bc5698
JG
1610 CBlockIndex *pindex = NULL;
1611 int target_confirms = 1;
a3e192a3 1612 isminefilter filter = ISMINE_SPENDABLE;
e3bc5698
JG
1613
1614 if (params.size() > 0)
1615 {
4f152496 1616 uint256 blockId;
e3bc5698
JG
1617
1618 blockId.SetHex(params[0].get_str());
145d5be8 1619 BlockMap::iterator it = mapBlockIndex.find(blockId);
e4daecda
PW
1620 if (it != mapBlockIndex.end())
1621 pindex = it->second;
e3bc5698
JG
1622 }
1623
1624 if (params.size() > 1)
1625 {
1626 target_confirms = params[1].get_int();
1627
1628 if (target_confirms < 1)
738835d7 1629 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
e3bc5698
JG
1630 }
1631
a5c6c5d6
J
1632 if(params.size() > 2)
1633 if(params[2].get_bool())
a3e192a3 1634 filter = filter | ISMINE_WATCH_ONLY;
a5c6c5d6 1635
4c6d41b8 1636 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
e3bc5698
JG
1637
1638 Array transactions;
1639
1640 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1641 {
1642 CWalletTx tx = (*it).second;
1643
1644 if (depth == -1 || tx.GetDepthInMainChain() < depth)
d7d5d23b 1645 ListTransactions(tx, "*", 0, true, transactions, filter);
e3bc5698
JG
1646 }
1647
4c6d41b8 1648 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
4f152496 1649 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
e3bc5698
JG
1650
1651 Object ret;
1652 ret.push_back(Pair("transactions", transactions));
1653 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1654
1655 return ret;
1656}
1657
1658Value gettransaction(const Array& params, bool fHelp)
1659{
b9fb692d
JS
1660 if (!EnsureWalletIsAvailable(fHelp))
1661 return Value::null;
1662
f87ba3df 1663 if (fHelp || params.size() < 1 || params.size() > 2)
e3bc5698 1664 throw runtime_error(
57e1716d 1665 "gettransaction \"txid\" ( includeWatchonly )\n"
a6099ef3 1666 "\nGet detailed information about in-wallet transaction <txid>\n"
1667 "\nArguments:\n"
1668 "1. \"txid\" (string, required) The transaction id\n"
f87ba3df 1669 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
a6099ef3 1670 "\nResult:\n"
1671 "{\n"
1672 " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n"
1673 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1674 " \"blockhash\" : \"hash\", (string) The block hash\n"
1675 " \"blockindex\" : xx, (numeric) The block index\n"
1676 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
b5ef85c7 1677 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
a6099ef3 1678 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1679 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1680 " \"details\" : [\n"
1681 " {\n"
7b782f5b 1682 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
a6099ef3 1683 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
1684 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1685 " \"amount\" : x.xxx (numeric) The amount in btc\n"
1b4568cb 1686 " \"vout\" : n, (numeric) the vout value\n"
a6099ef3 1687 " }\n"
1688 " ,...\n"
3a1c20b7
WL
1689 " ],\n"
1690 " \"hex\" : \"data\" (string) Raw data for transaction\n"
a6099ef3 1691 "}\n"
1692
ab45ddb5 1693 "\nExamples:\n"
a6099ef3 1694 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
57e1716d 1695 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
a6099ef3 1696 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1697 );
e3bc5698 1698
4401b2d7
EL
1699 LOCK2(cs_main, pwalletMain->cs_wallet);
1700
e3bc5698
JG
1701 uint256 hash;
1702 hash.SetHex(params[0].get_str());
1703
a3e192a3 1704 isminefilter filter = ISMINE_SPENDABLE;
f87ba3df
J
1705 if(params.size() > 1)
1706 if(params[1].get_bool())
a3e192a3 1707 filter = filter | ISMINE_WATCH_ONLY;
f87ba3df 1708
e3bc5698
JG
1709 Object entry;
1710 if (!pwalletMain->mapWallet.count(hash))
738835d7 1711 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
e3bc5698
JG
1712 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1713
ccca27a7 1714 CAmount nCredit = wtx.GetCredit(filter);
a372168e
MF
1715 CAmount nDebit = wtx.GetDebit(filter);
1716 CAmount nNet = nCredit - nDebit;
1717 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
e3bc5698
JG
1718
1719 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
80dda36a 1720 if (wtx.IsFromMe(filter))
e3bc5698
JG
1721 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1722
1723 WalletTxToJSON(wtx, entry);
1724
1725 Array details;
f87ba3df 1726 ListTransactions(wtx, "*", 0, false, details, filter);
e3bc5698
JG
1727 entry.push_back(Pair("details", details));
1728
ae775b5b 1729 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
3a1c20b7
WL
1730 entry.push_back(Pair("hex", strHex));
1731
e3bc5698
JG
1732 return entry;
1733}
1734
1735
1736Value backupwallet(const Array& params, bool fHelp)
1737{
b9fb692d
JS
1738 if (!EnsureWalletIsAvailable(fHelp))
1739 return Value::null;
1740
e3bc5698
JG
1741 if (fHelp || params.size() != 1)
1742 throw runtime_error(
a6099ef3 1743 "backupwallet \"destination\"\n"
1744 "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1745 "\nArguments:\n"
1746 "1. \"destination\" (string) The destination directory or file\n"
1747 "\nExamples:\n"
1748 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1749 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1750 );
e3bc5698 1751
4401b2d7
EL
1752 LOCK2(cs_main, pwalletMain->cs_wallet);
1753
e3bc5698 1754 string strDest = params[0].get_str();
ad525e9c
PK
1755 if (!BackupWallet(*pwalletMain, strDest))
1756 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
e3bc5698
JG
1757
1758 return Value::null;
1759}
1760
1761
1762Value keypoolrefill(const Array& params, bool fHelp)
1763{
b9fb692d
JS
1764 if (!EnsureWalletIsAvailable(fHelp))
1765 return Value::null;
1766
36bd46f1 1767 if (fHelp || params.size() > 1)
e3bc5698 1768 throw runtime_error(
a6099ef3 1769 "keypoolrefill ( newsize )\n"
1770 "\nFills the keypool."
1771 + HelpRequiringPassphrase() + "\n"
1772 "\nArguments\n"
1773 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1774 "\nExamples:\n"
1775 + HelpExampleCli("keypoolrefill", "")
1776 + HelpExampleRpc("keypoolrefill", "")
1777 );
e3bc5698 1778
4401b2d7
EL
1779 LOCK2(cs_main, pwalletMain->cs_wallet);
1780
f914c7a1
PK
1781 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1782 unsigned int kpSize = 0;
36bd46f1
JG
1783 if (params.size() > 0) {
1784 if (params[0].get_int() < 0)
f914c7a1
PK
1785 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1786 kpSize = (unsigned int)params[0].get_int();
36bd46f1
JG
1787 }
1788
e3bc5698 1789 EnsureWalletIsUnlocked();
36bd46f1 1790 pwalletMain->TopUpKeyPool(kpSize);
e3bc5698 1791
36bd46f1 1792 if (pwalletMain->GetKeyPoolSize() < kpSize)
738835d7 1793 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
e3bc5698
JG
1794
1795 return Value::null;
1796}
1797
1798
92f2c1fe 1799static void LockWallet(CWallet* pWallet)
e3bc5698 1800{
92f2c1fe
GA
1801 LOCK(cs_nWalletUnlockTime);
1802 nWalletUnlockTime = 0;
1803 pWallet->Lock();
e3bc5698
JG
1804}
1805
1806Value walletpassphrase(const Array& params, bool fHelp)
1807{
b9fb692d
JS
1808 if (!EnsureWalletIsAvailable(fHelp))
1809 return Value::null;
1810
e3bc5698
JG
1811 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1812 throw runtime_error(
a6099ef3 1813 "walletpassphrase \"passphrase\" timeout\n"
1814 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1815 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1816 "\nArguments:\n"
1817 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1818 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
6c0db81c
WL
1819 "\nNote:\n"
1820 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1821 "time that overrides the old one.\n"
a6099ef3 1822 "\nExamples:\n"
1823 "\nunlock the wallet for 60 seconds\n"
1824 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1825 "\nLock the wallet again (before 60 seconds)\n"
1826 + HelpExampleCli("walletlock", "") +
1827 "\nAs json rpc call\n"
1828 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1829 );
1830
4401b2d7
EL
1831 LOCK2(cs_main, pwalletMain->cs_wallet);
1832
e3bc5698
JG
1833 if (fHelp)
1834 return true;
1835 if (!pwalletMain->IsCrypted())
738835d7 1836 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
e3bc5698 1837
e3bc5698
JG
1838 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1839 SecureString strWalletPass;
1840 strWalletPass.reserve(100);
1841 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1842 // Alternately, find a way to make params[0] mlock()'d to begin with.
1843 strWalletPass = params[0].get_str().c_str();
1844
1845 if (strWalletPass.length() > 0)
1846 {
1847 if (!pwalletMain->Unlock(strWalletPass))
738835d7 1848 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
e3bc5698
JG
1849 }
1850 else
1851 throw runtime_error(
1852 "walletpassphrase <passphrase> <timeout>\n"
1853 "Stores the wallet decryption key in memory for <timeout> seconds.");
1854
92f2c1fe
GA
1855 pwalletMain->TopUpKeyPool();
1856
51ed9ec9 1857 int64_t nSleepTime = params[1].get_int64();
92f2c1fe
GA
1858 LOCK(cs_nWalletUnlockTime);
1859 nWalletUnlockTime = GetTime() + nSleepTime;
1860 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
e3bc5698
JG
1861
1862 return Value::null;
1863}
1864
1865
1866Value walletpassphrasechange(const Array& params, bool fHelp)
1867{
b9fb692d
JS
1868 if (!EnsureWalletIsAvailable(fHelp))
1869 return Value::null;
1870
e3bc5698
JG
1871 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1872 throw runtime_error(
a6099ef3 1873 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1874 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1875 "\nArguments:\n"
1876 "1. \"oldpassphrase\" (string) The current passphrase\n"
1877 "2. \"newpassphrase\" (string) The new passphrase\n"
1878 "\nExamples:\n"
1879 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1880 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1881 );
1882
4401b2d7
EL
1883 LOCK2(cs_main, pwalletMain->cs_wallet);
1884
e3bc5698
JG
1885 if (fHelp)
1886 return true;
1887 if (!pwalletMain->IsCrypted())
738835d7 1888 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
e3bc5698
JG
1889
1890 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1891 // Alternately, find a way to make params[0] mlock()'d to begin with.
1892 SecureString strOldWalletPass;
1893 strOldWalletPass.reserve(100);
1894 strOldWalletPass = params[0].get_str().c_str();
1895
1896 SecureString strNewWalletPass;
1897 strNewWalletPass.reserve(100);
1898 strNewWalletPass = params[1].get_str().c_str();
1899
1900 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1901 throw runtime_error(
1902 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1903 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1904
1905 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
738835d7 1906 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
e3bc5698
JG
1907
1908 return Value::null;
1909}
1910
1911
1912Value walletlock(const Array& params, bool fHelp)
1913{
b9fb692d
JS
1914 if (!EnsureWalletIsAvailable(fHelp))
1915 return Value::null;
1916
e3bc5698
JG
1917 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1918 throw runtime_error(
1919 "walletlock\n"
a6099ef3 1920 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
e3bc5698 1921 "After calling this method, you will need to call walletpassphrase again\n"
a6099ef3 1922 "before being able to call any methods which require the wallet to be unlocked.\n"
1923 "\nExamples:\n"
1924 "\nSet the passphrase for 2 minutes to perform a transaction\n"
1925 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1926 "\nPerform a send (requires passphrase set)\n"
1927 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1928 "\nClear the passphrase since we are done before 2 minutes is up\n"
1929 + HelpExampleCli("walletlock", "") +
1930 "\nAs json rpc call\n"
1931 + HelpExampleRpc("walletlock", "")
1932 );
1933
4401b2d7
EL
1934 LOCK2(cs_main, pwalletMain->cs_wallet);
1935
e3bc5698
JG
1936 if (fHelp)
1937 return true;
1938 if (!pwalletMain->IsCrypted())
738835d7 1939 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
e3bc5698
JG
1940
1941 {
1942 LOCK(cs_nWalletUnlockTime);
1943 pwalletMain->Lock();
1944 nWalletUnlockTime = 0;
1945 }
1946
1947 return Value::null;
1948}
1949
1950
1951Value encryptwallet(const Array& params, bool fHelp)
1952{
b9fb692d
JS
1953 if (!EnsureWalletIsAvailable(fHelp))
1954 return Value::null;
1955
e3bc5698
JG
1956 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1957 throw runtime_error(
a6099ef3 1958 "encryptwallet \"passphrase\"\n"
1959 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1960 "After this, any calls that interact with private keys such as sending or signing \n"
1961 "will require the passphrase to be set prior the making these calls.\n"
1962 "Use the walletpassphrase call for this, and then walletlock call.\n"
1963 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1964 "Note that this will shutdown the server.\n"
1965 "\nArguments:\n"
1966 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1967 "\nExamples:\n"
1968 "\nEncrypt you wallet\n"
1969 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1970 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1971 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1972 "\nNow we can so something like sign\n"
1973 + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1974 "\nNow lock the wallet again by removing the passphrase\n"
1975 + HelpExampleCli("walletlock", "") +
1976 "\nAs a json rpc call\n"
1977 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1978 );
1979
4401b2d7
EL
1980 LOCK2(cs_main, pwalletMain->cs_wallet);
1981
e3bc5698
JG
1982 if (fHelp)
1983 return true;
1984 if (pwalletMain->IsCrypted())
738835d7 1985 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
e3bc5698
JG
1986
1987 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1988 // Alternately, find a way to make params[0] mlock()'d to begin with.
1989 SecureString strWalletPass;
1990 strWalletPass.reserve(100);
1991 strWalletPass = params[0].get_str().c_str();
1992
1993 if (strWalletPass.length() < 1)
1994 throw runtime_error(
1995 "encryptwallet <passphrase>\n"
1996 "Encrypts the wallet with <passphrase>.");
1997
1998 if (!pwalletMain->EncryptWallet(strWalletPass))
738835d7 1999 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
e3bc5698
JG
2000
2001 // BDB seems to have a bad habit of writing old data into
2002 // slack space in .dat files; that is bad if the old data is
331544bc 2003 // unencrypted private keys. So:
e3bc5698 2004 StartShutdown();
6b3783a9 2005 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
2006}
2007
fdbb537d
JG
2008Value lockunspent(const Array& params, bool fHelp)
2009{
b9fb692d
JS
2010 if (!EnsureWalletIsAvailable(fHelp))
2011 return Value::null;
2012
fdbb537d
JG
2013 if (fHelp || params.size() < 1 || params.size() > 2)
2014 throw runtime_error(
a6099ef3 2015 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2016 "\nUpdates list of temporarily unspendable outputs.\n"
90fd8737 2017 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
a6099ef3 2018 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2019 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2020 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2021 "Also see the listunspent call\n"
2022 "\nArguments:\n"
2023 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2024 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2025 " [ (json array of json objects)\n"
2026 " {\n"
2027 " \"txid\":\"id\", (string) The transaction id\n"
2028 " \"vout\": n (numeric) The output number\n"
2029 " }\n"
2030 " ,...\n"
2031 " ]\n"
2032
2033 "\nResult:\n"
2034 "true|false (boolean) Whether the command was successful or not\n"
2035
2036 "\nExamples:\n"
2037 "\nList the unspent transactions\n"
2038 + HelpExampleCli("listunspent", "") +
2039 "\nLock an unspent transaction\n"
2040 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2041 "\nList the locked transactions\n"
2042 + HelpExampleCli("listlockunspent", "") +
2043 "\nUnlock the transaction again\n"
2044 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2045 "\nAs a json rpc call\n"
2046 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2047 );
fdbb537d 2048
4401b2d7
EL
2049 LOCK2(cs_main, pwalletMain->cs_wallet);
2050
fdbb537d 2051 if (params.size() == 1)
856e862f 2052 RPCTypeCheck(params, boost::assign::list_of(bool_type));
fdbb537d 2053 else
856e862f 2054 RPCTypeCheck(params, boost::assign::list_of(bool_type)(array_type));
fdbb537d
JG
2055
2056 bool fUnlock = params[0].get_bool();
2057
2058 if (params.size() == 1) {
2059 if (fUnlock)
2060 pwalletMain->UnlockAllCoins();
2061 return true;
2062 }
2063
2064 Array outputs = params[1].get_array();
2065 BOOST_FOREACH(Value& output, outputs)
2066 {
2067 if (output.type() != obj_type)
15117692 2068 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
fdbb537d
JG
2069 const Object& o = output.get_obj();
2070
856e862f 2071 RPCTypeCheck(o, boost::assign::map_list_of("txid", str_type)("vout", int_type));
fdbb537d
JG
2072
2073 string txid = find_value(o, "txid").get_str();
2074 if (!IsHex(txid))
15117692 2075 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
fdbb537d
JG
2076
2077 int nOutput = find_value(o, "vout").get_int();
2078 if (nOutput < 0)
15117692 2079 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
fdbb537d 2080
34cdc411 2081 COutPoint outpt(uint256S(txid), nOutput);
fdbb537d
JG
2082
2083 if (fUnlock)
2084 pwalletMain->UnlockCoin(outpt);
2085 else
2086 pwalletMain->LockCoin(outpt);
2087 }
2088
2089 return true;
2090}
2091
2092Value listlockunspent(const Array& params, bool fHelp)
2093{
b9fb692d
JS
2094 if (!EnsureWalletIsAvailable(fHelp))
2095 return Value::null;
2096
fdbb537d
JG
2097 if (fHelp || params.size() > 0)
2098 throw runtime_error(
2099 "listlockunspent\n"
a6099ef3 2100 "\nReturns list of temporarily unspendable outputs.\n"
2101 "See the lockunspent call to lock and unlock transactions for spending.\n"
2102 "\nResult:\n"
2103 "[\n"
2104 " {\n"
2105 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2106 " \"vout\" : n (numeric) The vout value\n"
2107 " }\n"
2108 " ,...\n"
2109 "]\n"
2110 "\nExamples:\n"
2111 "\nList the unspent transactions\n"
2112 + HelpExampleCli("listunspent", "") +
2113 "\nLock an unspent transaction\n"
2114 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2115 "\nList the locked transactions\n"
2116 + HelpExampleCli("listlockunspent", "") +
2117 "\nUnlock the transaction again\n"
2118 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2119 "\nAs a json rpc call\n"
2120 + HelpExampleRpc("listlockunspent", "")
2121 );
fdbb537d 2122
4401b2d7
EL
2123 LOCK2(cs_main, pwalletMain->cs_wallet);
2124
fdbb537d
JG
2125 vector<COutPoint> vOutpts;
2126 pwalletMain->ListLockedCoins(vOutpts);
2127
2128 Array ret;
2129
2130 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2131 Object o;
2132
2133 o.push_back(Pair("txid", outpt.hash.GetHex()));
2134 o.push_back(Pair("vout", (int)outpt.n));
2135 ret.push_back(o);
2136 }
2137
2138 return ret;
2139}
2140
a943bde6
WL
2141Value settxfee(const Array& params, bool fHelp)
2142{
b9fb692d
JS
2143 if (!EnsureWalletIsAvailable(fHelp))
2144 return Value::null;
2145
a943bde6
WL
2146 if (fHelp || params.size() < 1 || params.size() > 1)
2147 throw runtime_error(
2148 "settxfee amount\n"
6943cb9b 2149 "\nSet the transaction fee per kB.\n"
a943bde6 2150 "\nArguments:\n"
6943cb9b 2151 "1. amount (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
a943bde6
WL
2152 "\nResult\n"
2153 "true|false (boolean) Returns true if successful\n"
2154 "\nExamples:\n"
2155 + HelpExampleCli("settxfee", "0.00001")
2156 + HelpExampleRpc("settxfee", "0.00001")
2157 );
2158
4401b2d7
EL
2159 LOCK2(cs_main, pwalletMain->cs_wallet);
2160
a943bde6 2161 // Amount
a372168e 2162 CAmount nAmount = 0;
a943bde6
WL
2163 if (params[0].get_real() != 0.0)
2164 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
2165
c6cb21d1 2166 payTxFee = CFeeRate(nAmount, 1000);
a943bde6
WL
2167 return true;
2168}
2169
a00ebb51
DN
2170Value getwalletinfo(const Array& params, bool fHelp)
2171{
b9fb692d
JS
2172 if (!EnsureWalletIsAvailable(fHelp))
2173 return Value::null;
2174
a00ebb51
DN
2175 if (fHelp || params.size() != 0)
2176 throw runtime_error(
2177 "getwalletinfo\n"
2178 "Returns an object containing various wallet state info.\n"
2179 "\nResult:\n"
2180 "{\n"
2181 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
d44c5456 2182 " \"balance\": xxxxxxx, (numeric) the total confirmed bitcoin balance of the wallet\n"
8024d67d
GM
2183 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed bitcoin balance of the wallet\n"
2184 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet\n"
a00ebb51
DN
2185 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2186 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
2187 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
2188 " \"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"
2189 "}\n"
2190 "\nExamples:\n"
2191 + HelpExampleCli("getwalletinfo", "")
2192 + HelpExampleRpc("getwalletinfo", "")
2193 );
2194
4401b2d7
EL
2195 LOCK2(cs_main, pwalletMain->cs_wallet);
2196
a00ebb51
DN
2197 Object obj;
2198 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2199 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
8024d67d
GM
2200 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2201 obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
a00ebb51 2202 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
d56e30ca 2203 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
a00ebb51
DN
2204 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2205 if (pwalletMain->IsCrypted())
d56e30ca 2206 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
a00ebb51
DN
2207 return obj;
2208}
0f5954c4
GA
2209
2210Value resendwallettransactions(const Array& params, bool fHelp)
2211{
b9fb692d
JS
2212 if (!EnsureWalletIsAvailable(fHelp))
2213 return Value::null;
2214
0f5954c4
GA
2215 if (fHelp || params.size() != 0)
2216 throw runtime_error(
2217 "resendwallettransactions\n"
2218 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2219 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2220 "automatically.\n"
2221 "Returns array of transaction ids that were re-broadcast.\n"
2222 );
2223
2224 LOCK2(cs_main, pwalletMain->cs_wallet);
2225
2226 std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2227 Array result;
2228 BOOST_FOREACH(const uint256& txid, txids)
2229 {
2230 result.push_back(txid.ToString());
2231 }
2232 return result;
2233}
0b9dc9c8
JS
2234
2235Value listunspent(const Array& params, bool fHelp)
2236{
2237 if (!EnsureWalletIsAvailable(fHelp))
2238 return Value::null;
2239
2240 if (fHelp || params.size() > 3)
ea9e82df
JS
2241 throw runtime_error(
2242 "listunspent ( minconf maxconf [\"address\",...] )\n"
2243 "\nReturns array of unspent transaction outputs\n"
2244 "with between minconf and maxconf (inclusive) confirmations.\n"
2245 "Optionally filter to only include txouts paid to specified addresses.\n"
2246 "Results are an array of Objects, each of which has:\n"
2247 "{txid, vout, scriptPubKey, amount, confirmations}\n"
2248 "\nArguments:\n"
2249 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2250 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2251 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2252 " [\n"
2253 " \"address\" (string) bitcoin address\n"
2254 " ,...\n"
2255 " ]\n"
2256 "\nResult\n"
2257 "[ (array of json object)\n"
2258 " {\n"
2259 " \"txid\" : \"txid\", (string) the transaction id \n"
2260 " \"vout\" : n, (numeric) the vout value\n"
2261 " \"address\" : \"address\", (string) the bitcoin address\n"
2262 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2263 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2264 " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n"
2265 " \"confirmations\" : n (numeric) The number of confirmations\n"
2266 " }\n"
2267 " ,...\n"
2268 "]\n"
2269
2270 "\nExamples\n"
2271 + HelpExampleCli("listunspent", "")
2272 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2273 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2274 );
2275
0b9dc9c8 2276 RPCTypeCheck(params, boost::assign::list_of(int_type)(int_type)(array_type));
ea9e82df 2277
0b9dc9c8
JS
2278 int nMinDepth = 1;
2279 if (params.size() > 0)
ea9e82df
JS
2280 nMinDepth = params[0].get_int();
2281
0b9dc9c8
JS
2282 int nMaxDepth = 9999999;
2283 if (params.size() > 1)
ea9e82df
JS
2284 nMaxDepth = params[1].get_int();
2285
0b9dc9c8
JS
2286 set<CBitcoinAddress> setAddress;
2287 if (params.size() > 2) {
2288 Array inputs = params[2].get_array();
2289 BOOST_FOREACH(Value& input, inputs) {
2290 CBitcoinAddress address(input.get_str());
2291 if (!address.IsValid())
ea9e82df 2292 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
0b9dc9c8 2293 if (setAddress.count(address))
ea9e82df
JS
2294 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
2295 setAddress.insert(address);
0b9dc9c8
JS
2296 }
2297 }
ea9e82df 2298
0b9dc9c8
JS
2299 Array results;
2300 vector<COutput> vecOutputs;
2301 assert(pwalletMain != NULL);
2302 LOCK2(cs_main, pwalletMain->cs_wallet);
219953ce 2303 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
0b9dc9c8
JS
2304 BOOST_FOREACH(const COutput& out, vecOutputs) {
2305 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
ea9e82df
JS
2306 continue;
2307
0b9dc9c8
JS
2308 if (setAddress.size()) {
2309 CTxDestination address;
2310 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
ea9e82df
JS
2311 continue;
2312
0b9dc9c8 2313 if (!setAddress.count(address))
ea9e82df 2314 continue;
0b9dc9c8 2315 }
ea9e82df 2316
0b9dc9c8
JS
2317 CAmount nValue = out.tx->vout[out.i].nValue;
2318 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
2319 Object entry;
2320 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2321 entry.push_back(Pair("vout", out.i));
2322 CTxDestination address;
2323 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
2324 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
2325 if (pwalletMain->mapAddressBook.count(address))
ea9e82df 2326 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
0b9dc9c8
JS
2327 }
2328 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
2329 if (pk.IsPayToScriptHash()) {
2330 CTxDestination address;
2331 if (ExtractDestination(pk, address)) {
8b08d953 2332 const CScriptID& hash = boost::get<CScriptID>(address);
0b9dc9c8
JS
2333 CScript redeemScript;
2334 if (pwalletMain->GetCScript(hash, redeemScript))
ea9e82df 2335 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
0b9dc9c8
JS
2336 }
2337 }
2338 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
2339 entry.push_back(Pair("confirmations",out.nDepth));
2340 entry.push_back(Pair("spendable", out.fSpendable));
2341 results.push_back(entry);
2342 }
ea9e82df 2343
0b9dc9c8 2344 return results;
c9fd9078 2345}
730790f7 2346
a8ac403d
SB
2347Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
2348{
f15b9549
NW
2349 if (!EnsureWalletIsAvailable(fHelp)) {
2350 return Value::null;
2351 }
2352
2353 if (fHelp || params.size() != 2) {
2354 throw runtime_error(
2355 "zcrawreceive zcsecretkey encryptedbucket\n"
2356 "\n"
2357 "Decrypts encryptedbucket and checks if the coin commitments\n"
2358 "are in the blockchain as indicated by the \"exists\" result.\n"
2359 "\n"
2360 "Output: {\n"
2361 " \"amount\": value,\n"
2362 " \"bucket\": cleartextbucket,\n"
2363 " \"exists\": exists\n"
2364 "}\n"
2365 );
2366 }
2367
a8ac403d 2368 RPCTypeCheck(params, boost::assign::list_of(str_type)(str_type));
f15b9549 2369
a8ac403d
SB
2370 LOCK(cs_main);
2371
2372 std::vector<unsigned char> a_sk;
2373 std::string sk_enc;
2374
2375 {
2376 CDataStream ssData(ParseHexV(params[0], "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
2377 try {
2378 ssData >> a_sk;
2379 ssData >> sk_enc;
2380 } catch(const std::exception &) {
2381 throw runtime_error(
2382 "zcsecretkey could not be decoded"
2383 );
2384 }
2385 }
2386
2387 libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc);
2388 libzerocash::Address zcaddress(zcsecretkey);
2389
2390 auto encrypted_bucket_vec = ParseHexV(params[1], "encrypted_bucket");
2391 std::string encrypted_bucket(encrypted_bucket_vec.begin(), encrypted_bucket_vec.end());
2392 libzerocash::Coin decrypted_bucket(encrypted_bucket, zcaddress);
2393
2394 std::vector<unsigned char> commitment_v = decrypted_bucket.getCoinCommitment().getCommitmentValue();
2395 uint256 commitment = uint256(commitment_v);
2396
2397 assert(pwalletMain != NULL);
2398 libsnark::merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH); // We don't care during receive... yet! :)
2399 size_t path_index = 0;
2400 uint256 anchor;
2401 auto found_in_chain = pwalletMain->WitnessBucketCommitment(commitment, path, path_index, anchor);
2402
2403 CAmount value_of_bucket = decrypted_bucket.getValue();
2404
2405 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2406 {
2407 ss << decrypted_bucket.getValue();
2408 ss << decrypted_bucket.getRho();
2409 ss << decrypted_bucket.getR();
2410 }
2411
2412 Object result;
2413 result.push_back(Pair("amount", ValueFromAmount(value_of_bucket)));
2414 result.push_back(Pair("bucket", HexStr(ss.begin(), ss.end())));
2415 result.push_back(Pair("exists", found_in_chain));
2416 return result;
2417}
2418
730790f7
SB
2419Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
2420{
f15b9549
NW
2421 if (!EnsureWalletIsAvailable(fHelp)) {
2422 return Value::null;
2423 }
2424
2425 if (fHelp || params.size() != 5) {
2426 throw runtime_error(
2427 "zcrawpour rawtx inputs outputs vpub_old vpub_new\n"
2428 " inputs: a JSON object mapping {bucket: zcsecretkey, ...}\n"
2429 " outputs: a JSON object mapping {zcaddr: value, ...}\n"
2430 "\n"
2431 "Splices a Pour into rawtx. Inputs are unilaterally confidential.\n"
2432 "Outputs are confidential between sender/receiver. The vpub_old and\n"
2433 "vpub_new values are globally public and move transparent value into\n"
2434 "or out of the confidential value store, respectively.\n"
2435 "\n"
2436 "Note: The caller is responsible for delivering the output enc1 and\n"
2437 "enc2 to the appropriate recipients, as well as signing rawtxout and\n"
2438 "ensuring it is mined. (A future RPC call will deliver the confidential\n"
2439 "payments in-band on the blockchain.)\n"
2440 "\n"
2441 "Output: {\n"
2442 " \"encryptedbucket1\": enc1,\n"
2443 " \"encryptedbucket2\": enc2,\n"
2444 " \"rawtxn\": rawtxout\n"
2445 "}\n"
2446 );
2447 }
2448
2449 RPCTypeCheck(params, boost::assign::list_of(str_type)(obj_type)(obj_type)(int_type)(int_type));
a8ac403d
SB
2450
2451 LOCK(cs_main);
730790f7
SB
2452
2453 CTransaction tx;
2454 if (!DecodeHexTx(tx, params[0].get_str()))
2455 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2456
2457 Object inputs = params[1].get_obj();
2458 Object outputs = params[2].get_obj();
2459
2460 CAmount vpub_old(0);
2461 CAmount vpub_new(0);
2462
2463 if (params[3].get_real() != 0.0)
2464 vpub_old = AmountFromValue(params[3]);
2465
2466 if (params[4].get_real() != 0.0)
2467 vpub_new = AmountFromValue(params[4]);
2468
2469 std::vector<PourInput> vpourin;
2470 std::vector<PourOutput> vpourout;
2471
a8ac403d
SB
2472 uint256 anchor;
2473
730790f7
SB
2474 BOOST_FOREACH(const Pair& s, inputs)
2475 {
a8ac403d
SB
2476 CDataStream ssData(ParseHexV(s.name_, "bucket"), SER_NETWORK, PROTOCOL_VERSION);
2477 uint64_t value;
2478 std::vector<unsigned char> rho;
2479 std::vector<unsigned char> r;
2480
2481 ssData >> value;
2482 ssData >> rho;
2483 ssData >> r;
2484
2485 std::vector<unsigned char> a_sk;
2486 std::string sk_enc;
2487
2488 {
2489 CDataStream ssData2(ParseHexV(s.value_, "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
2490 try {
2491 ssData2 >> a_sk;
2492 ssData2 >> sk_enc;
2493 } catch(const std::exception &) {
2494 throw runtime_error(
2495 "zcsecretkey could not be decoded"
2496 );
2497 }
2498 }
2499
2500 libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc);
2501 libzerocash::Address zcaddress(zcsecretkey);
2502 libzerocash::Coin input_coin(zcaddress.getPublicAddress(), value, rho, r);
2503
2504 std::vector<unsigned char> commitment_v = input_coin.getCoinCommitment().getCommitmentValue();
2505 uint256 commitment = uint256(commitment_v);
2506
2507 libsnark::merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH);
2508 size_t path_index = 0;
2509 assert(pwalletMain != NULL);
2510 if (!pwalletMain->WitnessBucketCommitment(commitment, path, path_index, anchor)) {
2511 throw std::runtime_error("Couldn't find bucket in the blockchain");
2512 }
2513
2514 vpourin.push_back(PourInput(input_coin, zcaddress, path_index, path));
730790f7 2515 }
730790f7 2516
a8ac403d
SB
2517 while (vpourin.size() < 2) {
2518 vpourin.push_back(PourInput(INCREMENTAL_MERKLE_TREE_DEPTH));
2519 }
730790f7
SB
2520
2521 BOOST_FOREACH(const Pair& s, outputs)
2522 {
2523 libzerocash::PublicAddress addrTo;
2524
2525 {
a8ac403d 2526 CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION);
730790f7
SB
2527
2528 std::vector<unsigned char> pubAddressSecret;
2529 std::string encryptionPublicKey;
2530
2531 ssData >> pubAddressSecret;
2532 ssData >> encryptionPublicKey;
2533
2534 addrTo = libzerocash::PublicAddress(pubAddressSecret, encryptionPublicKey);
2535 }
2536 CAmount nAmount = AmountFromValue(s.value_);
2537
2538 libzerocash::Coin coin(addrTo, nAmount);
2539 libzerocash::PourOutput output(coin, addrTo);
2540
2541 vpourout.push_back(output);
2542 }
2543
2544 while (vpourout.size() < 2) {
2545 vpourout.push_back(PourOutput(0));
2546 }
2547
2548 // TODO
2549 if (vpourout.size() > 2 || vpourin.size() > 2) {
2550 throw runtime_error("unsupported");
2551 }
2552
730790f7
SB
2553 CScript scriptPubKey;
2554 CPourTx pourtx(*pzerocashParams,
2555 scriptPubKey,
2556 anchor,
2557 {vpourin[0], vpourin[1]},
2558 {vpourout[0], vpourout[1]},
2559 vpub_old,
2560 vpub_new);
2561
a8ac403d
SB
2562 assert(pourtx.Verify(*pzerocashParams));
2563
730790f7
SB
2564 CMutableTransaction mtx(tx);
2565 mtx.nVersion = 2;
2566 mtx.vpour.push_back(pourtx);
2567
2568 CTransaction rawTx(mtx);
2569
2570 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2571 ss << rawTx;
2572
2573 Object result;
2574 result.push_back(Pair("encryptedbucket1", HexStr(pourtx.ciphertexts[0].begin(), pourtx.ciphertexts[0].end())));
2575 result.push_back(Pair("encryptedbucket2", HexStr(pourtx.ciphertexts[1].begin(), pourtx.ciphertexts[1].end())));
2576 result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
2577 return result;
2578}
2579
2580Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp)
2581{
f15b9549
NW
2582 if (!EnsureWalletIsAvailable(fHelp)) {
2583 return Value::null;
2584 }
2585
2586 if (fHelp || params.size() != 0) {
2587 throw runtime_error(
2588 "zcrawkeygen\n"
2589 "\n"
2590 "Generate a zcaddr which can send and receive confidential values.\n"
2591 "\n"
2592 "Output: {\n"
2593 " \"zcaddress\": zcaddr,\n"
2594 " \"zcsecretkey\": zcsecretkey,\n"
2595 "}\n"
2596 );
2597 }
2598
730790f7
SB
2599 auto zckeypair = libzerocash::Address::CreateNewRandomAddress();
2600
2601 CDataStream pub(SER_NETWORK, PROTOCOL_VERSION);
2602 CDataStream priv(SER_NETWORK, PROTOCOL_VERSION);
2603
2604 pub << zckeypair.getPublicAddress().getPublicAddressSecret(); // a_pk
2605 pub << zckeypair.getPublicAddress().getEncryptionPublicKey(); // pk_enc
2606
2607 priv << zckeypair.getPrivateAddress().getAddressSecret(); // a_sk
2608 priv << zckeypair.getPrivateAddress().getEncryptionSecretKey(); // sk_enc
2609
2610 std::string pub_hex = HexStr(pub.begin(), pub.end());
2611 std::string priv_hex = HexStr(priv.begin(), priv.end());
2612
2613 Object result;
2614 result.push_back(Pair("zcaddress", pub_hex));
2615 result.push_back(Pair("zcsecretkey", priv_hex));
2616 return result;
f15b9549 2617}
This page took 0.536751 seconds and 4 git commands to generate.