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);
796 int64 nNow = GetAdjustedTime();
799 CAccountingEntry debit;
800 debit.strAccount = strFrom;
801 debit.nCreditDebit = -nAmount;
803 debit.strOtherAccount = strTo;
804 debit.strComment = strComment;
805 walletdb.WriteAccountingEntry(debit);
808 CAccountingEntry credit;
809 credit.strAccount = strTo;
810 credit.nCreditDebit = nAmount;
812 credit.strOtherAccount = strFrom;
813 credit.strComment = strComment;
814 walletdb.WriteAccountingEntry(credit);
816 walletdb.TxnCommit();
822 Value sendfrom(const Array& params, bool fHelp)
824 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
826 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
827 "<amount> is a real and is rounded to the nearest 0.00000001\n"
828 "requires wallet passphrase to be set with walletpassphrase first");
829 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
831 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
832 "<amount> is a real and is rounded to the nearest 0.00000001");
834 string strAccount = AccountFromValue(params[0]);
835 CBitcoinAddress address(params[1].get_str());
836 if (!address.IsValid())
837 throw JSONRPCError(-5, "Invalid bitcoin address");
838 int64 nAmount = AmountFromValue(params[2]);
840 if (params.size() > 3)
841 nMinDepth = params[3].get_int();
844 wtx.strFromAccount = strAccount;
845 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
846 wtx.mapValue["comment"] = params[4].get_str();
847 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
848 wtx.mapValue["to"] = params[5].get_str();
850 if (pwalletMain->IsLocked())
851 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
854 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
855 if (nAmount > nBalance)
856 throw JSONRPCError(-6, "Account has insufficient funds");
859 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
861 throw JSONRPCError(-4, strError);
863 return wtx.GetHash().GetHex();
867 Value sendmany(const Array& params, bool fHelp)
869 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
871 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
872 "amounts are double-precision floating point numbers\n"
873 "requires wallet passphrase to be set with walletpassphrase first");
874 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
876 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
877 "amounts are double-precision floating point numbers");
879 string strAccount = AccountFromValue(params[0]);
880 Object sendTo = params[1].get_obj();
882 if (params.size() > 2)
883 nMinDepth = params[2].get_int();
886 wtx.strFromAccount = strAccount;
887 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
888 wtx.mapValue["comment"] = params[3].get_str();
890 set<CBitcoinAddress> setAddress;
891 vector<pair<CScript, int64> > vecSend;
893 int64 totalAmount = 0;
894 BOOST_FOREACH(const Pair& s, sendTo)
896 CBitcoinAddress address(s.name_);
897 if (!address.IsValid())
898 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
900 if (setAddress.count(address))
901 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
902 setAddress.insert(address);
904 CScript scriptPubKey;
905 scriptPubKey.SetBitcoinAddress(address);
906 int64 nAmount = AmountFromValue(s.value_);
907 totalAmount += nAmount;
909 vecSend.push_back(make_pair(scriptPubKey, nAmount));
912 if (pwalletMain->IsLocked())
913 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
916 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
917 if (totalAmount > nBalance)
918 throw JSONRPCError(-6, "Account has insufficient funds");
921 CReserveKey keyChange(pwalletMain);
922 int64 nFeeRequired = 0;
923 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
926 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
927 throw JSONRPCError(-6, "Insufficient funds");
928 throw JSONRPCError(-4, "Transaction creation failed");
930 if (!pwalletMain->CommitTransaction(wtx, keyChange))
931 throw JSONRPCError(-4, "Transaction commit failed");
933 return wtx.GetHash().GetHex();
948 Value ListReceived(const Array& params, bool fByAccounts)
950 // Minimum confirmations
952 if (params.size() > 0)
953 nMinDepth = params[0].get_int();
955 // Whether to include empty accounts
956 bool fIncludeEmpty = false;
957 if (params.size() > 1)
958 fIncludeEmpty = params[1].get_bool();
961 map<CBitcoinAddress, tallyitem> mapTally;
962 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
964 const CWalletTx& wtx = (*it).second;
965 if (wtx.IsCoinBase() || !wtx.IsFinal())
968 int nDepth = wtx.GetDepthInMainChain();
969 if (nDepth < nMinDepth)
972 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
974 CBitcoinAddress address;
975 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
978 tallyitem& item = mapTally[address];
979 item.nAmount += txout.nValue;
980 item.nConf = min(item.nConf, nDepth);
986 map<string, tallyitem> mapAccountTally;
987 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
989 const CBitcoinAddress& address = item.first;
990 const string& strAccount = item.second;
991 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
992 if (it == mapTally.end() && !fIncludeEmpty)
997 if (it != mapTally.end())
999 nAmount = (*it).second.nAmount;
1000 nConf = (*it).second.nConf;
1005 tallyitem& item = mapAccountTally[strAccount];
1006 item.nAmount += nAmount;
1007 item.nConf = min(item.nConf, nConf);
1012 obj.push_back(Pair("address", address.ToString()));
1013 obj.push_back(Pair("account", strAccount));
1014 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1015 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1022 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1024 int64 nAmount = (*it).second.nAmount;
1025 int nConf = (*it).second.nConf;
1027 obj.push_back(Pair("account", (*it).first));
1028 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1029 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1037 Value listreceivedbyaddress(const Array& params, bool fHelp)
1039 if (fHelp || params.size() > 2)
1040 throw runtime_error(
1041 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1042 "[minconf] is the minimum number of confirmations before payments are included.\n"
1043 "[includeempty] whether to include addresses that haven't received any payments.\n"
1044 "Returns an array of objects containing:\n"
1045 " \"address\" : receiving address\n"
1046 " \"account\" : the account of the receiving address\n"
1047 " \"amount\" : total amount received by the address\n"
1048 " \"confirmations\" : number of confirmations of the most recent transaction included");
1050 return ListReceived(params, false);
1053 Value listreceivedbyaccount(const Array& params, bool fHelp)
1055 if (fHelp || params.size() > 2)
1056 throw runtime_error(
1057 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1058 "[minconf] is the minimum number of confirmations before payments are included.\n"
1059 "[includeempty] whether to include accounts that haven't received any payments.\n"
1060 "Returns an array of objects containing:\n"
1061 " \"account\" : the account of the receiving addresses\n"
1062 " \"amount\" : total amount received by addresses with this account\n"
1063 " \"confirmations\" : number of confirmations of the most recent transaction included");
1065 return ListReceived(params, true);
1068 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1070 int64 nGeneratedImmature, nGeneratedMature, nFee;
1071 string strSentAccount;
1072 list<pair<CBitcoinAddress, int64> > listReceived;
1073 list<pair<CBitcoinAddress, int64> > listSent;
1074 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1076 bool fAllAccounts = (strAccount == string("*"));
1078 // Generated blocks assigned to account ""
1079 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1082 entry.push_back(Pair("account", string("")));
1083 if (nGeneratedImmature)
1085 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1086 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1090 entry.push_back(Pair("category", "generate"));
1091 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1094 WalletTxToJSON(wtx, entry);
1095 ret.push_back(entry);
1099 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1101 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1104 entry.push_back(Pair("account", strSentAccount));
1105 entry.push_back(Pair("address", s.first.ToString()));
1106 entry.push_back(Pair("category", "send"));
1107 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1108 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1110 WalletTxToJSON(wtx, entry);
1111 ret.push_back(entry);
1116 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1118 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1121 if (pwalletMain->mapAddressBook.count(r.first))
1122 account = pwalletMain->mapAddressBook[r.first];
1123 if (fAllAccounts || (account == strAccount))
1126 entry.push_back(Pair("account", account));
1127 entry.push_back(Pair("address", r.first.ToString()));
1128 entry.push_back(Pair("category", "receive"));
1129 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1131 WalletTxToJSON(wtx, entry);
1132 ret.push_back(entry);
1138 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1140 bool fAllAccounts = (strAccount == string("*"));
1142 if (fAllAccounts || acentry.strAccount == strAccount)
1145 entry.push_back(Pair("account", acentry.strAccount));
1146 entry.push_back(Pair("category", "move"));
1147 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1148 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1149 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1150 entry.push_back(Pair("comment", acentry.strComment));
1151 ret.push_back(entry);
1155 Value listtransactions(const Array& params, bool fHelp)
1157 if (fHelp || params.size() > 3)
1158 throw runtime_error(
1159 "listtransactions [account] [count=10] [from=0]\n"
1160 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1162 string strAccount = "*";
1163 if (params.size() > 0)
1164 strAccount = params[0].get_str();
1166 if (params.size() > 1)
1167 nCount = params[1].get_int();
1169 if (params.size() > 2)
1170 nFrom = params[2].get_int();
1173 throw JSONRPCError(-8, "Negative count");
1175 throw JSONRPCError(-8, "Negative from");
1178 CWalletDB walletdb(pwalletMain->strWalletFile);
1180 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1181 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1182 typedef multimap<int64, TxPair > TxItems;
1185 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1186 // would make this much faster for applications that do this a lot.
1187 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1189 CWalletTx* wtx = &((*it).second);
1190 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1192 list<CAccountingEntry> acentries;
1193 walletdb.ListAccountCreditDebit(strAccount, acentries);
1194 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1196 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1199 // iterate backwards until we have nCount items to return:
1200 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1202 CWalletTx *const pwtx = (*it).second.first;
1204 ListTransactions(*pwtx, strAccount, 0, true, ret);
1205 CAccountingEntry *const pacentry = (*it).second.second;
1207 AcentryToJSON(*pacentry, strAccount, ret);
1209 if (ret.size() >= (nCount+nFrom)) break;
1211 // ret is newest to oldest
1213 if (nFrom > ret.size()) nFrom = ret.size();
1214 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1215 Array::iterator first = ret.begin();
1216 std::advance(first, nFrom);
1217 Array::iterator last = ret.begin();
1218 std::advance(last, nFrom+nCount);
1220 if (last != ret.end()) ret.erase(last, ret.end());
1221 if (first != ret.begin()) ret.erase(ret.begin(), first);
1223 std::reverse(ret.begin(), ret.end()); // Return 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 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1241 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1242 mapAccountBalances[entry.second] = 0;
1245 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1247 const CWalletTx& wtx = (*it).second;
1248 int64 nGeneratedImmature, nGeneratedMature, nFee;
1249 string strSentAccount;
1250 list<pair<CBitcoinAddress, int64> > listReceived;
1251 list<pair<CBitcoinAddress, int64> > listSent;
1252 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1253 mapAccountBalances[strSentAccount] -= nFee;
1254 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1255 mapAccountBalances[strSentAccount] -= s.second;
1256 if (wtx.GetDepthInMainChain() >= nMinDepth)
1258 mapAccountBalances[""] += nGeneratedMature;
1259 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1260 if (pwalletMain->mapAddressBook.count(r.first))
1261 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1263 mapAccountBalances[""] += r.second;
1267 list<CAccountingEntry> acentries;
1268 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1269 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1270 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1273 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1274 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1279 Value listsinceblock(const Array& params, bool fHelp)
1282 throw runtime_error(
1283 "listsinceblock [blockhash] [target-confirmations]\n"
1284 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1286 CBlockIndex *pindex = NULL;
1287 int target_confirms = 1;
1289 if (params.size() > 0)
1291 uint256 blockId = 0;
1293 blockId.SetHex(params[0].get_str());
1294 pindex = CBlockLocator(blockId).GetBlockIndex();
1297 if (params.size() > 1)
1299 target_confirms = params[1].get_int();
1301 if (target_confirms < 1)
1302 throw JSONRPCError(-8, "Invalid parameter");
1305 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1309 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1311 CWalletTx tx = (*it).second;
1313 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1314 ListTransactions(tx, "*", 0, true, transactions);
1319 if (target_confirms == 1)
1321 lastblock = hashBestChain;
1325 int target_height = pindexBest->nHeight + 1 - target_confirms;
1328 for (block = pindexBest;
1329 block && block->nHeight > target_height;
1330 block = block->pprev) { }
1332 lastblock = block ? block->GetBlockHash() : 0;
1336 ret.push_back(Pair("transactions", transactions));
1337 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1342 Value gettransaction(const Array& params, bool fHelp)
1344 if (fHelp || params.size() != 1)
1345 throw runtime_error(
1346 "gettransaction <txid>\n"
1347 "Get detailed information about <txid>");
1350 hash.SetHex(params[0].get_str());
1354 if (!pwalletMain->mapWallet.count(hash))
1355 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1356 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1358 int64 nCredit = wtx.GetCredit();
1359 int64 nDebit = wtx.GetDebit();
1360 int64 nNet = nCredit - nDebit;
1361 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1363 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1365 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1367 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1370 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1371 entry.push_back(Pair("details", details));
1377 Value backupwallet(const Array& params, bool fHelp)
1379 if (fHelp || params.size() != 1)
1380 throw runtime_error(
1381 "backupwallet <destination>\n"
1382 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1384 string strDest = params[0].get_str();
1385 BackupWallet(*pwalletMain, strDest);
1391 Value keypoolrefill(const Array& params, bool fHelp)
1393 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1394 throw runtime_error(
1396 "Fills the keypool, requires wallet passphrase to be set.");
1397 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1398 throw runtime_error(
1400 "Fills the keypool.");
1402 if (pwalletMain->IsLocked())
1403 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1405 pwalletMain->TopUpKeyPool();
1407 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1408 throw JSONRPCError(-4, "Error refreshing keypool.");
1414 void ThreadTopUpKeyPool(void* parg)
1416 pwalletMain->TopUpKeyPool();
1419 void ThreadCleanWalletPassphrase(void* parg)
1421 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1423 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1425 if (nWalletUnlockTime == 0)
1427 nWalletUnlockTime = nMyWakeTime;
1431 if (nWalletUnlockTime==0)
1433 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1437 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1439 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1443 if (nWalletUnlockTime)
1445 nWalletUnlockTime = 0;
1446 pwalletMain->Lock();
1451 if (nWalletUnlockTime < nMyWakeTime)
1452 nWalletUnlockTime = nMyWakeTime;
1455 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1457 delete (int64*)parg;
1460 Value walletpassphrase(const Array& params, bool fHelp)
1462 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1463 throw runtime_error(
1464 "walletpassphrase <passphrase> <timeout>\n"
1465 "Stores the wallet decryption key in memory for <timeout> seconds.");
1468 if (!pwalletMain->IsCrypted())
1469 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1471 if (!pwalletMain->IsLocked())
1472 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1474 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1475 SecureString strWalletPass;
1476 strWalletPass.reserve(100);
1477 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1478 // Alternately, find a way to make params[0] mlock()'d to begin with.
1479 strWalletPass = params[0].get_str().c_str();
1481 if (strWalletPass.length() > 0)
1483 if (!pwalletMain->Unlock(strWalletPass))
1484 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1487 throw runtime_error(
1488 "walletpassphrase <passphrase> <timeout>\n"
1489 "Stores the wallet decryption key in memory for <timeout> seconds.");
1491 CreateThread(ThreadTopUpKeyPool, NULL);
1492 int64* pnSleepTime = new int64(params[1].get_int64());
1493 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1499 Value walletpassphrasechange(const Array& params, bool fHelp)
1501 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1502 throw runtime_error(
1503 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1504 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1507 if (!pwalletMain->IsCrypted())
1508 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1510 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1511 // Alternately, find a way to make params[0] mlock()'d to begin with.
1512 SecureString strOldWalletPass;
1513 strOldWalletPass.reserve(100);
1514 strOldWalletPass = params[0].get_str().c_str();
1516 SecureString strNewWalletPass;
1517 strNewWalletPass.reserve(100);
1518 strNewWalletPass = params[1].get_str().c_str();
1520 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1521 throw runtime_error(
1522 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1523 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1525 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1526 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1532 Value walletlock(const Array& params, bool fHelp)
1534 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1535 throw runtime_error(
1537 "Removes the wallet encryption key from memory, locking the wallet.\n"
1538 "After calling this method, you will need to call walletpassphrase again\n"
1539 "before being able to call any methods which require the wallet to be unlocked.");
1542 if (!pwalletMain->IsCrypted())
1543 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1545 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1547 pwalletMain->Lock();
1548 nWalletUnlockTime = 0;
1555 Value encryptwallet(const Array& params, bool fHelp)
1557 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1558 throw runtime_error(
1559 "encryptwallet <passphrase>\n"
1560 "Encrypts the wallet with <passphrase>.");
1563 if (pwalletMain->IsCrypted())
1564 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1567 // shutting down via RPC while the GUI is running does not work (yet):
1568 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1571 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1572 // Alternately, find a way to make params[0] mlock()'d to begin with.
1573 SecureString strWalletPass;
1574 strWalletPass.reserve(100);
1575 strWalletPass = params[0].get_str().c_str();
1577 if (strWalletPass.length() < 1)
1578 throw runtime_error(
1579 "encryptwallet <passphrase>\n"
1580 "Encrypts the wallet with <passphrase>.");
1582 if (!pwalletMain->EncryptWallet(strWalletPass))
1583 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1585 // BDB seems to have a bad habit of writing old data into
1586 // slack space in .dat files; that is bad if the old data is
1587 // unencrypted private keys. So:
1588 CreateThread(Shutdown, NULL);
1589 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1593 Value validateaddress(const Array& params, bool fHelp)
1595 if (fHelp || params.size() != 1)
1596 throw runtime_error(
1597 "validateaddress <bitcoinaddress>\n"
1598 "Return information about <bitcoinaddress>.");
1600 CBitcoinAddress address(params[0].get_str());
1601 bool isValid = address.IsValid();
1604 ret.push_back(Pair("isvalid", isValid));
1607 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1608 // version of the address:
1609 string currentAddress = address.ToString();
1610 ret.push_back(Pair("address", currentAddress));
1611 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1612 if (pwalletMain->mapAddressBook.count(address))
1613 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1619 Value getwork(const Array& params, bool fHelp)
1621 if (fHelp || params.size() > 1)
1622 throw runtime_error(
1624 "If [data] is not specified, returns formatted hash data to work on:\n"
1625 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1626 " \"data\" : block data\n"
1627 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1628 " \"target\" : little endian hash target\n"
1629 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1632 throw JSONRPCError(-9, "Bitcoin is not connected!");
1634 if (IsInitialBlockDownload())
1635 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1637 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1638 static mapNewBlock_t mapNewBlock;
1639 static vector<CBlock*> vNewBlock;
1640 static CReserveKey reservekey(pwalletMain);
1642 if (params.size() == 0)
1645 static unsigned int nTransactionsUpdatedLast;
1646 static CBlockIndex* pindexPrev;
1647 static int64 nStart;
1648 static CBlock* pblock;
1649 if (pindexPrev != pindexBest ||
1650 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1652 if (pindexPrev != pindexBest)
1654 // Deallocate old blocks since they're obsolete now
1655 mapNewBlock.clear();
1656 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1660 nTransactionsUpdatedLast = nTransactionsUpdated;
1661 pindexPrev = pindexBest;
1665 pblock = CreateNewBlock(reservekey);
1667 throw JSONRPCError(-7, "Out of memory");
1668 vNewBlock.push_back(pblock);
1672 pblock->UpdateTime(pindexPrev);
1675 // Update nExtraNonce
1676 static unsigned int nExtraNonce = 0;
1677 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1680 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1682 // Prebuild hash buffers
1686 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1688 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1691 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1692 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1693 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1694 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1700 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1701 if (vchData.size() != 128)
1702 throw JSONRPCError(-8, "Invalid parameter");
1703 CBlock* pdata = (CBlock*)&vchData[0];
1706 for (int i = 0; i < 128/4; i++)
1707 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1710 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1712 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1714 pblock->nTime = pdata->nTime;
1715 pblock->nNonce = pdata->nNonce;
1716 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1717 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1719 return CheckWork(pblock, *pwalletMain, reservekey);
1724 Value getmemorypool(const Array& params, bool fHelp)
1726 if (fHelp || params.size() > 1)
1727 throw runtime_error(
1728 "getmemorypool [data]\n"
1729 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1730 " \"version\" : block version\n"
1731 " \"previousblockhash\" : hash of current highest block\n"
1732 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1733 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1734 " \"time\" : timestamp appropriate for next block\n"
1735 " \"bits\" : compressed target of next block\n"
1736 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1738 if (params.size() == 0)
1741 throw JSONRPCError(-9, "Bitcoin is not connected!");
1743 if (IsInitialBlockDownload())
1744 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1746 static CReserveKey reservekey(pwalletMain);
1749 static unsigned int nTransactionsUpdatedLast;
1750 static CBlockIndex* pindexPrev;
1751 static int64 nStart;
1752 static CBlock* pblock;
1753 if (pindexPrev != pindexBest ||
1754 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1756 nTransactionsUpdatedLast = nTransactionsUpdated;
1757 pindexPrev = pindexBest;
1763 pblock = CreateNewBlock(reservekey);
1765 throw JSONRPCError(-7, "Out of memory");
1769 pblock->UpdateTime(pindexPrev);
1773 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1780 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1784 result.push_back(Pair("version", pblock->nVersion));
1785 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1786 result.push_back(Pair("transactions", transactions));
1787 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1788 result.push_back(Pair("time", (int64_t)pblock->nTime));
1794 uBits.nBits = htonl((int32_t)pblock->nBits);
1795 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1802 CDataStream ssBlock(ParseHex(params[0].get_str()));
1806 return ProcessBlock(NULL, &pblock);
1824 pair<string, rpcfn_type> pCallTable[] =
1826 make_pair("help", &help),
1827 make_pair("stop", &stop),
1828 make_pair("getblockcount", &getblockcount),
1829 make_pair("getblocknumber", &getblocknumber),
1830 make_pair("getconnectioncount", &getconnectioncount),
1831 make_pair("getdifficulty", &getdifficulty),
1832 make_pair("getgenerate", &getgenerate),
1833 make_pair("setgenerate", &setgenerate),
1834 make_pair("gethashespersec", &gethashespersec),
1835 make_pair("getinfo", &getinfo),
1836 make_pair("getnewaddress", &getnewaddress),
1837 make_pair("getaccountaddress", &getaccountaddress),
1838 make_pair("setaccount", &setaccount),
1839 make_pair("getaccount", &getaccount),
1840 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1841 make_pair("sendtoaddress", &sendtoaddress),
1842 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1843 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1844 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1845 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1846 make_pair("backupwallet", &backupwallet),
1847 make_pair("keypoolrefill", &keypoolrefill),
1848 make_pair("walletpassphrase", &walletpassphrase),
1849 make_pair("walletpassphrasechange", &walletpassphrasechange),
1850 make_pair("walletlock", &walletlock),
1851 make_pair("encryptwallet", &encryptwallet),
1852 make_pair("validateaddress", &validateaddress),
1853 make_pair("getbalance", &getbalance),
1854 make_pair("move", &movecmd),
1855 make_pair("sendfrom", &sendfrom),
1856 make_pair("sendmany", &sendmany),
1857 make_pair("gettransaction", &gettransaction),
1858 make_pair("listtransactions", &listtransactions),
1859 make_pair("signmessage", &signmessage),
1860 make_pair("verifymessage", &verifymessage),
1861 make_pair("getwork", &getwork),
1862 make_pair("listaccounts", &listaccounts),
1863 make_pair("settxfee", &settxfee),
1864 make_pair("getmemorypool", &getmemorypool),
1865 make_pair("listsinceblock", &listsinceblock),
1867 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1869 string pAllowInSafeMode[] =
1874 "getblocknumber", // deprecated
1875 "getconnectioncount",
1882 "getaccountaddress",
1884 "getaddressesbyaccount",
1893 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1901 // This ain't Apache. We're just using HTTP header for the length field
1902 // and to be compatible with other JSON-RPC implementations.
1905 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1908 s << "POST / HTTP/1.1\r\n"
1909 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1910 << "Host: 127.0.0.1\r\n"
1911 << "Content-Type: application/json\r\n"
1912 << "Content-Length: " << strMsg.size() << "\r\n"
1913 << "Connection: close\r\n"
1914 << "Accept: application/json\r\n";
1915 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1916 s << item.first << ": " << item.second << "\r\n";
1917 s << "\r\n" << strMsg;
1922 string rfc1123Time()
1927 struct tm* now_gmt = gmtime(&now);
1928 string locale(setlocale(LC_TIME, NULL));
1929 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1930 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1931 setlocale(LC_TIME, locale.c_str());
1932 return string(buffer);
1935 static string HTTPReply(int nStatus, const string& strMsg)
1938 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1940 "Server: bitcoin-json-rpc/%s\r\n"
1941 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1942 "Content-Type: text/html\r\n"
1943 "Content-Length: 296\r\n"
1945 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1946 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1949 "<TITLE>Error</TITLE>\r\n"
1950 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1952 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1953 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1954 const char *cStatus;
1955 if (nStatus == 200) cStatus = "OK";
1956 else if (nStatus == 400) cStatus = "Bad Request";
1957 else if (nStatus == 403) cStatus = "Forbidden";
1958 else if (nStatus == 404) cStatus = "Not Found";
1959 else if (nStatus == 500) cStatus = "Internal Server Error";
1962 "HTTP/1.1 %d %s\r\n"
1964 "Connection: close\r\n"
1965 "Content-Length: %d\r\n"
1966 "Content-Type: application/json\r\n"
1967 "Server: bitcoin-json-rpc/%s\r\n"
1972 rfc1123Time().c_str(),
1974 FormatFullVersion().c_str(),
1978 int ReadHTTPStatus(std::basic_istream<char>& stream)
1981 getline(stream, str);
1982 vector<string> vWords;
1983 boost::split(vWords, str, boost::is_any_of(" "));
1984 if (vWords.size() < 2)
1986 return atoi(vWords[1].c_str());
1989 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1995 std::getline(stream, str);
1996 if (str.empty() || str == "\r")
1998 string::size_type nColon = str.find(":");
1999 if (nColon != string::npos)
2001 string strHeader = str.substr(0, nColon);
2002 boost::trim(strHeader);
2003 boost::to_lower(strHeader);
2004 string strValue = str.substr(nColon+1);
2005 boost::trim(strValue);
2006 mapHeadersRet[strHeader] = strValue;
2007 if (strHeader == "content-length")
2008 nLen = atoi(strValue.c_str());
2014 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2016 mapHeadersRet.clear();
2020 int nStatus = ReadHTTPStatus(stream);
2023 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2024 if (nLen < 0 || nLen > MAX_SIZE)
2030 vector<char> vch(nLen);
2031 stream.read(&vch[0], nLen);
2032 strMessageRet = string(vch.begin(), vch.end());
2038 bool HTTPAuthorized(map<string, string>& mapHeaders)
2040 string strAuth = mapHeaders["authorization"];
2041 if (strAuth.substr(0,6) != "Basic ")
2043 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2044 string strUserPass = DecodeBase64(strUserPass64);
2045 return strUserPass == strRPCUserColonPass;
2049 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2050 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2051 // unspecified (HTTP errors and contents of 'error').
2053 // 1.0 spec: http://json-rpc.org/wiki/specification
2054 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2055 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2058 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2061 request.push_back(Pair("method", strMethod));
2062 request.push_back(Pair("params", params));
2063 request.push_back(Pair("id", id));
2064 return write_string(Value(request), false) + "\n";
2067 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2070 if (error.type() != null_type)
2071 reply.push_back(Pair("result", Value::null));
2073 reply.push_back(Pair("result", result));
2074 reply.push_back(Pair("error", error));
2075 reply.push_back(Pair("id", id));
2076 return write_string(Value(reply), false) + "\n";
2079 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2081 // Send error reply from json-rpc error object
2083 int code = find_value(objError, "code").get_int();
2084 if (code == -32600) nStatus = 400;
2085 else if (code == -32601) nStatus = 404;
2086 string strReply = JSONRPCReply(Value::null, objError, id);
2087 stream << HTTPReply(nStatus, strReply) << std::flush;
2090 bool ClientAllowed(const string& strAddress)
2092 if (strAddress == asio::ip::address_v4::loopback().to_string())
2094 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2095 BOOST_FOREACH(string strAllow, vAllow)
2096 if (WildcardMatch(strAddress, strAllow))
2103 // IOStream device that speaks SSL but can also speak non-SSL
2105 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2107 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2109 fUseSSL = fUseSSLIn;
2110 fNeedHandshake = fUseSSLIn;
2113 void handshake(ssl::stream_base::handshake_type role)
2115 if (!fNeedHandshake) return;
2116 fNeedHandshake = false;
2117 stream.handshake(role);
2119 std::streamsize read(char* s, std::streamsize n)
2121 handshake(ssl::stream_base::server); // HTTPS servers read first
2122 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2123 return stream.next_layer().read_some(asio::buffer(s, n));
2125 std::streamsize write(const char* s, std::streamsize n)
2127 handshake(ssl::stream_base::client); // HTTPS clients write first
2128 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2129 return asio::write(stream.next_layer(), asio::buffer(s, n));
2131 bool connect(const std::string& server, const std::string& port)
2133 ip::tcp::resolver resolver(stream.get_io_service());
2134 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2135 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2136 ip::tcp::resolver::iterator end;
2137 boost::system::error_code error = asio::error::host_not_found;
2138 while (error && endpoint_iterator != end)
2140 stream.lowest_layer().close();
2141 stream.lowest_layer().connect(*endpoint_iterator++, error);
2149 bool fNeedHandshake;
2155 void ThreadRPCServer(void* parg)
2157 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2160 vnThreadsRunning[4]++;
2161 ThreadRPCServer2(parg);
2162 vnThreadsRunning[4]--;
2164 catch (std::exception& e) {
2165 vnThreadsRunning[4]--;
2166 PrintException(&e, "ThreadRPCServer()");
2168 vnThreadsRunning[4]--;
2169 PrintException(NULL, "ThreadRPCServer()");
2171 printf("ThreadRPCServer exiting\n");
2175 extern bool HACK_SHUTDOWN;
2178 void ThreadRPCServer2(void* parg)
2180 printf("ThreadRPCServer started\n");
2182 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2183 if (strRPCUserColonPass == ":")
2185 unsigned char rand_pwd[32];
2186 RAND_bytes(rand_pwd, 32);
2187 string strWhatAmI = "To use bitcoind";
2188 if (mapArgs.count("-server"))
2189 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2190 else if (mapArgs.count("-daemon"))
2191 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2192 ThreadSafeMessageBox(strprintf(
2193 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2194 "It is recommended you use the following random password:\n"
2195 "rpcuser=bitcoinrpc\n"
2197 "(you do not need to remember this password)\n"
2198 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2200 GetConfigFile().c_str(),
2201 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2202 _("Error"), wxOK | wxMODAL);
2204 CreateThread(Shutdown, NULL);
2209 bool fUseSSL = GetBoolArg("-rpcssl");
2210 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2212 asio::io_service io_service;
2213 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2215 ip::tcp::acceptor acceptor(io_service, endpoint);
2217 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2219 ip::tcp::acceptor acceptor(io_service);
2222 acceptor.open(endpoint.protocol());
2223 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2224 acceptor.bind(endpoint);
2225 acceptor.listen(socket_base::max_connections);
2227 catch(boost::system::system_error &e)
2229 HACK_SHUTDOWN = true;
2230 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2231 _("Error"), wxOK | wxMODAL);
2237 ssl::context context(io_service, ssl::context::sslv23);
2240 context.set_options(ssl::context::no_sslv2);
2241 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2242 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2243 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2244 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2245 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2246 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2247 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2248 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2250 string ciphers = GetArg("-rpcsslciphers",
2251 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2252 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2256 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2261 // Accept connection
2263 SSLStream sslStream(io_service, context);
2264 SSLIOStreamDevice d(sslStream, fUseSSL);
2265 iostreams::stream<SSLIOStreamDevice> stream(d);
2267 ip::tcp::iostream stream;
2270 ip::tcp::endpoint peer;
2271 vnThreadsRunning[4]--;
2273 acceptor.accept(sslStream.lowest_layer(), peer);
2275 acceptor.accept(*stream.rdbuf(), peer);
2277 vnThreadsRunning[4]++;
2281 // Restrict callers by IP
2282 if (!ClientAllowed(peer.address().to_string()))
2284 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2286 stream << HTTPReply(403, "") << std::flush;
2290 map<string, string> mapHeaders;
2293 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2294 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2297 printf("ThreadRPCServer ReadHTTP timeout\n");
2301 // Check authorization
2302 if (mapHeaders.count("authorization") == 0)
2304 stream << HTTPReply(401, "") << std::flush;
2307 if (!HTTPAuthorized(mapHeaders))
2309 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2310 /* Deter brute-forcing short passwords.
2311 If this results in a DOS the user really
2312 shouldn't have their RPC port exposed.*/
2313 if (mapArgs["-rpcpassword"].size() < 20)
2316 stream << HTTPReply(401, "") << std::flush;
2320 Value id = Value::null;
2325 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2326 throw JSONRPCError(-32700, "Parse error");
2327 const Object& request = valRequest.get_obj();
2329 // Parse id now so errors from here on will have the id
2330 id = find_value(request, "id");
2333 Value valMethod = find_value(request, "method");
2334 if (valMethod.type() == null_type)
2335 throw JSONRPCError(-32600, "Missing method");
2336 if (valMethod.type() != str_type)
2337 throw JSONRPCError(-32600, "Method must be a string");
2338 string strMethod = valMethod.get_str();
2339 if (strMethod != "getwork" && strMethod != "getmemorypool")
2340 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2343 Value valParams = find_value(request, "params");
2345 if (valParams.type() == array_type)
2346 params = valParams.get_array();
2347 else if (valParams.type() == null_type)
2350 throw JSONRPCError(-32600, "Params must be an array");
2353 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2354 if (mi == mapCallTable.end())
2355 throw JSONRPCError(-32601, "Method not found");
2357 // Observe safe mode
2358 string strWarning = GetWarnings("rpc");
2359 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2360 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2366 CRITICAL_BLOCK(cs_main)
2367 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2368 result = (*(*mi).second)(params, false);
2371 string strReply = JSONRPCReply(result, Value::null, id);
2372 stream << HTTPReply(200, strReply) << std::flush;
2374 catch (std::exception& e)
2376 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2379 catch (Object& objError)
2381 ErrorReply(stream, objError, id);
2383 catch (std::exception& e)
2385 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2393 Object CallRPC(const string& strMethod, const Array& params)
2395 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2396 throw runtime_error(strprintf(
2397 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2398 "If the file does not exist, create it with owner-readable-only file permissions."),
2399 GetConfigFile().c_str()));
2401 // Connect to localhost
2402 bool fUseSSL = GetBoolArg("-rpcssl");
2404 asio::io_service io_service;
2405 ssl::context context(io_service, ssl::context::sslv23);
2406 context.set_options(ssl::context::no_sslv2);
2407 SSLStream sslStream(io_service, context);
2408 SSLIOStreamDevice d(sslStream, fUseSSL);
2409 iostreams::stream<SSLIOStreamDevice> stream(d);
2410 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2411 throw runtime_error("couldn't connect to server");
2414 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2416 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2418 throw runtime_error("couldn't connect to server");
2422 // HTTP basic authentication
2423 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2424 map<string, string> mapRequestHeaders;
2425 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2428 string strRequest = JSONRPCRequest(strMethod, params, 1);
2429 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2430 stream << strPost << std::flush;
2433 map<string, string> mapHeaders;
2435 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2437 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2438 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2439 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2440 else if (strReply.empty())
2441 throw runtime_error("no response from server");
2445 if (!read_string(strReply, valReply))
2446 throw runtime_error("couldn't parse reply from server");
2447 const Object& reply = valReply.get_obj();
2449 throw runtime_error("expected reply to have result, error and id properties");
2457 template<typename T>
2458 void ConvertTo(Value& value)
2460 if (value.type() == str_type)
2462 // reinterpret string as unquoted json value
2464 if (!read_string(value.get_str(), value2))
2465 throw runtime_error("type mismatch");
2466 value = value2.get_value<T>();
2470 value = value.get_value<T>();
2474 int CommandLineRPC(int argc, char *argv[])
2481 while (argc > 1 && IsSwitchChar(argv[1][0]))
2489 throw runtime_error("too few parameters");
2490 string strMethod = argv[1];
2492 // Parameters default to strings
2494 for (int i = 2; i < argc; i++)
2495 params.push_back(argv[i]);
2496 int n = params.size();
2499 // Special case non-string parameter types
2501 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2502 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2503 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2504 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2505 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2506 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2507 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2508 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2509 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2510 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2511 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2512 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2513 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2514 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2515 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2516 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2517 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2518 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2519 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2520 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2521 if (strMethod == "sendmany" && n > 1)
2523 string s = params[1].get_str();
2525 if (!read_string(s, v) || v.type() != obj_type)
2526 throw runtime_error("type mismatch");
2527 params[1] = v.get_obj();
2529 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2532 Object reply = CallRPC(strMethod, params);
2535 const Value& result = find_value(reply, "result");
2536 const Value& error = find_value(reply, "error");
2538 if (error.type() != null_type)
2541 strPrint = "error: " + write_string(error, false);
2542 int code = find_value(error.get_obj(), "code").get_int();
2548 if (result.type() == null_type)
2550 else if (result.type() == str_type)
2551 strPrint = result.get_str();
2553 strPrint = write_string(result, true);
2556 catch (std::exception& e)
2558 strPrint = string("error: ") + e.what();
2563 PrintException(NULL, "CommandLineRPC()");
2568 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2577 int main(int argc, char *argv[])
2580 // Turn off microsoft heap dump noise
2581 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2582 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2584 setbuf(stdin, NULL);
2585 setbuf(stdout, NULL);
2586 setbuf(stderr, NULL);
2590 if (argc >= 2 && string(argv[1]) == "-server")
2592 printf("server ready\n");
2593 ThreadRPCServer(NULL);
2597 return CommandLineRPC(argc, argv);
2600 catch (std::exception& e) {
2601 PrintException(&e, "main()");
2603 PrintException(NULL, "main()");