1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
6 #include "cryptopp/sha.h"
11 #include <boost/asio.hpp>
12 #include <boost/iostreams/concepts.hpp>
13 #include <boost/iostreams/stream.hpp>
14 #include <boost/algorithm/string.hpp>
16 #include <boost/asio/ssl.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/filesystem/fstream.hpp>
19 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #include "json/json_spirit_reader_template.h"
22 #include "json/json_spirit_writer_template.h"
23 #include "json/json_spirit_utils.h"
24 #define printf OutputDebugStringF
25 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
26 // precompiled in headers.h. The problem might be when the pch file goes over
27 // a certain size around 145MB. If we need access to json_spirit outside this
28 // file, we could use the compiled json_spirit option.
31 using namespace boost;
32 using namespace boost::asio;
33 using namespace json_spirit;
35 void ThreadRPCServer2(void* parg);
36 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
37 extern map<string, rpcfn_type> mapCallTable;
39 static int64 nWalletUnlockTime;
40 static CCriticalSection cs_nWalletUnlockTime;
43 Object JSONRPCError(int code, const string& message)
46 error.push_back(Pair("code", code));
47 error.push_back(Pair("message", message));
52 void PrintConsole(const std::string &format, ...)
55 int limit = sizeof(buffer);
57 va_start(arg_ptr, format);
58 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
60 if (ret < 0 || ret >= limit)
66 #if defined(__WXMSW__) && defined(GUI)
67 MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
69 fprintf(stdout, "%s", buffer);
74 int64 AmountFromValue(const Value& value)
76 double dAmount = value.get_real();
77 if (dAmount <= 0.0 || dAmount > 21000000.0)
78 throw JSONRPCError(-3, "Invalid amount");
79 int64 nAmount = roundint64(dAmount * COIN);
80 if (!MoneyRange(nAmount))
81 throw JSONRPCError(-3, "Invalid amount");
85 Value ValueFromAmount(int64 amount)
87 return (double)amount / (double)COIN;
90 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
92 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
93 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
94 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
95 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
96 entry.push_back(Pair(item.first, item.second));
99 string AccountFromValue(const Value& value)
101 string strAccount = value.get_str();
102 if (strAccount == "*")
103 throw JSONRPCError(-11, "Invalid account name");
110 /// Note: This interface may still be subject to change.
114 Value help(const Array& params, bool fHelp)
116 if (fHelp || params.size() > 1)
119 "List commands, or get help for a command.");
122 if (params.size() > 0)
123 strCommand = params[0].get_str();
126 set<rpcfn_type> setDone;
127 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
129 string strMethod = (*mi).first;
130 // We already filter duplicates, but these deprecated screw up the sort order
131 if (strMethod == "getamountreceived" ||
132 strMethod == "getallreceived" ||
133 (strMethod.find("label") != string::npos))
135 if (strCommand != "" && strMethod != strCommand)
140 rpcfn_type pfn = (*mi).second;
141 if (setDone.insert(pfn).second)
142 (*pfn)(params, true);
144 catch (std::exception& e)
146 // Help text is returned in an exception
147 string strHelp = string(e.what());
148 if (strCommand == "")
149 if (strHelp.find('\n') != -1)
150 strHelp = strHelp.substr(0, strHelp.find('\n'));
151 strRet += strHelp + "\n";
155 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
156 strRet = strRet.substr(0,strRet.size()-1);
161 Value stop(const Array& params, bool fHelp)
163 if (fHelp || params.size() != 0)
166 "Stop bitcoin server.");
168 // Shutdown will take long enough that the response should get back
169 CreateThread(Shutdown, NULL);
170 return "bitcoin server stopping";
174 Value getblockcount(const Array& params, bool fHelp)
176 if (fHelp || params.size() != 0)
179 "Returns the number of blocks in the longest block chain.");
185 Value getblocknumber(const Array& params, bool fHelp)
187 if (fHelp || params.size() != 0)
190 "Returns the block number of the latest block in the longest block chain.");
196 Value getconnectioncount(const Array& params, bool fHelp)
198 if (fHelp || params.size() != 0)
200 "getconnectioncount\n"
201 "Returns the number of connections to other nodes.");
203 return (int)vNodes.size();
207 double GetDifficulty()
209 // Floating point number that is a multiple of the minimum difficulty,
210 // minimum difficulty = 1.0.
212 if (pindexBest == NULL)
214 int nShift = (pindexBest->nBits >> 24) & 0xff;
217 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
233 Value getdifficulty(const Array& params, bool fHelp)
235 if (fHelp || params.size() != 0)
238 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
240 return GetDifficulty();
244 Value getgenerate(const Array& params, bool fHelp)
246 if (fHelp || params.size() != 0)
249 "Returns true or false.");
251 return (bool)fGenerateBitcoins;
255 Value setgenerate(const Array& params, bool fHelp)
257 if (fHelp || params.size() < 1 || params.size() > 2)
259 "setgenerate <generate> [genproclimit]\n"
260 "<generate> is true or false to turn generation on or off.\n"
261 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
263 bool fGenerate = true;
264 if (params.size() > 0)
265 fGenerate = params[0].get_bool();
267 if (params.size() > 1)
269 int nGenProcLimit = params[1].get_int();
270 fLimitProcessors = (nGenProcLimit != -1);
271 WriteSetting("fLimitProcessors", fLimitProcessors);
272 if (nGenProcLimit != -1)
273 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
274 if (nGenProcLimit == 0)
278 GenerateBitcoins(fGenerate, pwalletMain);
283 Value gethashespersec(const Array& params, bool fHelp)
285 if (fHelp || params.size() != 0)
288 "Returns a recent hashes per second performance measurement while generating.");
290 if (GetTimeMillis() - nHPSTimerStart > 8000)
291 return (boost::int64_t)0;
292 return (boost::int64_t)dHashesPerSec;
296 Value getinfo(const Array& params, bool fHelp)
298 if (fHelp || params.size() != 0)
301 "Returns an object containing various state info.");
304 obj.push_back(Pair("version", (int)VERSION));
305 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
306 obj.push_back(Pair("blocks", (int)nBestHeight));
307 obj.push_back(Pair("connections", (int)vNodes.size()));
308 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
309 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
310 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
311 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
312 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
313 obj.push_back(Pair("testnet", fTestNet));
314 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
315 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
316 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
317 if (pwalletMain->IsCrypted())
318 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
319 obj.push_back(Pair("errors", GetWarnings("statusbar")));
324 Value getnewaddress(const Array& params, bool fHelp)
326 if (fHelp || params.size() > 1)
328 "getnewaddress [account]\n"
329 "Returns a new bitcoin address for receiving payments. "
330 "If [account] is specified (recommended), it is added to the address book "
331 "so payments received with the address will be credited to [account].");
333 if (!pwalletMain->IsLocked())
334 pwalletMain->TopUpKeyPool();
336 if (pwalletMain->GetKeyPoolSize() < 1)
337 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
339 // Parse the account first so we don't generate a key if there's an error
341 if (params.size() > 0)
342 strAccount = AccountFromValue(params[0]);
344 // Generate a new key that is added to wallet
345 string strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
347 // This could be done in the same main CS as GetKeyFromKeyPool.
348 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
349 pwalletMain->SetAddressBookName(strAddress, strAccount);
355 // requires cs_main, cs_mapWallet, cs_mapAddressBook locks
356 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
360 CWalletDB walletdb(pwalletMain->strWalletFile);
363 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
365 walletdb.ReadAccount(strAccount, account);
367 bool bKeyUsed = false;
369 // Check if the current key has been used
370 if (!account.vchPubKey.empty())
372 CScript scriptPubKey;
373 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
374 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
375 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
378 const CWalletTx& wtx = (*it).second;
379 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
380 if (txout.scriptPubKey == scriptPubKey)
385 // Generate a new key
386 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
388 if (pwalletMain->GetKeyPoolSize() < 1)
390 if (bKeyUsed || bForceNew)
391 throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
395 account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
396 string strAddress = CBitcoinAddress(account.vchPubKey).ToString();
397 pwalletMain->SetAddressBookName(strAddress, strAccount);
398 walletdb.WriteAccount(strAccount, account);
403 return CBitcoinAddress(account.vchPubKey);
406 Value getaccountaddress(const Array& params, bool fHelp)
408 if (fHelp || params.size() != 1)
410 "getaccountaddress <account>\n"
411 "Returns the current bitcoin address for receiving payments to this account.");
413 // Parse the account first so we don't generate a key if there's an error
414 string strAccount = AccountFromValue(params[0]);
418 CRITICAL_BLOCK(cs_main)
419 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
420 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
422 ret = GetAccountAddress(strAccount).ToString();
430 Value setaccount(const Array& params, bool fHelp)
432 if (fHelp || params.size() < 1 || params.size() > 2)
434 "setaccount <bitcoinaddress> <account>\n"
435 "Sets the account associated with the given address.");
437 string strAddress = params[0].get_str();
438 CBitcoinAddress address(strAddress);
439 if (!address.IsValid())
440 throw JSONRPCError(-5, "Invalid bitcoin address");
444 if (params.size() > 1)
445 strAccount = AccountFromValue(params[1]);
447 // Detect when changing the account of an address that is the 'unused current key' of another account:
448 CRITICAL_BLOCK(cs_main)
449 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
450 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
452 if (pwalletMain->mapAddressBook.count(address))
454 string strOldAccount = pwalletMain->mapAddressBook[address];
455 if (address == GetAccountAddress(strOldAccount))
456 GetAccountAddress(strOldAccount, true);
459 pwalletMain->SetAddressBookName(strAddress, strAccount);
466 Value getaccount(const Array& params, bool fHelp)
468 if (fHelp || params.size() != 1)
470 "getaccount <bitcoinaddress>\n"
471 "Returns the account associated with the given address.");
473 string strAddress = params[0].get_str();
474 CBitcoinAddress address(strAddress);
477 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
479 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
480 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
481 strAccount = (*mi).second;
487 Value getaddressesbyaccount(const Array& params, bool fHelp)
489 if (fHelp || params.size() != 1)
491 "getaddressesbyaccount <account>\n"
492 "Returns the list of addresses for the given account.");
494 string strAccount = AccountFromValue(params[0]);
496 // Find all addresses that have the given account
498 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
500 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
502 const CBitcoinAddress& address = item.first;
503 const string& strName = item.second;
504 if (strName == strAccount)
505 ret.push_back(address.ToString());
511 Value settxfee(const Array& params, bool fHelp)
513 if (fHelp || params.size() < 1 || params.size() > 1)
515 "settxfee <amount>\n"
516 "<amount> is a real and is rounded to the nearest 0.00000001");
520 if (params[0].get_real() != 0.0)
521 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
523 nTransactionFee = nAmount;
527 Value sendtoaddress(const Array& params, bool fHelp)
529 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
531 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
532 "<amount> is a real and is rounded to the nearest 0.00000001\n"
533 "requires wallet passphrase to be set with walletpassphrase first");
534 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
536 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
537 "<amount> is a real and is rounded to the nearest 0.00000001");
539 string strAddress = params[0].get_str();
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(strAddress, 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 string strAddress = params[1].get_str();
811 int64 nAmount = AmountFromValue(params[2]);
813 if (params.size() > 3)
814 nMinDepth = params[3].get_int();
817 wtx.strFromAccount = strAccount;
818 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
819 wtx.mapValue["comment"] = params[4].get_str();
820 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
821 wtx.mapValue["to"] = params[5].get_str();
823 CRITICAL_BLOCK(cs_main)
824 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
825 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
827 if(pwalletMain->IsLocked())
828 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
831 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
832 if (nAmount > nBalance)
833 throw JSONRPCError(-6, "Account has insufficient funds");
836 string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
838 throw JSONRPCError(-4, strError);
841 return wtx.GetHash().GetHex();
845 Value sendmany(const Array& params, bool fHelp)
847 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
849 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
850 "amounts are double-precision floating point numbers\n"
851 "requires wallet passphrase to be set with walletpassphrase first");
852 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
854 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
855 "amounts are double-precision floating point numbers");
857 string strAccount = AccountFromValue(params[0]);
858 Object sendTo = params[1].get_obj();
860 if (params.size() > 2)
861 nMinDepth = params[2].get_int();
864 wtx.strFromAccount = strAccount;
865 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
866 wtx.mapValue["comment"] = params[3].get_str();
868 set<CBitcoinAddress> setAddress;
869 vector<pair<CScript, int64> > vecSend;
871 int64 totalAmount = 0;
872 BOOST_FOREACH(const Pair& s, sendTo)
874 CBitcoinAddress address(s.name_);
875 if (!address.IsValid())
876 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
878 if (setAddress.count(address))
879 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
880 setAddress.insert(address);
882 CScript scriptPubKey;
883 scriptPubKey.SetBitcoinAddress(address);
884 int64 nAmount = AmountFromValue(s.value_);
885 totalAmount += nAmount;
887 vecSend.push_back(make_pair(scriptPubKey, nAmount));
890 CRITICAL_BLOCK(cs_main)
891 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
892 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
894 if(pwalletMain->IsLocked())
895 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
898 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
899 if (totalAmount > nBalance)
900 throw JSONRPCError(-6, "Account has insufficient funds");
903 CReserveKey keyChange(pwalletMain);
904 int64 nFeeRequired = 0;
905 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
908 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
909 throw JSONRPCError(-6, "Insufficient funds");
910 throw JSONRPCError(-4, "Transaction creation failed");
912 if (!pwalletMain->CommitTransaction(wtx, keyChange))
913 throw JSONRPCError(-4, "Transaction commit failed");
916 return wtx.GetHash().GetHex();
931 Value ListReceived(const Array& params, bool fByAccounts)
933 // Minimum confirmations
935 if (params.size() > 0)
936 nMinDepth = params[0].get_int();
938 // Whether to include empty accounts
939 bool fIncludeEmpty = false;
940 if (params.size() > 1)
941 fIncludeEmpty = params[1].get_bool();
944 map<CBitcoinAddress, tallyitem> mapTally;
945 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
947 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
949 const CWalletTx& wtx = (*it).second;
950 if (wtx.IsCoinBase() || !wtx.IsFinal())
953 int nDepth = wtx.GetDepthInMainChain();
954 if (nDepth < nMinDepth)
957 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
959 CBitcoinAddress address;
960 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
963 tallyitem& item = mapTally[address];
964 item.nAmount += txout.nValue;
965 item.nConf = min(item.nConf, nDepth);
972 map<string, tallyitem> mapAccountTally;
973 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
975 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
977 const CBitcoinAddress& address = item.first;
978 const string& strAccount = item.second;
979 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
980 if (it == mapTally.end() && !fIncludeEmpty)
985 if (it != mapTally.end())
987 nAmount = (*it).second.nAmount;
988 nConf = (*it).second.nConf;
993 tallyitem& item = mapAccountTally[strAccount];
994 item.nAmount += nAmount;
995 item.nConf = min(item.nConf, nConf);
1000 obj.push_back(Pair("address", address.ToString()));
1001 obj.push_back(Pair("account", strAccount));
1002 obj.push_back(Pair("label", strAccount)); // deprecated
1003 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1004 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1012 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1014 int64 nAmount = (*it).second.nAmount;
1015 int nConf = (*it).second.nConf;
1017 obj.push_back(Pair("account", (*it).first));
1018 obj.push_back(Pair("label", (*it).first)); // deprecated
1019 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1020 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1028 Value listreceivedbyaddress(const Array& params, bool fHelp)
1030 if (fHelp || params.size() > 2)
1031 throw runtime_error(
1032 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1033 "[minconf] is the minimum number of confirmations before payments are included.\n"
1034 "[includeempty] whether to include addresses that haven't received any payments.\n"
1035 "Returns an array of objects containing:\n"
1036 " \"address\" : receiving address\n"
1037 " \"account\" : the account of the receiving address\n"
1038 " \"amount\" : total amount received by the address\n"
1039 " \"confirmations\" : number of confirmations of the most recent transaction included");
1041 return ListReceived(params, false);
1044 Value listreceivedbyaccount(const Array& params, bool fHelp)
1046 if (fHelp || params.size() > 2)
1047 throw runtime_error(
1048 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1049 "[minconf] is the minimum number of confirmations before payments are included.\n"
1050 "[includeempty] whether to include accounts that haven't received any payments.\n"
1051 "Returns an array of objects containing:\n"
1052 " \"account\" : the account of the receiving addresses\n"
1053 " \"amount\" : total amount received by addresses with this account\n"
1054 " \"confirmations\" : number of confirmations of the most recent transaction included");
1056 return ListReceived(params, true);
1059 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1061 int64 nGeneratedImmature, nGeneratedMature, nFee;
1062 string strSentAccount;
1063 list<pair<CBitcoinAddress, int64> > listReceived;
1064 list<pair<CBitcoinAddress, int64> > listSent;
1065 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1067 bool fAllAccounts = (strAccount == string("*"));
1069 // Generated blocks assigned to account ""
1070 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1073 entry.push_back(Pair("account", string("")));
1074 if (nGeneratedImmature)
1076 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1077 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1081 entry.push_back(Pair("category", "generate"));
1082 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1085 WalletTxToJSON(wtx, entry);
1086 ret.push_back(entry);
1090 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1092 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1095 entry.push_back(Pair("account", strSentAccount));
1096 entry.push_back(Pair("address", s.first.ToString()));
1097 entry.push_back(Pair("category", "send"));
1098 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1099 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1101 WalletTxToJSON(wtx, entry);
1102 ret.push_back(entry);
1107 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1108 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1110 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1113 if (pwalletMain->mapAddressBook.count(r.first))
1114 account = pwalletMain->mapAddressBook[r.first];
1115 if (fAllAccounts || (account == strAccount))
1118 entry.push_back(Pair("account", account));
1119 entry.push_back(Pair("address", r.first.ToString()));
1120 entry.push_back(Pair("category", "receive"));
1121 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1123 WalletTxToJSON(wtx, entry);
1124 ret.push_back(entry);
1131 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1133 bool fAllAccounts = (strAccount == string("*"));
1135 if (fAllAccounts || acentry.strAccount == strAccount)
1138 entry.push_back(Pair("account", acentry.strAccount));
1139 entry.push_back(Pair("category", "move"));
1140 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1141 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1142 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1143 entry.push_back(Pair("comment", acentry.strComment));
1144 ret.push_back(entry);
1148 Value listtransactions(const Array& params, bool fHelp)
1150 if (fHelp || params.size() > 3)
1151 throw runtime_error(
1152 "listtransactions [account] [count=10] [from=0]\n"
1153 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1155 string strAccount = "*";
1156 if (params.size() > 0)
1157 strAccount = params[0].get_str();
1159 if (params.size() > 1)
1160 nCount = params[1].get_int();
1162 if (params.size() > 2)
1163 nFrom = params[2].get_int();
1166 CWalletDB walletdb(pwalletMain->strWalletFile);
1168 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1170 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1171 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1172 typedef multimap<int64, TxPair > TxItems;
1175 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1177 CWalletTx* wtx = &((*it).second);
1178 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1180 list<CAccountingEntry> acentries;
1181 walletdb.ListAccountCreditDebit(strAccount, acentries);
1182 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1184 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1187 // Now: iterate backwards until we have nCount items to return:
1188 TxItems::reverse_iterator it = txByTime.rbegin();
1189 for (std::advance(it, nFrom); it != txByTime.rend(); ++it)
1191 CWalletTx *const pwtx = (*it).second.first;
1193 ListTransactions(*pwtx, strAccount, 0, true, ret);
1194 CAccountingEntry *const pacentry = (*it).second.second;
1196 AcentryToJSON(*pacentry, strAccount, ret);
1198 if (ret.size() >= nCount) break;
1200 // ret is now newest to oldest
1203 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1204 if (ret.size() > nCount)
1206 Array::iterator last = ret.begin();
1207 std::advance(last, nCount);
1208 ret.erase(last, ret.end());
1210 std::reverse(ret.begin(), ret.end()); // oldest to newest
1215 Value listaccounts(const Array& params, bool fHelp)
1217 if (fHelp || params.size() > 1)
1218 throw runtime_error(
1219 "listaccounts [minconf=1]\n"
1220 "Returns Object that has account names as keys, account balances as values.");
1223 if (params.size() > 0)
1224 nMinDepth = params[0].get_int();
1226 map<string, int64> mapAccountBalances;
1227 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1228 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1230 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1231 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1232 mapAccountBalances[entry.second] = 0;
1235 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1237 const CWalletTx& wtx = (*it).second;
1238 int64 nGeneratedImmature, nGeneratedMature, nFee;
1239 string strSentAccount;
1240 list<pair<CBitcoinAddress, int64> > listReceived;
1241 list<pair<CBitcoinAddress, int64> > listSent;
1242 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1243 mapAccountBalances[strSentAccount] -= nFee;
1244 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1245 mapAccountBalances[strSentAccount] -= s.second;
1246 if (wtx.GetDepthInMainChain() >= nMinDepth)
1248 mapAccountBalances[""] += nGeneratedMature;
1249 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1250 if (pwalletMain->mapAddressBook.count(r.first))
1251 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1253 mapAccountBalances[""] += r.second;
1258 list<CAccountingEntry> acentries;
1259 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1260 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1261 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1264 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1265 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1270 Value gettransaction(const Array& params, bool fHelp)
1272 if (fHelp || params.size() != 1)
1273 throw runtime_error(
1274 "gettransaction <txid>\n"
1275 "Get detailed information about <txid>");
1278 hash.SetHex(params[0].get_str());
1281 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1283 if (!pwalletMain->mapWallet.count(hash))
1284 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1285 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1287 int64 nCredit = wtx.GetCredit();
1288 int64 nDebit = wtx.GetDebit();
1289 int64 nNet = nCredit - nDebit;
1290 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1292 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1294 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1296 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1299 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1300 entry.push_back(Pair("details", details));
1307 Value backupwallet(const Array& params, bool fHelp)
1309 if (fHelp || params.size() != 1)
1310 throw runtime_error(
1311 "backupwallet <destination>\n"
1312 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1314 string strDest = params[0].get_str();
1315 BackupWallet(*pwalletMain, strDest);
1321 Value keypoolrefill(const Array& params, bool fHelp)
1323 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1324 throw runtime_error(
1326 "Fills the keypool, requires wallet passphrase to be set.");
1327 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1328 throw runtime_error(
1330 "Fills the keypool.");
1332 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1334 if (pwalletMain->IsLocked())
1335 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1337 pwalletMain->TopUpKeyPool();
1340 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1341 throw JSONRPCError(-4, "Error refreshing keypool.");
1347 void ThreadTopUpKeyPool(void* parg)
1349 pwalletMain->TopUpKeyPool();
1352 void ThreadCleanWalletPassphrase(void* parg)
1354 int64 nMyWakeTime = GetTime() + *((int*)parg);
1356 if (nWalletUnlockTime == 0)
1358 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1360 nWalletUnlockTime = nMyWakeTime;
1363 while (GetTime() < nWalletUnlockTime)
1364 Sleep(GetTime() - nWalletUnlockTime);
1366 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1368 nWalletUnlockTime = 0;
1373 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1375 if (nWalletUnlockTime < nMyWakeTime)
1376 nWalletUnlockTime = nMyWakeTime;
1382 pwalletMain->Lock();
1387 Value walletpassphrase(const Array& params, bool fHelp)
1389 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1390 throw runtime_error(
1391 "walletpassphrase <passphrase> <timeout>\n"
1392 "Stores the wallet decryption key in memory for <timeout> seconds.");
1395 if (!pwalletMain->IsCrypted())
1396 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1398 if (!pwalletMain->IsLocked())
1399 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1401 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1402 string strWalletPass;
1403 strWalletPass.reserve(100);
1404 mlock(&strWalletPass[0], strWalletPass.capacity());
1405 strWalletPass = params[0].get_str();
1407 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1409 if (strWalletPass.length() > 0)
1411 if (!pwalletMain->Unlock(strWalletPass))
1413 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1414 munlock(&strWalletPass[0], strWalletPass.capacity());
1415 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1417 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1418 munlock(&strWalletPass[0], strWalletPass.capacity());
1421 throw runtime_error(
1422 "walletpassphrase <passphrase> <timeout>\n"
1423 "Stores the wallet decryption key in memory for <timeout> seconds.");
1426 CreateThread(ThreadTopUpKeyPool, NULL);
1427 int* pnSleepTime = new int(params[1].get_int());
1428 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1434 Value walletpassphrasechange(const Array& params, bool fHelp)
1436 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1437 throw runtime_error(
1438 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1439 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1442 if (!pwalletMain->IsCrypted())
1443 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1445 string strOldWalletPass;
1446 strOldWalletPass.reserve(100);
1447 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1448 strOldWalletPass = params[0].get_str();
1450 string strNewWalletPass;
1451 strNewWalletPass.reserve(100);
1452 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1453 strNewWalletPass = params[1].get_str();
1455 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1456 throw runtime_error(
1457 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1458 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1460 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1462 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1463 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1464 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1465 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1466 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1468 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1469 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1470 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1471 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1477 Value walletlock(const Array& params, bool fHelp)
1479 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1480 throw runtime_error(
1482 "Removes the wallet encryption key from memory, locking the wallet.\n"
1483 "After calling this method, you will need to call walletpassphrase again\n"
1484 "before being able to call any methods which require the wallet to be unlocked.");
1487 if (!pwalletMain->IsCrypted())
1488 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1490 pwalletMain->Lock();
1491 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1493 nWalletUnlockTime = 0;
1500 Value encryptwallet(const Array& params, bool fHelp)
1502 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1503 throw runtime_error(
1504 "encryptwallet <passphrase>\n"
1505 "Encrypts the wallet with <passphrase>.");
1508 if (pwalletMain->IsCrypted())
1509 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1511 string strWalletPass;
1512 strWalletPass.reserve(100);
1513 mlock(&strWalletPass[0], strWalletPass.capacity());
1514 strWalletPass = params[0].get_str();
1516 if (strWalletPass.length() < 1)
1517 throw runtime_error(
1518 "encryptwallet <passphrase>\n"
1519 "Encrypts the wallet with <passphrase>.");
1521 if (!pwalletMain->EncryptWallet(strWalletPass))
1523 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1524 munlock(&strWalletPass[0], strWalletPass.capacity());
1525 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1527 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1528 munlock(&strWalletPass[0], strWalletPass.capacity());
1534 Value validateaddress(const Array& params, bool fHelp)
1536 if (fHelp || params.size() != 1)
1537 throw runtime_error(
1538 "validateaddress <bitcoinaddress>\n"
1539 "Return information about <bitcoinaddress>.");
1541 string strAddress = params[0].get_str();
1542 CBitcoinAddress address(strAddress);
1543 bool isValid = address.IsValid();
1546 ret.push_back(Pair("isvalid", isValid));
1549 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1550 // version of the address:
1551 string currentAddress = address.ToString();
1552 ret.push_back(Pair("address", currentAddress));
1553 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1554 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1556 if (pwalletMain->mapAddressBook.count(address))
1557 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1564 Value getwork(const Array& params, bool fHelp)
1566 if (fHelp || params.size() > 1)
1567 throw runtime_error(
1569 "If [data] is not specified, returns formatted hash data to work on:\n"
1570 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1571 " \"data\" : block data\n"
1572 " \"hash1\" : formatted hash buffer for second hash\n"
1573 " \"target\" : little endian hash target\n"
1574 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1577 throw JSONRPCError(-9, "Bitcoin is not connected!");
1579 if (IsInitialBlockDownload())
1580 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1582 static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1583 static vector<CBlock*> vNewBlock;
1584 static CReserveKey reservekey(pwalletMain);
1586 if (params.size() == 0)
1589 static unsigned int nTransactionsUpdatedLast;
1590 static CBlockIndex* pindexPrev;
1591 static int64 nStart;
1592 static CBlock* pblock;
1593 if (pindexPrev != pindexBest ||
1594 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1596 if (pindexPrev != pindexBest)
1598 // Deallocate old blocks since they're obsolete now
1599 mapNewBlock.clear();
1600 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1604 nTransactionsUpdatedLast = nTransactionsUpdated;
1605 pindexPrev = pindexBest;
1609 pblock = CreateNewBlock(reservekey);
1611 throw JSONRPCError(-7, "Out of memory");
1612 vNewBlock.push_back(pblock);
1616 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1619 // Update nExtraNonce
1620 static unsigned int nExtraNonce = 0;
1621 static int64 nPrevTime = 0;
1622 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1625 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1627 // Prebuild hash buffers
1631 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1633 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1636 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1637 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1638 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1639 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1645 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1646 if (vchData.size() != 128)
1647 throw JSONRPCError(-8, "Invalid parameter");
1648 CBlock* pdata = (CBlock*)&vchData[0];
1651 for (int i = 0; i < 128/4; i++)
1652 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1655 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1657 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1658 unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1660 pblock->nTime = pdata->nTime;
1661 pblock->nNonce = pdata->nNonce;
1662 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1663 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1665 return CheckWork(pblock, *pwalletMain, reservekey);
1683 pair<string, rpcfn_type> pCallTable[] =
1685 make_pair("help", &help),
1686 make_pair("stop", &stop),
1687 make_pair("getblockcount", &getblockcount),
1688 make_pair("getblocknumber", &getblocknumber),
1689 make_pair("getconnectioncount", &getconnectioncount),
1690 make_pair("getdifficulty", &getdifficulty),
1691 make_pair("getgenerate", &getgenerate),
1692 make_pair("setgenerate", &setgenerate),
1693 make_pair("gethashespersec", &gethashespersec),
1694 make_pair("getinfo", &getinfo),
1695 make_pair("getnewaddress", &getnewaddress),
1696 make_pair("getaccountaddress", &getaccountaddress),
1697 make_pair("setaccount", &setaccount),
1698 make_pair("setlabel", &setaccount), // deprecated
1699 make_pair("getaccount", &getaccount),
1700 make_pair("getlabel", &getaccount), // deprecated
1701 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1702 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1703 make_pair("sendtoaddress", &sendtoaddress),
1704 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1705 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1706 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1707 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1708 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1709 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1710 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1711 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1712 make_pair("backupwallet", &backupwallet),
1713 make_pair("keypoolrefill", &keypoolrefill),
1714 make_pair("walletpassphrase", &walletpassphrase),
1715 make_pair("walletpassphrasechange", &walletpassphrasechange),
1716 make_pair("walletlock", &walletlock),
1717 make_pair("encryptwallet", &encryptwallet),
1718 make_pair("validateaddress", &validateaddress),
1719 make_pair("getbalance", &getbalance),
1720 make_pair("move", &movecmd),
1721 make_pair("sendfrom", &sendfrom),
1722 make_pair("sendmany", &sendmany),
1723 make_pair("gettransaction", &gettransaction),
1724 make_pair("listtransactions", &listtransactions),
1725 make_pair("getwork", &getwork),
1726 make_pair("listaccounts", &listaccounts),
1727 make_pair("settxfee", &settxfee),
1729 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1731 string pAllowInSafeMode[] =
1737 "getconnectioncount",
1744 "getaccountaddress",
1747 "getlabel", // deprecated
1748 "getaddressesbyaccount",
1749 "getaddressesbylabel", // deprecated
1757 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1765 // This ain't Apache. We're just using HTTP header for the length field
1766 // and to be compatible with other JSON-RPC implementations.
1769 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1772 s << "POST / HTTP/1.1\r\n"
1773 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1774 << "Host: 127.0.0.1\r\n"
1775 << "Content-Type: application/json\r\n"
1776 << "Content-Length: " << strMsg.size() << "\r\n"
1777 << "Accept: application/json\r\n";
1778 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1779 s << item.first << ": " << item.second << "\r\n";
1780 s << "\r\n" << strMsg;
1785 string rfc1123Time()
1790 struct tm* now_gmt = gmtime(&now);
1791 string locale(setlocale(LC_TIME, NULL));
1792 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1793 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1794 setlocale(LC_TIME, locale.c_str());
1795 return string(buffer);
1798 static string HTTPReply(int nStatus, const string& strMsg)
1801 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1803 "Server: bitcoin-json-rpc/%s\r\n"
1804 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1805 "Content-Type: text/html\r\n"
1806 "Content-Length: 296\r\n"
1808 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1809 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1812 "<TITLE>Error</TITLE>\r\n"
1813 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1815 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1816 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1818 if (nStatus == 200) strStatus = "OK";
1819 else if (nStatus == 400) strStatus = "Bad Request";
1820 else if (nStatus == 403) strStatus = "Forbidden";
1821 else if (nStatus == 404) strStatus = "Not Found";
1822 else if (nStatus == 500) strStatus = "Internal Server Error";
1824 "HTTP/1.1 %d %s\r\n"
1826 "Connection: close\r\n"
1827 "Content-Length: %d\r\n"
1828 "Content-Type: application/json\r\n"
1829 "Server: bitcoin-json-rpc/%s\r\n"
1834 rfc1123Time().c_str(),
1836 FormatFullVersion().c_str(),
1840 int ReadHTTPStatus(std::basic_istream<char>& stream)
1843 getline(stream, str);
1844 vector<string> vWords;
1845 boost::split(vWords, str, boost::is_any_of(" "));
1846 if (vWords.size() < 2)
1848 return atoi(vWords[1].c_str());
1851 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1857 std::getline(stream, str);
1858 if (str.empty() || str == "\r")
1860 string::size_type nColon = str.find(":");
1861 if (nColon != string::npos)
1863 string strHeader = str.substr(0, nColon);
1864 boost::trim(strHeader);
1865 boost::to_lower(strHeader);
1866 string strValue = str.substr(nColon+1);
1867 boost::trim(strValue);
1868 mapHeadersRet[strHeader] = strValue;
1869 if (strHeader == "content-length")
1870 nLen = atoi(strValue.c_str());
1876 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1878 mapHeadersRet.clear();
1882 int nStatus = ReadHTTPStatus(stream);
1885 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1886 if (nLen < 0 || nLen > MAX_SIZE)
1892 vector<char> vch(nLen);
1893 stream.read(&vch[0], nLen);
1894 strMessageRet = string(vch.begin(), vch.end());
1900 string EncodeBase64(string s)
1905 b64 = BIO_new(BIO_f_base64());
1906 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1907 bmem = BIO_new(BIO_s_mem());
1908 b64 = BIO_push(b64, bmem);
1909 BIO_write(b64, s.c_str(), s.size());
1911 BIO_get_mem_ptr(b64, &bptr);
1913 string result(bptr->data, bptr->length);
1919 string DecodeBase64(string s)
1923 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1925 b64 = BIO_new(BIO_f_base64());
1926 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1927 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1928 bmem = BIO_push(b64, bmem);
1929 BIO_read(bmem, buffer, s.size());
1932 string result(buffer);
1937 bool HTTPAuthorized(map<string, string>& mapHeaders)
1939 string strAuth = mapHeaders["authorization"];
1940 if (strAuth.substr(0,6) != "Basic ")
1942 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1943 string strUserPass = DecodeBase64(strUserPass64);
1944 string::size_type nColon = strUserPass.find(":");
1945 if (nColon == string::npos)
1947 string strUser = strUserPass.substr(0, nColon);
1948 string strPassword = strUserPass.substr(nColon+1);
1949 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1953 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1954 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1955 // unspecified (HTTP errors and contents of 'error').
1957 // 1.0 spec: http://json-rpc.org/wiki/specification
1958 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1959 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1962 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1965 request.push_back(Pair("method", strMethod));
1966 request.push_back(Pair("params", params));
1967 request.push_back(Pair("id", id));
1968 return write_string(Value(request), false) + "\n";
1971 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1974 if (error.type() != null_type)
1975 reply.push_back(Pair("result", Value::null));
1977 reply.push_back(Pair("result", result));
1978 reply.push_back(Pair("error", error));
1979 reply.push_back(Pair("id", id));
1980 return write_string(Value(reply), false) + "\n";
1983 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1985 // Send error reply from json-rpc error object
1987 int code = find_value(objError, "code").get_int();
1988 if (code == -32600) nStatus = 400;
1989 else if (code == -32601) nStatus = 404;
1990 string strReply = JSONRPCReply(Value::null, objError, id);
1991 stream << HTTPReply(nStatus, strReply) << std::flush;
1994 bool ClientAllowed(const string& strAddress)
1996 if (strAddress == asio::ip::address_v4::loopback().to_string())
1998 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1999 BOOST_FOREACH(string strAllow, vAllow)
2000 if (WildcardMatch(strAddress, strAllow))
2007 // IOStream device that speaks SSL but can also speak non-SSL
2009 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2011 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2013 fUseSSL = fUseSSLIn;
2014 fNeedHandshake = fUseSSLIn;
2017 void handshake(ssl::stream_base::handshake_type role)
2019 if (!fNeedHandshake) return;
2020 fNeedHandshake = false;
2021 stream.handshake(role);
2023 std::streamsize read(char* s, std::streamsize n)
2025 handshake(ssl::stream_base::server); // HTTPS servers read first
2026 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2027 return stream.next_layer().read_some(asio::buffer(s, n));
2029 std::streamsize write(const char* s, std::streamsize n)
2031 handshake(ssl::stream_base::client); // HTTPS clients write first
2032 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2033 return asio::write(stream.next_layer(), asio::buffer(s, n));
2035 bool connect(const std::string& server, const std::string& port)
2037 ip::tcp::resolver resolver(stream.get_io_service());
2038 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2039 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2040 ip::tcp::resolver::iterator end;
2041 boost::system::error_code error = asio::error::host_not_found;
2042 while (error && endpoint_iterator != end)
2044 stream.lowest_layer().close();
2045 stream.lowest_layer().connect(*endpoint_iterator++, error);
2053 bool fNeedHandshake;
2059 void ThreadRPCServer(void* parg)
2061 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2064 vnThreadsRunning[4]++;
2065 ThreadRPCServer2(parg);
2066 vnThreadsRunning[4]--;
2068 catch (std::exception& e) {
2069 vnThreadsRunning[4]--;
2070 PrintException(&e, "ThreadRPCServer()");
2072 vnThreadsRunning[4]--;
2073 PrintException(NULL, "ThreadRPCServer()");
2075 printf("ThreadRPCServer exiting\n");
2078 void ThreadRPCServer2(void* parg)
2080 printf("ThreadRPCServer started\n");
2082 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2084 string strWhatAmI = "To use bitcoind";
2085 if (mapArgs.count("-server"))
2086 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2087 else if (mapArgs.count("-daemon"))
2088 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2090 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2091 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2093 GetConfigFile().c_str());
2094 CreateThread(Shutdown, NULL);
2098 bool fUseSSL = GetBoolArg("-rpcssl");
2099 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2101 asio::io_service io_service;
2102 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2103 ip::tcp::acceptor acceptor(io_service, endpoint);
2105 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2108 ssl::context context(io_service, ssl::context::sslv23);
2111 context.set_options(ssl::context::no_sslv2);
2112 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2113 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2114 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2115 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2116 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2117 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2118 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2119 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2121 string ciphers = GetArg("-rpcsslciphers",
2122 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2123 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2127 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2132 // Accept connection
2134 SSLStream sslStream(io_service, context);
2135 SSLIOStreamDevice d(sslStream, fUseSSL);
2136 iostreams::stream<SSLIOStreamDevice> stream(d);
2138 ip::tcp::iostream stream;
2141 ip::tcp::endpoint peer;
2142 vnThreadsRunning[4]--;
2144 acceptor.accept(sslStream.lowest_layer(), peer);
2146 acceptor.accept(*stream.rdbuf(), peer);
2148 vnThreadsRunning[4]++;
2152 // Restrict callers by IP
2153 if (!ClientAllowed(peer.address().to_string()))
2155 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2157 stream << HTTPReply(403, "") << std::flush;
2161 map<string, string> mapHeaders;
2164 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2165 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2168 printf("ThreadRPCServer ReadHTTP timeout\n");
2172 // Check authorization
2173 if (mapHeaders.count("authorization") == 0)
2175 stream << HTTPReply(401, "") << std::flush;
2178 if (!HTTPAuthorized(mapHeaders))
2180 // Deter brute-forcing short passwords
2181 if (mapArgs["-rpcpassword"].size() < 15)
2184 stream << HTTPReply(401, "") << std::flush;
2185 printf("ThreadRPCServer incorrect password attempt\n");
2189 Value id = Value::null;
2194 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2195 throw JSONRPCError(-32700, "Parse error");
2196 const Object& request = valRequest.get_obj();
2198 // Parse id now so errors from here on will have the id
2199 id = find_value(request, "id");
2202 Value valMethod = find_value(request, "method");
2203 if (valMethod.type() == null_type)
2204 throw JSONRPCError(-32600, "Missing method");
2205 if (valMethod.type() != str_type)
2206 throw JSONRPCError(-32600, "Method must be a string");
2207 string strMethod = valMethod.get_str();
2208 if (strMethod != "getwork")
2209 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2212 Value valParams = find_value(request, "params");
2214 if (valParams.type() == array_type)
2215 params = valParams.get_array();
2216 else if (valParams.type() == null_type)
2219 throw JSONRPCError(-32600, "Params must be an array");
2222 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2223 if (mi == mapCallTable.end())
2224 throw JSONRPCError(-32601, "Method not found");
2226 // Observe safe mode
2227 string strWarning = GetWarnings("rpc");
2228 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2229 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2234 Value result = (*(*mi).second)(params, false);
2237 string strReply = JSONRPCReply(result, Value::null, id);
2238 stream << HTTPReply(200, strReply) << std::flush;
2240 catch (std::exception& e)
2242 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2245 catch (Object& objError)
2247 ErrorReply(stream, objError, id);
2249 catch (std::exception& e)
2251 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2259 Object CallRPC(const string& strMethod, const Array& params)
2261 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2262 throw runtime_error(strprintf(
2263 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2264 "If the file does not exist, create it with owner-readable-only file permissions."),
2265 GetConfigFile().c_str()));
2267 // Connect to localhost
2268 bool fUseSSL = GetBoolArg("-rpcssl");
2270 asio::io_service io_service;
2271 ssl::context context(io_service, ssl::context::sslv23);
2272 context.set_options(ssl::context::no_sslv2);
2273 SSLStream sslStream(io_service, context);
2274 SSLIOStreamDevice d(sslStream, fUseSSL);
2275 iostreams::stream<SSLIOStreamDevice> stream(d);
2276 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2277 throw runtime_error("couldn't connect to server");
2280 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2282 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2284 throw runtime_error("couldn't connect to server");
2288 // HTTP basic authentication
2289 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2290 map<string, string> mapRequestHeaders;
2291 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2294 string strRequest = JSONRPCRequest(strMethod, params, 1);
2295 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2296 stream << strPost << std::flush;
2299 map<string, string> mapHeaders;
2301 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2303 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2304 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2305 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2306 else if (strReply.empty())
2307 throw runtime_error("no response from server");
2311 if (!read_string(strReply, valReply))
2312 throw runtime_error("couldn't parse reply from server");
2313 const Object& reply = valReply.get_obj();
2315 throw runtime_error("expected reply to have result, error and id properties");
2323 template<typename T>
2324 void ConvertTo(Value& value)
2326 if (value.type() == str_type)
2328 // reinterpret string as unquoted json value
2330 if (!read_string(value.get_str(), value2))
2331 throw runtime_error("type mismatch");
2332 value = value2.get_value<T>();
2336 value = value.get_value<T>();
2340 int CommandLineRPC(int argc, char *argv[])
2347 while (argc > 1 && IsSwitchChar(argv[1][0]))
2355 throw runtime_error("too few parameters");
2356 string strMethod = argv[1];
2358 // Parameters default to strings
2360 for (int i = 2; i < argc; i++)
2361 params.push_back(argv[i]);
2362 int n = params.size();
2365 // Special case non-string parameter types
2367 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2368 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2369 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2370 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2371 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2372 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2373 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2374 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2375 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2376 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]);
2377 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2378 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2379 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2380 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2381 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2382 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2383 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2384 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2385 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2386 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2387 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2388 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2389 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2390 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2391 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2392 if (strMethod == "sendmany" && n > 1)
2394 string s = params[1].get_str();
2396 if (!read_string(s, v) || v.type() != obj_type)
2397 throw runtime_error("type mismatch");
2398 params[1] = v.get_obj();
2400 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2403 Object reply = CallRPC(strMethod, params);
2406 const Value& result = find_value(reply, "result");
2407 const Value& error = find_value(reply, "error");
2409 if (error.type() != null_type)
2412 strPrint = "error: " + write_string(error, false);
2413 int code = find_value(error.get_obj(), "code").get_int();
2419 if (result.type() == null_type)
2421 else if (result.type() == str_type)
2422 strPrint = result.get_str();
2424 strPrint = write_string(result, true);
2427 catch (std::exception& e)
2429 strPrint = string("error: ") + e.what();
2434 PrintException(NULL, "CommandLineRPC()");
2439 #if defined(__WXMSW__) && defined(GUI)
2440 // Windows GUI apps can't print to command line,
2441 // so settle for a message box yuck
2442 MyMessageBox(strPrint, "Bitcoin", wxOK);
2444 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2454 int main(int argc, char *argv[])
2457 // Turn off microsoft heap dump noise
2458 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2459 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2461 setbuf(stdin, NULL);
2462 setbuf(stdout, NULL);
2463 setbuf(stderr, NULL);
2467 if (argc >= 2 && string(argv[1]) == "-server")
2469 printf("server ready\n");
2470 ThreadRPCServer(NULL);
2474 return CommandLineRPC(argc, argv);
2477 catch (std::exception& e) {
2478 PrintException(&e, "main()");
2480 PrintException(NULL, "main()");