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