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 char* format, ...)
55 int limit = sizeof(buffer);
57 va_start(arg_ptr, format);
58 int ret = _vsnprintf(buffer, limit, format, 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 CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
347 // This could be done in the same main CS as GetKeyFromKeyPool.
348 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
349 pwalletMain->SetAddressBookName(address, strAccount);
351 return address.ToString();
355 // requires cs_main, cs_mapWallet, cs_mapAddressBook locks
356 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
358 CWalletDB walletdb(pwalletMain->strWalletFile);
361 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
363 walletdb.ReadAccount(strAccount, account);
365 bool bKeyUsed = false;
367 // Check if the current key has been used
368 if (!account.vchPubKey.empty())
370 CScript scriptPubKey;
371 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
372 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
373 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
376 const CWalletTx& wtx = (*it).second;
377 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
378 if (txout.scriptPubKey == scriptPubKey)
383 // Generate a new key
384 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
386 if (pwalletMain->GetKeyPoolSize() < 1)
388 if (bKeyUsed || bForceNew)
389 throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
393 account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
394 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
395 walletdb.WriteAccount(strAccount, account);
400 return CBitcoinAddress(account.vchPubKey);
403 Value getaccountaddress(const Array& params, bool fHelp)
405 if (fHelp || params.size() != 1)
407 "getaccountaddress <account>\n"
408 "Returns the current bitcoin address for receiving payments to this account.");
410 // Parse the account first so we don't generate a key if there's an error
411 string strAccount = AccountFromValue(params[0]);
415 CRITICAL_BLOCK(cs_main)
416 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
417 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
419 ret = GetAccountAddress(strAccount).ToString();
427 Value setaccount(const Array& params, bool fHelp)
429 if (fHelp || params.size() < 1 || params.size() > 2)
431 "setaccount <bitcoinaddress> <account>\n"
432 "Sets the account associated with the given address.");
434 CBitcoinAddress address(params[0].get_str());
435 if (!address.IsValid())
436 throw JSONRPCError(-5, "Invalid bitcoin address");
440 if (params.size() > 1)
441 strAccount = AccountFromValue(params[1]);
443 // Detect when changing the account of an address that is the 'unused current key' of another account:
444 CRITICAL_BLOCK(cs_main)
445 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
446 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
448 if (pwalletMain->mapAddressBook.count(address))
450 string strOldAccount = pwalletMain->mapAddressBook[address];
451 if (address == GetAccountAddress(strOldAccount))
452 GetAccountAddress(strOldAccount, true);
455 pwalletMain->SetAddressBookName(address, strAccount);
462 Value getaccount(const Array& params, bool fHelp)
464 if (fHelp || params.size() != 1)
466 "getaccount <bitcoinaddress>\n"
467 "Returns the account associated with the given address.");
469 CBitcoinAddress address(params[0].get_str());
470 if (!address.IsValid())
471 throw JSONRPCError(-5, "Invalid bitcoin address");
474 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
476 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
477 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
478 strAccount = (*mi).second;
484 Value getaddressesbyaccount(const Array& params, bool fHelp)
486 if (fHelp || params.size() != 1)
488 "getaddressesbyaccount <account>\n"
489 "Returns the list of addresses for the given account.");
491 string strAccount = AccountFromValue(params[0]);
493 // Find all addresses that have the given account
495 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
497 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
499 const CBitcoinAddress& address = item.first;
500 const string& strName = item.second;
501 if (strName == strAccount)
502 ret.push_back(address.ToString());
508 Value settxfee(const Array& params, bool fHelp)
510 if (fHelp || params.size() < 1 || params.size() > 1)
512 "settxfee <amount>\n"
513 "<amount> is a real and is rounded to the nearest 0.00000001");
517 if (params[0].get_real() != 0.0)
518 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
520 nTransactionFee = nAmount;
524 Value sendtoaddress(const Array& params, bool fHelp)
526 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
528 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
529 "<amount> is a real and is rounded to the nearest 0.00000001\n"
530 "requires wallet passphrase to be set with walletpassphrase first");
531 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
533 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
534 "<amount> is a real and is rounded to the nearest 0.00000001");
536 CBitcoinAddress address(params[0].get_str());
537 if (!address.IsValid())
538 throw JSONRPCError(-5, "Invalid bitcoin address");
541 int64 nAmount = AmountFromValue(params[1]);
545 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
546 wtx.mapValue["comment"] = params[2].get_str();
547 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
548 wtx.mapValue["to"] = params[3].get_str();
550 CRITICAL_BLOCK(cs_main)
551 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
553 if(pwalletMain->IsLocked())
554 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
556 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
558 throw JSONRPCError(-4, strError);
561 return wtx.GetHash().GetHex();
565 Value getreceivedbyaddress(const Array& params, bool fHelp)
567 if (fHelp || params.size() < 1 || params.size() > 2)
569 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
570 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
573 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
574 CScript scriptPubKey;
575 if (!address.IsValid())
576 throw JSONRPCError(-5, "Invalid bitcoin address");
577 scriptPubKey.SetBitcoinAddress(address);
578 if (!IsMine(*pwalletMain,scriptPubKey))
581 // Minimum confirmations
583 if (params.size() > 1)
584 nMinDepth = params[1].get_int();
588 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
590 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
592 const CWalletTx& wtx = (*it).second;
593 if (wtx.IsCoinBase() || !wtx.IsFinal())
596 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
597 if (txout.scriptPubKey == scriptPubKey)
598 if (wtx.GetDepthInMainChain() >= nMinDepth)
599 nAmount += txout.nValue;
603 return ValueFromAmount(nAmount);
607 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
609 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
611 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
613 const CBitcoinAddress& address = item.first;
614 const string& strName = item.second;
615 if (strName == strAccount)
616 setAddress.insert(address);
622 Value getreceivedbyaccount(const Array& params, bool fHelp)
624 if (fHelp || params.size() < 1 || params.size() > 2)
626 "getreceivedbyaccount <account> [minconf=1]\n"
627 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
629 // Minimum confirmations
631 if (params.size() > 1)
632 nMinDepth = params[1].get_int();
634 // Get the set of pub keys that have the label
635 string strAccount = AccountFromValue(params[0]);
636 set<CBitcoinAddress> setAddress;
637 GetAccountAddresses(strAccount, setAddress);
641 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
643 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
645 const CWalletTx& wtx = (*it).second;
646 if (wtx.IsCoinBase() || !wtx.IsFinal())
649 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
651 CBitcoinAddress address;
652 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
653 if (wtx.GetDepthInMainChain() >= nMinDepth)
654 nAmount += txout.nValue;
659 return (double)nAmount / (double)COIN;
663 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
666 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
668 // Tally wallet transactions
669 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
671 const CWalletTx& wtx = (*it).second;
675 int64 nGenerated, nReceived, nSent, nFee;
676 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
678 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
679 nBalance += nReceived;
680 nBalance += nGenerated - nSent - nFee;
683 // Tally internal accounting entries
684 nBalance += walletdb.GetAccountCreditDebit(strAccount);
690 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
692 CWalletDB walletdb(pwalletMain->strWalletFile);
693 return GetAccountBalance(walletdb, strAccount, nMinDepth);
697 Value getbalance(const Array& params, bool fHelp)
699 if (fHelp || params.size() > 2)
701 "getbalance [account] [minconf=1]\n"
702 "If [account] is not specified, returns the server's total available balance.\n"
703 "If [account] is specified, returns the balance in the account.");
705 if (params.size() == 0)
706 return ValueFromAmount(pwalletMain->GetBalance());
709 if (params.size() > 1)
710 nMinDepth = params[1].get_int();
712 if (params[0].get_str() == "*") {
713 // Calculate total balance a different way from GetBalance()
714 // (GetBalance() sums up all unspent TxOuts)
715 // getbalance and getbalance '*' should always return the same number.
717 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
719 const CWalletTx& wtx = (*it).second;
723 int64 allGeneratedImmature, allGeneratedMature, allFee;
724 allGeneratedImmature = allGeneratedMature = allFee = 0;
725 string strSentAccount;
726 list<pair<CBitcoinAddress, int64> > listReceived;
727 list<pair<CBitcoinAddress, int64> > listSent;
728 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
729 if (wtx.GetDepthInMainChain() >= nMinDepth)
730 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
731 nBalance += r.second;
732 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
733 nBalance -= r.second;
735 nBalance += allGeneratedMature;
737 return ValueFromAmount(nBalance);
740 string strAccount = AccountFromValue(params[0]);
742 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
744 return ValueFromAmount(nBalance);
748 Value movecmd(const Array& params, bool fHelp)
750 if (fHelp || params.size() < 3 || params.size() > 5)
752 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
753 "Move from one account in your wallet to another.");
755 string strFrom = AccountFromValue(params[0]);
756 string strTo = AccountFromValue(params[1]);
757 int64 nAmount = AmountFromValue(params[2]);
758 if (params.size() > 3)
759 // unused parameter, used to be nMinDepth, keep type-checking it though
760 (void)params[3].get_int();
762 if (params.size() > 4)
763 strComment = params[4].get_str();
765 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
767 CWalletDB walletdb(pwalletMain->strWalletFile);
770 int64 nNow = GetAdjustedTime();
773 CAccountingEntry debit;
774 debit.strAccount = strFrom;
775 debit.nCreditDebit = -nAmount;
777 debit.strOtherAccount = strTo;
778 debit.strComment = strComment;
779 walletdb.WriteAccountingEntry(debit);
782 CAccountingEntry credit;
783 credit.strAccount = strTo;
784 credit.nCreditDebit = nAmount;
786 credit.strOtherAccount = strFrom;
787 credit.strComment = strComment;
788 walletdb.WriteAccountingEntry(credit);
790 walletdb.TxnCommit();
796 Value sendfrom(const Array& params, bool fHelp)
798 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
800 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
801 "<amount> is a real and is rounded to the nearest 0.00000001\n"
802 "requires wallet passphrase to be set with walletpassphrase first");
803 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
805 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
806 "<amount> is a real and is rounded to the nearest 0.00000001");
808 string strAccount = AccountFromValue(params[0]);
809 CBitcoinAddress address(params[1].get_str());
810 if (!address.IsValid())
811 throw JSONRPCError(-5, "Invalid bitcoin address");
812 int64 nAmount = AmountFromValue(params[2]);
814 if (params.size() > 3)
815 nMinDepth = params[3].get_int();
818 wtx.strFromAccount = strAccount;
819 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
820 wtx.mapValue["comment"] = params[4].get_str();
821 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
822 wtx.mapValue["to"] = params[5].get_str();
824 CRITICAL_BLOCK(cs_main)
825 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
826 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
828 if(pwalletMain->IsLocked())
829 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
832 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
833 if (nAmount > nBalance)
834 throw JSONRPCError(-6, "Account has insufficient funds");
837 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
839 throw JSONRPCError(-4, strError);
842 return wtx.GetHash().GetHex();
846 Value sendmany(const Array& params, bool fHelp)
848 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
850 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
851 "amounts are double-precision floating point numbers\n"
852 "requires wallet passphrase to be set with walletpassphrase first");
853 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
855 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
856 "amounts are double-precision floating point numbers");
858 string strAccount = AccountFromValue(params[0]);
859 Object sendTo = params[1].get_obj();
861 if (params.size() > 2)
862 nMinDepth = params[2].get_int();
865 wtx.strFromAccount = strAccount;
866 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
867 wtx.mapValue["comment"] = params[3].get_str();
869 set<CBitcoinAddress> setAddress;
870 vector<pair<CScript, int64> > vecSend;
872 int64 totalAmount = 0;
873 BOOST_FOREACH(const Pair& s, sendTo)
875 CBitcoinAddress address(s.name_);
876 if (!address.IsValid())
877 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
879 if (setAddress.count(address))
880 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
881 setAddress.insert(address);
883 CScript scriptPubKey;
884 scriptPubKey.SetBitcoinAddress(address);
885 int64 nAmount = AmountFromValue(s.value_);
886 totalAmount += nAmount;
888 vecSend.push_back(make_pair(scriptPubKey, nAmount));
891 CRITICAL_BLOCK(cs_main)
892 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
893 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
895 if(pwalletMain->IsLocked())
896 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
899 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
900 if (totalAmount > nBalance)
901 throw JSONRPCError(-6, "Account has insufficient funds");
904 CReserveKey keyChange(pwalletMain);
905 int64 nFeeRequired = 0;
906 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
909 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
910 throw JSONRPCError(-6, "Insufficient funds");
911 throw JSONRPCError(-4, "Transaction creation failed");
913 if (!pwalletMain->CommitTransaction(wtx, keyChange))
914 throw JSONRPCError(-4, "Transaction commit failed");
917 return wtx.GetHash().GetHex();
932 Value ListReceived(const Array& params, bool fByAccounts)
934 // Minimum confirmations
936 if (params.size() > 0)
937 nMinDepth = params[0].get_int();
939 // Whether to include empty accounts
940 bool fIncludeEmpty = false;
941 if (params.size() > 1)
942 fIncludeEmpty = params[1].get_bool();
945 map<CBitcoinAddress, tallyitem> mapTally;
946 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
948 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
950 const CWalletTx& wtx = (*it).second;
951 if (wtx.IsCoinBase() || !wtx.IsFinal())
954 int nDepth = wtx.GetDepthInMainChain();
955 if (nDepth < nMinDepth)
958 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
960 CBitcoinAddress address;
961 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
964 tallyitem& item = mapTally[address];
965 item.nAmount += txout.nValue;
966 item.nConf = min(item.nConf, nDepth);
973 map<string, tallyitem> mapAccountTally;
974 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
976 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
978 const CBitcoinAddress& address = item.first;
979 const string& strAccount = item.second;
980 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
981 if (it == mapTally.end() && !fIncludeEmpty)
986 if (it != mapTally.end())
988 nAmount = (*it).second.nAmount;
989 nConf = (*it).second.nConf;
994 tallyitem& item = mapAccountTally[strAccount];
995 item.nAmount += nAmount;
996 item.nConf = min(item.nConf, nConf);
1001 obj.push_back(Pair("address", address.ToString()));
1002 obj.push_back(Pair("account", strAccount));
1003 obj.push_back(Pair("label", strAccount)); // deprecated
1004 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1005 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1013 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1015 int64 nAmount = (*it).second.nAmount;
1016 int nConf = (*it).second.nConf;
1018 obj.push_back(Pair("account", (*it).first));
1019 obj.push_back(Pair("label", (*it).first)); // deprecated
1020 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1021 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1029 Value listreceivedbyaddress(const Array& params, bool fHelp)
1031 if (fHelp || params.size() > 2)
1032 throw runtime_error(
1033 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1034 "[minconf] is the minimum number of confirmations before payments are included.\n"
1035 "[includeempty] whether to include addresses that haven't received any payments.\n"
1036 "Returns an array of objects containing:\n"
1037 " \"address\" : receiving address\n"
1038 " \"account\" : the account of the receiving address\n"
1039 " \"amount\" : total amount received by the address\n"
1040 " \"confirmations\" : number of confirmations of the most recent transaction included");
1042 return ListReceived(params, false);
1045 Value listreceivedbyaccount(const Array& params, bool fHelp)
1047 if (fHelp || params.size() > 2)
1048 throw runtime_error(
1049 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1050 "[minconf] is the minimum number of confirmations before payments are included.\n"
1051 "[includeempty] whether to include accounts that haven't received any payments.\n"
1052 "Returns an array of objects containing:\n"
1053 " \"account\" : the account of the receiving addresses\n"
1054 " \"amount\" : total amount received by addresses with this account\n"
1055 " \"confirmations\" : number of confirmations of the most recent transaction included");
1057 return ListReceived(params, true);
1060 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1062 int64 nGeneratedImmature, nGeneratedMature, nFee;
1063 string strSentAccount;
1064 list<pair<CBitcoinAddress, int64> > listReceived;
1065 list<pair<CBitcoinAddress, int64> > listSent;
1066 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1068 bool fAllAccounts = (strAccount == string("*"));
1070 // Generated blocks assigned to account ""
1071 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1074 entry.push_back(Pair("account", string("")));
1075 if (nGeneratedImmature)
1077 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1078 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1082 entry.push_back(Pair("category", "generate"));
1083 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1086 WalletTxToJSON(wtx, entry);
1087 ret.push_back(entry);
1091 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1093 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1096 entry.push_back(Pair("account", strSentAccount));
1097 entry.push_back(Pair("address", s.first.ToString()));
1098 entry.push_back(Pair("category", "send"));
1099 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1100 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1102 WalletTxToJSON(wtx, entry);
1103 ret.push_back(entry);
1108 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1109 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1111 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1114 if (pwalletMain->mapAddressBook.count(r.first))
1115 account = pwalletMain->mapAddressBook[r.first];
1116 if (fAllAccounts || (account == strAccount))
1119 entry.push_back(Pair("account", account));
1120 entry.push_back(Pair("address", r.first.ToString()));
1121 entry.push_back(Pair("category", "receive"));
1122 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1124 WalletTxToJSON(wtx, entry);
1125 ret.push_back(entry);
1132 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1134 bool fAllAccounts = (strAccount == string("*"));
1136 if (fAllAccounts || acentry.strAccount == strAccount)
1139 entry.push_back(Pair("account", acentry.strAccount));
1140 entry.push_back(Pair("category", "move"));
1141 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1142 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1143 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1144 entry.push_back(Pair("comment", acentry.strComment));
1145 ret.push_back(entry);
1149 Value listtransactions(const Array& params, bool fHelp)
1151 if (fHelp || params.size() > 3)
1152 throw runtime_error(
1153 "listtransactions [account] [count=10] [from=0]\n"
1154 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1156 string strAccount = "*";
1157 if (params.size() > 0)
1158 strAccount = params[0].get_str();
1160 if (params.size() > 1)
1161 nCount = params[1].get_int();
1163 if (params.size() > 2)
1164 nFrom = params[2].get_int();
1167 CWalletDB walletdb(pwalletMain->strWalletFile);
1169 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1171 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1172 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1173 typedef multimap<int64, TxPair > TxItems;
1176 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1178 CWalletTx* wtx = &((*it).second);
1179 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1181 list<CAccountingEntry> acentries;
1182 walletdb.ListAccountCreditDebit(strAccount, acentries);
1183 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1185 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1188 // Now: iterate backwards until we have nCount items to return:
1189 TxItems::reverse_iterator it = txByTime.rbegin();
1190 for (std::advance(it, nFrom); it != txByTime.rend(); ++it)
1192 CWalletTx *const pwtx = (*it).second.first;
1194 ListTransactions(*pwtx, strAccount, 0, true, ret);
1195 CAccountingEntry *const pacentry = (*it).second.second;
1197 AcentryToJSON(*pacentry, strAccount, ret);
1199 if (ret.size() >= nCount) break;
1201 // ret is now newest to oldest
1204 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1205 if (ret.size() > nCount)
1207 Array::iterator last = ret.begin();
1208 std::advance(last, nCount);
1209 ret.erase(last, ret.end());
1211 std::reverse(ret.begin(), ret.end()); // oldest to newest
1216 Value listaccounts(const Array& params, bool fHelp)
1218 if (fHelp || params.size() > 1)
1219 throw runtime_error(
1220 "listaccounts [minconf=1]\n"
1221 "Returns Object that has account names as keys, account balances as values.");
1224 if (params.size() > 0)
1225 nMinDepth = params[0].get_int();
1227 map<string, int64> mapAccountBalances;
1228 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1229 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1231 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1232 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1233 mapAccountBalances[entry.second] = 0;
1236 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1238 const CWalletTx& wtx = (*it).second;
1239 int64 nGeneratedImmature, nGeneratedMature, nFee;
1240 string strSentAccount;
1241 list<pair<CBitcoinAddress, int64> > listReceived;
1242 list<pair<CBitcoinAddress, int64> > listSent;
1243 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1244 mapAccountBalances[strSentAccount] -= nFee;
1245 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1246 mapAccountBalances[strSentAccount] -= s.second;
1247 if (wtx.GetDepthInMainChain() >= nMinDepth)
1249 mapAccountBalances[""] += nGeneratedMature;
1250 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1251 if (pwalletMain->mapAddressBook.count(r.first))
1252 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1254 mapAccountBalances[""] += r.second;
1259 list<CAccountingEntry> acentries;
1260 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1261 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1262 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1265 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1266 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1271 Value gettransaction(const Array& params, bool fHelp)
1273 if (fHelp || params.size() != 1)
1274 throw runtime_error(
1275 "gettransaction <txid>\n"
1276 "Get detailed information about <txid>");
1279 hash.SetHex(params[0].get_str());
1282 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1284 if (!pwalletMain->mapWallet.count(hash))
1285 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1286 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1288 int64 nCredit = wtx.GetCredit();
1289 int64 nDebit = wtx.GetDebit();
1290 int64 nNet = nCredit - nDebit;
1291 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1293 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1295 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1297 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1300 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1301 entry.push_back(Pair("details", details));
1308 Value backupwallet(const Array& params, bool fHelp)
1310 if (fHelp || params.size() != 1)
1311 throw runtime_error(
1312 "backupwallet <destination>\n"
1313 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1315 string strDest = params[0].get_str();
1316 BackupWallet(*pwalletMain, strDest);
1322 Value keypoolrefill(const Array& params, bool fHelp)
1324 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1325 throw runtime_error(
1327 "Fills the keypool, requires wallet passphrase to be set.");
1328 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1329 throw runtime_error(
1331 "Fills the keypool.");
1333 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1335 if (pwalletMain->IsLocked())
1336 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1338 pwalletMain->TopUpKeyPool();
1341 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1342 throw JSONRPCError(-4, "Error refreshing keypool.");
1348 void ThreadTopUpKeyPool(void* parg)
1350 pwalletMain->TopUpKeyPool();
1353 void ThreadCleanWalletPassphrase(void* parg)
1355 int64 nMyWakeTime = GetTime() + *((int*)parg);
1357 if (nWalletUnlockTime == 0)
1359 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1361 nWalletUnlockTime = nMyWakeTime;
1364 while (GetTime() < nWalletUnlockTime)
1365 Sleep(GetTime() - nWalletUnlockTime);
1367 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1369 nWalletUnlockTime = 0;
1374 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1376 if (nWalletUnlockTime < nMyWakeTime)
1377 nWalletUnlockTime = nMyWakeTime;
1383 pwalletMain->Lock();
1388 Value walletpassphrase(const Array& params, bool fHelp)
1390 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1391 throw runtime_error(
1392 "walletpassphrase <passphrase> <timeout>\n"
1393 "Stores the wallet decryption key in memory for <timeout> seconds.");
1396 if (!pwalletMain->IsCrypted())
1397 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1399 if (!pwalletMain->IsLocked())
1400 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1402 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1403 string strWalletPass;
1404 strWalletPass.reserve(100);
1405 mlock(&strWalletPass[0], strWalletPass.capacity());
1406 strWalletPass = params[0].get_str();
1408 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1410 if (strWalletPass.length() > 0)
1412 if (!pwalletMain->Unlock(strWalletPass))
1414 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1415 munlock(&strWalletPass[0], strWalletPass.capacity());
1416 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1418 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1419 munlock(&strWalletPass[0], strWalletPass.capacity());
1422 throw runtime_error(
1423 "walletpassphrase <passphrase> <timeout>\n"
1424 "Stores the wallet decryption key in memory for <timeout> seconds.");
1427 CreateThread(ThreadTopUpKeyPool, NULL);
1428 int* pnSleepTime = new int(params[1].get_int());
1429 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1435 Value walletpassphrasechange(const Array& params, bool fHelp)
1437 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1438 throw runtime_error(
1439 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1440 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1443 if (!pwalletMain->IsCrypted())
1444 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1446 string strOldWalletPass;
1447 strOldWalletPass.reserve(100);
1448 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1449 strOldWalletPass = params[0].get_str();
1451 string strNewWalletPass;
1452 strNewWalletPass.reserve(100);
1453 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1454 strNewWalletPass = params[1].get_str();
1456 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1457 throw runtime_error(
1458 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1459 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1461 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1463 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1464 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1465 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1466 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1467 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1469 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1470 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1471 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1472 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1478 Value walletlock(const Array& params, bool fHelp)
1480 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1481 throw runtime_error(
1483 "Removes the wallet encryption key from memory, locking the wallet.\n"
1484 "After calling this method, you will need to call walletpassphrase again\n"
1485 "before being able to call any methods which require the wallet to be unlocked.");
1488 if (!pwalletMain->IsCrypted())
1489 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1491 pwalletMain->Lock();
1492 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1494 nWalletUnlockTime = 0;
1501 Value encryptwallet(const Array& params, bool fHelp)
1503 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1504 throw runtime_error(
1505 "encryptwallet <passphrase>\n"
1506 "Encrypts the wallet with <passphrase>.");
1509 if (pwalletMain->IsCrypted())
1510 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1512 string strWalletPass;
1513 strWalletPass.reserve(100);
1514 mlock(&strWalletPass[0], strWalletPass.capacity());
1515 strWalletPass = params[0].get_str();
1517 if (strWalletPass.length() < 1)
1518 throw runtime_error(
1519 "encryptwallet <passphrase>\n"
1520 "Encrypts the wallet with <passphrase>.");
1522 if (!pwalletMain->EncryptWallet(strWalletPass))
1524 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1525 munlock(&strWalletPass[0], strWalletPass.capacity());
1526 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1528 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1529 munlock(&strWalletPass[0], strWalletPass.capacity());
1535 Value validateaddress(const Array& params, bool fHelp)
1537 if (fHelp || params.size() != 1)
1538 throw runtime_error(
1539 "validateaddress <bitcoinaddress>\n"
1540 "Return information about <bitcoinaddress>.");
1542 CBitcoinAddress address(params[0].get_str());
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",
1745 "setlabel", // deprecated
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]); // deprecated
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()");