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 std::string &format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format.c_str(), 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 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1192 for (; it != txByTime.rend(); ++it)
1194 CWalletTx *const pwtx = (*it).second.first;
1196 ListTransactions(*pwtx, strAccount, 0, true, ret);
1197 CAccountingEntry *const pacentry = (*it).second.second;
1199 AcentryToJSON(*pacentry, strAccount, ret);
1201 if (ret.size() >= nCount) break;
1203 // ret is now newest to oldest
1206 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1207 if (ret.size() > nCount)
1209 Array::iterator last = ret.begin();
1210 std::advance(last, nCount);
1211 ret.erase(last, ret.end());
1213 std::reverse(ret.begin(), ret.end()); // oldest to newest
1218 Value listaccounts(const Array& params, bool fHelp)
1220 if (fHelp || params.size() > 1)
1221 throw runtime_error(
1222 "listaccounts [minconf=1]\n"
1223 "Returns Object that has account names as keys, account balances as values.");
1226 if (params.size() > 0)
1227 nMinDepth = params[0].get_int();
1229 map<string, int64> mapAccountBalances;
1230 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1231 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1233 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1234 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1235 mapAccountBalances[entry.second] = 0;
1238 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1240 const CWalletTx& wtx = (*it).second;
1241 int64 nGeneratedImmature, nGeneratedMature, nFee;
1242 string strSentAccount;
1243 list<pair<CBitcoinAddress, int64> > listReceived;
1244 list<pair<CBitcoinAddress, int64> > listSent;
1245 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1246 mapAccountBalances[strSentAccount] -= nFee;
1247 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1248 mapAccountBalances[strSentAccount] -= s.second;
1249 if (wtx.GetDepthInMainChain() >= nMinDepth)
1251 mapAccountBalances[""] += nGeneratedMature;
1252 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1253 if (pwalletMain->mapAddressBook.count(r.first))
1254 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1256 mapAccountBalances[""] += r.second;
1261 list<CAccountingEntry> acentries;
1262 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1263 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1264 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1267 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1268 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1273 Value gettransaction(const Array& params, bool fHelp)
1275 if (fHelp || params.size() != 1)
1276 throw runtime_error(
1277 "gettransaction <txid>\n"
1278 "Get detailed information about <txid>");
1281 hash.SetHex(params[0].get_str());
1284 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1286 if (!pwalletMain->mapWallet.count(hash))
1287 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1288 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1290 int64 nCredit = wtx.GetCredit();
1291 int64 nDebit = wtx.GetDebit();
1292 int64 nNet = nCredit - nDebit;
1293 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1295 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1297 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1299 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1302 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1303 entry.push_back(Pair("details", details));
1310 Value backupwallet(const Array& params, bool fHelp)
1312 if (fHelp || params.size() != 1)
1313 throw runtime_error(
1314 "backupwallet <destination>\n"
1315 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1317 string strDest = params[0].get_str();
1318 BackupWallet(*pwalletMain, strDest);
1324 Value keypoolrefill(const Array& params, bool fHelp)
1326 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1327 throw runtime_error(
1329 "Fills the keypool, requires wallet passphrase to be set.");
1330 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1331 throw runtime_error(
1333 "Fills the keypool.");
1335 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1337 if (pwalletMain->IsLocked())
1338 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1340 pwalletMain->TopUpKeyPool();
1343 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1344 throw JSONRPCError(-4, "Error refreshing keypool.");
1350 void ThreadTopUpKeyPool(void* parg)
1352 pwalletMain->TopUpKeyPool();
1355 void ThreadCleanWalletPassphrase(void* parg)
1357 int64 nMyWakeTime = GetTime() + *((int*)parg);
1359 if (nWalletUnlockTime == 0)
1361 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1363 nWalletUnlockTime = nMyWakeTime;
1366 while (GetTime() < nWalletUnlockTime)
1367 Sleep(GetTime() - nWalletUnlockTime);
1369 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1371 nWalletUnlockTime = 0;
1376 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1378 if (nWalletUnlockTime < nMyWakeTime)
1379 nWalletUnlockTime = nMyWakeTime;
1385 pwalletMain->Lock();
1390 Value walletpassphrase(const Array& params, bool fHelp)
1392 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1393 throw runtime_error(
1394 "walletpassphrase <passphrase> <timeout>\n"
1395 "Stores the wallet decryption key in memory for <timeout> seconds.");
1398 if (!pwalletMain->IsCrypted())
1399 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1401 if (!pwalletMain->IsLocked())
1402 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1404 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1405 string strWalletPass;
1406 strWalletPass.reserve(100);
1407 mlock(&strWalletPass[0], strWalletPass.capacity());
1408 strWalletPass = params[0].get_str();
1410 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1412 if (strWalletPass.length() > 0)
1414 if (!pwalletMain->Unlock(strWalletPass))
1416 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1417 munlock(&strWalletPass[0], strWalletPass.capacity());
1418 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1420 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1421 munlock(&strWalletPass[0], strWalletPass.capacity());
1424 throw runtime_error(
1425 "walletpassphrase <passphrase> <timeout>\n"
1426 "Stores the wallet decryption key in memory for <timeout> seconds.");
1429 CreateThread(ThreadTopUpKeyPool, NULL);
1430 int* pnSleepTime = new int(params[1].get_int());
1431 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1437 Value walletpassphrasechange(const Array& params, bool fHelp)
1439 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1440 throw runtime_error(
1441 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1442 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1445 if (!pwalletMain->IsCrypted())
1446 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1448 string strOldWalletPass;
1449 strOldWalletPass.reserve(100);
1450 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1451 strOldWalletPass = params[0].get_str();
1453 string strNewWalletPass;
1454 strNewWalletPass.reserve(100);
1455 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1456 strNewWalletPass = params[1].get_str();
1458 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1459 throw runtime_error(
1460 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1461 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1463 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1465 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1466 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1467 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1468 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1469 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1471 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1472 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1473 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1474 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1480 Value walletlock(const Array& params, bool fHelp)
1482 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1483 throw runtime_error(
1485 "Removes the wallet encryption key from memory, locking the wallet.\n"
1486 "After calling this method, you will need to call walletpassphrase again\n"
1487 "before being able to call any methods which require the wallet to be unlocked.");
1490 if (!pwalletMain->IsCrypted())
1491 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1493 pwalletMain->Lock();
1494 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1496 nWalletUnlockTime = 0;
1503 Value encryptwallet(const Array& params, bool fHelp)
1505 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1506 throw runtime_error(
1507 "encryptwallet <passphrase>\n"
1508 "Encrypts the wallet with <passphrase>.");
1511 if (pwalletMain->IsCrypted())
1512 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1514 string strWalletPass;
1515 strWalletPass.reserve(100);
1516 mlock(&strWalletPass[0], strWalletPass.capacity());
1517 strWalletPass = params[0].get_str();
1519 if (strWalletPass.length() < 1)
1520 throw runtime_error(
1521 "encryptwallet <passphrase>\n"
1522 "Encrypts the wallet with <passphrase>.");
1524 if (!pwalletMain->EncryptWallet(strWalletPass))
1526 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1527 munlock(&strWalletPass[0], strWalletPass.capacity());
1528 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1530 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1531 munlock(&strWalletPass[0], strWalletPass.capacity());
1537 Value validateaddress(const Array& params, bool fHelp)
1539 if (fHelp || params.size() != 1)
1540 throw runtime_error(
1541 "validateaddress <bitcoinaddress>\n"
1542 "Return information about <bitcoinaddress>.");
1544 CBitcoinAddress address(params[0].get_str());
1545 bool isValid = address.IsValid();
1548 ret.push_back(Pair("isvalid", isValid));
1551 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1552 // version of the address:
1553 string currentAddress = address.ToString();
1554 ret.push_back(Pair("address", currentAddress));
1555 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1556 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1558 if (pwalletMain->mapAddressBook.count(address))
1559 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1566 Value getwork(const Array& params, bool fHelp)
1568 if (fHelp || params.size() > 1)
1569 throw runtime_error(
1571 "If [data] is not specified, returns formatted hash data to work on:\n"
1572 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1573 " \"data\" : block data\n"
1574 " \"hash1\" : formatted hash buffer for second hash\n"
1575 " \"target\" : little endian hash target\n"
1576 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1579 throw JSONRPCError(-9, "Bitcoin is not connected!");
1581 if (IsInitialBlockDownload())
1582 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1584 static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1585 static vector<CBlock*> vNewBlock;
1586 static CReserveKey reservekey(pwalletMain);
1588 if (params.size() == 0)
1591 static unsigned int nTransactionsUpdatedLast;
1592 static CBlockIndex* pindexPrev;
1593 static int64 nStart;
1594 static CBlock* pblock;
1595 if (pindexPrev != pindexBest ||
1596 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1598 if (pindexPrev != pindexBest)
1600 // Deallocate old blocks since they're obsolete now
1601 mapNewBlock.clear();
1602 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1606 nTransactionsUpdatedLast = nTransactionsUpdated;
1607 pindexPrev = pindexBest;
1611 pblock = CreateNewBlock(reservekey);
1613 throw JSONRPCError(-7, "Out of memory");
1614 vNewBlock.push_back(pblock);
1618 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1621 // Update nExtraNonce
1622 static unsigned int nExtraNonce = 0;
1623 static int64 nPrevTime = 0;
1624 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1627 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1629 // Prebuild hash buffers
1633 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1635 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1638 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1639 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1640 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1641 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1647 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1648 if (vchData.size() != 128)
1649 throw JSONRPCError(-8, "Invalid parameter");
1650 CBlock* pdata = (CBlock*)&vchData[0];
1653 for (int i = 0; i < 128/4; i++)
1654 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1657 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1659 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1660 unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1662 pblock->nTime = pdata->nTime;
1663 pblock->nNonce = pdata->nNonce;
1664 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1665 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1667 return CheckWork(pblock, *pwalletMain, reservekey);
1685 pair<string, rpcfn_type> pCallTable[] =
1687 make_pair("help", &help),
1688 make_pair("stop", &stop),
1689 make_pair("getblockcount", &getblockcount),
1690 make_pair("getblocknumber", &getblocknumber),
1691 make_pair("getconnectioncount", &getconnectioncount),
1692 make_pair("getdifficulty", &getdifficulty),
1693 make_pair("getgenerate", &getgenerate),
1694 make_pair("setgenerate", &setgenerate),
1695 make_pair("gethashespersec", &gethashespersec),
1696 make_pair("getinfo", &getinfo),
1697 make_pair("getnewaddress", &getnewaddress),
1698 make_pair("getaccountaddress", &getaccountaddress),
1699 make_pair("setaccount", &setaccount),
1700 make_pair("setlabel", &setaccount), // deprecated
1701 make_pair("getaccount", &getaccount),
1702 make_pair("getlabel", &getaccount), // deprecated
1703 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1704 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1705 make_pair("sendtoaddress", &sendtoaddress),
1706 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1707 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1708 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1709 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1710 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1711 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1712 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1713 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1714 make_pair("backupwallet", &backupwallet),
1715 make_pair("keypoolrefill", &keypoolrefill),
1716 make_pair("walletpassphrase", &walletpassphrase),
1717 make_pair("walletpassphrasechange", &walletpassphrasechange),
1718 make_pair("walletlock", &walletlock),
1719 make_pair("encryptwallet", &encryptwallet),
1720 make_pair("validateaddress", &validateaddress),
1721 make_pair("getbalance", &getbalance),
1722 make_pair("move", &movecmd),
1723 make_pair("sendfrom", &sendfrom),
1724 make_pair("sendmany", &sendmany),
1725 make_pair("gettransaction", &gettransaction),
1726 make_pair("listtransactions", &listtransactions),
1727 make_pair("getwork", &getwork),
1728 make_pair("listaccounts", &listaccounts),
1729 make_pair("settxfee", &settxfee),
1731 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1733 string pAllowInSafeMode[] =
1739 "getconnectioncount",
1746 "getaccountaddress",
1747 "setlabel", // deprecated
1749 "getlabel", // deprecated
1750 "getaddressesbyaccount",
1751 "getaddressesbylabel", // deprecated
1759 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1767 // This ain't Apache. We're just using HTTP header for the length field
1768 // and to be compatible with other JSON-RPC implementations.
1771 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1774 s << "POST / HTTP/1.1\r\n"
1775 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1776 << "Host: 127.0.0.1\r\n"
1777 << "Content-Type: application/json\r\n"
1778 << "Content-Length: " << strMsg.size() << "\r\n"
1779 << "Accept: application/json\r\n";
1780 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1781 s << item.first << ": " << item.second << "\r\n";
1782 s << "\r\n" << strMsg;
1787 string rfc1123Time()
1792 struct tm* now_gmt = gmtime(&now);
1793 string locale(setlocale(LC_TIME, NULL));
1794 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1795 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1796 setlocale(LC_TIME, locale.c_str());
1797 return string(buffer);
1800 static string HTTPReply(int nStatus, const string& strMsg)
1803 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1805 "Server: bitcoin-json-rpc/%s\r\n"
1806 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1807 "Content-Type: text/html\r\n"
1808 "Content-Length: 296\r\n"
1810 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1811 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1814 "<TITLE>Error</TITLE>\r\n"
1815 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1817 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1818 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1820 if (nStatus == 200) strStatus = "OK";
1821 else if (nStatus == 400) strStatus = "Bad Request";
1822 else if (nStatus == 403) strStatus = "Forbidden";
1823 else if (nStatus == 404) strStatus = "Not Found";
1824 else if (nStatus == 500) strStatus = "Internal Server Error";
1826 "HTTP/1.1 %d %s\r\n"
1828 "Connection: close\r\n"
1829 "Content-Length: %d\r\n"
1830 "Content-Type: application/json\r\n"
1831 "Server: bitcoin-json-rpc/%s\r\n"
1836 rfc1123Time().c_str(),
1838 FormatFullVersion().c_str(),
1842 int ReadHTTPStatus(std::basic_istream<char>& stream)
1845 getline(stream, str);
1846 vector<string> vWords;
1847 boost::split(vWords, str, boost::is_any_of(" "));
1848 if (vWords.size() < 2)
1850 return atoi(vWords[1].c_str());
1853 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1859 std::getline(stream, str);
1860 if (str.empty() || str == "\r")
1862 string::size_type nColon = str.find(":");
1863 if (nColon != string::npos)
1865 string strHeader = str.substr(0, nColon);
1866 boost::trim(strHeader);
1867 boost::to_lower(strHeader);
1868 string strValue = str.substr(nColon+1);
1869 boost::trim(strValue);
1870 mapHeadersRet[strHeader] = strValue;
1871 if (strHeader == "content-length")
1872 nLen = atoi(strValue.c_str());
1878 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1880 mapHeadersRet.clear();
1884 int nStatus = ReadHTTPStatus(stream);
1887 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1888 if (nLen < 0 || nLen > MAX_SIZE)
1894 vector<char> vch(nLen);
1895 stream.read(&vch[0], nLen);
1896 strMessageRet = string(vch.begin(), vch.end());
1902 string EncodeBase64(string s)
1907 b64 = BIO_new(BIO_f_base64());
1908 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1909 bmem = BIO_new(BIO_s_mem());
1910 b64 = BIO_push(b64, bmem);
1911 BIO_write(b64, s.c_str(), s.size());
1913 BIO_get_mem_ptr(b64, &bptr);
1915 string result(bptr->data, bptr->length);
1921 string DecodeBase64(string s)
1925 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1927 b64 = BIO_new(BIO_f_base64());
1928 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1929 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1930 bmem = BIO_push(b64, bmem);
1931 BIO_read(bmem, buffer, s.size());
1934 string result(buffer);
1939 bool HTTPAuthorized(map<string, string>& mapHeaders)
1941 string strAuth = mapHeaders["authorization"];
1942 if (strAuth.substr(0,6) != "Basic ")
1944 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1945 string strUserPass = DecodeBase64(strUserPass64);
1946 string::size_type nColon = strUserPass.find(":");
1947 if (nColon == string::npos)
1949 string strUser = strUserPass.substr(0, nColon);
1950 string strPassword = strUserPass.substr(nColon+1);
1951 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1955 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1956 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1957 // unspecified (HTTP errors and contents of 'error').
1959 // 1.0 spec: http://json-rpc.org/wiki/specification
1960 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1961 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1964 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1967 request.push_back(Pair("method", strMethod));
1968 request.push_back(Pair("params", params));
1969 request.push_back(Pair("id", id));
1970 return write_string(Value(request), false) + "\n";
1973 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1976 if (error.type() != null_type)
1977 reply.push_back(Pair("result", Value::null));
1979 reply.push_back(Pair("result", result));
1980 reply.push_back(Pair("error", error));
1981 reply.push_back(Pair("id", id));
1982 return write_string(Value(reply), false) + "\n";
1985 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1987 // Send error reply from json-rpc error object
1989 int code = find_value(objError, "code").get_int();
1990 if (code == -32600) nStatus = 400;
1991 else if (code == -32601) nStatus = 404;
1992 string strReply = JSONRPCReply(Value::null, objError, id);
1993 stream << HTTPReply(nStatus, strReply) << std::flush;
1996 bool ClientAllowed(const string& strAddress)
1998 if (strAddress == asio::ip::address_v4::loopback().to_string())
2000 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2001 BOOST_FOREACH(string strAllow, vAllow)
2002 if (WildcardMatch(strAddress, strAllow))
2009 // IOStream device that speaks SSL but can also speak non-SSL
2011 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2013 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2015 fUseSSL = fUseSSLIn;
2016 fNeedHandshake = fUseSSLIn;
2019 void handshake(ssl::stream_base::handshake_type role)
2021 if (!fNeedHandshake) return;
2022 fNeedHandshake = false;
2023 stream.handshake(role);
2025 std::streamsize read(char* s, std::streamsize n)
2027 handshake(ssl::stream_base::server); // HTTPS servers read first
2028 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2029 return stream.next_layer().read_some(asio::buffer(s, n));
2031 std::streamsize write(const char* s, std::streamsize n)
2033 handshake(ssl::stream_base::client); // HTTPS clients write first
2034 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2035 return asio::write(stream.next_layer(), asio::buffer(s, n));
2037 bool connect(const std::string& server, const std::string& port)
2039 ip::tcp::resolver resolver(stream.get_io_service());
2040 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2041 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2042 ip::tcp::resolver::iterator end;
2043 boost::system::error_code error = asio::error::host_not_found;
2044 while (error && endpoint_iterator != end)
2046 stream.lowest_layer().close();
2047 stream.lowest_layer().connect(*endpoint_iterator++, error);
2055 bool fNeedHandshake;
2061 void ThreadRPCServer(void* parg)
2063 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2066 vnThreadsRunning[4]++;
2067 ThreadRPCServer2(parg);
2068 vnThreadsRunning[4]--;
2070 catch (std::exception& e) {
2071 vnThreadsRunning[4]--;
2072 PrintException(&e, "ThreadRPCServer()");
2074 vnThreadsRunning[4]--;
2075 PrintException(NULL, "ThreadRPCServer()");
2077 printf("ThreadRPCServer exiting\n");
2080 void ThreadRPCServer2(void* parg)
2082 printf("ThreadRPCServer started\n");
2084 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2086 string strWhatAmI = "To use bitcoind";
2087 if (mapArgs.count("-server"))
2088 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2089 else if (mapArgs.count("-daemon"))
2090 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2092 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2093 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2095 GetConfigFile().c_str());
2096 CreateThread(Shutdown, NULL);
2100 bool fUseSSL = GetBoolArg("-rpcssl");
2101 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2103 asio::io_service io_service;
2104 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2105 ip::tcp::acceptor acceptor(io_service, endpoint);
2107 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2110 ssl::context context(io_service, ssl::context::sslv23);
2113 context.set_options(ssl::context::no_sslv2);
2114 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2115 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2116 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2117 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2118 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2119 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2120 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2121 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2123 string ciphers = GetArg("-rpcsslciphers",
2124 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2125 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2129 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2134 // Accept connection
2136 SSLStream sslStream(io_service, context);
2137 SSLIOStreamDevice d(sslStream, fUseSSL);
2138 iostreams::stream<SSLIOStreamDevice> stream(d);
2140 ip::tcp::iostream stream;
2143 ip::tcp::endpoint peer;
2144 vnThreadsRunning[4]--;
2146 acceptor.accept(sslStream.lowest_layer(), peer);
2148 acceptor.accept(*stream.rdbuf(), peer);
2150 vnThreadsRunning[4]++;
2154 // Restrict callers by IP
2155 if (!ClientAllowed(peer.address().to_string()))
2157 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2159 stream << HTTPReply(403, "") << std::flush;
2163 map<string, string> mapHeaders;
2166 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2167 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2170 printf("ThreadRPCServer ReadHTTP timeout\n");
2174 // Check authorization
2175 if (mapHeaders.count("authorization") == 0)
2177 stream << HTTPReply(401, "") << std::flush;
2180 if (!HTTPAuthorized(mapHeaders))
2182 // Deter brute-forcing short passwords
2183 if (mapArgs["-rpcpassword"].size() < 15)
2186 stream << HTTPReply(401, "") << std::flush;
2187 printf("ThreadRPCServer incorrect password attempt\n");
2191 Value id = Value::null;
2196 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2197 throw JSONRPCError(-32700, "Parse error");
2198 const Object& request = valRequest.get_obj();
2200 // Parse id now so errors from here on will have the id
2201 id = find_value(request, "id");
2204 Value valMethod = find_value(request, "method");
2205 if (valMethod.type() == null_type)
2206 throw JSONRPCError(-32600, "Missing method");
2207 if (valMethod.type() != str_type)
2208 throw JSONRPCError(-32600, "Method must be a string");
2209 string strMethod = valMethod.get_str();
2210 if (strMethod != "getwork")
2211 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2214 Value valParams = find_value(request, "params");
2216 if (valParams.type() == array_type)
2217 params = valParams.get_array();
2218 else if (valParams.type() == null_type)
2221 throw JSONRPCError(-32600, "Params must be an array");
2224 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2225 if (mi == mapCallTable.end())
2226 throw JSONRPCError(-32601, "Method not found");
2228 // Observe safe mode
2229 string strWarning = GetWarnings("rpc");
2230 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2231 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2236 Value result = (*(*mi).second)(params, false);
2239 string strReply = JSONRPCReply(result, Value::null, id);
2240 stream << HTTPReply(200, strReply) << std::flush;
2242 catch (std::exception& e)
2244 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2247 catch (Object& objError)
2249 ErrorReply(stream, objError, id);
2251 catch (std::exception& e)
2253 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2261 Object CallRPC(const string& strMethod, const Array& params)
2263 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2264 throw runtime_error(strprintf(
2265 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2266 "If the file does not exist, create it with owner-readable-only file permissions."),
2267 GetConfigFile().c_str()));
2269 // Connect to localhost
2270 bool fUseSSL = GetBoolArg("-rpcssl");
2272 asio::io_service io_service;
2273 ssl::context context(io_service, ssl::context::sslv23);
2274 context.set_options(ssl::context::no_sslv2);
2275 SSLStream sslStream(io_service, context);
2276 SSLIOStreamDevice d(sslStream, fUseSSL);
2277 iostreams::stream<SSLIOStreamDevice> stream(d);
2278 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2279 throw runtime_error("couldn't connect to server");
2282 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2284 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2286 throw runtime_error("couldn't connect to server");
2290 // HTTP basic authentication
2291 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2292 map<string, string> mapRequestHeaders;
2293 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2296 string strRequest = JSONRPCRequest(strMethod, params, 1);
2297 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2298 stream << strPost << std::flush;
2301 map<string, string> mapHeaders;
2303 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2305 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2306 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2307 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2308 else if (strReply.empty())
2309 throw runtime_error("no response from server");
2313 if (!read_string(strReply, valReply))
2314 throw runtime_error("couldn't parse reply from server");
2315 const Object& reply = valReply.get_obj();
2317 throw runtime_error("expected reply to have result, error and id properties");
2325 template<typename T>
2326 void ConvertTo(Value& value)
2328 if (value.type() == str_type)
2330 // reinterpret string as unquoted json value
2332 if (!read_string(value.get_str(), value2))
2333 throw runtime_error("type mismatch");
2334 value = value2.get_value<T>();
2338 value = value.get_value<T>();
2342 int CommandLineRPC(int argc, char *argv[])
2349 while (argc > 1 && IsSwitchChar(argv[1][0]))
2357 throw runtime_error("too few parameters");
2358 string strMethod = argv[1];
2360 // Parameters default to strings
2362 for (int i = 2; i < argc; i++)
2363 params.push_back(argv[i]);
2364 int n = params.size();
2367 // Special case non-string parameter types
2369 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2370 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2371 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2372 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2373 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2374 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2375 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2376 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2377 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2378 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2379 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2380 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2381 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2382 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2383 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2384 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2385 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2386 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2387 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2388 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2389 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2390 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2391 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2392 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2393 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2394 if (strMethod == "sendmany" && n > 1)
2396 string s = params[1].get_str();
2398 if (!read_string(s, v) || v.type() != obj_type)
2399 throw runtime_error("type mismatch");
2400 params[1] = v.get_obj();
2402 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2405 Object reply = CallRPC(strMethod, params);
2408 const Value& result = find_value(reply, "result");
2409 const Value& error = find_value(reply, "error");
2411 if (error.type() != null_type)
2414 strPrint = "error: " + write_string(error, false);
2415 int code = find_value(error.get_obj(), "code").get_int();
2421 if (result.type() == null_type)
2423 else if (result.type() == str_type)
2424 strPrint = result.get_str();
2426 strPrint = write_string(result, true);
2429 catch (std::exception& e)
2431 strPrint = string("error: ") + e.what();
2436 PrintException(NULL, "CommandLineRPC()");
2441 #if defined(__WXMSW__) && defined(GUI)
2442 // Windows GUI apps can't print to command line,
2443 // so settle for a message box yuck
2444 MyMessageBox(strPrint, "Bitcoin", wxOK);
2446 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2456 int main(int argc, char *argv[])
2459 // Turn off microsoft heap dump noise
2460 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2461 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2463 setbuf(stdin, NULL);
2464 setbuf(stdout, NULL);
2465 setbuf(stderr, NULL);
2469 if (argc >= 2 && string(argv[1]) == "-server")
2471 printf("server ready\n");
2472 ThreadRPCServer(NULL);
2476 return CommandLineRPC(argc, argv);
2479 catch (std::exception& e) {
2480 PrintException(&e, "main()");
2482 PrintException(NULL, "main()");