1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
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 std::string strRPCUserColonPass;
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
45 Object JSONRPCError(int code, const string& message)
48 error.push_back(Pair("code", code));
49 error.push_back(Pair("message", message));
54 void PrintConsole(const std::string &format, ...)
57 int limit = sizeof(buffer);
59 va_start(arg_ptr, format);
60 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
62 if (ret < 0 || ret >= limit)
68 fprintf(stdout, "%s", buffer);
72 int64 AmountFromValue(const Value& value)
74 double dAmount = value.get_real();
75 if (dAmount <= 0.0 || dAmount > 21000000.0)
76 throw JSONRPCError(-3, "Invalid amount");
77 int64 nAmount = roundint64(dAmount * COIN);
78 if (!MoneyRange(nAmount))
79 throw JSONRPCError(-3, "Invalid amount");
83 Value ValueFromAmount(int64 amount)
85 return (double)amount / (double)COIN;
88 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
90 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
91 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
92 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
93 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
94 entry.push_back(Pair(item.first, item.second));
97 string AccountFromValue(const Value& value)
99 string strAccount = value.get_str();
100 if (strAccount == "*")
101 throw JSONRPCError(-11, "Invalid account name");
108 /// Note: This interface may still be subject to change.
112 Value help(const Array& params, bool fHelp)
114 if (fHelp || params.size() > 1)
117 "List commands, or get help for a command.");
120 if (params.size() > 0)
121 strCommand = params[0].get_str();
124 set<rpcfn_type> setDone;
125 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
127 string strMethod = (*mi).first;
128 // We already filter duplicates, but these deprecated screw up the sort order
129 if (strMethod == "getamountreceived" ||
130 strMethod == "getallreceived" ||
131 strMethod == "getblocknumber" || // deprecated
132 (strMethod.find("label") != string::npos))
134 if (strCommand != "" && strMethod != strCommand)
139 rpcfn_type pfn = (*mi).second;
140 if (setDone.insert(pfn).second)
141 (*pfn)(params, true);
143 catch (std::exception& e)
145 // Help text is returned in an exception
146 string strHelp = string(e.what());
147 if (strCommand == "")
148 if (strHelp.find('\n') != string::npos)
149 strHelp = strHelp.substr(0, strHelp.find('\n'));
150 strRet += strHelp + "\n";
154 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
155 strRet = strRet.substr(0,strRet.size()-1);
160 Value stop(const Array& params, bool fHelp)
162 if (fHelp || params.size() != 0)
165 "Stop bitcoin server.");
167 // Shutdown will take long enough that the response should get back
168 CreateThread(Shutdown, NULL);
169 return "bitcoin server stopping";
171 throw runtime_error("NYI: cannot shut down GUI with RPC command");
176 Value getblockcount(const Array& params, bool fHelp)
178 if (fHelp || params.size() != 0)
181 "Returns the number of blocks in the longest block chain.");
188 Value getblocknumber(const Array& params, bool fHelp)
190 if (fHelp || params.size() != 0)
193 "Deprecated. Use getblockcount.");
199 Value getconnectioncount(const Array& params, bool fHelp)
201 if (fHelp || params.size() != 0)
203 "getconnectioncount\n"
204 "Returns the number of connections to other nodes.");
206 return (int)vNodes.size();
210 double GetDifficulty()
212 // Floating point number that is a multiple of the minimum difficulty,
213 // minimum difficulty = 1.0.
215 if (pindexBest == NULL)
217 int nShift = (pindexBest->nBits >> 24) & 0xff;
220 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
236 Value getdifficulty(const Array& params, bool fHelp)
238 if (fHelp || params.size() != 0)
241 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
243 return GetDifficulty();
247 Value getgenerate(const Array& params, bool fHelp)
249 if (fHelp || params.size() != 0)
252 "Returns true or false.");
254 return (bool)fGenerateBitcoins;
258 Value setgenerate(const Array& params, bool fHelp)
260 if (fHelp || params.size() < 1 || params.size() > 2)
262 "setgenerate <generate> [genproclimit]\n"
263 "<generate> is true or false to turn generation on or off.\n"
264 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
266 bool fGenerate = true;
267 if (params.size() > 0)
268 fGenerate = params[0].get_bool();
270 if (params.size() > 1)
272 int nGenProcLimit = params[1].get_int();
273 fLimitProcessors = (nGenProcLimit != -1);
274 WriteSetting("fLimitProcessors", fLimitProcessors);
275 if (nGenProcLimit != -1)
276 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
277 if (nGenProcLimit == 0)
281 GenerateBitcoins(fGenerate, pwalletMain);
286 Value gethashespersec(const Array& params, bool fHelp)
288 if (fHelp || params.size() != 0)
291 "Returns a recent hashes per second performance measurement while generating.");
293 if (GetTimeMillis() - nHPSTimerStart > 8000)
294 return (boost::int64_t)0;
295 return (boost::int64_t)dHashesPerSec;
299 Value getinfo(const Array& params, bool fHelp)
301 if (fHelp || params.size() != 0)
304 "Returns an object containing various state info.");
307 obj.push_back(Pair("version", (int)VERSION));
308 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
309 obj.push_back(Pair("blocks", (int)nBestHeight));
310 obj.push_back(Pair("connections", (int)vNodes.size()));
311 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
312 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
313 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
314 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
315 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
316 obj.push_back(Pair("testnet", fTestNet));
317 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
318 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
319 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
320 if (pwalletMain->IsCrypted())
321 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
322 obj.push_back(Pair("errors", GetWarnings("statusbar")));
327 Value getnewaddress(const Array& params, bool fHelp)
329 if (fHelp || params.size() > 1)
331 "getnewaddress [account]\n"
332 "Returns a new bitcoin address for receiving payments. "
333 "If [account] is specified (recommended), it is added to the address book "
334 "so payments received with the address will be credited to [account].");
336 // Parse the account first so we don't generate a key if there's an error
338 if (params.size() > 0)
339 strAccount = AccountFromValue(params[0]);
341 if (!pwalletMain->IsLocked())
342 pwalletMain->TopUpKeyPool();
344 // Generate a new key that is added to wallet
345 std::vector<unsigned char> newKey;
346 if (!pwalletMain->GetKeyFromPool(newKey, false))
347 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
348 CBitcoinAddress address(newKey);
350 pwalletMain->SetAddressBookName(address, strAccount);
352 return address.ToString();
356 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
358 CWalletDB walletdb(pwalletMain->strWalletFile);
361 walletdb.ReadAccount(strAccount, account);
363 bool bKeyUsed = false;
365 // Check if the current key has been used
366 if (!account.vchPubKey.empty())
368 CScript scriptPubKey;
369 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
370 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
371 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
374 const CWalletTx& wtx = (*it).second;
375 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
376 if (txout.scriptPubKey == scriptPubKey)
381 // Generate a new key
382 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
384 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
385 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
387 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
388 walletdb.WriteAccount(strAccount, account);
391 return CBitcoinAddress(account.vchPubKey);
394 Value getaccountaddress(const Array& params, bool fHelp)
396 if (fHelp || params.size() != 1)
398 "getaccountaddress <account>\n"
399 "Returns the current bitcoin address for receiving payments to this account.");
401 // Parse the account first so we don't generate a key if there's an error
402 string strAccount = AccountFromValue(params[0]);
406 ret = GetAccountAddress(strAccount).ToString();
413 Value setaccount(const Array& params, bool fHelp)
415 if (fHelp || params.size() < 1 || params.size() > 2)
417 "setaccount <bitcoinaddress> <account>\n"
418 "Sets the account associated with the given address.");
420 CBitcoinAddress address(params[0].get_str());
421 if (!address.IsValid())
422 throw JSONRPCError(-5, "Invalid bitcoin address");
426 if (params.size() > 1)
427 strAccount = AccountFromValue(params[1]);
429 // Detect when changing the account of an address that is the 'unused current key' of another account:
430 if (pwalletMain->mapAddressBook.count(address))
432 string strOldAccount = pwalletMain->mapAddressBook[address];
433 if (address == GetAccountAddress(strOldAccount))
434 GetAccountAddress(strOldAccount, true);
437 pwalletMain->SetAddressBookName(address, strAccount);
443 Value getaccount(const Array& params, bool fHelp)
445 if (fHelp || params.size() != 1)
447 "getaccount <bitcoinaddress>\n"
448 "Returns the account associated with the given address.");
450 CBitcoinAddress address(params[0].get_str());
451 if (!address.IsValid())
452 throw JSONRPCError(-5, "Invalid bitcoin address");
455 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
456 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
457 strAccount = (*mi).second;
462 Value getaddressesbyaccount(const Array& params, bool fHelp)
464 if (fHelp || params.size() != 1)
466 "getaddressesbyaccount <account>\n"
467 "Returns the list of addresses for the given account.");
469 string strAccount = AccountFromValue(params[0]);
471 // Find all addresses that have the given account
473 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
475 const CBitcoinAddress& address = item.first;
476 const string& strName = item.second;
477 if (strName == strAccount)
478 ret.push_back(address.ToString());
483 Value settxfee(const Array& params, bool fHelp)
485 if (fHelp || params.size() < 1 || params.size() > 1)
487 "settxfee <amount>\n"
488 "<amount> is a real and is rounded to the nearest 0.00000001");
492 if (params[0].get_real() != 0.0)
493 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
495 nTransactionFee = nAmount;
499 Value sendtoaddress(const Array& params, bool fHelp)
501 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
503 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
504 "<amount> is a real and is rounded to the nearest 0.00000001\n"
505 "requires wallet passphrase to be set with walletpassphrase first");
506 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
508 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
509 "<amount> is a real and is rounded to the nearest 0.00000001");
511 CBitcoinAddress address(params[0].get_str());
512 if (!address.IsValid())
513 throw JSONRPCError(-5, "Invalid bitcoin address");
516 int64 nAmount = AmountFromValue(params[1]);
520 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
521 wtx.mapValue["comment"] = params[2].get_str();
522 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
523 wtx.mapValue["to"] = params[3].get_str();
525 if (pwalletMain->IsLocked())
526 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
528 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
530 throw JSONRPCError(-4, strError);
532 return wtx.GetHash().GetHex();
535 static const string strMessageMagic = "Bitcoin Signed Message:\n";
537 Value signmessage(const Array& params, bool fHelp)
539 if (fHelp || params.size() != 2)
541 "signmessage <bitcoinaddress> <message>\n"
542 "Sign a message with the private key of an address");
544 if (pwalletMain->IsLocked())
545 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
547 string strAddress = params[0].get_str();
548 string strMessage = params[1].get_str();
550 CBitcoinAddress addr(strAddress);
552 throw JSONRPCError(-3, "Invalid address");
555 if (!pwalletMain->GetKey(addr, key))
556 throw JSONRPCError(-4, "Private key not available");
558 CDataStream ss(SER_GETHASH);
559 ss << strMessageMagic;
562 vector<unsigned char> vchSig;
563 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
564 throw JSONRPCError(-5, "Sign failed");
566 return EncodeBase64(&vchSig[0], vchSig.size());
569 Value verifymessage(const Array& params, bool fHelp)
571 if (fHelp || params.size() != 3)
573 "verifymessage <bitcoinaddress> <signature> <message>\n"
574 "Verify a signed message");
576 string strAddress = params[0].get_str();
577 string strSign = params[1].get_str();
578 string strMessage = params[2].get_str();
580 CBitcoinAddress addr(strAddress);
582 throw JSONRPCError(-3, "Invalid address");
584 bool fInvalid = false;
585 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
588 throw JSONRPCError(-5, "Malformed base64 encoding");
590 CDataStream ss(SER_GETHASH);
591 ss << strMessageMagic;
595 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
598 return (key.GetAddress() == addr);
602 Value getreceivedbyaddress(const Array& params, bool fHelp)
604 if (fHelp || params.size() < 1 || params.size() > 2)
606 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
607 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
610 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
611 CScript scriptPubKey;
612 if (!address.IsValid())
613 throw JSONRPCError(-5, "Invalid bitcoin address");
614 scriptPubKey.SetBitcoinAddress(address);
615 if (!IsMine(*pwalletMain,scriptPubKey))
618 // Minimum confirmations
620 if (params.size() > 1)
621 nMinDepth = params[1].get_int();
625 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
627 const CWalletTx& wtx = (*it).second;
628 if (wtx.IsCoinBase() || !wtx.IsFinal())
631 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
632 if (txout.scriptPubKey == scriptPubKey)
633 if (wtx.GetDepthInMainChain() >= nMinDepth)
634 nAmount += txout.nValue;
637 return ValueFromAmount(nAmount);
641 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
643 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
645 const CBitcoinAddress& address = item.first;
646 const string& strName = item.second;
647 if (strName == strAccount)
648 setAddress.insert(address);
653 Value getreceivedbyaccount(const Array& params, bool fHelp)
655 if (fHelp || params.size() < 1 || params.size() > 2)
657 "getreceivedbyaccount <account> [minconf=1]\n"
658 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
660 // Minimum confirmations
662 if (params.size() > 1)
663 nMinDepth = params[1].get_int();
665 // Get the set of pub keys that have the label
666 string strAccount = AccountFromValue(params[0]);
667 set<CBitcoinAddress> setAddress;
668 GetAccountAddresses(strAccount, setAddress);
672 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
674 const CWalletTx& wtx = (*it).second;
675 if (wtx.IsCoinBase() || !wtx.IsFinal())
678 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
680 CBitcoinAddress address;
681 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
682 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 nAmount += txout.nValue;
687 return (double)nAmount / (double)COIN;
691 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
695 // Tally wallet transactions
696 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
698 const CWalletTx& wtx = (*it).second;
702 int64 nGenerated, nReceived, nSent, nFee;
703 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
705 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
706 nBalance += nReceived;
707 nBalance += nGenerated - nSent - nFee;
710 // Tally internal accounting entries
711 nBalance += walletdb.GetAccountCreditDebit(strAccount);
716 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
718 CWalletDB walletdb(pwalletMain->strWalletFile);
719 return GetAccountBalance(walletdb, strAccount, nMinDepth);
723 Value getbalance(const Array& params, bool fHelp)
725 if (fHelp || params.size() > 2)
727 "getbalance [account] [minconf=1]\n"
728 "If [account] is not specified, returns the server's total available balance.\n"
729 "If [account] is specified, returns the balance in the account.");
731 if (params.size() == 0)
732 return ValueFromAmount(pwalletMain->GetBalance());
735 if (params.size() > 1)
736 nMinDepth = params[1].get_int();
738 if (params[0].get_str() == "*") {
739 // Calculate total balance a different way from GetBalance()
740 // (GetBalance() sums up all unspent TxOuts)
741 // getbalance and getbalance '*' should always return the same number.
743 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
745 const CWalletTx& wtx = (*it).second;
749 int64 allGeneratedImmature, allGeneratedMature, allFee;
750 allGeneratedImmature = allGeneratedMature = allFee = 0;
751 string strSentAccount;
752 list<pair<CBitcoinAddress, int64> > listReceived;
753 list<pair<CBitcoinAddress, int64> > listSent;
754 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
755 if (wtx.GetDepthInMainChain() >= nMinDepth)
757 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
758 nBalance += r.second;
760 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
761 nBalance -= r.second;
763 nBalance += allGeneratedMature;
765 return ValueFromAmount(nBalance);
768 string strAccount = AccountFromValue(params[0]);
770 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
772 return ValueFromAmount(nBalance);
776 Value movecmd(const Array& params, bool fHelp)
778 if (fHelp || params.size() < 3 || params.size() > 5)
780 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
781 "Move from one account in your wallet to another.");
783 string strFrom = AccountFromValue(params[0]);
784 string strTo = AccountFromValue(params[1]);
785 int64 nAmount = AmountFromValue(params[2]);
786 if (params.size() > 3)
787 // unused parameter, used to be nMinDepth, keep type-checking it though
788 (void)params[3].get_int();
790 if (params.size() > 4)
791 strComment = params[4].get_str();
793 CWalletDB walletdb(pwalletMain->strWalletFile);
794 if (!walletdb.TxnBegin())
795 throw JSONRPCError(-20, "database error");
797 int64 nNow = GetAdjustedTime();
800 CAccountingEntry debit;
801 debit.strAccount = strFrom;
802 debit.nCreditDebit = -nAmount;
804 debit.strOtherAccount = strTo;
805 debit.strComment = strComment;
806 walletdb.WriteAccountingEntry(debit);
809 CAccountingEntry credit;
810 credit.strAccount = strTo;
811 credit.nCreditDebit = nAmount;
813 credit.strOtherAccount = strFrom;
814 credit.strComment = strComment;
815 walletdb.WriteAccountingEntry(credit);
817 if (!walletdb.TxnCommit())
818 throw JSONRPCError(-20, "database error");
824 Value sendfrom(const Array& params, bool fHelp)
826 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
828 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
829 "<amount> is a real and is rounded to the nearest 0.00000001\n"
830 "requires wallet passphrase to be set with walletpassphrase first");
831 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
833 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
834 "<amount> is a real and is rounded to the nearest 0.00000001");
836 string strAccount = AccountFromValue(params[0]);
837 CBitcoinAddress address(params[1].get_str());
838 if (!address.IsValid())
839 throw JSONRPCError(-5, "Invalid bitcoin address");
840 int64 nAmount = AmountFromValue(params[2]);
842 if (params.size() > 3)
843 nMinDepth = params[3].get_int();
846 wtx.strFromAccount = strAccount;
847 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
848 wtx.mapValue["comment"] = params[4].get_str();
849 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
850 wtx.mapValue["to"] = params[5].get_str();
852 if (pwalletMain->IsLocked())
853 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
856 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
857 if (nAmount > nBalance)
858 throw JSONRPCError(-6, "Account has insufficient funds");
861 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
863 throw JSONRPCError(-4, strError);
865 return wtx.GetHash().GetHex();
869 Value sendmany(const Array& params, bool fHelp)
871 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
873 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
874 "amounts are double-precision floating point numbers\n"
875 "requires wallet passphrase to be set with walletpassphrase first");
876 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
878 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
879 "amounts are double-precision floating point numbers");
881 string strAccount = AccountFromValue(params[0]);
882 Object sendTo = params[1].get_obj();
884 if (params.size() > 2)
885 nMinDepth = params[2].get_int();
888 wtx.strFromAccount = strAccount;
889 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
890 wtx.mapValue["comment"] = params[3].get_str();
892 set<CBitcoinAddress> setAddress;
893 vector<pair<CScript, int64> > vecSend;
895 int64 totalAmount = 0;
896 BOOST_FOREACH(const Pair& s, sendTo)
898 CBitcoinAddress address(s.name_);
899 if (!address.IsValid())
900 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
902 if (setAddress.count(address))
903 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
904 setAddress.insert(address);
906 CScript scriptPubKey;
907 scriptPubKey.SetBitcoinAddress(address);
908 int64 nAmount = AmountFromValue(s.value_);
909 totalAmount += nAmount;
911 vecSend.push_back(make_pair(scriptPubKey, nAmount));
914 if (pwalletMain->IsLocked())
915 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
918 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
919 if (totalAmount > nBalance)
920 throw JSONRPCError(-6, "Account has insufficient funds");
923 CReserveKey keyChange(pwalletMain);
924 int64 nFeeRequired = 0;
925 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
928 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
929 throw JSONRPCError(-6, "Insufficient funds");
930 throw JSONRPCError(-4, "Transaction creation failed");
932 if (!pwalletMain->CommitTransaction(wtx, keyChange))
933 throw JSONRPCError(-4, "Transaction commit failed");
935 return wtx.GetHash().GetHex();
950 Value ListReceived(const Array& params, bool fByAccounts)
952 // Minimum confirmations
954 if (params.size() > 0)
955 nMinDepth = params[0].get_int();
957 // Whether to include empty accounts
958 bool fIncludeEmpty = false;
959 if (params.size() > 1)
960 fIncludeEmpty = params[1].get_bool();
963 map<CBitcoinAddress, tallyitem> mapTally;
964 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
966 const CWalletTx& wtx = (*it).second;
967 if (wtx.IsCoinBase() || !wtx.IsFinal())
970 int nDepth = wtx.GetDepthInMainChain();
971 if (nDepth < nMinDepth)
974 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
976 CBitcoinAddress address;
977 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
980 tallyitem& item = mapTally[address];
981 item.nAmount += txout.nValue;
982 item.nConf = min(item.nConf, nDepth);
988 map<string, tallyitem> mapAccountTally;
989 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
991 const CBitcoinAddress& address = item.first;
992 const string& strAccount = item.second;
993 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
994 if (it == mapTally.end() && !fIncludeEmpty)
999 if (it != mapTally.end())
1001 nAmount = (*it).second.nAmount;
1002 nConf = (*it).second.nConf;
1007 tallyitem& item = mapAccountTally[strAccount];
1008 item.nAmount += nAmount;
1009 item.nConf = min(item.nConf, nConf);
1014 obj.push_back(Pair("address", address.ToString()));
1015 obj.push_back(Pair("account", strAccount));
1016 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1017 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1024 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1026 int64 nAmount = (*it).second.nAmount;
1027 int nConf = (*it).second.nConf;
1029 obj.push_back(Pair("account", (*it).first));
1030 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1031 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1039 Value listreceivedbyaddress(const Array& params, bool fHelp)
1041 if (fHelp || params.size() > 2)
1042 throw runtime_error(
1043 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1044 "[minconf] is the minimum number of confirmations before payments are included.\n"
1045 "[includeempty] whether to include addresses that haven't received any payments.\n"
1046 "Returns an array of objects containing:\n"
1047 " \"address\" : receiving address\n"
1048 " \"account\" : the account of the receiving address\n"
1049 " \"amount\" : total amount received by the address\n"
1050 " \"confirmations\" : number of confirmations of the most recent transaction included");
1052 return ListReceived(params, false);
1055 Value listreceivedbyaccount(const Array& params, bool fHelp)
1057 if (fHelp || params.size() > 2)
1058 throw runtime_error(
1059 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1060 "[minconf] is the minimum number of confirmations before payments are included.\n"
1061 "[includeempty] whether to include accounts that haven't received any payments.\n"
1062 "Returns an array of objects containing:\n"
1063 " \"account\" : the account of the receiving addresses\n"
1064 " \"amount\" : total amount received by addresses with this account\n"
1065 " \"confirmations\" : number of confirmations of the most recent transaction included");
1067 return ListReceived(params, true);
1070 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1072 int64 nGeneratedImmature, nGeneratedMature, nFee;
1073 string strSentAccount;
1074 list<pair<CBitcoinAddress, int64> > listReceived;
1075 list<pair<CBitcoinAddress, int64> > listSent;
1076 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1078 bool fAllAccounts = (strAccount == string("*"));
1080 // Generated blocks assigned to account ""
1081 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1084 entry.push_back(Pair("account", string("")));
1085 if (nGeneratedImmature)
1087 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1088 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1092 entry.push_back(Pair("category", "generate"));
1093 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1096 WalletTxToJSON(wtx, entry);
1097 ret.push_back(entry);
1101 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1103 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1106 entry.push_back(Pair("account", strSentAccount));
1107 entry.push_back(Pair("address", s.first.ToString()));
1108 entry.push_back(Pair("category", "send"));
1109 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1110 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1112 WalletTxToJSON(wtx, entry);
1113 ret.push_back(entry);
1118 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1120 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1123 if (pwalletMain->mapAddressBook.count(r.first))
1124 account = pwalletMain->mapAddressBook[r.first];
1125 if (fAllAccounts || (account == strAccount))
1128 entry.push_back(Pair("account", account));
1129 entry.push_back(Pair("address", r.first.ToString()));
1130 entry.push_back(Pair("category", "receive"));
1131 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1133 WalletTxToJSON(wtx, entry);
1134 ret.push_back(entry);
1140 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1142 bool fAllAccounts = (strAccount == string("*"));
1144 if (fAllAccounts || acentry.strAccount == strAccount)
1147 entry.push_back(Pair("account", acentry.strAccount));
1148 entry.push_back(Pair("category", "move"));
1149 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1150 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1151 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1152 entry.push_back(Pair("comment", acentry.strComment));
1153 ret.push_back(entry);
1157 Value listtransactions(const Array& params, bool fHelp)
1159 if (fHelp || params.size() > 3)
1160 throw runtime_error(
1161 "listtransactions [account] [count=10] [from=0]\n"
1162 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1164 string strAccount = "*";
1165 if (params.size() > 0)
1166 strAccount = params[0].get_str();
1168 if (params.size() > 1)
1169 nCount = params[1].get_int();
1171 if (params.size() > 2)
1172 nFrom = params[2].get_int();
1175 throw JSONRPCError(-8, "Negative count");
1177 throw JSONRPCError(-8, "Negative from");
1180 CWalletDB walletdb(pwalletMain->strWalletFile);
1182 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1183 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1184 typedef multimap<int64, TxPair > TxItems;
1187 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1188 // would make this much faster for applications that do this a lot.
1189 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1191 CWalletTx* wtx = &((*it).second);
1192 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1194 list<CAccountingEntry> acentries;
1195 walletdb.ListAccountCreditDebit(strAccount, acentries);
1196 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1198 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1201 // iterate backwards until we have nCount items to return:
1202 for (TxItems::reverse_iterator it = txByTime.rbegin(); 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+nFrom)) break;
1213 // ret is newest to oldest
1215 if (nFrom > ret.size()) nFrom = ret.size();
1216 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1217 Array::iterator first = ret.begin();
1218 std::advance(first, nFrom);
1219 Array::iterator last = ret.begin();
1220 std::advance(last, nFrom+nCount);
1222 if (last != ret.end()) ret.erase(last, ret.end());
1223 if (first != ret.begin()) ret.erase(ret.begin(), first);
1225 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1230 Value listaccounts(const Array& params, bool fHelp)
1232 if (fHelp || params.size() > 1)
1233 throw runtime_error(
1234 "listaccounts [minconf=1]\n"
1235 "Returns Object that has account names as keys, account balances as values.");
1238 if (params.size() > 0)
1239 nMinDepth = params[0].get_int();
1241 map<string, int64> mapAccountBalances;
1242 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1243 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1244 mapAccountBalances[entry.second] = 0;
1247 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1249 const CWalletTx& wtx = (*it).second;
1250 int64 nGeneratedImmature, nGeneratedMature, nFee;
1251 string strSentAccount;
1252 list<pair<CBitcoinAddress, int64> > listReceived;
1253 list<pair<CBitcoinAddress, int64> > listSent;
1254 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1255 mapAccountBalances[strSentAccount] -= nFee;
1256 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1257 mapAccountBalances[strSentAccount] -= s.second;
1258 if (wtx.GetDepthInMainChain() >= nMinDepth)
1260 mapAccountBalances[""] += nGeneratedMature;
1261 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1262 if (pwalletMain->mapAddressBook.count(r.first))
1263 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1265 mapAccountBalances[""] += r.second;
1269 list<CAccountingEntry> acentries;
1270 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1271 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1272 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1275 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1276 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1281 Value listsinceblock(const Array& params, bool fHelp)
1284 throw runtime_error(
1285 "listsinceblock [blockhash] [target-confirmations]\n"
1286 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1288 CBlockIndex *pindex = NULL;
1289 int target_confirms = 1;
1291 if (params.size() > 0)
1293 uint256 blockId = 0;
1295 blockId.SetHex(params[0].get_str());
1296 pindex = CBlockLocator(blockId).GetBlockIndex();
1299 if (params.size() > 1)
1301 target_confirms = params[1].get_int();
1303 if (target_confirms < 1)
1304 throw JSONRPCError(-8, "Invalid parameter");
1307 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1311 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1313 CWalletTx tx = (*it).second;
1315 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1316 ListTransactions(tx, "*", 0, true, transactions);
1321 if (target_confirms == 1)
1323 lastblock = hashBestChain;
1327 int target_height = pindexBest->nHeight + 1 - target_confirms;
1330 for (block = pindexBest;
1331 block && block->nHeight > target_height;
1332 block = block->pprev) { }
1334 lastblock = block ? block->GetBlockHash() : 0;
1338 ret.push_back(Pair("transactions", transactions));
1339 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1344 Value gettransaction(const Array& params, bool fHelp)
1346 if (fHelp || params.size() != 1)
1347 throw runtime_error(
1348 "gettransaction <txid>\n"
1349 "Get detailed information about <txid>");
1352 hash.SetHex(params[0].get_str());
1356 if (!pwalletMain->mapWallet.count(hash))
1357 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1358 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1360 int64 nCredit = wtx.GetCredit();
1361 int64 nDebit = wtx.GetDebit();
1362 int64 nNet = nCredit - nDebit;
1363 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1365 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1367 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1369 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1372 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1373 entry.push_back(Pair("details", details));
1379 Value backupwallet(const Array& params, bool fHelp)
1381 if (fHelp || params.size() != 1)
1382 throw runtime_error(
1383 "backupwallet <destination>\n"
1384 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1386 string strDest = params[0].get_str();
1387 BackupWallet(*pwalletMain, strDest);
1393 Value keypoolrefill(const Array& params, bool fHelp)
1395 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1396 throw runtime_error(
1398 "Fills the keypool, requires wallet passphrase to be set.");
1399 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1400 throw runtime_error(
1402 "Fills the keypool.");
1404 if (pwalletMain->IsLocked())
1405 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1407 pwalletMain->TopUpKeyPool();
1409 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1410 throw JSONRPCError(-4, "Error refreshing keypool.");
1416 void ThreadTopUpKeyPool(void* parg)
1418 pwalletMain->TopUpKeyPool();
1421 void ThreadCleanWalletPassphrase(void* parg)
1423 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1425 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1427 if (nWalletUnlockTime == 0)
1429 nWalletUnlockTime = nMyWakeTime;
1433 if (nWalletUnlockTime==0)
1435 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1439 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1441 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1445 if (nWalletUnlockTime)
1447 nWalletUnlockTime = 0;
1448 pwalletMain->Lock();
1453 if (nWalletUnlockTime < nMyWakeTime)
1454 nWalletUnlockTime = nMyWakeTime;
1457 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1459 delete (int64*)parg;
1462 Value walletpassphrase(const Array& params, bool fHelp)
1464 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1465 throw runtime_error(
1466 "walletpassphrase <passphrase> <timeout>\n"
1467 "Stores the wallet decryption key in memory for <timeout> seconds.");
1470 if (!pwalletMain->IsCrypted())
1471 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1473 if (!pwalletMain->IsLocked())
1474 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1476 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1477 SecureString strWalletPass;
1478 strWalletPass.reserve(100);
1479 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1480 // Alternately, find a way to make params[0] mlock()'d to begin with.
1481 strWalletPass = params[0].get_str().c_str();
1483 if (strWalletPass.length() > 0)
1485 if (!pwalletMain->Unlock(strWalletPass))
1486 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1489 throw runtime_error(
1490 "walletpassphrase <passphrase> <timeout>\n"
1491 "Stores the wallet decryption key in memory for <timeout> seconds.");
1493 CreateThread(ThreadTopUpKeyPool, NULL);
1494 int64* pnSleepTime = new int64(params[1].get_int64());
1495 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1501 Value walletpassphrasechange(const Array& params, bool fHelp)
1503 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1504 throw runtime_error(
1505 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1506 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1509 if (!pwalletMain->IsCrypted())
1510 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1512 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1513 // Alternately, find a way to make params[0] mlock()'d to begin with.
1514 SecureString strOldWalletPass;
1515 strOldWalletPass.reserve(100);
1516 strOldWalletPass = params[0].get_str().c_str();
1518 SecureString strNewWalletPass;
1519 strNewWalletPass.reserve(100);
1520 strNewWalletPass = params[1].get_str().c_str();
1522 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1523 throw runtime_error(
1524 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1525 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1527 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1528 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1534 Value walletlock(const Array& params, bool fHelp)
1536 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1537 throw runtime_error(
1539 "Removes the wallet encryption key from memory, locking the wallet.\n"
1540 "After calling this method, you will need to call walletpassphrase again\n"
1541 "before being able to call any methods which require the wallet to be unlocked.");
1544 if (!pwalletMain->IsCrypted())
1545 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1547 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1549 pwalletMain->Lock();
1550 nWalletUnlockTime = 0;
1557 Value encryptwallet(const Array& params, bool fHelp)
1559 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1560 throw runtime_error(
1561 "encryptwallet <passphrase>\n"
1562 "Encrypts the wallet with <passphrase>.");
1565 if (pwalletMain->IsCrypted())
1566 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1569 // shutting down via RPC while the GUI is running does not work (yet):
1570 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1573 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1574 // Alternately, find a way to make params[0] mlock()'d to begin with.
1575 SecureString strWalletPass;
1576 strWalletPass.reserve(100);
1577 strWalletPass = params[0].get_str().c_str();
1579 if (strWalletPass.length() < 1)
1580 throw runtime_error(
1581 "encryptwallet <passphrase>\n"
1582 "Encrypts the wallet with <passphrase>.");
1584 if (!pwalletMain->EncryptWallet(strWalletPass))
1585 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1587 // BDB seems to have a bad habit of writing old data into
1588 // slack space in .dat files; that is bad if the old data is
1589 // unencrypted private keys. So:
1590 CreateThread(Shutdown, NULL);
1591 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1595 Value validateaddress(const Array& params, bool fHelp)
1597 if (fHelp || params.size() != 1)
1598 throw runtime_error(
1599 "validateaddress <bitcoinaddress>\n"
1600 "Return information about <bitcoinaddress>.");
1602 CBitcoinAddress address(params[0].get_str());
1603 bool isValid = address.IsValid();
1606 ret.push_back(Pair("isvalid", isValid));
1609 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1610 // version of the address:
1611 string currentAddress = address.ToString();
1612 ret.push_back(Pair("address", currentAddress));
1613 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1614 if (pwalletMain->mapAddressBook.count(address))
1615 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1621 Value getwork(const Array& params, bool fHelp)
1623 if (fHelp || params.size() > 1)
1624 throw runtime_error(
1626 "If [data] is not specified, returns formatted hash data to work on:\n"
1627 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1628 " \"data\" : block data\n"
1629 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1630 " \"target\" : little endian hash target\n"
1631 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1634 throw JSONRPCError(-9, "Bitcoin is not connected!");
1636 if (IsInitialBlockDownload())
1637 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1639 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1640 static mapNewBlock_t mapNewBlock;
1641 static vector<CBlock*> vNewBlock;
1642 static CReserveKey reservekey(pwalletMain);
1644 if (params.size() == 0)
1647 static unsigned int nTransactionsUpdatedLast;
1648 static CBlockIndex* pindexPrev;
1649 static int64 nStart;
1650 static CBlock* pblock;
1651 if (pindexPrev != pindexBest ||
1652 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1654 if (pindexPrev != pindexBest)
1656 // Deallocate old blocks since they're obsolete now
1657 mapNewBlock.clear();
1658 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1662 nTransactionsUpdatedLast = nTransactionsUpdated;
1663 pindexPrev = pindexBest;
1667 pblock = CreateNewBlock(reservekey);
1669 throw JSONRPCError(-7, "Out of memory");
1670 vNewBlock.push_back(pblock);
1674 pblock->UpdateTime(pindexPrev);
1677 // Update nExtraNonce
1678 static unsigned int nExtraNonce = 0;
1679 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1682 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1684 // Prebuild hash buffers
1688 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1690 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1693 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1694 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1695 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1696 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1702 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1703 if (vchData.size() != 128)
1704 throw JSONRPCError(-8, "Invalid parameter");
1705 CBlock* pdata = (CBlock*)&vchData[0];
1708 for (int i = 0; i < 128/4; i++)
1709 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1712 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1714 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1716 pblock->nTime = pdata->nTime;
1717 pblock->nNonce = pdata->nNonce;
1718 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1719 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1721 return CheckWork(pblock, *pwalletMain, reservekey);
1726 Value getmemorypool(const Array& params, bool fHelp)
1728 if (fHelp || params.size() > 1)
1729 throw runtime_error(
1730 "getmemorypool [data]\n"
1731 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1732 " \"version\" : block version\n"
1733 " \"previousblockhash\" : hash of current highest block\n"
1734 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1735 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1736 " \"time\" : timestamp appropriate for next block\n"
1737 " \"bits\" : compressed target of next block\n"
1738 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1740 if (params.size() == 0)
1743 throw JSONRPCError(-9, "Bitcoin is not connected!");
1745 if (IsInitialBlockDownload())
1746 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1748 static CReserveKey reservekey(pwalletMain);
1751 static unsigned int nTransactionsUpdatedLast;
1752 static CBlockIndex* pindexPrev;
1753 static int64 nStart;
1754 static CBlock* pblock;
1755 if (pindexPrev != pindexBest ||
1756 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1758 nTransactionsUpdatedLast = nTransactionsUpdated;
1759 pindexPrev = pindexBest;
1765 pblock = CreateNewBlock(reservekey);
1767 throw JSONRPCError(-7, "Out of memory");
1771 pblock->UpdateTime(pindexPrev);
1775 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1782 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1786 result.push_back(Pair("version", pblock->nVersion));
1787 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1788 result.push_back(Pair("transactions", transactions));
1789 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1790 result.push_back(Pair("time", (int64_t)pblock->nTime));
1796 uBits.nBits = htonl((int32_t)pblock->nBits);
1797 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1804 CDataStream ssBlock(ParseHex(params[0].get_str()));
1808 return ProcessBlock(NULL, &pblock);
1826 pair<string, rpcfn_type> pCallTable[] =
1828 make_pair("help", &help),
1829 make_pair("stop", &stop),
1830 make_pair("getblockcount", &getblockcount),
1831 make_pair("getblocknumber", &getblocknumber),
1832 make_pair("getconnectioncount", &getconnectioncount),
1833 make_pair("getdifficulty", &getdifficulty),
1834 make_pair("getgenerate", &getgenerate),
1835 make_pair("setgenerate", &setgenerate),
1836 make_pair("gethashespersec", &gethashespersec),
1837 make_pair("getinfo", &getinfo),
1838 make_pair("getnewaddress", &getnewaddress),
1839 make_pair("getaccountaddress", &getaccountaddress),
1840 make_pair("setaccount", &setaccount),
1841 make_pair("getaccount", &getaccount),
1842 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1843 make_pair("sendtoaddress", &sendtoaddress),
1844 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1845 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1846 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1847 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1848 make_pair("backupwallet", &backupwallet),
1849 make_pair("keypoolrefill", &keypoolrefill),
1850 make_pair("walletpassphrase", &walletpassphrase),
1851 make_pair("walletpassphrasechange", &walletpassphrasechange),
1852 make_pair("walletlock", &walletlock),
1853 make_pair("encryptwallet", &encryptwallet),
1854 make_pair("validateaddress", &validateaddress),
1855 make_pair("getbalance", &getbalance),
1856 make_pair("move", &movecmd),
1857 make_pair("sendfrom", &sendfrom),
1858 make_pair("sendmany", &sendmany),
1859 make_pair("gettransaction", &gettransaction),
1860 make_pair("listtransactions", &listtransactions),
1861 make_pair("signmessage", &signmessage),
1862 make_pair("verifymessage", &verifymessage),
1863 make_pair("getwork", &getwork),
1864 make_pair("listaccounts", &listaccounts),
1865 make_pair("settxfee", &settxfee),
1866 make_pair("getmemorypool", &getmemorypool),
1867 make_pair("listsinceblock", &listsinceblock),
1869 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1871 string pAllowInSafeMode[] =
1876 "getblocknumber", // deprecated
1877 "getconnectioncount",
1884 "getaccountaddress",
1886 "getaddressesbyaccount",
1895 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1903 // This ain't Apache. We're just using HTTP header for the length field
1904 // and to be compatible with other JSON-RPC implementations.
1907 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1910 s << "POST / HTTP/1.1\r\n"
1911 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1912 << "Host: 127.0.0.1\r\n"
1913 << "Content-Type: application/json\r\n"
1914 << "Content-Length: " << strMsg.size() << "\r\n"
1915 << "Connection: close\r\n"
1916 << "Accept: application/json\r\n";
1917 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1918 s << item.first << ": " << item.second << "\r\n";
1919 s << "\r\n" << strMsg;
1924 string rfc1123Time()
1929 struct tm* now_gmt = gmtime(&now);
1930 string locale(setlocale(LC_TIME, NULL));
1931 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1932 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1933 setlocale(LC_TIME, locale.c_str());
1934 return string(buffer);
1937 static string HTTPReply(int nStatus, const string& strMsg)
1940 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1942 "Server: bitcoin-json-rpc/%s\r\n"
1943 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1944 "Content-Type: text/html\r\n"
1945 "Content-Length: 296\r\n"
1947 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1948 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1951 "<TITLE>Error</TITLE>\r\n"
1952 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1954 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1955 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1956 const char *cStatus;
1957 if (nStatus == 200) cStatus = "OK";
1958 else if (nStatus == 400) cStatus = "Bad Request";
1959 else if (nStatus == 403) cStatus = "Forbidden";
1960 else if (nStatus == 404) cStatus = "Not Found";
1961 else if (nStatus == 500) cStatus = "Internal Server Error";
1964 "HTTP/1.1 %d %s\r\n"
1966 "Connection: close\r\n"
1967 "Content-Length: %d\r\n"
1968 "Content-Type: application/json\r\n"
1969 "Server: bitcoin-json-rpc/%s\r\n"
1974 rfc1123Time().c_str(),
1976 FormatFullVersion().c_str(),
1980 int ReadHTTPStatus(std::basic_istream<char>& stream)
1983 getline(stream, str);
1984 vector<string> vWords;
1985 boost::split(vWords, str, boost::is_any_of(" "));
1986 if (vWords.size() < 2)
1988 return atoi(vWords[1].c_str());
1991 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1997 std::getline(stream, str);
1998 if (str.empty() || str == "\r")
2000 string::size_type nColon = str.find(":");
2001 if (nColon != string::npos)
2003 string strHeader = str.substr(0, nColon);
2004 boost::trim(strHeader);
2005 boost::to_lower(strHeader);
2006 string strValue = str.substr(nColon+1);
2007 boost::trim(strValue);
2008 mapHeadersRet[strHeader] = strValue;
2009 if (strHeader == "content-length")
2010 nLen = atoi(strValue.c_str());
2016 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2018 mapHeadersRet.clear();
2022 int nStatus = ReadHTTPStatus(stream);
2025 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2026 if (nLen < 0 || nLen > MAX_SIZE)
2032 vector<char> vch(nLen);
2033 stream.read(&vch[0], nLen);
2034 strMessageRet = string(vch.begin(), vch.end());
2040 bool HTTPAuthorized(map<string, string>& mapHeaders)
2042 string strAuth = mapHeaders["authorization"];
2043 if (strAuth.substr(0,6) != "Basic ")
2045 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2046 string strUserPass = DecodeBase64(strUserPass64);
2047 return strUserPass == strRPCUserColonPass;
2051 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2052 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2053 // unspecified (HTTP errors and contents of 'error').
2055 // 1.0 spec: http://json-rpc.org/wiki/specification
2056 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2057 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2060 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2063 request.push_back(Pair("method", strMethod));
2064 request.push_back(Pair("params", params));
2065 request.push_back(Pair("id", id));
2066 return write_string(Value(request), false) + "\n";
2069 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2072 if (error.type() != null_type)
2073 reply.push_back(Pair("result", Value::null));
2075 reply.push_back(Pair("result", result));
2076 reply.push_back(Pair("error", error));
2077 reply.push_back(Pair("id", id));
2078 return write_string(Value(reply), false) + "\n";
2081 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2083 // Send error reply from json-rpc error object
2085 int code = find_value(objError, "code").get_int();
2086 if (code == -32600) nStatus = 400;
2087 else if (code == -32601) nStatus = 404;
2088 string strReply = JSONRPCReply(Value::null, objError, id);
2089 stream << HTTPReply(nStatus, strReply) << std::flush;
2092 bool ClientAllowed(const string& strAddress)
2094 if (strAddress == asio::ip::address_v4::loopback().to_string())
2096 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2097 BOOST_FOREACH(string strAllow, vAllow)
2098 if (WildcardMatch(strAddress, strAllow))
2105 // IOStream device that speaks SSL but can also speak non-SSL
2107 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2109 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2111 fUseSSL = fUseSSLIn;
2112 fNeedHandshake = fUseSSLIn;
2115 void handshake(ssl::stream_base::handshake_type role)
2117 if (!fNeedHandshake) return;
2118 fNeedHandshake = false;
2119 stream.handshake(role);
2121 std::streamsize read(char* s, std::streamsize n)
2123 handshake(ssl::stream_base::server); // HTTPS servers read first
2124 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2125 return stream.next_layer().read_some(asio::buffer(s, n));
2127 std::streamsize write(const char* s, std::streamsize n)
2129 handshake(ssl::stream_base::client); // HTTPS clients write first
2130 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2131 return asio::write(stream.next_layer(), asio::buffer(s, n));
2133 bool connect(const std::string& server, const std::string& port)
2135 ip::tcp::resolver resolver(stream.get_io_service());
2136 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2137 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2138 ip::tcp::resolver::iterator end;
2139 boost::system::error_code error = asio::error::host_not_found;
2140 while (error && endpoint_iterator != end)
2142 stream.lowest_layer().close();
2143 stream.lowest_layer().connect(*endpoint_iterator++, error);
2151 bool fNeedHandshake;
2157 void ThreadRPCServer(void* parg)
2159 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2162 vnThreadsRunning[4]++;
2163 ThreadRPCServer2(parg);
2164 vnThreadsRunning[4]--;
2166 catch (std::exception& e) {
2167 vnThreadsRunning[4]--;
2168 PrintException(&e, "ThreadRPCServer()");
2170 vnThreadsRunning[4]--;
2171 PrintException(NULL, "ThreadRPCServer()");
2173 printf("ThreadRPCServer exiting\n");
2177 extern bool HACK_SHUTDOWN;
2180 void ThreadRPCServer2(void* parg)
2182 printf("ThreadRPCServer started\n");
2184 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2185 if (strRPCUserColonPass == ":")
2187 unsigned char rand_pwd[32];
2188 RAND_bytes(rand_pwd, 32);
2189 string strWhatAmI = "To use bitcoind";
2190 if (mapArgs.count("-server"))
2191 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2192 else if (mapArgs.count("-daemon"))
2193 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2194 ThreadSafeMessageBox(strprintf(
2195 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2196 "It is recommended you use the following random password:\n"
2197 "rpcuser=bitcoinrpc\n"
2199 "(you do not need to remember this password)\n"
2200 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2202 GetConfigFile().c_str(),
2203 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2204 _("Error"), wxOK | wxMODAL);
2206 CreateThread(Shutdown, NULL);
2211 bool fUseSSL = GetBoolArg("-rpcssl");
2212 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2214 asio::io_service io_service;
2215 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2217 ip::tcp::acceptor acceptor(io_service, endpoint);
2219 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2221 ip::tcp::acceptor acceptor(io_service);
2224 acceptor.open(endpoint.protocol());
2225 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2226 acceptor.bind(endpoint);
2227 acceptor.listen(socket_base::max_connections);
2229 catch(boost::system::system_error &e)
2231 HACK_SHUTDOWN = true;
2232 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2233 _("Error"), wxOK | wxMODAL);
2239 ssl::context context(io_service, ssl::context::sslv23);
2242 context.set_options(ssl::context::no_sslv2);
2243 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2244 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2245 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2246 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2247 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2248 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2249 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2250 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2252 string ciphers = GetArg("-rpcsslciphers",
2253 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2254 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2258 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2263 // Accept connection
2265 SSLStream sslStream(io_service, context);
2266 SSLIOStreamDevice d(sslStream, fUseSSL);
2267 iostreams::stream<SSLIOStreamDevice> stream(d);
2269 ip::tcp::iostream stream;
2272 ip::tcp::endpoint peer;
2273 vnThreadsRunning[4]--;
2275 acceptor.accept(sslStream.lowest_layer(), peer);
2277 acceptor.accept(*stream.rdbuf(), peer);
2279 vnThreadsRunning[4]++;
2283 // Restrict callers by IP
2284 if (!ClientAllowed(peer.address().to_string()))
2286 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2288 stream << HTTPReply(403, "") << std::flush;
2292 map<string, string> mapHeaders;
2295 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2296 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2299 printf("ThreadRPCServer ReadHTTP timeout\n");
2303 // Check authorization
2304 if (mapHeaders.count("authorization") == 0)
2306 stream << HTTPReply(401, "") << std::flush;
2309 if (!HTTPAuthorized(mapHeaders))
2311 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2312 /* Deter brute-forcing short passwords.
2313 If this results in a DOS the user really
2314 shouldn't have their RPC port exposed.*/
2315 if (mapArgs["-rpcpassword"].size() < 20)
2318 stream << HTTPReply(401, "") << std::flush;
2322 Value id = Value::null;
2327 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2328 throw JSONRPCError(-32700, "Parse error");
2329 const Object& request = valRequest.get_obj();
2331 // Parse id now so errors from here on will have the id
2332 id = find_value(request, "id");
2335 Value valMethod = find_value(request, "method");
2336 if (valMethod.type() == null_type)
2337 throw JSONRPCError(-32600, "Missing method");
2338 if (valMethod.type() != str_type)
2339 throw JSONRPCError(-32600, "Method must be a string");
2340 string strMethod = valMethod.get_str();
2341 if (strMethod != "getwork" && strMethod != "getmemorypool")
2342 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2345 Value valParams = find_value(request, "params");
2347 if (valParams.type() == array_type)
2348 params = valParams.get_array();
2349 else if (valParams.type() == null_type)
2352 throw JSONRPCError(-32600, "Params must be an array");
2355 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2356 if (mi == mapCallTable.end())
2357 throw JSONRPCError(-32601, "Method not found");
2359 // Observe safe mode
2360 string strWarning = GetWarnings("rpc");
2361 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2362 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2368 CRITICAL_BLOCK(cs_main)
2369 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2370 result = (*(*mi).second)(params, false);
2373 string strReply = JSONRPCReply(result, Value::null, id);
2374 stream << HTTPReply(200, strReply) << std::flush;
2376 catch (std::exception& e)
2378 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2381 catch (Object& objError)
2383 ErrorReply(stream, objError, id);
2385 catch (std::exception& e)
2387 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2395 Object CallRPC(const string& strMethod, const Array& params)
2397 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2398 throw runtime_error(strprintf(
2399 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2400 "If the file does not exist, create it with owner-readable-only file permissions."),
2401 GetConfigFile().c_str()));
2403 // Connect to localhost
2404 bool fUseSSL = GetBoolArg("-rpcssl");
2406 asio::io_service io_service;
2407 ssl::context context(io_service, ssl::context::sslv23);
2408 context.set_options(ssl::context::no_sslv2);
2409 SSLStream sslStream(io_service, context);
2410 SSLIOStreamDevice d(sslStream, fUseSSL);
2411 iostreams::stream<SSLIOStreamDevice> stream(d);
2412 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2413 throw runtime_error("couldn't connect to server");
2416 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2418 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2420 throw runtime_error("couldn't connect to server");
2424 // HTTP basic authentication
2425 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2426 map<string, string> mapRequestHeaders;
2427 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2430 string strRequest = JSONRPCRequest(strMethod, params, 1);
2431 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2432 stream << strPost << std::flush;
2435 map<string, string> mapHeaders;
2437 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2439 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2440 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2441 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2442 else if (strReply.empty())
2443 throw runtime_error("no response from server");
2447 if (!read_string(strReply, valReply))
2448 throw runtime_error("couldn't parse reply from server");
2449 const Object& reply = valReply.get_obj();
2451 throw runtime_error("expected reply to have result, error and id properties");
2459 template<typename T>
2460 void ConvertTo(Value& value)
2462 if (value.type() == str_type)
2464 // reinterpret string as unquoted json value
2466 if (!read_string(value.get_str(), value2))
2467 throw runtime_error("type mismatch");
2468 value = value2.get_value<T>();
2472 value = value.get_value<T>();
2476 int CommandLineRPC(int argc, char *argv[])
2483 while (argc > 1 && IsSwitchChar(argv[1][0]))
2491 throw runtime_error("too few parameters");
2492 string strMethod = argv[1];
2494 // Parameters default to strings
2496 for (int i = 2; i < argc; i++)
2497 params.push_back(argv[i]);
2498 int n = params.size();
2501 // Special case non-string parameter types
2503 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2504 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2505 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2506 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2507 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2508 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2509 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2510 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2511 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2512 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2513 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2514 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2515 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2516 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2517 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2518 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2519 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2520 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2521 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2522 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2523 if (strMethod == "sendmany" && n > 1)
2525 string s = params[1].get_str();
2527 if (!read_string(s, v) || v.type() != obj_type)
2528 throw runtime_error("type mismatch");
2529 params[1] = v.get_obj();
2531 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2534 Object reply = CallRPC(strMethod, params);
2537 const Value& result = find_value(reply, "result");
2538 const Value& error = find_value(reply, "error");
2540 if (error.type() != null_type)
2543 strPrint = "error: " + write_string(error, false);
2544 int code = find_value(error.get_obj(), "code").get_int();
2550 if (result.type() == null_type)
2552 else if (result.type() == str_type)
2553 strPrint = result.get_str();
2555 strPrint = write_string(result, true);
2558 catch (std::exception& e)
2560 strPrint = string("error: ") + e.what();
2565 PrintException(NULL, "CommandLineRPC()");
2570 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2579 int main(int argc, char *argv[])
2582 // Turn off microsoft heap dump noise
2583 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2584 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2586 setbuf(stdin, NULL);
2587 setbuf(stdout, NULL);
2588 setbuf(stderr, NULL);
2592 if (argc >= 2 && string(argv[1]) == "-server")
2594 printf("server ready\n");
2595 ThreadRPCServer(NULL);
2599 return CommandLineRPC(argc, argv);
2602 catch (std::exception& e) {
2603 PrintException(&e, "main()");
2605 PrintException(NULL, "main()");