]> Git Repo - VerusCoin.git/blob - src/rpcwallet.cpp
Merge pull request #5576
[VerusCoin.git] / src / rpcwallet.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "amount.h"
7 #include "base58.h"
8 #include "core_io.h"
9 #include "rpcserver.h"
10 #include "init.h"
11 #include "net.h"
12 #include "netbase.h"
13 #include "timedata.h"
14 #include "util.h"
15 #include "utilmoneystr.h"
16 #include "wallet.h"
17 #include "walletdb.h"
18
19 #include <stdint.h>
20
21 #include <boost/assign/list_of.hpp>
22 #include "json/json_spirit_utils.h"
23 #include "json/json_spirit_value.h"
24
25 using namespace std;
26 using namespace boost;
27 using namespace boost::assign;
28 using namespace json_spirit;
29
30 int64_t nWalletUnlockTime;
31 static CCriticalSection cs_nWalletUnlockTime;
32
33 std::string HelpRequiringPassphrase()
34 {
35     return pwalletMain && pwalletMain->IsCrypted()
36         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
37         : "";
38 }
39
40 void EnsureWalletIsUnlocked()
41 {
42     if (pwalletMain->IsLocked())
43         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
44 }
45
46 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
47 {
48     int confirms = wtx.GetDepthInMainChain();
49     entry.push_back(Pair("confirmations", confirms));
50     if (wtx.IsCoinBase())
51         entry.push_back(Pair("generated", true));
52     if (confirms > 0)
53     {
54         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
55         entry.push_back(Pair("blockindex", wtx.nIndex));
56         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
57     }
58     uint256 hash = wtx.GetHash();
59     entry.push_back(Pair("txid", hash.GetHex()));
60     Array conflicts;
61     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
62         conflicts.push_back(conflict.GetHex());
63     entry.push_back(Pair("walletconflicts", conflicts));
64     entry.push_back(Pair("time", wtx.GetTxTime()));
65     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
66     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
67         entry.push_back(Pair(item.first, item.second));
68 }
69
70 string AccountFromValue(const Value& value)
71 {
72     string strAccount = value.get_str();
73     if (strAccount == "*")
74         throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
75     return strAccount;
76 }
77
78 Value getnewaddress(const Array& params, bool fHelp)
79 {
80     if (fHelp || params.size() > 1)
81         throw runtime_error(
82             "getnewaddress ( \"account\" )\n"
83             "\nReturns a new Bitcoin address for receiving payments.\n"
84             "If 'account' is specified (recommended), it is added to the address book \n"
85             "so payments received with the address will be credited to 'account'.\n"
86             "\nArguments:\n"
87             "1. \"account\"        (string, optional) 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"
88             "\nResult:\n"
89             "\"bitcoinaddress\"    (string) The new bitcoin address\n"
90             "\nExamples:\n"
91             + HelpExampleCli("getnewaddress", "")
92             + HelpExampleCli("getnewaddress", "\"\"")
93             + HelpExampleCli("getnewaddress", "\"myaccount\"")
94             + HelpExampleRpc("getnewaddress", "\"myaccount\"")
95         );
96
97     // Parse the account first so we don't generate a key if there's an error
98     string strAccount;
99     if (params.size() > 0)
100         strAccount = AccountFromValue(params[0]);
101
102     if (!pwalletMain->IsLocked())
103         pwalletMain->TopUpKeyPool();
104
105     // Generate a new key that is added to wallet
106     CPubKey newKey;
107     if (!pwalletMain->GetKeyFromPool(newKey))
108         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
109     CKeyID keyID = newKey.GetID();
110
111     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
112
113     return CBitcoinAddress(keyID).ToString();
114 }
115
116
117 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
118 {
119     CWalletDB walletdb(pwalletMain->strWalletFile);
120
121     CAccount account;
122     walletdb.ReadAccount(strAccount, account);
123
124     bool bKeyUsed = false;
125
126     // Check if the current key has been used
127     if (account.vchPubKey.IsValid())
128     {
129         CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
130         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
131              it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
132              ++it)
133         {
134             const CWalletTx& wtx = (*it).second;
135             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
136                 if (txout.scriptPubKey == scriptPubKey)
137                     bKeyUsed = true;
138         }
139     }
140
141     // Generate a new key
142     if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
143     {
144         if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
145             throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
146
147         pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
148         walletdb.WriteAccount(strAccount, account);
149     }
150
151     return CBitcoinAddress(account.vchPubKey.GetID());
152 }
153
154 Value getaccountaddress(const Array& params, bool fHelp)
155 {
156     if (fHelp || params.size() != 1)
157         throw runtime_error(
158             "getaccountaddress \"account\"\n"
159             "\nReturns the current Bitcoin address for receiving payments to this account.\n"
160             "\nArguments:\n"
161             "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"
162             "\nResult:\n"
163             "\"bitcoinaddress\"   (string) The account bitcoin address\n"
164             "\nExamples:\n"
165             + HelpExampleCli("getaccountaddress", "")
166             + HelpExampleCli("getaccountaddress", "\"\"")
167             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
168             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
169         );
170
171     // Parse the account first so we don't generate a key if there's an error
172     string strAccount = AccountFromValue(params[0]);
173
174     Value ret;
175
176     ret = GetAccountAddress(strAccount).ToString();
177
178     return ret;
179 }
180
181
182 Value getrawchangeaddress(const Array& params, bool fHelp)
183 {
184     if (fHelp || params.size() > 1)
185         throw runtime_error(
186             "getrawchangeaddress\n"
187             "\nReturns a new Bitcoin address, for receiving change.\n"
188             "This is for use with raw transactions, NOT normal use.\n"
189             "\nResult:\n"
190             "\"address\"    (string) The address\n"
191             "\nExamples:\n"
192             + HelpExampleCli("getrawchangeaddress", "")
193             + HelpExampleRpc("getrawchangeaddress", "")
194        );
195
196     if (!pwalletMain->IsLocked())
197         pwalletMain->TopUpKeyPool();
198
199     CReserveKey reservekey(pwalletMain);
200     CPubKey vchPubKey;
201     if (!reservekey.GetReservedKey(vchPubKey))
202         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
203
204     reservekey.KeepKey();
205
206     CKeyID keyID = vchPubKey.GetID();
207
208     return CBitcoinAddress(keyID).ToString();
209 }
210
211
212 Value setaccount(const Array& params, bool fHelp)
213 {
214     if (fHelp || params.size() < 1 || params.size() > 2)
215         throw runtime_error(
216             "setaccount \"bitcoinaddress\" \"account\"\n"
217             "\nSets the account associated with the given address.\n"
218             "\nArguments:\n"
219             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to be associated with an account.\n"
220             "2. \"account\"         (string, required) The account to assign the address to.\n"
221             "\nExamples:\n"
222             + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
223             + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
224         );
225
226     CBitcoinAddress address(params[0].get_str());
227     if (!address.IsValid())
228         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
229
230
231     string strAccount;
232     if (params.size() > 1)
233         strAccount = AccountFromValue(params[1]);
234
235     // Only add the account if the address is yours.
236     if (IsMine(*pwalletMain, address.Get()))
237     {
238         // Detect when changing the account of an address that is the 'unused current key' of another account:
239         if (pwalletMain->mapAddressBook.count(address.Get()))
240         {
241             string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
242             if (address == GetAccountAddress(strOldAccount))
243                 GetAccountAddress(strOldAccount, true);
244         }
245         pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
246     }
247     else
248         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
249
250     return Value::null;
251 }
252
253
254 Value getaccount(const Array& params, bool fHelp)
255 {
256     if (fHelp || params.size() != 1)
257         throw runtime_error(
258             "getaccount \"bitcoinaddress\"\n"
259             "\nReturns the account associated with the given address.\n"
260             "\nArguments:\n"
261             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for account lookup.\n"
262             "\nResult:\n"
263             "\"accountname\"        (string) the account address\n"
264             "\nExamples:\n"
265             + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
266             + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
267         );
268
269     CBitcoinAddress address(params[0].get_str());
270     if (!address.IsValid())
271         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
272
273     string strAccount;
274     map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
275     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
276         strAccount = (*mi).second.name;
277     return strAccount;
278 }
279
280
281 Value getaddressesbyaccount(const Array& params, bool fHelp)
282 {
283     if (fHelp || params.size() != 1)
284         throw runtime_error(
285             "getaddressesbyaccount \"account\"\n"
286             "\nReturns the list of addresses for the given account.\n"
287             "\nArguments:\n"
288             "1. \"account\"  (string, required) The account name.\n"
289             "\nResult:\n"
290             "[                     (json array of string)\n"
291             "  \"bitcoinaddress\"  (string) a bitcoin address associated with the given account\n"
292             "  ,...\n"
293             "]\n"
294             "\nExamples:\n"
295             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
296             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
297         );
298
299     string strAccount = AccountFromValue(params[0]);
300
301     // Find all addresses that have the given account
302     Array ret;
303     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
304     {
305         const CBitcoinAddress& address = item.first;
306         const string& strName = item.second.name;
307         if (strName == strAccount)
308             ret.push_back(address.ToString());
309     }
310     return ret;
311 }
312
313 void SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
314 {
315     // Check amount
316     if (nValue <= 0)
317         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
318
319     if (nValue > pwalletMain->GetBalance())
320         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
321
322     string strError;
323     if (pwalletMain->IsLocked())
324     {
325         strError = "Error: Wallet locked, unable to create transaction!";
326         LogPrintf("SendMoney() : %s", strError);
327         throw JSONRPCError(RPC_WALLET_ERROR, strError);
328     }
329
330     // Parse Bitcoin address
331     CScript scriptPubKey = GetScriptForDestination(address);
332
333     // Create and send the transaction
334     CReserveKey reservekey(pwalletMain);
335     CAmount nFeeRequired;
336     if (!pwalletMain->CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
337     {
338         if (nValue + nFeeRequired > pwalletMain->GetBalance())
339             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));
340         LogPrintf("SendMoney() : %s\n", strError);
341         throw JSONRPCError(RPC_WALLET_ERROR, strError);
342     }
343     if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
344         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.");
345 }
346
347 Value sendtoaddress(const Array& params, bool fHelp)
348 {
349     if (fHelp || params.size() < 2 || params.size() > 4)
350         throw runtime_error(
351             "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
352             "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
353             + HelpRequiringPassphrase() +
354             "\nArguments:\n"
355             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to send to.\n"
356             "2. \"amount\"      (numeric, required) The amount in btc to send. eg 0.1\n"
357             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
358             "                             This is not part of the transaction, just kept in your wallet.\n"
359             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
360             "                             to which you're sending the transaction. This is not part of the \n"
361             "                             transaction, just kept in your wallet.\n"
362             "\nResult:\n"
363             "\"transactionid\"  (string) The transaction id.\n"
364             "\nExamples:\n"
365             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
366             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
367             + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
368         );
369
370     CBitcoinAddress address(params[0].get_str());
371     if (!address.IsValid())
372         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
373
374     // Amount
375     CAmount nAmount = AmountFromValue(params[1]);
376
377     // Wallet comments
378     CWalletTx wtx;
379     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
380         wtx.mapValue["comment"] = params[2].get_str();
381     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
382         wtx.mapValue["to"]      = params[3].get_str();
383
384     EnsureWalletIsUnlocked();
385
386     SendMoney(address.Get(), nAmount, wtx);
387
388     return wtx.GetHash().GetHex();
389 }
390
391 Value listaddressgroupings(const Array& params, bool fHelp)
392 {
393     if (fHelp)
394         throw runtime_error(
395             "listaddressgroupings\n"
396             "\nLists groups of addresses which have had their common ownership\n"
397             "made public by common use as inputs or as the resulting change\n"
398             "in past transactions\n"
399             "\nResult:\n"
400             "[\n"
401             "  [\n"
402             "    [\n"
403             "      \"bitcoinaddress\",     (string) The bitcoin address\n"
404             "      amount,                 (numeric) The amount in btc\n"
405             "      \"account\"             (string, optional) The account\n"
406             "    ]\n"
407             "    ,...\n"
408             "  ]\n"
409             "  ,...\n"
410             "]\n"
411             "\nExamples:\n"
412             + HelpExampleCli("listaddressgroupings", "")
413             + HelpExampleRpc("listaddressgroupings", "")
414         );
415
416     Array jsonGroupings;
417     map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
418     BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
419     {
420         Array jsonGrouping;
421         BOOST_FOREACH(CTxDestination address, grouping)
422         {
423             Array addressInfo;
424             addressInfo.push_back(CBitcoinAddress(address).ToString());
425             addressInfo.push_back(ValueFromAmount(balances[address]));
426             {
427                 LOCK(pwalletMain->cs_wallet);
428                 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
429                     addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
430             }
431             jsonGrouping.push_back(addressInfo);
432         }
433         jsonGroupings.push_back(jsonGrouping);
434     }
435     return jsonGroupings;
436 }
437
438 Value signmessage(const Array& params, bool fHelp)
439 {
440     if (fHelp || params.size() != 2)
441         throw runtime_error(
442             "signmessage \"bitcoinaddress\" \"message\"\n"
443             "\nSign a message with the private key of an address"
444             + HelpRequiringPassphrase() + "\n"
445             "\nArguments:\n"
446             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the private key.\n"
447             "2. \"message\"         (string, required) The message to create a signature of.\n"
448             "\nResult:\n"
449             "\"signature\"          (string) The signature of the message encoded in base 64\n"
450             "\nExamples:\n"
451             "\nUnlock the wallet for 30 seconds\n"
452             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
453             "\nCreate the signature\n"
454             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
455             "\nVerify the signature\n"
456             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
457             "\nAs json rpc\n"
458             + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
459         );
460
461     EnsureWalletIsUnlocked();
462
463     string strAddress = params[0].get_str();
464     string strMessage = params[1].get_str();
465
466     CBitcoinAddress addr(strAddress);
467     if (!addr.IsValid())
468         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
469
470     CKeyID keyID;
471     if (!addr.GetKeyID(keyID))
472         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
473
474     CKey key;
475     if (!pwalletMain->GetKey(keyID, key))
476         throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
477
478     CHashWriter ss(SER_GETHASH, 0);
479     ss << strMessageMagic;
480     ss << strMessage;
481
482     vector<unsigned char> vchSig;
483     if (!key.SignCompact(ss.GetHash(), vchSig))
484         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
485
486     return EncodeBase64(&vchSig[0], vchSig.size());
487 }
488
489 Value getreceivedbyaddress(const Array& params, bool fHelp)
490 {
491     if (fHelp || params.size() < 1 || params.size() > 2)
492         throw runtime_error(
493             "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
494             "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
495             "\nArguments:\n"
496             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for transactions.\n"
497             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
498             "\nResult:\n"
499             "amount   (numeric) The total amount in btc received at this address.\n"
500             "\nExamples:\n"
501             "\nThe amount from transactions with at least 1 confirmation\n"
502             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
503             "\nThe amount including unconfirmed transactions, zero confirmations\n"
504             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
505             "\nThe amount with at least 6 confirmation, very safe\n"
506             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
507             "\nAs a json rpc call\n"
508             + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
509        );
510
511     // Bitcoin address
512     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
513     if (!address.IsValid())
514         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
515     CScript scriptPubKey = GetScriptForDestination(address.Get());
516     if (!IsMine(*pwalletMain,scriptPubKey))
517         return (double)0.0;
518
519     // Minimum confirmations
520     int nMinDepth = 1;
521     if (params.size() > 1)
522         nMinDepth = params[1].get_int();
523
524     // Tally
525     CAmount nAmount = 0;
526     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
527     {
528         const CWalletTx& wtx = (*it).second;
529         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
530             continue;
531
532         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
533             if (txout.scriptPubKey == scriptPubKey)
534                 if (wtx.GetDepthInMainChain() >= nMinDepth)
535                     nAmount += txout.nValue;
536     }
537
538     return  ValueFromAmount(nAmount);
539 }
540
541
542 Value getreceivedbyaccount(const Array& params, bool fHelp)
543 {
544     if (fHelp || params.size() < 1 || params.size() > 2)
545         throw runtime_error(
546             "getreceivedbyaccount \"account\" ( minconf )\n"
547             "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
548             "\nArguments:\n"
549             "1. \"account\"      (string, required) The selected account, may be the default account using \"\".\n"
550             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
551             "\nResult:\n"
552             "amount              (numeric) The total amount in btc received for this account.\n"
553             "\nExamples:\n"
554             "\nAmount received by the default account with at least 1 confirmation\n"
555             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
556             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
557             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
558             "\nThe amount with at least 6 confirmation, very safe\n"
559             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
560             "\nAs a json rpc call\n"
561             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
562         );
563
564     // Minimum confirmations
565     int nMinDepth = 1;
566     if (params.size() > 1)
567         nMinDepth = params[1].get_int();
568
569     // Get the set of pub keys assigned to account
570     string strAccount = AccountFromValue(params[0]);
571     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
572
573     // Tally
574     CAmount nAmount = 0;
575     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
576     {
577         const CWalletTx& wtx = (*it).second;
578         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
579             continue;
580
581         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
582         {
583             CTxDestination address;
584             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
585                 if (wtx.GetDepthInMainChain() >= nMinDepth)
586                     nAmount += txout.nValue;
587         }
588     }
589
590     return (double)nAmount / (double)COIN;
591 }
592
593
594 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
595 {
596     CAmount nBalance = 0;
597
598     // Tally wallet transactions
599     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
600     {
601         const CWalletTx& wtx = (*it).second;
602         if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
603             continue;
604
605         CAmount nReceived, nSent, nFee;
606         wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
607
608         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
609             nBalance += nReceived;
610         nBalance -= nSent + nFee;
611     }
612
613     // Tally internal accounting entries
614     nBalance += walletdb.GetAccountCreditDebit(strAccount);
615
616     return nBalance;
617 }
618
619 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
620 {
621     CWalletDB walletdb(pwalletMain->strWalletFile);
622     return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
623 }
624
625
626 Value getbalance(const Array& params, bool fHelp)
627 {
628     if (fHelp || params.size() > 3)
629         throw runtime_error(
630             "getbalance ( \"account\" minconf includeWatchonly )\n"
631             "\nIf account is not specified, returns the server's total available balance.\n"
632             "If account is specified, returns the balance in the account.\n"
633             "Note that the account \"\" is not the same as leaving the parameter out.\n"
634             "The server total may be different to the balance in the default \"\" account.\n"
635             "\nArguments:\n"
636             "1. \"account\"      (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
637             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
638             "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
639             "\nResult:\n"
640             "amount              (numeric) The total amount in btc received for this account.\n"
641             "\nExamples:\n"
642             "\nThe total amount in the server across all accounts\n"
643             + HelpExampleCli("getbalance", "") +
644             "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
645             + HelpExampleCli("getbalance", "\"*\" 6") +
646             "\nThe total amount in the default account with at least 1 confirmation\n"
647             + HelpExampleCli("getbalance", "\"\"") +
648             "\nThe total amount in the account named tabby with at least 6 confirmations\n"
649             + HelpExampleCli("getbalance", "\"tabby\" 6") +
650             "\nAs a json rpc call\n"
651             + HelpExampleRpc("getbalance", "\"tabby\", 6")
652         );
653
654     if (params.size() == 0)
655         return  ValueFromAmount(pwalletMain->GetBalance());
656
657     int nMinDepth = 1;
658     if (params.size() > 1)
659         nMinDepth = params[1].get_int();
660     isminefilter filter = ISMINE_SPENDABLE;
661     if(params.size() > 2)
662         if(params[2].get_bool())
663             filter = filter | ISMINE_WATCH_ONLY;
664
665     if (params[0].get_str() == "*") {
666         // Calculate total balance a different way from GetBalance()
667         // (GetBalance() sums up all unspent TxOuts)
668         // getbalance and getbalance '*' 0 should return the same number
669         CAmount nBalance = 0;
670         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
671         {
672             const CWalletTx& wtx = (*it).second;
673             if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
674                 continue;
675
676             CAmount allFee;
677             string strSentAccount;
678             list<COutputEntry> listReceived;
679             list<COutputEntry> listSent;
680             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
681             if (wtx.GetDepthInMainChain() >= nMinDepth)
682             {
683                 BOOST_FOREACH(const COutputEntry& r, listReceived)
684                     nBalance += r.amount;
685             }
686             BOOST_FOREACH(const COutputEntry& s, listSent)
687                 nBalance -= s.amount;
688             nBalance -= allFee;
689         }
690         return  ValueFromAmount(nBalance);
691     }
692
693     string strAccount = AccountFromValue(params[0]);
694
695     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
696
697     return ValueFromAmount(nBalance);
698 }
699
700 Value getunconfirmedbalance(const Array &params, bool fHelp)
701 {
702     if (fHelp || params.size() > 0)
703         throw runtime_error(
704                 "getunconfirmedbalance\n"
705                 "Returns the server's total unconfirmed balance\n");
706     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
707 }
708
709
710 Value movecmd(const Array& params, bool fHelp)
711 {
712     if (fHelp || params.size() < 3 || params.size() > 5)
713         throw runtime_error(
714             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
715             "\nMove a specified amount from one account in your wallet to another.\n"
716             "\nArguments:\n"
717             "1. \"fromaccount\"   (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
718             "2. \"toaccount\"     (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
719             "3. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
720             "4. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
721             "\nResult:\n"
722             "true|false           (boolean) true if successfull.\n"
723             "\nExamples:\n"
724             "\nMove 0.01 btc from the default account to the account named tabby\n"
725             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
726             "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
727             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
728             "\nAs a json rpc call\n"
729             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
730         );
731
732     string strFrom = AccountFromValue(params[0]);
733     string strTo = AccountFromValue(params[1]);
734     CAmount nAmount = AmountFromValue(params[2]);
735     if (params.size() > 3)
736         // unused parameter, used to be nMinDepth, keep type-checking it though
737         (void)params[3].get_int();
738     string strComment;
739     if (params.size() > 4)
740         strComment = params[4].get_str();
741
742     CWalletDB walletdb(pwalletMain->strWalletFile);
743     if (!walletdb.TxnBegin())
744         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
745
746     int64_t nNow = GetAdjustedTime();
747
748     // Debit
749     CAccountingEntry debit;
750     debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
751     debit.strAccount = strFrom;
752     debit.nCreditDebit = -nAmount;
753     debit.nTime = nNow;
754     debit.strOtherAccount = strTo;
755     debit.strComment = strComment;
756     walletdb.WriteAccountingEntry(debit);
757
758     // Credit
759     CAccountingEntry credit;
760     credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
761     credit.strAccount = strTo;
762     credit.nCreditDebit = nAmount;
763     credit.nTime = nNow;
764     credit.strOtherAccount = strFrom;
765     credit.strComment = strComment;
766     walletdb.WriteAccountingEntry(credit);
767
768     if (!walletdb.TxnCommit())
769         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
770
771     return true;
772 }
773
774
775 Value sendfrom(const Array& params, bool fHelp)
776 {
777     if (fHelp || params.size() < 3 || params.size() > 6)
778         throw runtime_error(
779             "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
780             "\nSent an amount from an account to a bitcoin address.\n"
781             "The amount is a real and is rounded to the nearest 0.00000001."
782             + HelpRequiringPassphrase() + "\n"
783             "\nArguments:\n"
784             "1. \"fromaccount\"       (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
785             "2. \"tobitcoinaddress\"  (string, required) The bitcoin address to send funds to.\n"
786             "3. amount                (numeric, required) The amount in btc. (transaction fee is added on top).\n"
787             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
788             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
789             "                                     This is not part of the transaction, just kept in your wallet.\n"
790             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
791             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
792             "                                     it is just kept in your wallet.\n"
793             "\nResult:\n"
794             "\"transactionid\"        (string) The transaction id.\n"
795             "\nExamples:\n"
796             "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
797             + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
798             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
799             + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
800             "\nAs a json rpc call\n"
801             + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
802         );
803
804     string strAccount = AccountFromValue(params[0]);
805     CBitcoinAddress address(params[1].get_str());
806     if (!address.IsValid())
807         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
808     CAmount nAmount = AmountFromValue(params[2]);
809     int nMinDepth = 1;
810     if (params.size() > 3)
811         nMinDepth = params[3].get_int();
812
813     CWalletTx wtx;
814     wtx.strFromAccount = strAccount;
815     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
816         wtx.mapValue["comment"] = params[4].get_str();
817     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
818         wtx.mapValue["to"]      = params[5].get_str();
819
820     EnsureWalletIsUnlocked();
821
822     // Check funds
823     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
824     if (nAmount > nBalance)
825         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
826
827     SendMoney(address.Get(), nAmount, wtx);
828
829     return wtx.GetHash().GetHex();
830 }
831
832
833 Value sendmany(const Array& params, bool fHelp)
834 {
835     if (fHelp || params.size() < 2 || params.size() > 4)
836         throw runtime_error(
837             "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
838             "\nSend multiple times. Amounts are double-precision floating point numbers."
839             + HelpRequiringPassphrase() + "\n"
840             "\nArguments:\n"
841             "1. \"fromaccount\"         (string, required) The account to send the funds from, can be \"\" for the default account\n"
842             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
843             "    {\n"
844             "      \"address\":amount   (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
845             "      ,...\n"
846             "    }\n"
847             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
848             "4. \"comment\"             (string, optional) A comment\n"
849             "\nResult:\n"
850             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
851             "                                    the number of addresses.\n"
852             "\nExamples:\n"
853             "\nSend two amounts to two different addresses:\n"
854             + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
855             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
856             + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
857             "\nAs a json rpc call\n"
858             + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
859         );
860
861     string strAccount = AccountFromValue(params[0]);
862     Object sendTo = params[1].get_obj();
863     int nMinDepth = 1;
864     if (params.size() > 2)
865         nMinDepth = params[2].get_int();
866
867     CWalletTx wtx;
868     wtx.strFromAccount = strAccount;
869     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
870         wtx.mapValue["comment"] = params[3].get_str();
871
872     set<CBitcoinAddress> setAddress;
873     vector<pair<CScript, CAmount> > vecSend;
874
875     CAmount totalAmount = 0;
876     BOOST_FOREACH(const Pair& s, sendTo)
877     {
878         CBitcoinAddress address(s.name_);
879         if (!address.IsValid())
880             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
881
882         if (setAddress.count(address))
883             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
884         setAddress.insert(address);
885
886         CScript scriptPubKey = GetScriptForDestination(address.Get());
887         CAmount nAmount = AmountFromValue(s.value_);
888         totalAmount += nAmount;
889
890         vecSend.push_back(make_pair(scriptPubKey, nAmount));
891     }
892
893     EnsureWalletIsUnlocked();
894
895     // Check funds
896     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
897     if (totalAmount > nBalance)
898         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
899
900     // Send
901     CReserveKey keyChange(pwalletMain);
902     CAmount nFeeRequired = 0;
903     string strFailReason;
904     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
905     if (!fCreated)
906         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
907     if (!pwalletMain->CommitTransaction(wtx, keyChange))
908         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
909
910     return wtx.GetHash().GetHex();
911 }
912
913 // Defined in rpcmisc.cpp
914 extern CScript _createmultisig_redeemScript(const Array& params);
915
916 Value addmultisigaddress(const Array& params, bool fHelp)
917 {
918     if (fHelp || params.size() < 2 || params.size() > 3)
919     {
920         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
921             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
922             "Each key is a Bitcoin address or hex-encoded public key.\n"
923             "If 'account' is specified, assign address to that account.\n"
924
925             "\nArguments:\n"
926             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
927             "2. \"keysobject\"   (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
928             "     [\n"
929             "       \"address\"  (string) bitcoin address or hex-encoded public key\n"
930             "       ...,\n"
931             "     ]\n"
932             "3. \"account\"      (string, optional) An account to assign the addresses to.\n"
933
934             "\nResult:\n"
935             "\"bitcoinaddress\"  (string) A bitcoin address associated with the keys.\n"
936
937             "\nExamples:\n"
938             "\nAdd a multisig address from 2 addresses\n"
939             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
940             "\nAs json rpc call\n"
941             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
942         ;
943         throw runtime_error(msg);
944     }
945
946     string strAccount;
947     if (params.size() > 2)
948         strAccount = AccountFromValue(params[2]);
949
950     // Construct using pay-to-script-hash:
951     CScript inner = _createmultisig_redeemScript(params);
952     CScriptID innerID(inner);
953     pwalletMain->AddCScript(inner);
954
955     pwalletMain->SetAddressBook(innerID, strAccount, "send");
956     return CBitcoinAddress(innerID).ToString();
957 }
958
959
960 struct tallyitem
961 {
962     CAmount nAmount;
963     int nConf;
964     vector<uint256> txids;
965     bool fIsWatchonly;
966     tallyitem()
967     {
968         nAmount = 0;
969         nConf = std::numeric_limits<int>::max();
970         fIsWatchonly = false;
971     }
972 };
973
974 Value ListReceived(const Array& params, bool fByAccounts)
975 {
976     // Minimum confirmations
977     int nMinDepth = 1;
978     if (params.size() > 0)
979         nMinDepth = params[0].get_int();
980
981     // Whether to include empty accounts
982     bool fIncludeEmpty = false;
983     if (params.size() > 1)
984         fIncludeEmpty = params[1].get_bool();
985
986     isminefilter filter = ISMINE_SPENDABLE;
987     if(params.size() > 2)
988         if(params[2].get_bool())
989             filter = filter | ISMINE_WATCH_ONLY;
990
991     // Tally
992     map<CBitcoinAddress, tallyitem> mapTally;
993     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
994     {
995         const CWalletTx& wtx = (*it).second;
996
997         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
998             continue;
999
1000         int nDepth = wtx.GetDepthInMainChain();
1001         if (nDepth < nMinDepth)
1002             continue;
1003
1004         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1005         {
1006             CTxDestination address;
1007             if (!ExtractDestination(txout.scriptPubKey, address))
1008                 continue;
1009
1010             isminefilter mine = IsMine(*pwalletMain, address);
1011             if(!(mine & filter))
1012                 continue;
1013
1014             tallyitem& item = mapTally[address];
1015             item.nAmount += txout.nValue;
1016             item.nConf = min(item.nConf, nDepth);
1017             item.txids.push_back(wtx.GetHash());
1018             if (mine & ISMINE_WATCH_ONLY)
1019                 item.fIsWatchonly = true;
1020         }
1021     }
1022
1023     // Reply
1024     Array ret;
1025     map<string, tallyitem> mapAccountTally;
1026     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1027     {
1028         const CBitcoinAddress& address = item.first;
1029         const string& strAccount = item.second.name;
1030         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1031         if (it == mapTally.end() && !fIncludeEmpty)
1032             continue;
1033
1034         CAmount nAmount = 0;
1035         int nConf = std::numeric_limits<int>::max();
1036         bool fIsWatchonly = false;
1037         if (it != mapTally.end())
1038         {
1039             nAmount = (*it).second.nAmount;
1040             nConf = (*it).second.nConf;
1041             fIsWatchonly = (*it).second.fIsWatchonly;
1042         }
1043
1044         if (fByAccounts)
1045         {
1046             tallyitem& item = mapAccountTally[strAccount];
1047             item.nAmount += nAmount;
1048             item.nConf = min(item.nConf, nConf);
1049             item.fIsWatchonly = fIsWatchonly;
1050         }
1051         else
1052         {
1053             Object obj;
1054             if(fIsWatchonly)
1055                 obj.push_back(Pair("involvesWatchonly", true));
1056             obj.push_back(Pair("address",       address.ToString()));
1057             obj.push_back(Pair("account",       strAccount));
1058             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1059             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1060             Array transactions;
1061             if (it != mapTally.end())
1062             {
1063                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1064                 {
1065                     transactions.push_back(item.GetHex());
1066                 }
1067             }
1068             obj.push_back(Pair("txids", transactions));
1069             ret.push_back(obj);
1070         }
1071     }
1072
1073     if (fByAccounts)
1074     {
1075         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1076         {
1077             CAmount nAmount = (*it).second.nAmount;
1078             int nConf = (*it).second.nConf;
1079             Object obj;
1080             if((*it).second.fIsWatchonly)
1081                 obj.push_back(Pair("involvesWatchonly", true));
1082             obj.push_back(Pair("account",       (*it).first));
1083             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1084             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1085             ret.push_back(obj);
1086         }
1087     }
1088
1089     return ret;
1090 }
1091
1092 Value listreceivedbyaddress(const Array& params, bool fHelp)
1093 {
1094     if (fHelp || params.size() > 3)
1095         throw runtime_error(
1096             "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1097             "\nList balances by receiving address.\n"
1098             "\nArguments:\n"
1099             "1. minconf       (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1100             "2. includeempty  (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1101             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1102
1103             "\nResult:\n"
1104             "[\n"
1105             "  {\n"
1106             "    \"involvesWatchonly\" : true,        (bool) Only returned if imported addresses were involved in transaction\n"
1107             "    \"address\" : \"receivingaddress\",  (string) The receiving address\n"
1108             "    \"account\" : \"accountname\",       (string) The account of the receiving address. The default account is \"\".\n"
1109             "    \"amount\" : x.xxx,                  (numeric) The total amount in btc received by the address\n"
1110             "    \"confirmations\" : n                (numeric) The number of confirmations of the most recent transaction included\n"
1111             "  }\n"
1112             "  ,...\n"
1113             "]\n"
1114
1115             "\nExamples:\n"
1116             + HelpExampleCli("listreceivedbyaddress", "")
1117             + HelpExampleCli("listreceivedbyaddress", "6 true")
1118             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1119         );
1120
1121     return ListReceived(params, false);
1122 }
1123
1124 Value listreceivedbyaccount(const Array& params, bool fHelp)
1125 {
1126     if (fHelp || params.size() > 3)
1127         throw runtime_error(
1128             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1129             "\nList balances by account.\n"
1130             "\nArguments:\n"
1131             "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1132             "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1133             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1134
1135             "\nResult:\n"
1136             "[\n"
1137             "  {\n"
1138             "    \"involvesWatchonly\" : true,   (bool) Only returned if imported addresses were involved in transaction\n"
1139             "    \"account\" : \"accountname\",  (string) The account name of the receiving account\n"
1140             "    \"amount\" : x.xxx,             (numeric) The total amount received by addresses with this account\n"
1141             "    \"confirmations\" : n           (numeric) The number of confirmations of the most recent transaction included\n"
1142             "  }\n"
1143             "  ,...\n"
1144             "]\n"
1145
1146             "\nExamples:\n"
1147             + HelpExampleCli("listreceivedbyaccount", "")
1148             + HelpExampleCli("listreceivedbyaccount", "6 true")
1149             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1150         );
1151
1152     return ListReceived(params, true);
1153 }
1154
1155 static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1156 {
1157     CBitcoinAddress addr;
1158     if (addr.Set(dest))
1159         entry.push_back(Pair("address", addr.ToString()));
1160 }
1161
1162 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
1163 {
1164     CAmount nFee;
1165     string strSentAccount;
1166     list<COutputEntry> listReceived;
1167     list<COutputEntry> listSent;
1168
1169     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1170
1171     bool fAllAccounts = (strAccount == string("*"));
1172     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1173
1174     // Sent
1175     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1176     {
1177         BOOST_FOREACH(const COutputEntry& s, listSent)
1178         {
1179             Object entry;
1180             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1181                 entry.push_back(Pair("involvesWatchonly", true));
1182             entry.push_back(Pair("account", strSentAccount));
1183             MaybePushAddress(entry, s.destination);
1184             entry.push_back(Pair("category", "send"));
1185             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1186             entry.push_back(Pair("vout", s.vout));
1187             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1188             if (fLong)
1189                 WalletTxToJSON(wtx, entry);
1190             ret.push_back(entry);
1191         }
1192     }
1193
1194     // Received
1195     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1196     {
1197         BOOST_FOREACH(const COutputEntry& r, listReceived)
1198         {
1199             string account;
1200             if (pwalletMain->mapAddressBook.count(r.destination))
1201                 account = pwalletMain->mapAddressBook[r.destination].name;
1202             if (fAllAccounts || (account == strAccount))
1203             {
1204                 Object entry;
1205                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1206                     entry.push_back(Pair("involvesWatchonly", true));
1207                 entry.push_back(Pair("account", account));
1208                 MaybePushAddress(entry, r.destination);
1209                 if (wtx.IsCoinBase())
1210                 {
1211                     if (wtx.GetDepthInMainChain() < 1)
1212                         entry.push_back(Pair("category", "orphan"));
1213                     else if (wtx.GetBlocksToMaturity() > 0)
1214                         entry.push_back(Pair("category", "immature"));
1215                     else
1216                         entry.push_back(Pair("category", "generate"));
1217                 }
1218                 else
1219                 {
1220                     entry.push_back(Pair("category", "receive"));
1221                 }
1222                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1223                 entry.push_back(Pair("vout", r.vout));
1224                 if (fLong)
1225                     WalletTxToJSON(wtx, entry);
1226                 ret.push_back(entry);
1227             }
1228         }
1229     }
1230 }
1231
1232 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1233 {
1234     bool fAllAccounts = (strAccount == string("*"));
1235
1236     if (fAllAccounts || acentry.strAccount == strAccount)
1237     {
1238         Object entry;
1239         entry.push_back(Pair("account", acentry.strAccount));
1240         entry.push_back(Pair("category", "move"));
1241         entry.push_back(Pair("time", acentry.nTime));
1242         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1243         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1244         entry.push_back(Pair("comment", acentry.strComment));
1245         ret.push_back(entry);
1246     }
1247 }
1248
1249 Value listtransactions(const Array& params, bool fHelp)
1250 {
1251     if (fHelp || params.size() > 4)
1252         throw runtime_error(
1253             "listtransactions ( \"account\" count from includeWatchonly)\n"
1254             "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1255             "\nArguments:\n"
1256             "1. \"account\"    (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
1257             "                                     If \"\" is set, it will list transactions for the default account.\n"
1258             "2. count          (numeric, optional, default=10) The number of transactions to return\n"
1259             "3. from           (numeric, optional, default=0) The number of transactions to skip\n"
1260             "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1261             "\nResult:\n"
1262             "[\n"
1263             "  {\n"
1264             "    \"account\":\"accountname\",       (string) The account name associated with the transaction. \n"
1265             "                                                It will be \"\" for the default account.\n"
1266             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for \n"
1267             "                                                move transactions (category = move).\n"
1268             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1269             "                                                transaction between accounts, and not associated with an address,\n"
1270             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
1271             "                                                associated with an address, transaction id and block details\n"
1272             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1273             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
1274             "                                         and for the 'move' category for inbound funds.\n"
1275             "    \"vout\" : n,               (numeric) the vout value\n"
1276             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1277             "                                         'send' category of transactions.\n"
1278             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1279             "                                         'receive' category of transactions.\n"
1280             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1281             "                                          category of transactions.\n"
1282             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1283             "                                          category of transactions.\n"
1284             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1285             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1286             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1287             "                                          for 'send' and 'receive' category of transactions.\n"
1288             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1289             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
1290             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1291             "                                          negative amounts).\n"
1292             "  }\n"
1293             "]\n"
1294
1295             "\nExamples:\n"
1296             "\nList the most recent 10 transactions in the systems\n"
1297             + HelpExampleCli("listtransactions", "") +
1298             "\nList the most recent 10 transactions for the tabby account\n"
1299             + HelpExampleCli("listtransactions", "\"tabby\"") +
1300             "\nList transactions 100 to 120 from the tabby account\n"
1301             + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
1302             "\nAs a json rpc call\n"
1303             + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
1304         );
1305
1306     string strAccount = "*";
1307     if (params.size() > 0)
1308         strAccount = params[0].get_str();
1309     int nCount = 10;
1310     if (params.size() > 1)
1311         nCount = params[1].get_int();
1312     int nFrom = 0;
1313     if (params.size() > 2)
1314         nFrom = params[2].get_int();
1315     isminefilter filter = ISMINE_SPENDABLE;
1316     if(params.size() > 3)
1317         if(params[3].get_bool())
1318             filter = filter | ISMINE_WATCH_ONLY;
1319
1320     if (nCount < 0)
1321         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1322     if (nFrom < 0)
1323         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1324
1325     Array ret;
1326
1327     std::list<CAccountingEntry> acentries;
1328     CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1329
1330     // iterate backwards until we have nCount items to return:
1331     for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1332     {
1333         CWalletTx *const pwtx = (*it).second.first;
1334         if (pwtx != 0)
1335             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1336         CAccountingEntry *const pacentry = (*it).second.second;
1337         if (pacentry != 0)
1338             AcentryToJSON(*pacentry, strAccount, ret);
1339
1340         if ((int)ret.size() >= (nCount+nFrom)) break;
1341     }
1342     // ret is newest to oldest
1343
1344     if (nFrom > (int)ret.size())
1345         nFrom = ret.size();
1346     if ((nFrom + nCount) > (int)ret.size())
1347         nCount = ret.size() - nFrom;
1348     Array::iterator first = ret.begin();
1349     std::advance(first, nFrom);
1350     Array::iterator last = ret.begin();
1351     std::advance(last, nFrom+nCount);
1352
1353     if (last != ret.end()) ret.erase(last, ret.end());
1354     if (first != ret.begin()) ret.erase(ret.begin(), first);
1355
1356     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1357
1358     return ret;
1359 }
1360
1361 Value listaccounts(const Array& params, bool fHelp)
1362 {
1363     if (fHelp || params.size() > 2)
1364         throw runtime_error(
1365             "listaccounts ( minconf includeWatchonly)\n"
1366             "\nReturns Object that has account names as keys, account balances as values.\n"
1367             "\nArguments:\n"
1368             "1. minconf          (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1369             "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1370             "\nResult:\n"
1371             "{                      (json object where keys are account names, and values are numeric balances\n"
1372             "  \"account\": x.xxx,  (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1373             "  ...\n"
1374             "}\n"
1375             "\nExamples:\n"
1376             "\nList account balances where there at least 1 confirmation\n"
1377             + HelpExampleCli("listaccounts", "") +
1378             "\nList account balances including zero confirmation transactions\n"
1379             + HelpExampleCli("listaccounts", "0") +
1380             "\nList account balances for 6 or more confirmations\n"
1381             + HelpExampleCli("listaccounts", "6") +
1382             "\nAs json rpc call\n"
1383             + HelpExampleRpc("listaccounts", "6")
1384         );
1385
1386     int nMinDepth = 1;
1387     if (params.size() > 0)
1388         nMinDepth = params[0].get_int();
1389     isminefilter includeWatchonly = ISMINE_SPENDABLE;
1390     if(params.size() > 1)
1391         if(params[1].get_bool())
1392             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1393
1394     map<string, CAmount> mapAccountBalances;
1395     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1396         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1397             mapAccountBalances[entry.second.name] = 0;
1398     }
1399
1400     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1401     {
1402         const CWalletTx& wtx = (*it).second;
1403         CAmount nFee;
1404         string strSentAccount;
1405         list<COutputEntry> listReceived;
1406         list<COutputEntry> listSent;
1407         int nDepth = wtx.GetDepthInMainChain();
1408         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1409             continue;
1410         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1411         mapAccountBalances[strSentAccount] -= nFee;
1412         BOOST_FOREACH(const COutputEntry& s, listSent)
1413             mapAccountBalances[strSentAccount] -= s.amount;
1414         if (nDepth >= nMinDepth)
1415         {
1416             BOOST_FOREACH(const COutputEntry& r, listReceived)
1417                 if (pwalletMain->mapAddressBook.count(r.destination))
1418                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1419                 else
1420                     mapAccountBalances[""] += r.amount;
1421         }
1422     }
1423
1424     list<CAccountingEntry> acentries;
1425     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1426     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1427         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1428
1429     Object ret;
1430     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1431         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1432     }
1433     return ret;
1434 }
1435
1436 Value listsinceblock(const Array& params, bool fHelp)
1437 {
1438     if (fHelp)
1439         throw runtime_error(
1440             "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1441             "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1442             "\nArguments:\n"
1443             "1. \"blockhash\"   (string, optional) The block hash to list transactions since\n"
1444             "2. target-confirmations:    (numeric, optional) The confirmations required, must be 1 or more\n"
1445             "3. includeWatchonly:        (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1446             "\nResult:\n"
1447             "{\n"
1448             "  \"transactions\": [\n"
1449             "    \"account\":\"accountname\",       (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
1450             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1451             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1452             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1453             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1454             "    \"vout\" : n,               (numeric) the vout value\n"
1455             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1456             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1457             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1458             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1459             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1460             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1461             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1462             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1463             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1464             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
1465              "  ],\n"
1466             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
1467             "}\n"
1468             "\nExamples:\n"
1469             + HelpExampleCli("listsinceblock", "")
1470             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1471             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1472         );
1473
1474     CBlockIndex *pindex = NULL;
1475     int target_confirms = 1;
1476     isminefilter filter = ISMINE_SPENDABLE;
1477
1478     if (params.size() > 0)
1479     {
1480         uint256 blockId = 0;
1481
1482         blockId.SetHex(params[0].get_str());
1483         BlockMap::iterator it = mapBlockIndex.find(blockId);
1484         if (it != mapBlockIndex.end())
1485             pindex = it->second;
1486     }
1487
1488     if (params.size() > 1)
1489     {
1490         target_confirms = params[1].get_int();
1491
1492         if (target_confirms < 1)
1493             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1494     }
1495
1496     if(params.size() > 2)
1497         if(params[2].get_bool())
1498             filter = filter | ISMINE_WATCH_ONLY;
1499
1500     int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1501
1502     Array transactions;
1503
1504     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1505     {
1506         CWalletTx tx = (*it).second;
1507
1508         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1509             ListTransactions(tx, "*", 0, true, transactions, filter);
1510     }
1511
1512     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1513     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
1514
1515     Object ret;
1516     ret.push_back(Pair("transactions", transactions));
1517     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1518
1519     return ret;
1520 }
1521
1522 Value gettransaction(const Array& params, bool fHelp)
1523 {
1524     if (fHelp || params.size() < 1 || params.size() > 2)
1525         throw runtime_error(
1526             "gettransaction \"txid\" ( includeWatchonly )\n"
1527             "\nGet detailed information about in-wallet transaction <txid>\n"
1528             "\nArguments:\n"
1529             "1. \"txid\"    (string, required) The transaction id\n"
1530             "2. \"includeWatchonly\"    (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1531             "\nResult:\n"
1532             "{\n"
1533             "  \"amount\" : x.xxx,        (numeric) The transaction amount in btc\n"
1534             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
1535             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
1536             "  \"blockindex\" : xx,       (numeric) The block index\n"
1537             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1538             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
1539             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1540             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1541             "  \"details\" : [\n"
1542             "    {\n"
1543             "      \"account\" : \"accountname\",  (string) The account name involved in the transaction, can be \"\" for the default account.\n"
1544             "      \"address\" : \"bitcoinaddress\",   (string) The bitcoin address involved in the transaction\n"
1545             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
1546             "      \"amount\" : x.xxx                  (numeric) The amount in btc\n"
1547             "      \"vout\" : n,                       (numeric) the vout value\n"
1548             "    }\n"
1549             "    ,...\n"
1550             "  ],\n"
1551             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
1552             "}\n"
1553
1554             "\nExamples:\n"
1555             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1556             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1557             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1558         );
1559
1560     uint256 hash;
1561     hash.SetHex(params[0].get_str());
1562
1563     isminefilter filter = ISMINE_SPENDABLE;
1564     if(params.size() > 1)
1565         if(params[1].get_bool())
1566             filter = filter | ISMINE_WATCH_ONLY;
1567
1568     Object entry;
1569     if (!pwalletMain->mapWallet.count(hash))
1570         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1571     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1572
1573     CAmount nCredit = wtx.GetCredit(filter);
1574     CAmount nDebit = wtx.GetDebit(filter);
1575     CAmount nNet = nCredit - nDebit;
1576     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1577
1578     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1579     if (wtx.IsFromMe(filter))
1580         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1581
1582     WalletTxToJSON(wtx, entry);
1583
1584     Array details;
1585     ListTransactions(wtx, "*", 0, false, details, filter);
1586     entry.push_back(Pair("details", details));
1587
1588     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1589     entry.push_back(Pair("hex", strHex));
1590
1591     return entry;
1592 }
1593
1594
1595 Value backupwallet(const Array& params, bool fHelp)
1596 {
1597     if (fHelp || params.size() != 1)
1598         throw runtime_error(
1599             "backupwallet \"destination\"\n"
1600             "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1601             "\nArguments:\n"
1602             "1. \"destination\"   (string) The destination directory or file\n"
1603             "\nExamples:\n"
1604             + HelpExampleCli("backupwallet", "\"backup.dat\"")
1605             + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1606         );
1607
1608     string strDest = params[0].get_str();
1609     if (!BackupWallet(*pwalletMain, strDest))
1610         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1611
1612     return Value::null;
1613 }
1614
1615
1616 Value keypoolrefill(const Array& params, bool fHelp)
1617 {
1618     if (fHelp || params.size() > 1)
1619         throw runtime_error(
1620             "keypoolrefill ( newsize )\n"
1621             "\nFills the keypool."
1622             + HelpRequiringPassphrase() + "\n"
1623             "\nArguments\n"
1624             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
1625             "\nExamples:\n"
1626             + HelpExampleCli("keypoolrefill", "")
1627             + HelpExampleRpc("keypoolrefill", "")
1628         );
1629
1630     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1631     unsigned int kpSize = 0;
1632     if (params.size() > 0) {
1633         if (params[0].get_int() < 0)
1634             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1635         kpSize = (unsigned int)params[0].get_int();
1636     }
1637
1638     EnsureWalletIsUnlocked();
1639     pwalletMain->TopUpKeyPool(kpSize);
1640
1641     if (pwalletMain->GetKeyPoolSize() < kpSize)
1642         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1643
1644     return Value::null;
1645 }
1646
1647
1648 static void LockWallet(CWallet* pWallet)
1649 {
1650     LOCK(cs_nWalletUnlockTime);
1651     nWalletUnlockTime = 0;
1652     pWallet->Lock();
1653 }
1654
1655 Value walletpassphrase(const Array& params, bool fHelp)
1656 {
1657     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1658         throw runtime_error(
1659             "walletpassphrase \"passphrase\" timeout\n"
1660             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1661             "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1662             "\nArguments:\n"
1663             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
1664             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
1665             "\nNote:\n"
1666             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1667             "time that overrides the old one.\n"
1668             "\nExamples:\n"
1669             "\nunlock the wallet for 60 seconds\n"
1670             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1671             "\nLock the wallet again (before 60 seconds)\n"
1672             + HelpExampleCli("walletlock", "") +
1673             "\nAs json rpc call\n"
1674             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1675         );
1676
1677     if (fHelp)
1678         return true;
1679     if (!pwalletMain->IsCrypted())
1680         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1681
1682     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1683     SecureString strWalletPass;
1684     strWalletPass.reserve(100);
1685     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1686     // Alternately, find a way to make params[0] mlock()'d to begin with.
1687     strWalletPass = params[0].get_str().c_str();
1688
1689     if (strWalletPass.length() > 0)
1690     {
1691         if (!pwalletMain->Unlock(strWalletPass))
1692             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1693     }
1694     else
1695         throw runtime_error(
1696             "walletpassphrase <passphrase> <timeout>\n"
1697             "Stores the wallet decryption key in memory for <timeout> seconds.");
1698
1699     pwalletMain->TopUpKeyPool();
1700
1701     int64_t nSleepTime = params[1].get_int64();
1702     LOCK(cs_nWalletUnlockTime);
1703     nWalletUnlockTime = GetTime() + nSleepTime;
1704     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1705
1706     return Value::null;
1707 }
1708
1709
1710 Value walletpassphrasechange(const Array& params, bool fHelp)
1711 {
1712     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1713         throw runtime_error(
1714             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1715             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1716             "\nArguments:\n"
1717             "1. \"oldpassphrase\"      (string) The current passphrase\n"
1718             "2. \"newpassphrase\"      (string) The new passphrase\n"
1719             "\nExamples:\n"
1720             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1721             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1722         );
1723
1724     if (fHelp)
1725         return true;
1726     if (!pwalletMain->IsCrypted())
1727         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1728
1729     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1730     // Alternately, find a way to make params[0] mlock()'d to begin with.
1731     SecureString strOldWalletPass;
1732     strOldWalletPass.reserve(100);
1733     strOldWalletPass = params[0].get_str().c_str();
1734
1735     SecureString strNewWalletPass;
1736     strNewWalletPass.reserve(100);
1737     strNewWalletPass = params[1].get_str().c_str();
1738
1739     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1740         throw runtime_error(
1741             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1742             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1743
1744     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1745         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1746
1747     return Value::null;
1748 }
1749
1750
1751 Value walletlock(const Array& params, bool fHelp)
1752 {
1753     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1754         throw runtime_error(
1755             "walletlock\n"
1756             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1757             "After calling this method, you will need to call walletpassphrase again\n"
1758             "before being able to call any methods which require the wallet to be unlocked.\n"
1759             "\nExamples:\n"
1760             "\nSet the passphrase for 2 minutes to perform a transaction\n"
1761             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1762             "\nPerform a send (requires passphrase set)\n"
1763             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1764             "\nClear the passphrase since we are done before 2 minutes is up\n"
1765             + HelpExampleCli("walletlock", "") +
1766             "\nAs json rpc call\n"
1767             + HelpExampleRpc("walletlock", "")
1768         );
1769
1770     if (fHelp)
1771         return true;
1772     if (!pwalletMain->IsCrypted())
1773         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
1774
1775     {
1776         LOCK(cs_nWalletUnlockTime);
1777         pwalletMain->Lock();
1778         nWalletUnlockTime = 0;
1779     }
1780
1781     return Value::null;
1782 }
1783
1784
1785 Value encryptwallet(const Array& params, bool fHelp)
1786 {
1787     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1788         throw runtime_error(
1789             "encryptwallet \"passphrase\"\n"
1790             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1791             "After this, any calls that interact with private keys such as sending or signing \n"
1792             "will require the passphrase to be set prior the making these calls.\n"
1793             "Use the walletpassphrase call for this, and then walletlock call.\n"
1794             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1795             "Note that this will shutdown the server.\n"
1796             "\nArguments:\n"
1797             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1798             "\nExamples:\n"
1799             "\nEncrypt you wallet\n"
1800             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1801             "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1802             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1803             "\nNow we can so something like sign\n"
1804             + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1805             "\nNow lock the wallet again by removing the passphrase\n"
1806             + HelpExampleCli("walletlock", "") +
1807             "\nAs a json rpc call\n"
1808             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1809         );
1810
1811     if (fHelp)
1812         return true;
1813     if (pwalletMain->IsCrypted())
1814         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
1815
1816     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1817     // Alternately, find a way to make params[0] mlock()'d to begin with.
1818     SecureString strWalletPass;
1819     strWalletPass.reserve(100);
1820     strWalletPass = params[0].get_str().c_str();
1821
1822     if (strWalletPass.length() < 1)
1823         throw runtime_error(
1824             "encryptwallet <passphrase>\n"
1825             "Encrypts the wallet with <passphrase>.");
1826
1827     if (!pwalletMain->EncryptWallet(strWalletPass))
1828         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
1829
1830     // BDB seems to have a bad habit of writing old data into
1831     // slack space in .dat files; that is bad if the old data is
1832     // unencrypted private keys. So:
1833     StartShutdown();
1834     return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
1835 }
1836
1837 Value lockunspent(const Array& params, bool fHelp)
1838 {
1839     if (fHelp || params.size() < 1 || params.size() > 2)
1840         throw runtime_error(
1841             "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
1842             "\nUpdates list of temporarily unspendable outputs.\n"
1843             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
1844             "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
1845             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
1846             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
1847             "Also see the listunspent call\n"
1848             "\nArguments:\n"
1849             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
1850             "2. \"transactions\"  (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
1851             "     [           (json array of json objects)\n"
1852             "       {\n"
1853             "         \"txid\":\"id\",    (string) The transaction id\n"
1854             "         \"vout\": n         (numeric) The output number\n"
1855             "       }\n"
1856             "       ,...\n"
1857             "     ]\n"
1858
1859             "\nResult:\n"
1860             "true|false    (boolean) Whether the command was successful or not\n"
1861
1862             "\nExamples:\n"
1863             "\nList the unspent transactions\n"
1864             + HelpExampleCli("listunspent", "") +
1865             "\nLock an unspent transaction\n"
1866             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1867             "\nList the locked transactions\n"
1868             + HelpExampleCli("listlockunspent", "") +
1869             "\nUnlock the transaction again\n"
1870             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1871             "\nAs a json rpc call\n"
1872             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
1873         );
1874
1875     if (params.size() == 1)
1876         RPCTypeCheck(params, list_of(bool_type));
1877     else
1878         RPCTypeCheck(params, list_of(bool_type)(array_type));
1879
1880     bool fUnlock = params[0].get_bool();
1881
1882     if (params.size() == 1) {
1883         if (fUnlock)
1884             pwalletMain->UnlockAllCoins();
1885         return true;
1886     }
1887
1888     Array outputs = params[1].get_array();
1889     BOOST_FOREACH(Value& output, outputs)
1890     {
1891         if (output.type() != obj_type)
1892             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1893         const Object& o = output.get_obj();
1894
1895         RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
1896
1897         string txid = find_value(o, "txid").get_str();
1898         if (!IsHex(txid))
1899             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
1900
1901         int nOutput = find_value(o, "vout").get_int();
1902         if (nOutput < 0)
1903             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
1904
1905         COutPoint outpt(uint256(txid), nOutput);
1906
1907         if (fUnlock)
1908             pwalletMain->UnlockCoin(outpt);
1909         else
1910             pwalletMain->LockCoin(outpt);
1911     }
1912
1913     return true;
1914 }
1915
1916 Value listlockunspent(const Array& params, bool fHelp)
1917 {
1918     if (fHelp || params.size() > 0)
1919         throw runtime_error(
1920             "listlockunspent\n"
1921             "\nReturns list of temporarily unspendable outputs.\n"
1922             "See the lockunspent call to lock and unlock transactions for spending.\n"
1923             "\nResult:\n"
1924             "[\n"
1925             "  {\n"
1926             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
1927             "    \"vout\" : n                      (numeric) The vout value\n"
1928             "  }\n"
1929             "  ,...\n"
1930             "]\n"
1931             "\nExamples:\n"
1932             "\nList the unspent transactions\n"
1933             + HelpExampleCli("listunspent", "") +
1934             "\nLock an unspent transaction\n"
1935             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1936             "\nList the locked transactions\n"
1937             + HelpExampleCli("listlockunspent", "") +
1938             "\nUnlock the transaction again\n"
1939             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1940             "\nAs a json rpc call\n"
1941             + HelpExampleRpc("listlockunspent", "")
1942         );
1943
1944     vector<COutPoint> vOutpts;
1945     pwalletMain->ListLockedCoins(vOutpts);
1946
1947     Array ret;
1948
1949     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
1950         Object o;
1951
1952         o.push_back(Pair("txid", outpt.hash.GetHex()));
1953         o.push_back(Pair("vout", (int)outpt.n));
1954         ret.push_back(o);
1955     }
1956
1957     return ret;
1958 }
1959
1960 Value settxfee(const Array& params, bool fHelp)
1961 {
1962     if (fHelp || params.size() < 1 || params.size() > 1)
1963         throw runtime_error(
1964             "settxfee amount\n"
1965             "\nSet the transaction fee per kB.\n"
1966             "\nArguments:\n"
1967             "1. amount         (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
1968             "\nResult\n"
1969             "true|false        (boolean) Returns true if successful\n"
1970             "\nExamples:\n"
1971             + HelpExampleCli("settxfee", "0.00001")
1972             + HelpExampleRpc("settxfee", "0.00001")
1973         );
1974
1975     // Amount
1976     CAmount nAmount = 0;
1977     if (params[0].get_real() != 0.0)
1978         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
1979
1980     payTxFee = CFeeRate(nAmount, 1000);
1981     return true;
1982 }
1983
1984 Value getwalletinfo(const Array& params, bool fHelp)
1985 {
1986     if (fHelp || params.size() != 0)
1987         throw runtime_error(
1988             "getwalletinfo\n"
1989             "Returns an object containing various wallet state info.\n"
1990             "\nResult:\n"
1991             "{\n"
1992             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
1993             "  \"balance\": xxxxxxx,         (numeric) the total bitcoin balance of the wallet\n"
1994             "  \"txcount\": xxxxxxx,         (numeric) the total number of transactions in the wallet\n"
1995             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
1996             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
1997             "  \"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"
1998             "}\n"
1999             "\nExamples:\n"
2000             + HelpExampleCli("getwalletinfo", "")
2001             + HelpExampleRpc("getwalletinfo", "")
2002         );
2003
2004     Object obj;
2005     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2006     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
2007     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
2008     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2009     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
2010     if (pwalletMain->IsCrypted())
2011         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2012     return obj;
2013 }
This page took 0.138093 seconds and 4 git commands to generate.