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 string strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
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 string 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 = PubKeyToAddress(account.vchPubKey);
397 pwalletMain->SetAddressBookName(strAddress, strAccount);
398 walletdb.WriteAccount(strAccount, account);
403 strAddress = PubKeyToAddress(account.vchPubKey);
408 Value getaccountaddress(const Array& params, bool fHelp)
410 if (fHelp || params.size() != 1)
412 "getaccountaddress <account>\n"
413 "Returns the current bitcoin address for receiving payments to this account.");
415 // Parse the account first so we don't generate a key if there's an error
416 string strAccount = AccountFromValue(params[0]);
420 CRITICAL_BLOCK(cs_main)
421 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
422 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
424 ret = GetAccountAddress(strAccount);
432 Value setaccount(const Array& params, bool fHelp)
434 if (fHelp || params.size() < 1 || params.size() > 2)
436 "setaccount <bitcoinaddress> <account>\n"
437 "Sets the account associated with the given address.");
439 string strAddress = params[0].get_str();
441 bool isValid = AddressToHash160(strAddress, hash160);
443 throw JSONRPCError(-5, "Invalid bitcoin address");
447 if (params.size() > 1)
448 strAccount = AccountFromValue(params[1]);
450 // Detect when changing the account of an address that is the 'unused current key' of another account:
451 CRITICAL_BLOCK(cs_main)
452 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
453 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
455 if (pwalletMain->mapAddressBook.count(strAddress))
457 string strOldAccount = pwalletMain->mapAddressBook[strAddress];
458 if (strAddress == GetAccountAddress(strOldAccount))
459 GetAccountAddress(strOldAccount, true);
462 pwalletMain->SetAddressBookName(strAddress, strAccount);
469 Value getaccount(const Array& params, bool fHelp)
471 if (fHelp || params.size() != 1)
473 "getaccount <bitcoinaddress>\n"
474 "Returns the account associated with the given address.");
476 string strAddress = params[0].get_str();
479 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
481 map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
482 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
483 strAccount = (*mi).second;
489 Value getaddressesbyaccount(const Array& params, bool fHelp)
491 if (fHelp || params.size() != 1)
493 "getaddressesbyaccount <account>\n"
494 "Returns the list of addresses for the given account.");
496 string strAccount = AccountFromValue(params[0]);
498 // Find all addresses that have the given account
500 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
502 BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
504 const string& strAddress = item.first;
505 const string& strName = item.second;
506 if (strName == strAccount)
508 // We're only adding valid bitcoin addresses and not ip addresses
509 CScript scriptPubKey;
510 if (scriptPubKey.SetBitcoinAddress(strAddress))
511 ret.push_back(strAddress);
518 Value settxfee(const Array& params, bool fHelp)
520 if (fHelp || params.size() < 1 || params.size() > 1)
522 "settxfee <amount>\n"
523 "<amount> is a real and is rounded to the nearest 0.00000001");
527 if (params[0].get_real() != 0.0)
528 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
530 nTransactionFee = nAmount;
534 Value sendtoaddress(const Array& params, bool fHelp)
536 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
538 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
539 "<amount> is a real and is rounded to the nearest 0.00000001\n"
540 "requires wallet passphrase to be set with walletpassphrase first");
541 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
543 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
544 "<amount> is a real and is rounded to the nearest 0.00000001");
546 string strAddress = params[0].get_str();
549 int64 nAmount = AmountFromValue(params[1]);
553 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
554 wtx.mapValue["comment"] = params[2].get_str();
555 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
556 wtx.mapValue["to"] = params[3].get_str();
558 CRITICAL_BLOCK(cs_main)
559 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
561 if(pwalletMain->IsLocked())
562 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
564 string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
566 throw JSONRPCError(-4, strError);
569 return wtx.GetHash().GetHex();
573 Value getreceivedbyaddress(const Array& params, bool fHelp)
575 if (fHelp || params.size() < 1 || params.size() > 2)
577 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
578 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
581 string strAddress = params[0].get_str();
582 CScript scriptPubKey;
583 if (!scriptPubKey.SetBitcoinAddress(strAddress))
584 throw JSONRPCError(-5, "Invalid bitcoin address");
585 if (!IsMine(*pwalletMain,scriptPubKey))
588 // Minimum confirmations
590 if (params.size() > 1)
591 nMinDepth = params[1].get_int();
595 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
597 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
599 const CWalletTx& wtx = (*it).second;
600 if (wtx.IsCoinBase() || !wtx.IsFinal())
603 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
604 if (txout.scriptPubKey == scriptPubKey)
605 if (wtx.GetDepthInMainChain() >= nMinDepth)
606 nAmount += txout.nValue;
610 return ValueFromAmount(nAmount);
614 void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
616 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
618 BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
620 const string& strAddress = item.first;
621 const string& strName = item.second;
622 if (strName == strAccount)
624 // We're only counting our own valid bitcoin addresses and not ip addresses
625 CScript scriptPubKey;
626 if (scriptPubKey.SetBitcoinAddress(strAddress))
627 if (IsMine(*pwalletMain,scriptPubKey))
628 setPubKey.insert(scriptPubKey);
635 Value getreceivedbyaccount(const Array& params, bool fHelp)
637 if (fHelp || params.size() < 1 || params.size() > 2)
639 "getreceivedbyaccount <account> [minconf=1]\n"
640 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
642 // Minimum confirmations
644 if (params.size() > 1)
645 nMinDepth = params[1].get_int();
647 // Get the set of pub keys that have the label
648 string strAccount = AccountFromValue(params[0]);
649 set<CScript> setPubKey;
650 GetAccountPubKeys(strAccount, setPubKey);
654 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
656 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
658 const CWalletTx& wtx = (*it).second;
659 if (wtx.IsCoinBase() || !wtx.IsFinal())
662 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
663 if (setPubKey.count(txout.scriptPubKey))
664 if (wtx.GetDepthInMainChain() >= nMinDepth)
665 nAmount += txout.nValue;
669 return (double)nAmount / (double)COIN;
673 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
676 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
678 // Tally wallet transactions
679 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
681 const CWalletTx& wtx = (*it).second;
685 int64 nGenerated, nReceived, nSent, nFee;
686 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
688 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
689 nBalance += nReceived;
690 nBalance += nGenerated - nSent - nFee;
693 // Tally internal accounting entries
694 nBalance += walletdb.GetAccountCreditDebit(strAccount);
700 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
702 CWalletDB walletdb(pwalletMain->strWalletFile);
703 return GetAccountBalance(walletdb, strAccount, nMinDepth);
707 Value getbalance(const Array& params, bool fHelp)
709 if (fHelp || params.size() < 0 || params.size() > 2)
711 "getbalance [account] [minconf=1]\n"
712 "If [account] is not specified, returns the server's total available balance.\n"
713 "If [account] is specified, returns the balance in the account.");
715 if (params.size() == 0)
716 return ValueFromAmount(pwalletMain->GetBalance());
719 if (params.size() > 1)
720 nMinDepth = params[1].get_int();
722 if (params[0].get_str() == "*") {
723 // Calculate total balance a different way from GetBalance()
724 // (GetBalance() sums up all unspent TxOuts)
725 // getbalance and getbalance '*' should always return the same number.
727 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
729 const CWalletTx& wtx = (*it).second;
733 int64 allGeneratedImmature, allGeneratedMature, allFee;
734 allGeneratedImmature = allGeneratedMature = allFee = 0;
735 string strSentAccount;
736 list<pair<string, int64> > listReceived;
737 list<pair<string, int64> > listSent;
738 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
739 if (wtx.GetDepthInMainChain() >= nMinDepth)
740 BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
741 nBalance += r.second;
742 BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listSent)
743 nBalance -= r.second;
745 nBalance += allGeneratedMature;
747 return ValueFromAmount(nBalance);
750 string strAccount = AccountFromValue(params[0]);
752 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
754 return ValueFromAmount(nBalance);
758 Value movecmd(const Array& params, bool fHelp)
760 if (fHelp || params.size() < 3 || params.size() > 5)
762 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
763 "Move from one account in your wallet to another.");
765 string strFrom = AccountFromValue(params[0]);
766 string strTo = AccountFromValue(params[1]);
767 int64 nAmount = AmountFromValue(params[2]);
769 if (params.size() > 3)
770 nMinDepth = params[3].get_int();
772 if (params.size() > 4)
773 strComment = params[4].get_str();
775 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
777 CWalletDB walletdb(pwalletMain->strWalletFile);
780 int64 nNow = GetAdjustedTime();
783 CAccountingEntry debit;
784 debit.strAccount = strFrom;
785 debit.nCreditDebit = -nAmount;
787 debit.strOtherAccount = strTo;
788 debit.strComment = strComment;
789 walletdb.WriteAccountingEntry(debit);
792 CAccountingEntry credit;
793 credit.strAccount = strTo;
794 credit.nCreditDebit = nAmount;
796 credit.strOtherAccount = strFrom;
797 credit.strComment = strComment;
798 walletdb.WriteAccountingEntry(credit);
800 walletdb.TxnCommit();
806 Value sendfrom(const Array& params, bool fHelp)
808 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
810 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
811 "<amount> is a real and is rounded to the nearest 0.00000001\n"
812 "requires wallet passphrase to be set with walletpassphrase first");
813 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
815 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
816 "<amount> is a real and is rounded to the nearest 0.00000001");
818 string strAccount = AccountFromValue(params[0]);
819 string strAddress = params[1].get_str();
820 int64 nAmount = AmountFromValue(params[2]);
822 if (params.size() > 3)
823 nMinDepth = params[3].get_int();
826 wtx.strFromAccount = strAccount;
827 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
828 wtx.mapValue["comment"] = params[4].get_str();
829 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
830 wtx.mapValue["to"] = params[5].get_str();
832 CRITICAL_BLOCK(cs_main)
833 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
834 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
836 if(pwalletMain->IsLocked())
837 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
840 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
841 if (nAmount > nBalance)
842 throw JSONRPCError(-6, "Account has insufficient funds");
845 string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
847 throw JSONRPCError(-4, strError);
850 return wtx.GetHash().GetHex();
854 Value sendmany(const Array& params, bool fHelp)
856 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
858 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
859 "amounts are double-precision floating point numbers\n"
860 "requires wallet passphrase to be set with walletpassphrase first");
861 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
863 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
864 "amounts are double-precision floating point numbers");
866 string strAccount = AccountFromValue(params[0]);
867 Object sendTo = params[1].get_obj();
869 if (params.size() > 2)
870 nMinDepth = params[2].get_int();
873 wtx.strFromAccount = strAccount;
874 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
875 wtx.mapValue["comment"] = params[3].get_str();
877 set<string> setAddress;
878 vector<pair<CScript, int64> > vecSend;
880 int64 totalAmount = 0;
881 BOOST_FOREACH(const Pair& s, sendTo)
884 string strAddress = s.name_;
886 if (setAddress.count(strAddress))
887 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+strAddress);
888 setAddress.insert(strAddress);
890 CScript scriptPubKey;
891 if (!scriptPubKey.SetBitcoinAddress(strAddress))
892 throw JSONRPCError(-5, string("Invalid bitcoin address:")+strAddress);
893 int64 nAmount = AmountFromValue(s.value_);
894 totalAmount += nAmount;
896 vecSend.push_back(make_pair(scriptPubKey, nAmount));
899 CRITICAL_BLOCK(cs_main)
900 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
901 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
903 if(pwalletMain->IsLocked())
904 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
907 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
908 if (totalAmount > nBalance)
909 throw JSONRPCError(-6, "Account has insufficient funds");
912 CReserveKey keyChange(pwalletMain);
913 int64 nFeeRequired = 0;
914 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
917 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
918 throw JSONRPCError(-6, "Insufficient funds");
919 throw JSONRPCError(-4, "Transaction creation failed");
921 if (!pwalletMain->CommitTransaction(wtx, keyChange))
922 throw JSONRPCError(-4, "Transaction commit failed");
925 return wtx.GetHash().GetHex();
940 Value ListReceived(const Array& params, bool fByAccounts)
942 // Minimum confirmations
944 if (params.size() > 0)
945 nMinDepth = params[0].get_int();
947 // Whether to include empty accounts
948 bool fIncludeEmpty = false;
949 if (params.size() > 1)
950 fIncludeEmpty = params[1].get_bool();
953 map<uint160, tallyitem> mapTally;
954 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
956 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
958 const CWalletTx& wtx = (*it).second;
959 if (wtx.IsCoinBase() || !wtx.IsFinal())
962 int nDepth = wtx.GetDepthInMainChain();
963 if (nDepth < nMinDepth)
966 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
968 // Only counting our own bitcoin addresses and not ip addresses
969 uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
970 if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine
973 tallyitem& item = mapTally[hash160];
974 item.nAmount += txout.nValue;
975 item.nConf = min(item.nConf, nDepth);
982 map<string, tallyitem> mapAccountTally;
983 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
985 BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
987 const string& strAddress = item.first;
988 const string& strAccount = item.second;
990 if (!AddressToHash160(strAddress, hash160))
992 map<uint160, tallyitem>::iterator it = mapTally.find(hash160);
993 if (it == mapTally.end() && !fIncludeEmpty)
998 if (it != mapTally.end())
1000 nAmount = (*it).second.nAmount;
1001 nConf = (*it).second.nConf;
1006 tallyitem& item = mapAccountTally[strAccount];
1007 item.nAmount += nAmount;
1008 item.nConf = min(item.nConf, nConf);
1013 obj.push_back(Pair("address", strAddress));
1014 obj.push_back(Pair("account", strAccount));
1015 obj.push_back(Pair("label", strAccount)); // deprecated
1016 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1017 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1025 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1027 int64 nAmount = (*it).second.nAmount;
1028 int nConf = (*it).second.nConf;
1030 obj.push_back(Pair("account", (*it).first));
1031 obj.push_back(Pair("label", (*it).first)); // deprecated
1032 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1033 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1041 Value listreceivedbyaddress(const Array& params, bool fHelp)
1043 if (fHelp || params.size() > 2)
1044 throw runtime_error(
1045 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1046 "[minconf] is the minimum number of confirmations before payments are included.\n"
1047 "[includeempty] whether to include addresses that haven't received any payments.\n"
1048 "Returns an array of objects containing:\n"
1049 " \"address\" : receiving address\n"
1050 " \"account\" : the account of the receiving address\n"
1051 " \"amount\" : total amount received by the address\n"
1052 " \"confirmations\" : number of confirmations of the most recent transaction included");
1054 return ListReceived(params, false);
1057 Value listreceivedbyaccount(const Array& params, bool fHelp)
1059 if (fHelp || params.size() > 2)
1060 throw runtime_error(
1061 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1062 "[minconf] is the minimum number of confirmations before payments are included.\n"
1063 "[includeempty] whether to include accounts that haven't received any payments.\n"
1064 "Returns an array of objects containing:\n"
1065 " \"account\" : the account of the receiving addresses\n"
1066 " \"amount\" : total amount received by addresses with this account\n"
1067 " \"confirmations\" : number of confirmations of the most recent transaction included");
1069 return ListReceived(params, true);
1072 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1074 int64 nGeneratedImmature, nGeneratedMature, nFee;
1075 string strSentAccount;
1076 list<pair<string, int64> > listReceived;
1077 list<pair<string, int64> > listSent;
1078 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1080 bool fAllAccounts = (strAccount == string("*"));
1082 // Generated blocks assigned to account ""
1083 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1086 entry.push_back(Pair("account", string("")));
1087 if (nGeneratedImmature)
1089 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1090 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1094 entry.push_back(Pair("category", "generate"));
1095 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1098 WalletTxToJSON(wtx, entry);
1099 ret.push_back(entry);
1103 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1105 BOOST_FOREACH(const PAIRTYPE(string, int64)& s, listSent)
1108 entry.push_back(Pair("account", strSentAccount));
1109 entry.push_back(Pair("address", s.first));
1110 entry.push_back(Pair("category", "send"));
1111 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1112 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1114 WalletTxToJSON(wtx, entry);
1115 ret.push_back(entry);
1120 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1121 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1123 BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
1126 if (pwalletMain->mapAddressBook.count(r.first))
1127 account = pwalletMain->mapAddressBook[r.first];
1128 if (fAllAccounts || (account == strAccount))
1131 entry.push_back(Pair("account", account));
1132 entry.push_back(Pair("address", r.first));
1133 entry.push_back(Pair("category", "receive"));
1134 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1136 WalletTxToJSON(wtx, entry);
1137 ret.push_back(entry);
1144 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1146 bool fAllAccounts = (strAccount == string("*"));
1148 if (fAllAccounts || acentry.strAccount == strAccount)
1151 entry.push_back(Pair("account", acentry.strAccount));
1152 entry.push_back(Pair("category", "move"));
1153 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1154 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1155 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1156 entry.push_back(Pair("comment", acentry.strComment));
1157 ret.push_back(entry);
1161 Value listtransactions(const Array& params, bool fHelp)
1163 if (fHelp || params.size() > 3)
1164 throw runtime_error(
1165 "listtransactions [account] [count=10] [from=0]\n"
1166 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1168 string strAccount = "*";
1169 if (params.size() > 0)
1170 strAccount = params[0].get_str();
1172 if (params.size() > 1)
1173 nCount = params[1].get_int();
1175 if (params.size() > 2)
1176 nFrom = params[2].get_int();
1179 CWalletDB walletdb(pwalletMain->strWalletFile);
1181 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1183 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1184 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1185 typedef multimap<int64, TxPair > TxItems;
1188 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1190 CWalletTx* wtx = &((*it).second);
1191 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1193 list<CAccountingEntry> acentries;
1194 walletdb.ListAccountCreditDebit(strAccount, acentries);
1195 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1197 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1200 // Now: iterate backwards until we have nCount items to return:
1201 TxItems::reverse_iterator it = txByTime.rbegin();
1202 for (std::advance(it, nFrom); it != txByTime.rend(); ++it)
1204 CWalletTx *const pwtx = (*it).second.first;
1206 ListTransactions(*pwtx, strAccount, 0, true, ret);
1207 CAccountingEntry *const pacentry = (*it).second.second;
1209 AcentryToJSON(*pacentry, strAccount, ret);
1211 if (ret.size() >= nCount) break;
1213 // ret is now newest to oldest
1216 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1217 if (ret.size() > nCount)
1219 Array::iterator last = ret.begin();
1220 std::advance(last, nCount);
1221 ret.erase(last, ret.end());
1223 std::reverse(ret.begin(), ret.end()); // oldest to newest
1228 Value listaccounts(const Array& params, bool fHelp)
1230 if (fHelp || params.size() > 1)
1231 throw runtime_error(
1232 "listaccounts [minconf=1]\n"
1233 "Returns Object that has account names as keys, account balances as values.");
1236 if (params.size() > 0)
1237 nMinDepth = params[0].get_int();
1239 map<string, int64> mapAccountBalances;
1240 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1241 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1243 BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
1245 if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
1246 mapAccountBalances[entry.second] = 0;
1249 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1251 const CWalletTx& wtx = (*it).second;
1252 int64 nGeneratedImmature, nGeneratedMature, nFee;
1253 string strSentAccount;
1254 list<pair<string, int64> > listReceived;
1255 list<pair<string, int64> > listSent;
1256 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1257 mapAccountBalances[strSentAccount] -= nFee;
1258 BOOST_FOREACH(const PAIRTYPE(string, int64)& s, listSent)
1259 mapAccountBalances[strSentAccount] -= s.second;
1260 if (wtx.GetDepthInMainChain() >= nMinDepth)
1262 mapAccountBalances[""] += nGeneratedMature;
1263 BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
1264 if (pwalletMain->mapAddressBook.count(r.first))
1265 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1267 mapAccountBalances[""] += r.second;
1272 list<CAccountingEntry> acentries;
1273 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1274 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1275 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1278 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1279 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1284 Value gettransaction(const Array& params, bool fHelp)
1286 if (fHelp || params.size() != 1)
1287 throw runtime_error(
1288 "gettransaction <txid>\n"
1289 "Get detailed information about <txid>");
1292 hash.SetHex(params[0].get_str());
1295 CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1297 if (!pwalletMain->mapWallet.count(hash))
1298 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1299 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1301 int64 nCredit = wtx.GetCredit();
1302 int64 nDebit = wtx.GetDebit();
1303 int64 nNet = nCredit - nDebit;
1304 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1306 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1308 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1310 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1313 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1314 entry.push_back(Pair("details", details));
1321 Value backupwallet(const Array& params, bool fHelp)
1323 if (fHelp || params.size() != 1)
1324 throw runtime_error(
1325 "backupwallet <destination>\n"
1326 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1328 string strDest = params[0].get_str();
1329 BackupWallet(*pwalletMain, strDest);
1335 Value keypoolrefill(const Array& params, bool fHelp)
1337 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1338 throw runtime_error(
1340 "Fills the keypool, requires wallet passphrase to be set.");
1341 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1342 throw runtime_error(
1344 "Fills the keypool.");
1346 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1348 if (pwalletMain->IsLocked())
1349 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1351 pwalletMain->TopUpKeyPool();
1354 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1355 throw JSONRPCError(-4, "Error refreshing keypool.");
1361 void ThreadTopUpKeyPool(void* parg)
1363 pwalletMain->TopUpKeyPool();
1366 void ThreadCleanWalletPassphrase(void* parg)
1368 int64 nMyWakeTime = GetTime() + *((int*)parg);
1370 if (nWalletUnlockTime == 0)
1372 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1374 nWalletUnlockTime = nMyWakeTime;
1377 while (GetTime() < nWalletUnlockTime)
1378 Sleep(GetTime() - nWalletUnlockTime);
1380 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1382 nWalletUnlockTime = 0;
1387 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1389 if (nWalletUnlockTime < nMyWakeTime)
1390 nWalletUnlockTime = nMyWakeTime;
1396 pwalletMain->Lock();
1401 Value walletpassphrase(const Array& params, bool fHelp)
1403 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1404 throw runtime_error(
1405 "walletpassphrase <passphrase> <timeout>\n"
1406 "Stores the wallet decryption key in memory for <timeout> seconds.");
1409 if (!pwalletMain->IsCrypted())
1410 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1412 if (!pwalletMain->IsLocked())
1413 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1415 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1416 string strWalletPass;
1417 strWalletPass.reserve(100);
1418 mlock(&strWalletPass[0], strWalletPass.capacity());
1419 strWalletPass = params[0].get_str();
1421 CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1423 if (strWalletPass.length() > 0)
1425 if (!pwalletMain->Unlock(strWalletPass))
1427 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1428 munlock(&strWalletPass[0], strWalletPass.capacity());
1429 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1431 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1432 munlock(&strWalletPass[0], strWalletPass.capacity());
1435 throw runtime_error(
1436 "walletpassphrase <passphrase> <timeout>\n"
1437 "Stores the wallet decryption key in memory for <timeout> seconds.");
1440 CreateThread(ThreadTopUpKeyPool, NULL);
1441 int* pnSleepTime = new int(params[1].get_int());
1442 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1448 Value walletpassphrasechange(const Array& params, bool fHelp)
1450 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1451 throw runtime_error(
1452 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1453 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1456 if (!pwalletMain->IsCrypted())
1457 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1459 string strOldWalletPass;
1460 strOldWalletPass.reserve(100);
1461 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1462 strOldWalletPass = params[0].get_str();
1464 string strNewWalletPass;
1465 strNewWalletPass.reserve(100);
1466 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1467 strNewWalletPass = params[1].get_str();
1469 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1470 throw runtime_error(
1471 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1472 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1474 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1476 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1477 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1478 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1479 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1480 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1482 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1483 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1484 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1485 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1491 Value walletlock(const Array& params, bool fHelp)
1493 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1494 throw runtime_error(
1496 "Removes the wallet encryption key from memory, locking the wallet.\n"
1497 "After calling this method, you will need to call walletpassphrase again\n"
1498 "before being able to call any methods which require the wallet to be unlocked.");
1501 if (!pwalletMain->IsCrypted())
1502 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1504 pwalletMain->Lock();
1505 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1507 nWalletUnlockTime = 0;
1514 Value encryptwallet(const Array& params, bool fHelp)
1516 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1517 throw runtime_error(
1518 "encryptwallet <passphrase>\n"
1519 "Encrypts the wallet with <passphrase>.");
1522 if (pwalletMain->IsCrypted())
1523 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1525 string strWalletPass;
1526 strWalletPass.reserve(100);
1527 mlock(&strWalletPass[0], strWalletPass.capacity());
1528 strWalletPass = params[0].get_str();
1530 if (strWalletPass.length() < 1)
1531 throw runtime_error(
1532 "encryptwallet <passphrase>\n"
1533 "Encrypts the wallet with <passphrase>.");
1535 if (!pwalletMain->EncryptWallet(strWalletPass))
1537 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1538 munlock(&strWalletPass[0], strWalletPass.capacity());
1539 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1541 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1542 munlock(&strWalletPass[0], strWalletPass.capacity());
1548 Value validateaddress(const Array& params, bool fHelp)
1550 if (fHelp || params.size() != 1)
1551 throw runtime_error(
1552 "validateaddress <bitcoinaddress>\n"
1553 "Return information about <bitcoinaddress>.");
1555 string strAddress = params[0].get_str();
1557 bool isValid = AddressToHash160(strAddress, hash160);
1560 ret.push_back(Pair("isvalid", isValid));
1563 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1564 // version of the address:
1565 string currentAddress = Hash160ToAddress(hash160);
1566 ret.push_back(Pair("address", currentAddress));
1567 ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
1568 CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1570 if (pwalletMain->mapAddressBook.count(currentAddress))
1571 ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
1578 Value getwork(const Array& params, bool fHelp)
1580 if (fHelp || params.size() > 1)
1581 throw runtime_error(
1583 "If [data] is not specified, returns formatted hash data to work on:\n"
1584 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1585 " \"data\" : block data\n"
1586 " \"hash1\" : formatted hash buffer for second hash\n"
1587 " \"target\" : little endian hash target\n"
1588 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1591 throw JSONRPCError(-9, "Bitcoin is not connected!");
1593 if (IsInitialBlockDownload())
1594 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1596 static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1597 static vector<CBlock*> vNewBlock;
1598 static CReserveKey reservekey(pwalletMain);
1600 if (params.size() == 0)
1603 static unsigned int nTransactionsUpdatedLast;
1604 static CBlockIndex* pindexPrev;
1605 static int64 nStart;
1606 static CBlock* pblock;
1607 if (pindexPrev != pindexBest ||
1608 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1610 if (pindexPrev != pindexBest)
1612 // Deallocate old blocks since they're obsolete now
1613 mapNewBlock.clear();
1614 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1618 nTransactionsUpdatedLast = nTransactionsUpdated;
1619 pindexPrev = pindexBest;
1623 pblock = CreateNewBlock(reservekey);
1625 throw JSONRPCError(-7, "Out of memory");
1626 vNewBlock.push_back(pblock);
1630 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1633 // Update nExtraNonce
1634 static unsigned int nExtraNonce = 0;
1635 static int64 nPrevTime = 0;
1636 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1639 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1641 // Prebuild hash buffers
1645 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1647 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1650 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1651 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1652 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1653 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1659 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1660 if (vchData.size() != 128)
1661 throw JSONRPCError(-8, "Invalid parameter");
1662 CBlock* pdata = (CBlock*)&vchData[0];
1665 for (int i = 0; i < 128/4; i++)
1666 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1669 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1671 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1672 unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1674 pblock->nTime = pdata->nTime;
1675 pblock->nNonce = pdata->nNonce;
1676 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1677 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1679 return CheckWork(pblock, *pwalletMain, reservekey);
1697 pair<string, rpcfn_type> pCallTable[] =
1699 make_pair("help", &help),
1700 make_pair("stop", &stop),
1701 make_pair("getblockcount", &getblockcount),
1702 make_pair("getblocknumber", &getblocknumber),
1703 make_pair("getconnectioncount", &getconnectioncount),
1704 make_pair("getdifficulty", &getdifficulty),
1705 make_pair("getgenerate", &getgenerate),
1706 make_pair("setgenerate", &setgenerate),
1707 make_pair("gethashespersec", &gethashespersec),
1708 make_pair("getinfo", &getinfo),
1709 make_pair("getnewaddress", &getnewaddress),
1710 make_pair("getaccountaddress", &getaccountaddress),
1711 make_pair("setaccount", &setaccount),
1712 make_pair("setlabel", &setaccount), // deprecated
1713 make_pair("getaccount", &getaccount),
1714 make_pair("getlabel", &getaccount), // deprecated
1715 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1716 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1717 make_pair("sendtoaddress", &sendtoaddress),
1718 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1719 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1720 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1721 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1722 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1723 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1724 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1725 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1726 make_pair("backupwallet", &backupwallet),
1727 make_pair("keypoolrefill", &keypoolrefill),
1728 make_pair("walletpassphrase", &walletpassphrase),
1729 make_pair("walletpassphrasechange", &walletpassphrasechange),
1730 make_pair("walletlock", &walletlock),
1731 make_pair("encryptwallet", &encryptwallet),
1732 make_pair("validateaddress", &validateaddress),
1733 make_pair("getbalance", &getbalance),
1734 make_pair("move", &movecmd),
1735 make_pair("sendfrom", &sendfrom),
1736 make_pair("sendmany", &sendmany),
1737 make_pair("gettransaction", &gettransaction),
1738 make_pair("listtransactions", &listtransactions),
1739 make_pair("getwork", &getwork),
1740 make_pair("listaccounts", &listaccounts),
1741 make_pair("settxfee", &settxfee),
1743 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1745 string pAllowInSafeMode[] =
1751 "getconnectioncount",
1758 "getaccountaddress",
1761 "getlabel", // deprecated
1762 "getaddressesbyaccount",
1763 "getaddressesbylabel", // deprecated
1771 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1779 // This ain't Apache. We're just using HTTP header for the length field
1780 // and to be compatible with other JSON-RPC implementations.
1783 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1786 s << "POST / HTTP/1.1\r\n"
1787 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1788 << "Host: 127.0.0.1\r\n"
1789 << "Content-Type: application/json\r\n"
1790 << "Content-Length: " << strMsg.size() << "\r\n"
1791 << "Accept: application/json\r\n";
1792 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1793 s << item.first << ": " << item.second << "\r\n";
1794 s << "\r\n" << strMsg;
1799 string rfc1123Time()
1804 struct tm* now_gmt = gmtime(&now);
1805 string locale(setlocale(LC_TIME, NULL));
1806 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1807 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1808 setlocale(LC_TIME, locale.c_str());
1809 return string(buffer);
1812 static string HTTPReply(int nStatus, const string& strMsg)
1815 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1817 "Server: bitcoin-json-rpc/%s\r\n"
1818 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1819 "Content-Type: text/html\r\n"
1820 "Content-Length: 296\r\n"
1822 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1823 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1826 "<TITLE>Error</TITLE>\r\n"
1827 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1829 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1830 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1832 if (nStatus == 200) strStatus = "OK";
1833 else if (nStatus == 400) strStatus = "Bad Request";
1834 else if (nStatus == 403) strStatus = "Forbidden";
1835 else if (nStatus == 404) strStatus = "Not Found";
1836 else if (nStatus == 500) strStatus = "Internal Server Error";
1838 "HTTP/1.1 %d %s\r\n"
1840 "Connection: close\r\n"
1841 "Content-Length: %d\r\n"
1842 "Content-Type: application/json\r\n"
1843 "Server: bitcoin-json-rpc/%s\r\n"
1848 rfc1123Time().c_str(),
1850 FormatFullVersion().c_str(),
1854 int ReadHTTPStatus(std::basic_istream<char>& stream)
1857 getline(stream, str);
1858 vector<string> vWords;
1859 boost::split(vWords, str, boost::is_any_of(" "));
1860 if (vWords.size() < 2)
1862 return atoi(vWords[1].c_str());
1865 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1871 std::getline(stream, str);
1872 if (str.empty() || str == "\r")
1874 string::size_type nColon = str.find(":");
1875 if (nColon != string::npos)
1877 string strHeader = str.substr(0, nColon);
1878 boost::trim(strHeader);
1879 boost::to_lower(strHeader);
1880 string strValue = str.substr(nColon+1);
1881 boost::trim(strValue);
1882 mapHeadersRet[strHeader] = strValue;
1883 if (strHeader == "content-length")
1884 nLen = atoi(strValue.c_str());
1890 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1892 mapHeadersRet.clear();
1896 int nStatus = ReadHTTPStatus(stream);
1899 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1900 if (nLen < 0 || nLen > MAX_SIZE)
1906 vector<char> vch(nLen);
1907 stream.read(&vch[0], nLen);
1908 strMessageRet = string(vch.begin(), vch.end());
1914 string EncodeBase64(string s)
1919 b64 = BIO_new(BIO_f_base64());
1920 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1921 bmem = BIO_new(BIO_s_mem());
1922 b64 = BIO_push(b64, bmem);
1923 BIO_write(b64, s.c_str(), s.size());
1925 BIO_get_mem_ptr(b64, &bptr);
1927 string result(bptr->data, bptr->length);
1933 string DecodeBase64(string s)
1937 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1939 b64 = BIO_new(BIO_f_base64());
1940 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1941 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1942 bmem = BIO_push(b64, bmem);
1943 BIO_read(bmem, buffer, s.size());
1946 string result(buffer);
1951 bool HTTPAuthorized(map<string, string>& mapHeaders)
1953 string strAuth = mapHeaders["authorization"];
1954 if (strAuth.substr(0,6) != "Basic ")
1956 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1957 string strUserPass = DecodeBase64(strUserPass64);
1958 string::size_type nColon = strUserPass.find(":");
1959 if (nColon == string::npos)
1961 string strUser = strUserPass.substr(0, nColon);
1962 string strPassword = strUserPass.substr(nColon+1);
1963 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1967 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1968 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1969 // unspecified (HTTP errors and contents of 'error').
1971 // 1.0 spec: http://json-rpc.org/wiki/specification
1972 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1973 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1976 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1979 request.push_back(Pair("method", strMethod));
1980 request.push_back(Pair("params", params));
1981 request.push_back(Pair("id", id));
1982 return write_string(Value(request), false) + "\n";
1985 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1988 if (error.type() != null_type)
1989 reply.push_back(Pair("result", Value::null));
1991 reply.push_back(Pair("result", result));
1992 reply.push_back(Pair("error", error));
1993 reply.push_back(Pair("id", id));
1994 return write_string(Value(reply), false) + "\n";
1997 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1999 // Send error reply from json-rpc error object
2001 int code = find_value(objError, "code").get_int();
2002 if (code == -32600) nStatus = 400;
2003 else if (code == -32601) nStatus = 404;
2004 string strReply = JSONRPCReply(Value::null, objError, id);
2005 stream << HTTPReply(nStatus, strReply) << std::flush;
2008 bool ClientAllowed(const string& strAddress)
2010 if (strAddress == asio::ip::address_v4::loopback().to_string())
2012 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2013 BOOST_FOREACH(string strAllow, vAllow)
2014 if (WildcardMatch(strAddress, strAllow))
2021 // IOStream device that speaks SSL but can also speak non-SSL
2023 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2025 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2027 fUseSSL = fUseSSLIn;
2028 fNeedHandshake = fUseSSLIn;
2031 void handshake(ssl::stream_base::handshake_type role)
2033 if (!fNeedHandshake) return;
2034 fNeedHandshake = false;
2035 stream.handshake(role);
2037 std::streamsize read(char* s, std::streamsize n)
2039 handshake(ssl::stream_base::server); // HTTPS servers read first
2040 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2041 return stream.next_layer().read_some(asio::buffer(s, n));
2043 std::streamsize write(const char* s, std::streamsize n)
2045 handshake(ssl::stream_base::client); // HTTPS clients write first
2046 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2047 return asio::write(stream.next_layer(), asio::buffer(s, n));
2049 bool connect(const std::string& server, const std::string& port)
2051 ip::tcp::resolver resolver(stream.get_io_service());
2052 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2053 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2054 ip::tcp::resolver::iterator end;
2055 boost::system::error_code error = asio::error::host_not_found;
2056 while (error && endpoint_iterator != end)
2058 stream.lowest_layer().close();
2059 stream.lowest_layer().connect(*endpoint_iterator++, error);
2067 bool fNeedHandshake;
2073 void ThreadRPCServer(void* parg)
2075 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2078 vnThreadsRunning[4]++;
2079 ThreadRPCServer2(parg);
2080 vnThreadsRunning[4]--;
2082 catch (std::exception& e) {
2083 vnThreadsRunning[4]--;
2084 PrintException(&e, "ThreadRPCServer()");
2086 vnThreadsRunning[4]--;
2087 PrintException(NULL, "ThreadRPCServer()");
2089 printf("ThreadRPCServer exiting\n");
2092 void ThreadRPCServer2(void* parg)
2094 printf("ThreadRPCServer started\n");
2096 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2098 string strWhatAmI = "To use bitcoind";
2099 if (mapArgs.count("-server"))
2100 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2101 else if (mapArgs.count("-daemon"))
2102 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2104 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2105 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2107 GetConfigFile().c_str());
2108 CreateThread(Shutdown, NULL);
2112 bool fUseSSL = GetBoolArg("-rpcssl");
2113 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2115 asio::io_service io_service;
2116 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2117 ip::tcp::acceptor acceptor(io_service, endpoint);
2119 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2122 ssl::context context(io_service, ssl::context::sslv23);
2125 context.set_options(ssl::context::no_sslv2);
2126 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2127 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2128 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2129 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2130 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2131 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2132 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2133 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2135 string ciphers = GetArg("-rpcsslciphers",
2136 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2137 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2141 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2146 // Accept connection
2148 SSLStream sslStream(io_service, context);
2149 SSLIOStreamDevice d(sslStream, fUseSSL);
2150 iostreams::stream<SSLIOStreamDevice> stream(d);
2152 ip::tcp::iostream stream;
2155 ip::tcp::endpoint peer;
2156 vnThreadsRunning[4]--;
2158 acceptor.accept(sslStream.lowest_layer(), peer);
2160 acceptor.accept(*stream.rdbuf(), peer);
2162 vnThreadsRunning[4]++;
2166 // Restrict callers by IP
2167 if (!ClientAllowed(peer.address().to_string()))
2169 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2171 stream << HTTPReply(403, "") << std::flush;
2175 map<string, string> mapHeaders;
2178 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2179 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2182 printf("ThreadRPCServer ReadHTTP timeout\n");
2186 // Check authorization
2187 if (mapHeaders.count("authorization") == 0)
2189 stream << HTTPReply(401, "") << std::flush;
2192 if (!HTTPAuthorized(mapHeaders))
2194 // Deter brute-forcing short passwords
2195 if (mapArgs["-rpcpassword"].size() < 15)
2198 stream << HTTPReply(401, "") << std::flush;
2199 printf("ThreadRPCServer incorrect password attempt\n");
2203 Value id = Value::null;
2208 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2209 throw JSONRPCError(-32700, "Parse error");
2210 const Object& request = valRequest.get_obj();
2212 // Parse id now so errors from here on will have the id
2213 id = find_value(request, "id");
2216 Value valMethod = find_value(request, "method");
2217 if (valMethod.type() == null_type)
2218 throw JSONRPCError(-32600, "Missing method");
2219 if (valMethod.type() != str_type)
2220 throw JSONRPCError(-32600, "Method must be a string");
2221 string strMethod = valMethod.get_str();
2222 if (strMethod != "getwork")
2223 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2226 Value valParams = find_value(request, "params");
2228 if (valParams.type() == array_type)
2229 params = valParams.get_array();
2230 else if (valParams.type() == null_type)
2233 throw JSONRPCError(-32600, "Params must be an array");
2236 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2237 if (mi == mapCallTable.end())
2238 throw JSONRPCError(-32601, "Method not found");
2240 // Observe safe mode
2241 string strWarning = GetWarnings("rpc");
2242 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2243 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2248 Value result = (*(*mi).second)(params, false);
2251 string strReply = JSONRPCReply(result, Value::null, id);
2252 stream << HTTPReply(200, strReply) << std::flush;
2254 catch (std::exception& e)
2256 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2259 catch (Object& objError)
2261 ErrorReply(stream, objError, id);
2263 catch (std::exception& e)
2265 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2273 Object CallRPC(const string& strMethod, const Array& params)
2275 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2276 throw runtime_error(strprintf(
2277 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2278 "If the file does not exist, create it with owner-readable-only file permissions."),
2279 GetConfigFile().c_str()));
2281 // Connect to localhost
2282 bool fUseSSL = GetBoolArg("-rpcssl");
2284 asio::io_service io_service;
2285 ssl::context context(io_service, ssl::context::sslv23);
2286 context.set_options(ssl::context::no_sslv2);
2287 SSLStream sslStream(io_service, context);
2288 SSLIOStreamDevice d(sslStream, fUseSSL);
2289 iostreams::stream<SSLIOStreamDevice> stream(d);
2290 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2291 throw runtime_error("couldn't connect to server");
2294 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2296 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2298 throw runtime_error("couldn't connect to server");
2302 // HTTP basic authentication
2303 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2304 map<string, string> mapRequestHeaders;
2305 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2308 string strRequest = JSONRPCRequest(strMethod, params, 1);
2309 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2310 stream << strPost << std::flush;
2313 map<string, string> mapHeaders;
2315 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2317 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2318 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2319 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2320 else if (strReply.empty())
2321 throw runtime_error("no response from server");
2325 if (!read_string(strReply, valReply))
2326 throw runtime_error("couldn't parse reply from server");
2327 const Object& reply = valReply.get_obj();
2329 throw runtime_error("expected reply to have result, error and id properties");
2337 template<typename T>
2338 void ConvertTo(Value& value)
2340 if (value.type() == str_type)
2342 // reinterpret string as unquoted json value
2344 if (!read_string(value.get_str(), value2))
2345 throw runtime_error("type mismatch");
2346 value = value2.get_value<T>();
2350 value = value.get_value<T>();
2354 int CommandLineRPC(int argc, char *argv[])
2361 while (argc > 1 && IsSwitchChar(argv[1][0]))
2369 throw runtime_error("too few parameters");
2370 string strMethod = argv[1];
2372 // Parameters default to strings
2374 for (int i = 2; i < argc; i++)
2375 params.push_back(argv[i]);
2376 int n = params.size();
2379 // Special case non-string parameter types
2381 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2382 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2383 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2384 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2385 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2386 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2387 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2388 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2389 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2390 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]);
2391 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2392 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2393 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2394 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2395 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2396 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2397 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2398 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2399 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2400 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2401 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2402 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2403 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2404 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2405 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2406 if (strMethod == "sendmany" && n > 1)
2408 string s = params[1].get_str();
2410 if (!read_string(s, v) || v.type() != obj_type)
2411 throw runtime_error("type mismatch");
2412 params[1] = v.get_obj();
2414 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2417 Object reply = CallRPC(strMethod, params);
2420 const Value& result = find_value(reply, "result");
2421 const Value& error = find_value(reply, "error");
2422 const Value& id = find_value(reply, "id");
2424 if (error.type() != null_type)
2427 strPrint = "error: " + write_string(error, false);
2428 int code = find_value(error.get_obj(), "code").get_int();
2434 if (result.type() == null_type)
2436 else if (result.type() == str_type)
2437 strPrint = result.get_str();
2439 strPrint = write_string(result, true);
2442 catch (std::exception& e)
2444 strPrint = string("error: ") + e.what();
2449 PrintException(NULL, "CommandLineRPC()");
2454 #if defined(__WXMSW__) && defined(GUI)
2455 // Windows GUI apps can't print to command line,
2456 // so settle for a message box yuck
2457 MyMessageBox(strPrint, "Bitcoin", wxOK);
2459 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2469 int main(int argc, char *argv[])
2472 // Turn off microsoft heap dump noise
2473 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2474 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2476 setbuf(stdin, NULL);
2477 setbuf(stdout, NULL);
2478 setbuf(stderr, NULL);
2482 if (argc >= 2 && string(argv[1]) == "-server")
2484 printf("server ready\n");
2485 ThreadRPCServer(NULL);
2489 return CommandLineRPC(argc, argv);
2492 catch (std::exception& e) {
2493 PrintException(&e, "main()");
2495 PrintException(NULL, "main()");