1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
7 #include "cryptopp/sha.h"
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
44 Object JSONRPCError(int code, const string& message)
47 error.push_back(Pair("code", code));
48 error.push_back(Pair("message", message));
53 void PrintConsole(const char* format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
61 if (ret < 0 || ret >= limit)
67 #if defined(__WXMSW__) && defined(GUI)
68 MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
70 fprintf(stdout, "%s", buffer);
75 int64 AmountFromValue(const Value& value)
77 double dAmount = value.get_real();
78 if (dAmount <= 0.0 || dAmount > 21000000.0)
79 throw JSONRPCError(-3, "Invalid amount");
80 int64 nAmount = roundint64(dAmount * COIN);
81 if (!MoneyRange(nAmount))
82 throw JSONRPCError(-3, "Invalid amount");
86 Value ValueFromAmount(int64 amount)
88 return (double)amount / (double)COIN;
91 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
93 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
94 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
95 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
96 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
97 entry.push_back(Pair(item.first, item.second));
100 string AccountFromValue(const Value& value)
102 string strAccount = value.get_str();
103 if (strAccount == "*")
104 throw JSONRPCError(-11, "Invalid account name");
111 /// Note: This interface may still be subject to change.
115 Value help(const Array& params, bool fHelp)
117 if (fHelp || params.size() > 1)
120 "List commands, or get help for a command.");
123 if (params.size() > 0)
124 strCommand = params[0].get_str();
127 set<rpcfn_type> setDone;
128 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
130 string strMethod = (*mi).first;
131 // We already filter duplicates, but these deprecated screw up the sort order
132 if (strMethod == "getamountreceived" ||
133 strMethod == "getallreceived" ||
134 (strMethod.find("label") != string::npos))
136 if (strCommand != "" && strMethod != strCommand)
141 rpcfn_type pfn = (*mi).second;
142 if (setDone.insert(pfn).second)
143 (*pfn)(params, true);
145 catch (std::exception& e)
147 // Help text is returned in an exception
148 string strHelp = string(e.what());
149 if (strCommand == "")
150 if (strHelp.find('\n') != -1)
151 strHelp = strHelp.substr(0, strHelp.find('\n'));
152 strRet += strHelp + "\n";
156 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
157 strRet = strRet.substr(0,strRet.size()-1);
162 Value stop(const Array& params, bool fHelp)
164 if (fHelp || params.size() != 0)
167 "Stop bitcoin server.");
169 // Shutdown will take long enough that the response should get back
170 CreateThread(Shutdown, NULL);
171 return "bitcoin server stopping";
175 Value getblockcount(const Array& params, bool fHelp)
177 if (fHelp || params.size() != 0)
180 "Returns the number of blocks in the longest block chain.");
186 Value getblocknumber(const Array& params, bool fHelp)
188 if (fHelp || params.size() != 0)
191 "Returns the block number of the latest block in the longest block chain.");
197 Value getconnectioncount(const Array& params, bool fHelp)
199 if (fHelp || params.size() != 0)
201 "getconnectioncount\n"
202 "Returns the number of connections to other nodes.");
204 return (int)vNodes.size();
208 double GetDifficulty()
210 // Floating point number that is a multiple of the minimum difficulty,
211 // minimum difficulty = 1.0.
213 if (pindexBest == NULL)
215 int nShift = (pindexBest->nBits >> 24) & 0xff;
218 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
234 Value getdifficulty(const Array& params, bool fHelp)
236 if (fHelp || params.size() != 0)
239 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
241 return GetDifficulty();
245 Value getgenerate(const Array& params, bool fHelp)
247 if (fHelp || params.size() != 0)
250 "Returns true or false.");
252 return (bool)fGenerateBitcoins;
256 Value setgenerate(const Array& params, bool fHelp)
258 if (fHelp || params.size() < 1 || params.size() > 2)
260 "setgenerate <generate> [genproclimit]\n"
261 "<generate> is true or false to turn generation on or off.\n"
262 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
264 bool fGenerate = true;
265 if (params.size() > 0)
266 fGenerate = params[0].get_bool();
268 if (params.size() > 1)
270 int nGenProcLimit = params[1].get_int();
271 fLimitProcessors = (nGenProcLimit != -1);
272 WriteSetting("fLimitProcessors", fLimitProcessors);
273 if (nGenProcLimit != -1)
274 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
275 if (nGenProcLimit == 0)
279 GenerateBitcoins(fGenerate, pwalletMain);
284 Value gethashespersec(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns a recent hashes per second performance measurement while generating.");
291 if (GetTimeMillis() - nHPSTimerStart > 8000)
292 return (boost::int64_t)0;
293 return (boost::int64_t)dHashesPerSec;
297 Value getinfo(const Array& params, bool fHelp)
299 if (fHelp || params.size() != 0)
302 "Returns an object containing various state info.");
305 obj.push_back(Pair("version", (int)VERSION));
306 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
307 obj.push_back(Pair("blocks", (int)nBestHeight));
308 obj.push_back(Pair("connections", (int)vNodes.size()));
309 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
310 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
311 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
312 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
313 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
314 obj.push_back(Pair("testnet", fTestNet));
315 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
316 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
317 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
318 if (pwalletMain->IsCrypted())
319 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
320 obj.push_back(Pair("errors", GetWarnings("statusbar")));
325 Value getnewaddress(const Array& params, bool fHelp)
327 if (fHelp || params.size() > 1)
329 "getnewaddress [account]\n"
330 "Returns a new bitcoin address for receiving payments. "
331 "If [account] is specified (recommended), it is added to the address book "
332 "so payments received with the address will be credited to [account].");
334 if (!pwalletMain->IsLocked())
335 pwalletMain->TopUpKeyPool();
337 if (pwalletMain->GetKeyPoolSize() < 1)
338 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
340 // Parse the account first so we don't generate a key if there's an error
342 if (params.size() > 0)
343 strAccount = AccountFromValue(params[0]);
345 // Generate a new key that is added to wallet
346 CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
348 // This could be done in the same main CS as GetKeyFromKeyPool.
349 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
350 pwalletMain->SetAddressBookName(address, strAccount);
352 return address.ToString();
356 // requires cs_main, cs_mapWallet, cs_mapAddressBook locks
357 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
359 CWalletDB walletdb(pwalletMain->strWalletFile);
362 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
364 walletdb.ReadAccount(strAccount, account);
366 bool bKeyUsed = false;
368 // Check if the current key has been used
369 if (!account.vchPubKey.empty())
371 CScript scriptPubKey;
372 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
373 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
374 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
377 const CWalletTx& wtx = (*it).second;
378 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
379 if (txout.scriptPubKey == scriptPubKey)
384 // Generate a new key
385 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
387 if (pwalletMain->GetKeyPoolSize() < 1)
389 if (bKeyUsed || bForceNew)
390 throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
394 account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
395 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
396 walletdb.WriteAccount(strAccount, account);
401 return CBitcoinAddress(account.vchPubKey);
404 Value getaccountaddress(const Array& params, bool fHelp)
406 if (fHelp || params.size() != 1)
408 "getaccountaddress <account>\n"
409 "Returns the current bitcoin address for receiving payments to this account.");
411 // Parse the account first so we don't generate a key if there's an error
412 string strAccount = AccountFromValue(params[0]);
416 CRITICAL_BLOCK(cs_main)
417 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
418 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
420 ret = GetAccountAddress(strAccount).ToString();
428 Value setaccount(const Array& params, bool fHelp)
430 if (fHelp || params.size() < 1 || params.size() > 2)
432 "setaccount <bitcoinaddress> <account>\n"
433 "Sets the account associated with the given address.");
435 CBitcoinAddress address(params[0].get_str());
436 if (!address.IsValid())
437 throw JSONRPCError(-5, "Invalid bitcoin address");
441 if (params.size() > 1)
442 strAccount = AccountFromValue(params[1]);
444 // Detect when changing the account of an address that is the 'unused current key' of another account:
445 CRITICAL_BLOCK(cs_main)
446 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
447 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
449 if (pwalletMain->mapAddressBook.count(address))
451 string strOldAccount = pwalletMain->mapAddressBook[address];
452 if (address == GetAccountAddress(strOldAccount))
453 GetAccountAddress(strOldAccount, true);
456 pwalletMain->SetAddressBookName(address, strAccount);
463 Value getaccount(const Array& params, bool fHelp)
465 if (fHelp || params.size() != 1)
467 "getaccount <bitcoinaddress>\n"
468 "Returns the account associated with the given address.");
470 CBitcoinAddress address(params[0].get_str());
471 if (!address.IsValid())
472 throw JSONRPCError(-5, "Invalid bitcoin address");
475 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
477 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
478 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
479 strAccount = (*mi).second;
485 Value getaddressesbyaccount(const Array& params, bool fHelp)
487 if (fHelp || params.size() != 1)
489 "getaddressesbyaccount <account>\n"
490 "Returns the list of addresses for the given account.");
492 string strAccount = AccountFromValue(params[0]);
494 // Find all addresses that have the given account
496 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
498 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
500 const CBitcoinAddress& address = item.first;
501 const string& strName = item.second;
502 if (strName == strAccount)
503 ret.push_back(address.ToString());
509 Value settxfee(const Array& params, bool fHelp)
511 if (fHelp || params.size() < 1 || params.size() > 1)
513 "settxfee <amount>\n"
514 "<amount> is a real and is rounded to the nearest 0.00000001");
518 if (params[0].get_real() != 0.0)
519 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
521 nTransactionFee = nAmount;
525 Value sendtoaddress(const Array& params, bool fHelp)
527 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
529 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
530 "<amount> is a real and is rounded to the nearest 0.00000001\n"
531 "requires wallet passphrase to be set with walletpassphrase first");
532 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
534 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
535 "<amount> is a real and is rounded to the nearest 0.00000001");
537 CBitcoinAddress address(params[0].get_str());
538 if (!address.IsValid())
539 throw JSONRPCError(-5, "Invalid bitcoin address");
542 int64 nAmount = AmountFromValue(params[1]);
546 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
547 wtx.mapValue["comment"] = params[2].get_str();
548 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
549 wtx.mapValue["to"] = params[3].get_str();
551 CRITICAL_BLOCK(cs_main)
552 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
554 if(pwalletMain->IsLocked())
555 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
557 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
559 throw JSONRPCError(-4, strError);
562 return wtx.GetHash().GetHex();
566 Value getreceivedbyaddress(const Array& params, bool fHelp)
568 if (fHelp || params.size() < 1 || params.size() > 2)
570 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
571 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
574 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
575 CScript scriptPubKey;
576 if (!address.IsValid())
577 throw JSONRPCError(-5, "Invalid bitcoin address");
578 scriptPubKey.SetBitcoinAddress(address);
579 if (!IsMine(*pwalletMain,scriptPubKey))
582 // Minimum confirmations
584 if (params.size() > 1)
585 nMinDepth = params[1].get_int();
589 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
591 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
593 const CWalletTx& wtx = (*it).second;
594 if (wtx.IsCoinBase() || !wtx.IsFinal())
597 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
598 if (txout.scriptPubKey == scriptPubKey)
599 if (wtx.GetDepthInMainChain() >= nMinDepth)
600 nAmount += txout.nValue;
604 return ValueFromAmount(nAmount);
608 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
610 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
612 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
614 const CBitcoinAddress& address = item.first;
615 const string& strName = item.second;
616 if (strName == strAccount)
617 setAddress.insert(address);
623 Value getreceivedbyaccount(const Array& params, bool fHelp)
625 if (fHelp || params.size() < 1 || params.size() > 2)
627 "getreceivedbyaccount <account> [minconf=1]\n"
628 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
630 // Minimum confirmations
632 if (params.size() > 1)
633 nMinDepth = params[1].get_int();
635 // Get the set of pub keys that have the label
636 string strAccount = AccountFromValue(params[0]);
637 set<CBitcoinAddress> setAddress;
638 GetAccountAddresses(strAccount, setAddress);
642 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
644 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
646 const CWalletTx& wtx = (*it).second;
647 if (wtx.IsCoinBase() || !wtx.IsFinal())
650 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
652 CBitcoinAddress address;
653 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
654 if (wtx.GetDepthInMainChain() >= nMinDepth)
655 nAmount += txout.nValue;
660 return (double)nAmount / (double)COIN;
664 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
667 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
669 // Tally wallet transactions
670 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
672 const CWalletTx& wtx = (*it).second;
676 int64 nGenerated, nReceived, nSent, nFee;
677 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
679 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
680 nBalance += nReceived;
681 nBalance += nGenerated - nSent - nFee;
684 // Tally internal accounting entries
685 nBalance += walletdb.GetAccountCreditDebit(strAccount);
691 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
693 CWalletDB walletdb(pwalletMain->strWalletFile);
694 return GetAccountBalance(walletdb, strAccount, nMinDepth);
698 Value getbalance(const Array& params, bool fHelp)
700 if (fHelp || params.size() > 2)
702 "getbalance [account] [minconf=1]\n"
703 "If [account] is not specified, returns the server's total available balance.\n"
704 "If [account] is specified, returns the balance in the account.");
706 if (params.size() == 0)
707 return ValueFromAmount(pwalletMain->GetBalance());
710 if (params.size() > 1)
711 nMinDepth = params[1].get_int();
713 if (params[0].get_str() == "*") {
714 // Calculate total balance a different way from GetBalance()
715 // (GetBalance() sums up all unspent TxOuts)
716 // getbalance and getbalance '*' should always return the same number.
718 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
720 const CWalletTx& wtx = (*it).second;
724 int64 allGeneratedImmature, allGeneratedMature, allFee;
725 allGeneratedImmature = allGeneratedMature = allFee = 0;
726 string strSentAccount;
727 list<pair<CBitcoinAddress, int64> > listReceived;
728 list<pair<CBitcoinAddress, int64> > listSent;
729 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
730 if (wtx.GetDepthInMainChain() >= nMinDepth)
731 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
732 nBalance += r.second;
733 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
734 nBalance -= r.second;
736 nBalance += allGeneratedMature;
738 return ValueFromAmount(nBalance);
741 string strAccount = AccountFromValue(params[0]);
743 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
745 return ValueFromAmount(nBalance);
749 Value movecmd(const Array& params, bool fHelp)
751 if (fHelp || params.size() < 3 || params.size() > 5)
753 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
754 "Move from one account in your wallet to another.");
756 string strFrom = AccountFromValue(params[0]);
757 string strTo = AccountFromValue(params[1]);
758 int64 nAmount = AmountFromValue(params[2]);
759 if (params.size() > 3)
760 // unused parameter, used to be nMinDepth, keep type-checking it though
761 (void)params[3].get_int();
763 if (params.size() > 4)
764 strComment = params[4].get_str();
766 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
768 CWalletDB walletdb(pwalletMain->strWalletFile);
771 int64 nNow = GetAdjustedTime();
774 CAccountingEntry debit;
775 debit.strAccount = strFrom;
776 debit.nCreditDebit = -nAmount;
778 debit.strOtherAccount = strTo;
779 debit.strComment = strComment;
780 walletdb.WriteAccountingEntry(debit);
783 CAccountingEntry credit;
784 credit.strAccount = strTo;
785 credit.nCreditDebit = nAmount;
787 credit.strOtherAccount = strFrom;
788 credit.strComment = strComment;
789 walletdb.WriteAccountingEntry(credit);
791 walletdb.TxnCommit();
797 Value sendfrom(const Array& params, bool fHelp)
799 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
801 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
802 "<amount> is a real and is rounded to the nearest 0.00000001\n"
803 "requires wallet passphrase to be set with walletpassphrase first");
804 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
806 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
807 "<amount> is a real and is rounded to the nearest 0.00000001");
809 string strAccount = AccountFromValue(params[0]);
810 CBitcoinAddress address(params[1].get_str());
811 if (!address.IsValid())
812 throw JSONRPCError(-5, "Invalid bitcoin address");
813 int64 nAmount = AmountFromValue(params[2]);
815 if (params.size() > 3)
816 nMinDepth = params[3].get_int();
819 wtx.strFromAccount = strAccount;
820 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
821 wtx.mapValue["comment"] = params[4].get_str();
822 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
823 wtx.mapValue["to"] = params[5].get_str();
825 CRITICAL_BLOCK(cs_main)
826 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
827 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
829 if(pwalletMain->IsLocked())
830 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
833 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
834 if (nAmount > nBalance)
835 throw JSONRPCError(-6, "Account has insufficient funds");
838 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
840 throw JSONRPCError(-4, strError);
843 return wtx.GetHash().GetHex();
847 Value sendmany(const Array& params, bool fHelp)
849 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
851 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
852 "amounts are double-precision floating point numbers\n"
853 "requires wallet passphrase to be set with walletpassphrase first");
854 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
856 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
857 "amounts are double-precision floating point numbers");
859 string strAccount = AccountFromValue(params[0]);
860 Object sendTo = params[1].get_obj();
862 if (params.size() > 2)
863 nMinDepth = params[2].get_int();
866 wtx.strFromAccount = strAccount;
867 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
868 wtx.mapValue["comment"] = params[3].get_str();
870 set<CBitcoinAddress> setAddress;
871 vector<pair<CScript, int64> > vecSend;
873 int64 totalAmount = 0;
874 BOOST_FOREACH(const Pair& s, sendTo)
876 CBitcoinAddress address(s.name_);
877 if (!address.IsValid())
878 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
880 if (setAddress.count(address))
881 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
882 setAddress.insert(address);
884 CScript scriptPubKey;
885 scriptPubKey.SetBitcoinAddress(address);
886 int64 nAmount = AmountFromValue(s.value_);
887 totalAmount += nAmount;
889 vecSend.push_back(make_pair(scriptPubKey, nAmount));
892 CRITICAL_BLOCK(cs_main)
893 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
894 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
896 if(pwalletMain->IsLocked())
897 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
900 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
901 if (totalAmount > nBalance)
902 throw JSONRPCError(-6, "Account has insufficient funds");
905 CReserveKey keyChange(pwalletMain);
906 int64 nFeeRequired = 0;
907 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
910 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
911 throw JSONRPCError(-6, "Insufficient funds");
912 throw JSONRPCError(-4, "Transaction creation failed");
914 if (!pwalletMain->CommitTransaction(wtx, keyChange))
915 throw JSONRPCError(-4, "Transaction commit failed");
918 return wtx.GetHash().GetHex();
933 Value ListReceived(const Array& params, bool fByAccounts)
935 // Minimum confirmations
937 if (params.size() > 0)
938 nMinDepth = params[0].get_int();
940 // Whether to include empty accounts
941 bool fIncludeEmpty = false;
942 if (params.size() > 1)
943 fIncludeEmpty = params[1].get_bool();
946 map<CBitcoinAddress, tallyitem> mapTally;
947 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
949 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
951 const CWalletTx& wtx = (*it).second;
952 if (wtx.IsCoinBase() || !wtx.IsFinal())
955 int nDepth = wtx.GetDepthInMainChain();
956 if (nDepth < nMinDepth)
959 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
961 CBitcoinAddress address;
962 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
965 tallyitem& item = mapTally[address];
966 item.nAmount += txout.nValue;
967 item.nConf = min(item.nConf, nDepth);
974 map<string, tallyitem> mapAccountTally;
975 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
977 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
979 const CBitcoinAddress& address = item.first;
980 const string& strAccount = item.second;
981 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
982 if (it == mapTally.end() && !fIncludeEmpty)
987 if (it != mapTally.end())
989 nAmount = (*it).second.nAmount;
990 nConf = (*it).second.nConf;
995 tallyitem& item = mapAccountTally[strAccount];
996 item.nAmount += nAmount;
997 item.nConf = min(item.nConf, nConf);
1002 obj.push_back(Pair("address", address.ToString()));
1003 obj.push_back(Pair("account", strAccount));
1004 obj.push_back(Pair("label", strAccount)); // deprecated
1005 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1006 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1014 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1016 int64 nAmount = (*it).second.nAmount;
1017 int nConf = (*it).second.nConf;
1019 obj.push_back(Pair("account", (*it).first));
1020 obj.push_back(Pair("label", (*it).first)); // deprecated
1021 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1022 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1030 Value listreceivedbyaddress(const Array& params, bool fHelp)
1032 if (fHelp || params.size() > 2)
1033 throw runtime_error(
1034 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1035 "[minconf] is the minimum number of confirmations before payments are included.\n"
1036 "[includeempty] whether to include addresses that haven't received any payments.\n"
1037 "Returns an array of objects containing:\n"
1038 " \"address\" : receiving address\n"
1039 " \"account\" : the account of the receiving address\n"
1040 " \"amount\" : total amount received by the address\n"
1041 " \"confirmations\" : number of confirmations of the most recent transaction included");
1043 return ListReceived(params, false);
1046 Value listreceivedbyaccount(const Array& params, bool fHelp)
1048 if (fHelp || params.size() > 2)
1049 throw runtime_error(
1050 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1051 "[minconf] is the minimum number of confirmations before payments are included.\n"
1052 "[includeempty] whether to include accounts that haven't received any payments.\n"
1053 "Returns an array of objects containing:\n"
1054 " \"account\" : the account of the receiving addresses\n"
1055 " \"amount\" : total amount received by addresses with this account\n"
1056 " \"confirmations\" : number of confirmations of the most recent transaction included");
1058 return ListReceived(params, true);
1061 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1063 int64 nGeneratedImmature, nGeneratedMature, nFee;
1064 string strSentAccount;
1065 list<pair<CBitcoinAddress, int64> > listReceived;
1066 list<pair<CBitcoinAddress, int64> > listSent;
1067 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1069 bool fAllAccounts = (strAccount == string("*"));
1071 // Generated blocks assigned to account ""
1072 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1075 entry.push_back(Pair("account", string("")));
1076 if (nGeneratedImmature)
1078 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1079 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1083 entry.push_back(Pair("category", "generate"));
1084 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1087 WalletTxToJSON(wtx, entry);
1088 ret.push_back(entry);
1092 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1094 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1097 entry.push_back(Pair("account", strSentAccount));
1098 entry.push_back(Pair("address", s.first.ToString()));
1099 entry.push_back(Pair("category", "send"));
1100 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1101 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1103 WalletTxToJSON(wtx, entry);
1104 ret.push_back(entry);
1109 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1110 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1112 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1115 if (pwalletMain->mapAddressBook.count(r.first))
1116 account = pwalletMain->mapAddressBook[r.first];
1117 if (fAllAccounts || (account == strAccount))
1120 entry.push_back(Pair("account", account));
1121 entry.push_back(Pair("address", r.first.ToString()));
1122 entry.push_back(Pair("category", "receive"));
1123 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1125 WalletTxToJSON(wtx, entry);
1126 ret.push_back(entry);
1133 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1135 bool fAllAccounts = (strAccount == string("*"));
1137 if (fAllAccounts || acentry.strAccount == strAccount)
1140 entry.push_back(Pair("account", acentry.strAccount));
1141 entry.push_back(Pair("category", "move"));
1142 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1143 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1144 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1145 entry.push_back(Pair("comment", acentry.strComment));
1146 ret.push_back(entry);
1150 Value listtransactions(const Array& params, bool fHelp)
1152 if (fHelp || params.size() > 3)
1153 throw runtime_error(
1154 "listtransactions [account] [count=10] [from=0]\n"
1155 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1157 string strAccount = "*";
1158 if (params.size() > 0)
1159 strAccount = params[0].get_str();
1161 if (params.size() > 1)
1162 nCount = params[1].get_int();
1164 if (params.size() > 2)
1165 nFrom = params[2].get_int();
1168 CWalletDB walletdb(pwalletMain->strWalletFile);
1170 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1172 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1173 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1174 typedef multimap<int64, TxPair > TxItems;
1177 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1179 CWalletTx* wtx = &((*it).second);
1180 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1182 list<CAccountingEntry> acentries;
1183 walletdb.ListAccountCreditDebit(strAccount, acentries);
1184 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1186 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1189 // Now: iterate backwards until we have nCount items to return:
1190 TxItems::reverse_iterator it = txByTime.rbegin();
1191 for (std::advance(it, nFrom); it != txByTime.rend(); ++it)
1193 CWalletTx *const pwtx = (*it).second.first;
1195 ListTransactions(*pwtx, strAccount, 0, true, ret);
1196 CAccountingEntry *const pacentry = (*it).second.second;
1198 AcentryToJSON(*pacentry, strAccount, ret);
1200 if (ret.size() >= nCount) break;
1202 // ret is now newest to oldest
1205 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1206 if (ret.size() > nCount)
1208 Array::iterator last = ret.begin();
1209 std::advance(last, nCount);
1210 ret.erase(last, ret.end());
1212 std::reverse(ret.begin(), ret.end()); // oldest to newest
1217 Value listaccounts(const Array& params, bool fHelp)
1219 if (fHelp || params.size() > 1)
1220 throw runtime_error(
1221 "listaccounts [minconf=1]\n"
1222 "Returns Object that has account names as keys, account balances as values.");
1225 if (params.size() > 0)
1226 nMinDepth = params[0].get_int();
1228 map<string, int64> mapAccountBalances;
1229 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1230 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1232 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1233 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1234 mapAccountBalances[entry.second] = 0;
1237 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1239 const CWalletTx& wtx = (*it).second;
1240 int64 nGeneratedImmature, nGeneratedMature, nFee;
1241 string strSentAccount;
1242 list<pair<CBitcoinAddress, int64> > listReceived;
1243 list<pair<CBitcoinAddress, int64> > listSent;
1244 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1245 mapAccountBalances[strSentAccount] -= nFee;
1246 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1247 mapAccountBalances[strSentAccount] -= s.second;
1248 if (wtx.GetDepthInMainChain() >= nMinDepth)
1250 mapAccountBalances[""] += nGeneratedMature;
1251 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1252 if (pwalletMain->mapAddressBook.count(r.first))
1253 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1255 mapAccountBalances[""] += r.second;
1260 list<CAccountingEntry> acentries;
1261 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1262 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1263 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1266 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1267 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1272 Value gettransaction(const Array& params, bool fHelp)
1274 if (fHelp || params.size() != 1)
1275 throw runtime_error(
1276 "gettransaction <txid>\n"
1277 "Get detailed information about <txid>");
1280 hash.SetHex(params[0].get_str());
1283 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1285 if (!pwalletMain->mapWallet.count(hash))
1286 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1287 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1289 int64 nCredit = wtx.GetCredit();
1290 int64 nDebit = wtx.GetDebit();
1291 int64 nNet = nCredit - nDebit;
1292 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1294 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1296 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1298 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1301 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1302 entry.push_back(Pair("details", details));
1309 Value backupwallet(const Array& params, bool fHelp)
1311 if (fHelp || params.size() != 1)
1312 throw runtime_error(
1313 "backupwallet <destination>\n"
1314 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1316 string strDest = params[0].get_str();
1317 BackupWallet(*pwalletMain, strDest);
1323 Value keypoolrefill(const Array& params, bool fHelp)
1325 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1326 throw runtime_error(
1328 "Fills the keypool, requires wallet passphrase to be set.");
1329 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1330 throw runtime_error(
1332 "Fills the keypool.");
1334 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1336 if (pwalletMain->IsLocked())
1337 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1339 pwalletMain->TopUpKeyPool();
1342 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1343 throw JSONRPCError(-4, "Error refreshing keypool.");
1349 void ThreadTopUpKeyPool(void* parg)
1351 pwalletMain->TopUpKeyPool();
1354 void ThreadCleanWalletPassphrase(void* parg)
1356 int64 nMyWakeTime = GetTime() + *((int*)parg);
1358 if (nWalletUnlockTime == 0)
1360 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1362 nWalletUnlockTime = nMyWakeTime;
1365 while (GetTime() < nWalletUnlockTime)
1366 Sleep(GetTime() - nWalletUnlockTime);
1368 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1370 nWalletUnlockTime = 0;
1375 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1377 if (nWalletUnlockTime < nMyWakeTime)
1378 nWalletUnlockTime = nMyWakeTime;
1384 pwalletMain->Lock();
1389 Value walletpassphrase(const Array& params, bool fHelp)
1391 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1392 throw runtime_error(
1393 "walletpassphrase <passphrase> <timeout>\n"
1394 "Stores the wallet decryption key in memory for <timeout> seconds.");
1397 if (!pwalletMain->IsCrypted())
1398 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1400 if (!pwalletMain->IsLocked())
1401 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1403 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1404 string strWalletPass;
1405 strWalletPass.reserve(100);
1406 mlock(&strWalletPass[0], strWalletPass.capacity());
1407 strWalletPass = params[0].get_str();
1409 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1411 if (strWalletPass.length() > 0)
1413 if (!pwalletMain->Unlock(strWalletPass))
1415 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1416 munlock(&strWalletPass[0], strWalletPass.capacity());
1417 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1419 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1420 munlock(&strWalletPass[0], strWalletPass.capacity());
1423 throw runtime_error(
1424 "walletpassphrase <passphrase> <timeout>\n"
1425 "Stores the wallet decryption key in memory for <timeout> seconds.");
1428 CreateThread(ThreadTopUpKeyPool, NULL);
1429 int* pnSleepTime = new int(params[1].get_int());
1430 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1436 Value walletpassphrasechange(const Array& params, bool fHelp)
1438 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1439 throw runtime_error(
1440 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1441 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1444 if (!pwalletMain->IsCrypted())
1445 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1447 string strOldWalletPass;
1448 strOldWalletPass.reserve(100);
1449 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1450 strOldWalletPass = params[0].get_str();
1452 string strNewWalletPass;
1453 strNewWalletPass.reserve(100);
1454 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1455 strNewWalletPass = params[1].get_str();
1457 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1458 throw runtime_error(
1459 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1460 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1462 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1464 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1465 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1466 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1467 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1468 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1470 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1471 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1472 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1473 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1479 Value walletlock(const Array& params, bool fHelp)
1481 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1482 throw runtime_error(
1484 "Removes the wallet encryption key from memory, locking the wallet.\n"
1485 "After calling this method, you will need to call walletpassphrase again\n"
1486 "before being able to call any methods which require the wallet to be unlocked.");
1489 if (!pwalletMain->IsCrypted())
1490 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1492 pwalletMain->Lock();
1493 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1495 nWalletUnlockTime = 0;
1502 Value encryptwallet(const Array& params, bool fHelp)
1504 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1505 throw runtime_error(
1506 "encryptwallet <passphrase>\n"
1507 "Encrypts the wallet with <passphrase>.");
1510 if (pwalletMain->IsCrypted())
1511 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1513 string strWalletPass;
1514 strWalletPass.reserve(100);
1515 mlock(&strWalletPass[0], strWalletPass.capacity());
1516 strWalletPass = params[0].get_str();
1518 if (strWalletPass.length() < 1)
1519 throw runtime_error(
1520 "encryptwallet <passphrase>\n"
1521 "Encrypts the wallet with <passphrase>.");
1523 if (!pwalletMain->EncryptWallet(strWalletPass))
1525 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1526 munlock(&strWalletPass[0], strWalletPass.capacity());
1527 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1529 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1530 munlock(&strWalletPass[0], strWalletPass.capacity());
1536 Value validateaddress(const Array& params, bool fHelp)
1538 if (fHelp || params.size() != 1)
1539 throw runtime_error(
1540 "validateaddress <bitcoinaddress>\n"
1541 "Return information about <bitcoinaddress>.");
1543 CBitcoinAddress address(params[0].get_str());
1544 bool isValid = address.IsValid();
1547 ret.push_back(Pair("isvalid", isValid));
1550 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1551 // version of the address:
1552 string currentAddress = address.ToString();
1553 ret.push_back(Pair("address", currentAddress));
1554 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1555 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1557 if (pwalletMain->mapAddressBook.count(address))
1558 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1565 Value getwork(const Array& params, bool fHelp)
1567 if (fHelp || params.size() > 1)
1568 throw runtime_error(
1570 "If [data] is not specified, returns formatted hash data to work on:\n"
1571 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1572 " \"data\" : block data\n"
1573 " \"hash1\" : formatted hash buffer for second hash\n"
1574 " \"target\" : little endian hash target\n"
1575 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1578 throw JSONRPCError(-9, "Bitcoin is not connected!");
1580 if (IsInitialBlockDownload())
1581 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1583 static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1584 static vector<CBlock*> vNewBlock;
1585 static CReserveKey reservekey(pwalletMain);
1587 if (params.size() == 0)
1590 static unsigned int nTransactionsUpdatedLast;
1591 static CBlockIndex* pindexPrev;
1592 static int64 nStart;
1593 static CBlock* pblock;
1594 if (pindexPrev != pindexBest ||
1595 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1597 if (pindexPrev != pindexBest)
1599 // Deallocate old blocks since they're obsolete now
1600 mapNewBlock.clear();
1601 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1605 nTransactionsUpdatedLast = nTransactionsUpdated;
1606 pindexPrev = pindexBest;
1610 pblock = CreateNewBlock(reservekey);
1612 throw JSONRPCError(-7, "Out of memory");
1613 vNewBlock.push_back(pblock);
1617 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1620 // Update nExtraNonce
1621 static unsigned int nExtraNonce = 0;
1622 static int64 nPrevTime = 0;
1623 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1626 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1628 // Prebuild hash buffers
1632 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1634 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1637 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1638 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1639 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1640 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1646 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1647 if (vchData.size() != 128)
1648 throw JSONRPCError(-8, "Invalid parameter");
1649 CBlock* pdata = (CBlock*)&vchData[0];
1652 for (int i = 0; i < 128/4; i++)
1653 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1656 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1658 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1659 unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1661 pblock->nTime = pdata->nTime;
1662 pblock->nNonce = pdata->nNonce;
1663 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1664 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1666 return CheckWork(pblock, *pwalletMain, reservekey);
1684 pair<string, rpcfn_type> pCallTable[] =
1686 make_pair("help", &help),
1687 make_pair("stop", &stop),
1688 make_pair("getblockcount", &getblockcount),
1689 make_pair("getblocknumber", &getblocknumber),
1690 make_pair("getconnectioncount", &getconnectioncount),
1691 make_pair("getdifficulty", &getdifficulty),
1692 make_pair("getgenerate", &getgenerate),
1693 make_pair("setgenerate", &setgenerate),
1694 make_pair("gethashespersec", &gethashespersec),
1695 make_pair("getinfo", &getinfo),
1696 make_pair("getnewaddress", &getnewaddress),
1697 make_pair("getaccountaddress", &getaccountaddress),
1698 make_pair("setaccount", &setaccount),
1699 make_pair("setlabel", &setaccount), // deprecated
1700 make_pair("getaccount", &getaccount),
1701 make_pair("getlabel", &getaccount), // deprecated
1702 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1703 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1704 make_pair("sendtoaddress", &sendtoaddress),
1705 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1706 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1707 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1708 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1709 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1710 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1711 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1712 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1713 make_pair("backupwallet", &backupwallet),
1714 make_pair("keypoolrefill", &keypoolrefill),
1715 make_pair("walletpassphrase", &walletpassphrase),
1716 make_pair("walletpassphrasechange", &walletpassphrasechange),
1717 make_pair("walletlock", &walletlock),
1718 make_pair("encryptwallet", &encryptwallet),
1719 make_pair("validateaddress", &validateaddress),
1720 make_pair("getbalance", &getbalance),
1721 make_pair("move", &movecmd),
1722 make_pair("sendfrom", &sendfrom),
1723 make_pair("sendmany", &sendmany),
1724 make_pair("gettransaction", &gettransaction),
1725 make_pair("listtransactions", &listtransactions),
1726 make_pair("getwork", &getwork),
1727 make_pair("listaccounts", &listaccounts),
1728 make_pair("settxfee", &settxfee),
1730 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1732 string pAllowInSafeMode[] =
1738 "getconnectioncount",
1745 "getaccountaddress",
1746 "setlabel", // deprecated
1748 "getlabel", // deprecated
1749 "getaddressesbyaccount",
1750 "getaddressesbylabel", // deprecated
1758 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1766 // This ain't Apache. We're just using HTTP header for the length field
1767 // and to be compatible with other JSON-RPC implementations.
1770 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1773 s << "POST / HTTP/1.1\r\n"
1774 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1775 << "Host: 127.0.0.1\r\n"
1776 << "Content-Type: application/json\r\n"
1777 << "Content-Length: " << strMsg.size() << "\r\n"
1778 << "Accept: application/json\r\n";
1779 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1780 s << item.first << ": " << item.second << "\r\n";
1781 s << "\r\n" << strMsg;
1786 string rfc1123Time()
1791 struct tm* now_gmt = gmtime(&now);
1792 string locale(setlocale(LC_TIME, NULL));
1793 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1794 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1795 setlocale(LC_TIME, locale.c_str());
1796 return string(buffer);
1799 static string HTTPReply(int nStatus, const string& strMsg)
1802 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1804 "Server: bitcoin-json-rpc/%s\r\n"
1805 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1806 "Content-Type: text/html\r\n"
1807 "Content-Length: 296\r\n"
1809 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1810 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1813 "<TITLE>Error</TITLE>\r\n"
1814 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1816 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1817 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1819 if (nStatus == 200) strStatus = "OK";
1820 else if (nStatus == 400) strStatus = "Bad Request";
1821 else if (nStatus == 403) strStatus = "Forbidden";
1822 else if (nStatus == 404) strStatus = "Not Found";
1823 else if (nStatus == 500) strStatus = "Internal Server Error";
1825 "HTTP/1.1 %d %s\r\n"
1827 "Connection: close\r\n"
1828 "Content-Length: %d\r\n"
1829 "Content-Type: application/json\r\n"
1830 "Server: bitcoin-json-rpc/%s\r\n"
1835 rfc1123Time().c_str(),
1837 FormatFullVersion().c_str(),
1841 int ReadHTTPStatus(std::basic_istream<char>& stream)
1844 getline(stream, str);
1845 vector<string> vWords;
1846 boost::split(vWords, str, boost::is_any_of(" "));
1847 if (vWords.size() < 2)
1849 return atoi(vWords[1].c_str());
1852 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1858 std::getline(stream, str);
1859 if (str.empty() || str == "\r")
1861 string::size_type nColon = str.find(":");
1862 if (nColon != string::npos)
1864 string strHeader = str.substr(0, nColon);
1865 boost::trim(strHeader);
1866 boost::to_lower(strHeader);
1867 string strValue = str.substr(nColon+1);
1868 boost::trim(strValue);
1869 mapHeadersRet[strHeader] = strValue;
1870 if (strHeader == "content-length")
1871 nLen = atoi(strValue.c_str());
1877 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1879 mapHeadersRet.clear();
1883 int nStatus = ReadHTTPStatus(stream);
1886 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1887 if (nLen < 0 || nLen > MAX_SIZE)
1893 vector<char> vch(nLen);
1894 stream.read(&vch[0], nLen);
1895 strMessageRet = string(vch.begin(), vch.end());
1901 string EncodeBase64(string s)
1906 b64 = BIO_new(BIO_f_base64());
1907 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1908 bmem = BIO_new(BIO_s_mem());
1909 b64 = BIO_push(b64, bmem);
1910 BIO_write(b64, s.c_str(), s.size());
1912 BIO_get_mem_ptr(b64, &bptr);
1914 string result(bptr->data, bptr->length);
1920 string DecodeBase64(string s)
1924 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1926 b64 = BIO_new(BIO_f_base64());
1927 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1928 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1929 bmem = BIO_push(b64, bmem);
1930 BIO_read(bmem, buffer, s.size());
1933 string result(buffer);
1938 bool HTTPAuthorized(map<string, string>& mapHeaders)
1940 string strAuth = mapHeaders["authorization"];
1941 if (strAuth.substr(0,6) != "Basic ")
1943 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1944 string strUserPass = DecodeBase64(strUserPass64);
1945 string::size_type nColon = strUserPass.find(":");
1946 if (nColon == string::npos)
1948 string strUser = strUserPass.substr(0, nColon);
1949 string strPassword = strUserPass.substr(nColon+1);
1950 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1954 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1955 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1956 // unspecified (HTTP errors and contents of 'error').
1958 // 1.0 spec: http://json-rpc.org/wiki/specification
1959 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1960 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1963 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1966 request.push_back(Pair("method", strMethod));
1967 request.push_back(Pair("params", params));
1968 request.push_back(Pair("id", id));
1969 return write_string(Value(request), false) + "\n";
1972 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1975 if (error.type() != null_type)
1976 reply.push_back(Pair("result", Value::null));
1978 reply.push_back(Pair("result", result));
1979 reply.push_back(Pair("error", error));
1980 reply.push_back(Pair("id", id));
1981 return write_string(Value(reply), false) + "\n";
1984 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1986 // Send error reply from json-rpc error object
1988 int code = find_value(objError, "code").get_int();
1989 if (code == -32600) nStatus = 400;
1990 else if (code == -32601) nStatus = 404;
1991 string strReply = JSONRPCReply(Value::null, objError, id);
1992 stream << HTTPReply(nStatus, strReply) << std::flush;
1995 bool ClientAllowed(const string& strAddress)
1997 if (strAddress == asio::ip::address_v4::loopback().to_string())
1999 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2000 BOOST_FOREACH(string strAllow, vAllow)
2001 if (WildcardMatch(strAddress, strAllow))
2008 // IOStream device that speaks SSL but can also speak non-SSL
2010 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2012 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2014 fUseSSL = fUseSSLIn;
2015 fNeedHandshake = fUseSSLIn;
2018 void handshake(ssl::stream_base::handshake_type role)
2020 if (!fNeedHandshake) return;
2021 fNeedHandshake = false;
2022 stream.handshake(role);
2024 std::streamsize read(char* s, std::streamsize n)
2026 handshake(ssl::stream_base::server); // HTTPS servers read first
2027 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2028 return stream.next_layer().read_some(asio::buffer(s, n));
2030 std::streamsize write(const char* s, std::streamsize n)
2032 handshake(ssl::stream_base::client); // HTTPS clients write first
2033 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2034 return asio::write(stream.next_layer(), asio::buffer(s, n));
2036 bool connect(const std::string& server, const std::string& port)
2038 ip::tcp::resolver resolver(stream.get_io_service());
2039 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2040 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2041 ip::tcp::resolver::iterator end;
2042 boost::system::error_code error = asio::error::host_not_found;
2043 while (error && endpoint_iterator != end)
2045 stream.lowest_layer().close();
2046 stream.lowest_layer().connect(*endpoint_iterator++, error);
2054 bool fNeedHandshake;
2060 void ThreadRPCServer(void* parg)
2062 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2065 vnThreadsRunning[4]++;
2066 ThreadRPCServer2(parg);
2067 vnThreadsRunning[4]--;
2069 catch (std::exception& e) {
2070 vnThreadsRunning[4]--;
2071 PrintException(&e, "ThreadRPCServer()");
2073 vnThreadsRunning[4]--;
2074 PrintException(NULL, "ThreadRPCServer()");
2076 printf("ThreadRPCServer exiting\n");
2079 void ThreadRPCServer2(void* parg)
2081 printf("ThreadRPCServer started\n");
2083 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2085 string strWhatAmI = "To use bitcoind";
2086 if (mapArgs.count("-server"))
2087 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2088 else if (mapArgs.count("-daemon"))
2089 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2091 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2092 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2094 GetConfigFile().c_str());
2095 CreateThread(Shutdown, NULL);
2099 bool fUseSSL = GetBoolArg("-rpcssl");
2100 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2102 asio::io_service io_service;
2103 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2104 ip::tcp::acceptor acceptor(io_service, endpoint);
2106 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2109 ssl::context context(io_service, ssl::context::sslv23);
2112 context.set_options(ssl::context::no_sslv2);
2113 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2114 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2115 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2116 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2117 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2118 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2119 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2120 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2122 string ciphers = GetArg("-rpcsslciphers",
2123 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2124 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2128 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2133 // Accept connection
2135 SSLStream sslStream(io_service, context);
2136 SSLIOStreamDevice d(sslStream, fUseSSL);
2137 iostreams::stream<SSLIOStreamDevice> stream(d);
2139 ip::tcp::iostream stream;
2142 ip::tcp::endpoint peer;
2143 vnThreadsRunning[4]--;
2145 acceptor.accept(sslStream.lowest_layer(), peer);
2147 acceptor.accept(*stream.rdbuf(), peer);
2149 vnThreadsRunning[4]++;
2153 // Restrict callers by IP
2154 if (!ClientAllowed(peer.address().to_string()))
2156 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2158 stream << HTTPReply(403, "") << std::flush;
2162 map<string, string> mapHeaders;
2165 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2166 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2169 printf("ThreadRPCServer ReadHTTP timeout\n");
2173 // Check authorization
2174 if (mapHeaders.count("authorization") == 0)
2176 stream << HTTPReply(401, "") << std::flush;
2179 if (!HTTPAuthorized(mapHeaders))
2181 // Deter brute-forcing short passwords
2182 if (mapArgs["-rpcpassword"].size() < 15)
2185 stream << HTTPReply(401, "") << std::flush;
2186 printf("ThreadRPCServer incorrect password attempt\n");
2190 Value id = Value::null;
2195 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2196 throw JSONRPCError(-32700, "Parse error");
2197 const Object& request = valRequest.get_obj();
2199 // Parse id now so errors from here on will have the id
2200 id = find_value(request, "id");
2203 Value valMethod = find_value(request, "method");
2204 if (valMethod.type() == null_type)
2205 throw JSONRPCError(-32600, "Missing method");
2206 if (valMethod.type() != str_type)
2207 throw JSONRPCError(-32600, "Method must be a string");
2208 string strMethod = valMethod.get_str();
2209 if (strMethod != "getwork")
2210 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2213 Value valParams = find_value(request, "params");
2215 if (valParams.type() == array_type)
2216 params = valParams.get_array();
2217 else if (valParams.type() == null_type)
2220 throw JSONRPCError(-32600, "Params must be an array");
2223 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2224 if (mi == mapCallTable.end())
2225 throw JSONRPCError(-32601, "Method not found");
2227 // Observe safe mode
2228 string strWarning = GetWarnings("rpc");
2229 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2230 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2235 Value result = (*(*mi).second)(params, false);
2238 string strReply = JSONRPCReply(result, Value::null, id);
2239 stream << HTTPReply(200, strReply) << std::flush;
2241 catch (std::exception& e)
2243 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2246 catch (Object& objError)
2248 ErrorReply(stream, objError, id);
2250 catch (std::exception& e)
2252 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2260 Object CallRPC(const string& strMethod, const Array& params)
2262 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2263 throw runtime_error(strprintf(
2264 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2265 "If the file does not exist, create it with owner-readable-only file permissions."),
2266 GetConfigFile().c_str()));
2268 // Connect to localhost
2269 bool fUseSSL = GetBoolArg("-rpcssl");
2271 asio::io_service io_service;
2272 ssl::context context(io_service, ssl::context::sslv23);
2273 context.set_options(ssl::context::no_sslv2);
2274 SSLStream sslStream(io_service, context);
2275 SSLIOStreamDevice d(sslStream, fUseSSL);
2276 iostreams::stream<SSLIOStreamDevice> stream(d);
2277 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2278 throw runtime_error("couldn't connect to server");
2281 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2283 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2285 throw runtime_error("couldn't connect to server");
2289 // HTTP basic authentication
2290 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2291 map<string, string> mapRequestHeaders;
2292 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2295 string strRequest = JSONRPCRequest(strMethod, params, 1);
2296 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2297 stream << strPost << std::flush;
2300 map<string, string> mapHeaders;
2302 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2304 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2305 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2306 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2307 else if (strReply.empty())
2308 throw runtime_error("no response from server");
2312 if (!read_string(strReply, valReply))
2313 throw runtime_error("couldn't parse reply from server");
2314 const Object& reply = valReply.get_obj();
2316 throw runtime_error("expected reply to have result, error and id properties");
2324 template<typename T>
2325 void ConvertTo(Value& value)
2327 if (value.type() == str_type)
2329 // reinterpret string as unquoted json value
2331 if (!read_string(value.get_str(), value2))
2332 throw runtime_error("type mismatch");
2333 value = value2.get_value<T>();
2337 value = value.get_value<T>();
2341 int CommandLineRPC(int argc, char *argv[])
2348 while (argc > 1 && IsSwitchChar(argv[1][0]))
2356 throw runtime_error("too few parameters");
2357 string strMethod = argv[1];
2359 // Parameters default to strings
2361 for (int i = 2; i < argc; i++)
2362 params.push_back(argv[i]);
2363 int n = params.size();
2366 // Special case non-string parameter types
2368 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2369 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2370 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2371 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2372 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2373 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2374 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2375 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2376 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2377 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2378 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2379 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2380 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2381 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2382 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2383 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2384 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2385 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2386 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2387 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2388 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2389 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2390 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2391 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2392 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2393 if (strMethod == "sendmany" && n > 1)
2395 string s = params[1].get_str();
2397 if (!read_string(s, v) || v.type() != obj_type)
2398 throw runtime_error("type mismatch");
2399 params[1] = v.get_obj();
2401 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2404 Object reply = CallRPC(strMethod, params);
2407 const Value& result = find_value(reply, "result");
2408 const Value& error = find_value(reply, "error");
2410 if (error.type() != null_type)
2413 strPrint = "error: " + write_string(error, false);
2414 int code = find_value(error.get_obj(), "code").get_int();
2420 if (result.type() == null_type)
2422 else if (result.type() == str_type)
2423 strPrint = result.get_str();
2425 strPrint = write_string(result, true);
2428 catch (std::exception& e)
2430 strPrint = string("error: ") + e.what();
2435 PrintException(NULL, "CommandLineRPC()");
2440 #if defined(__WXMSW__) && defined(GUI)
2441 // Windows GUI apps can't print to command line,
2442 // so settle for a message box yuck
2443 MyMessageBox(strPrint, "Bitcoin", wxOK);
2445 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2455 int main(int argc, char *argv[])
2458 // Turn off microsoft heap dump noise
2459 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2460 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2462 setbuf(stdin, NULL);
2463 setbuf(stdout, NULL);
2464 setbuf(stderr, NULL);
2468 if (argc >= 2 && string(argv[1]) == "-server")
2470 printf("server ready\n");
2471 ThreadRPCServer(NULL);
2475 return CommandLineRPC(argc, argv);
2478 catch (std::exception& e) {
2479 PrintException(&e, "main()");
2481 PrintException(NULL, "main()");