1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
13 #include <boost/asio.hpp>
14 #include <boost/filesystem.hpp>
15 #include <boost/iostreams/concepts.hpp>
16 #include <boost/iostreams/stream.hpp>
17 #include <boost/algorithm/string.hpp>
18 #include <boost/lexical_cast.hpp>
20 #include <boost/asio/ssl.hpp>
21 #include <boost/filesystem.hpp>
22 #include <boost/filesystem/fstream.hpp>
23 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
25 #include "json/json_spirit_reader_template.h"
26 #include "json/json_spirit_writer_template.h"
27 #include "json/json_spirit_utils.h"
28 #define printf OutputDebugStringF
29 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
30 // precompiled in headers.h. The problem might be when the pch file goes over
31 // a certain size around 145MB. If we need access to json_spirit outside this
32 // file, we could use the compiled json_spirit option.
35 using namespace boost;
36 using namespace boost::asio;
37 using namespace json_spirit;
39 void ThreadRPCServer2(void* parg);
40 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
41 extern map<string, rpcfn_type> mapCallTable;
43 static std::string strRPCUserColonPass;
45 static int64_t nWalletUnlockTime;
46 static CCriticalSection cs_nWalletUnlockTime;
48 extern Value dumpprivkey(const Array& params, bool fHelp);
49 extern Value importprivkey(const Array& params, bool fHelp);
51 Object JSONRPCError(int code, const string& message)
54 error.push_back(Pair("code", code));
55 error.push_back(Pair("message", message));
60 void PrintConsole(const std::string &format, ...)
63 int limit = sizeof(buffer);
65 va_start(arg_ptr, format);
66 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
68 if (ret < 0 || ret >= limit)
74 fprintf(stdout, "%s", buffer);
78 int64_t AmountFromValue(const Value& value)
80 double dAmount = value.get_real();
81 if (dAmount <= 0.0 || dAmount > 21000000.0)
82 throw JSONRPCError(-3, "Invalid amount");
83 int64_t nAmount = roundint64(dAmount * COIN);
84 if (!MoneyRange(nAmount))
85 throw JSONRPCError(-3, "Invalid amount");
89 Value ValueFromAmount(int64_t amount)
91 return (double)amount / (double)COIN;
94 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
96 int confirms = wtx.GetDepthInMainChain();
97 entry.push_back(Pair("confirmations", confirms));
100 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
101 entry.push_back(Pair("blockindex", wtx.nIndex));
103 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
104 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
105 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
106 entry.push_back(Pair(item.first, item.second));
109 string AccountFromValue(const Value& value)
111 string strAccount = value.get_str();
112 if (strAccount == "*")
113 throw JSONRPCError(-11, "Invalid account name");
120 /// Note: This interface may still be subject to change.
124 Value help(const Array& params, bool fHelp)
126 if (fHelp || params.size() > 1)
129 "List commands, or get help for a command.");
132 if (params.size() > 0)
133 strCommand = params[0].get_str();
136 set<rpcfn_type> setDone;
137 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
139 string strMethod = (*mi).first;
140 // We already filter duplicates, but these deprecated screw up the sort order
141 if (strMethod == "getamountreceived" ||
142 strMethod == "getallreceived" ||
143 strMethod == "getblocknumber" || // deprecated
144 (strMethod.find("label") != string::npos))
146 if (strCommand != "" && strMethod != strCommand)
151 rpcfn_type pfn = (*mi).second;
152 if (setDone.insert(pfn).second)
153 (*pfn)(params, true);
155 catch (std::exception& e)
157 // Help text is returned in an exception
158 string strHelp = string(e.what());
159 if (strCommand == "")
160 if (strHelp.find('\n') != -1)
161 strHelp = strHelp.substr(0, strHelp.find('\n'));
162 strRet += strHelp + "\n";
166 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
167 strRet = strRet.substr(0,strRet.size()-1);
172 Value stop(const Array& params, bool fHelp)
174 if (fHelp || params.size() != 0)
177 "Stop bitcoin server.");
179 // Shutdown will take long enough that the response should get back
180 CreateThread(Shutdown, NULL);
181 return "bitcoin server stopping";
183 throw runtime_error("NYI: cannot shut down GUI with RPC command");
188 Value getblockcount(const Array& params, bool fHelp)
190 if (fHelp || params.size() != 0)
193 "Returns the number of blocks in the longest block chain.");
200 Value getblocknumber(const Array& params, bool fHelp)
202 if (fHelp || params.size() != 0)
205 "Deprecated. Use getblockcount.");
211 Value getconnectioncount(const Array& params, bool fHelp)
213 if (fHelp || params.size() != 0)
215 "getconnectioncount\n"
216 "Returns the number of connections to other nodes.");
218 return (int)vNodes.size();
222 double GetDifficulty()
224 // Floating point number that is a multiple of the minimum difficulty,
225 // minimum difficulty = 1.0.
227 if (pindexBest == NULL)
229 int nShift = (pindexBest->nBits >> 24) & 0xff;
232 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
248 Value getdifficulty(const Array& params, bool fHelp)
250 if (fHelp || params.size() != 0)
253 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
255 return GetDifficulty();
259 Value getgenerate(const Array& params, bool fHelp)
261 if (fHelp || params.size() != 0)
264 "Returns true or false.");
266 return (bool)fGenerateBitcoins;
270 Value setgenerate(const Array& params, bool fHelp)
272 if (fHelp || params.size() < 1 || params.size() > 2)
274 "setgenerate <generate> [genproclimit]\n"
275 "<generate> is true or false to turn generation on or off.\n"
276 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
278 bool fGenerate = true;
279 if (params.size() > 0)
280 fGenerate = params[0].get_bool();
282 if (params.size() > 1)
284 int nGenProcLimit = params[1].get_int();
285 fLimitProcessors = (nGenProcLimit != -1);
286 WriteSetting("fLimitProcessors", fLimitProcessors);
287 if (nGenProcLimit != -1)
288 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
289 if (nGenProcLimit == 0)
293 GenerateBitcoins(fGenerate, pwalletMain);
298 Value gethashespersec(const Array& params, bool fHelp)
300 if (fHelp || params.size() != 0)
303 "Returns a recent hashes per second performance measurement while generating.");
305 if (GetTimeMillis() - nHPSTimerStart > 8000)
306 return (boost::int64_t)0;
307 return (boost::int64_t)dHashesPerSec;
311 Value getinfo(const Array& params, bool fHelp)
313 if (fHelp || params.size() != 0)
316 "Returns an object containing various state info.");
319 obj.push_back(Pair("version", (int)CLIENT_VERSION));
320 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
321 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
322 obj.push_back(Pair("blocks", (int)nBestHeight));
323 obj.push_back(Pair("connections", (int)vNodes.size()));
324 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
325 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
326 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
327 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
328 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
329 obj.push_back(Pair("testnet", fTestNet));
330 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
331 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
332 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
333 if (pwalletMain->IsCrypted())
334 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
335 obj.push_back(Pair("errors", GetWarnings("statusbar")));
340 Value getnewaddress(const Array& params, bool fHelp)
342 if (fHelp || params.size() > 1)
344 "getnewaddress [account]\n"
345 "Returns a new bitcoin address for receiving payments. "
346 "If [account] is specified (recommended), it is added to the address book "
347 "so payments received with the address will be credited to [account].");
349 // Parse the account first so we don't generate a key if there's an error
351 if (params.size() > 0)
352 strAccount = AccountFromValue(params[0]);
354 if (!pwalletMain->IsLocked())
355 pwalletMain->TopUpKeyPool();
357 // Generate a new key that is added to wallet
358 std::vector<unsigned char> newKey;
359 if (!pwalletMain->GetKeyFromPool(newKey, false))
360 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
361 CBitcoinAddress address(newKey);
363 pwalletMain->SetAddressBookName(address, strAccount);
365 return address.ToString();
369 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
371 CWalletDB walletdb(pwalletMain->strWalletFile);
374 walletdb.ReadAccount(strAccount, account);
376 bool bKeyUsed = false;
378 // Check if the current key has been used
379 if (!account.vchPubKey.empty())
381 CScript scriptPubKey;
382 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
383 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
384 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
387 const CWalletTx& wtx = (*it).second;
388 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
389 if (txout.scriptPubKey == scriptPubKey)
394 // Generate a new key
395 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
397 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
398 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
400 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
401 walletdb.WriteAccount(strAccount, account);
404 return CBitcoinAddress(account.vchPubKey);
407 Value getaccountaddress(const Array& params, bool fHelp)
409 if (fHelp || params.size() != 1)
411 "getaccountaddress <account>\n"
412 "Returns the current bitcoin address for receiving payments to this account.");
414 // Parse the account first so we don't generate a key if there's an error
415 string strAccount = AccountFromValue(params[0]);
419 ret = GetAccountAddress(strAccount).ToString();
426 Value setaccount(const Array& params, bool fHelp)
428 if (fHelp || params.size() < 1 || params.size() > 2)
430 "setaccount <bitcoinaddress> <account>\n"
431 "Sets the account associated with the given address.");
433 CBitcoinAddress address(params[0].get_str());
434 if (!address.IsValid())
435 throw JSONRPCError(-5, "Invalid bitcoin address");
439 if (params.size() > 1)
440 strAccount = AccountFromValue(params[1]);
442 // Detect when changing the account of an address that is the 'unused current key' of another account:
443 if (pwalletMain->mapAddressBook.count(address))
445 string strOldAccount = pwalletMain->mapAddressBook[address];
446 if (address == GetAccountAddress(strOldAccount))
447 GetAccountAddress(strOldAccount, true);
450 pwalletMain->SetAddressBookName(address, strAccount);
456 Value getaccount(const Array& params, bool fHelp)
458 if (fHelp || params.size() != 1)
460 "getaccount <bitcoinaddress>\n"
461 "Returns the account associated with the given address.");
463 CBitcoinAddress address(params[0].get_str());
464 if (!address.IsValid())
465 throw JSONRPCError(-5, "Invalid bitcoin address");
468 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
469 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
470 strAccount = (*mi).second;
475 Value getaddressesbyaccount(const Array& params, bool fHelp)
477 if (fHelp || params.size() != 1)
479 "getaddressesbyaccount <account>\n"
480 "Returns the list of addresses for the given account.");
482 string strAccount = AccountFromValue(params[0]);
484 // Find all addresses that have the given account
486 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
488 const CBitcoinAddress& address = item.first;
489 const string& strName = item.second;
490 if (strName == strAccount)
491 ret.push_back(address.ToString());
496 Value settxfee(const Array& params, bool fHelp)
498 if (fHelp || params.size() < 1 || params.size() > 1)
500 "settxfee <amount>\n"
501 "<amount> is a real and is rounded to the nearest 0.00000001");
505 if (params[0].get_real() != 0.0)
506 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
508 nTransactionFee = nAmount;
512 Value sendtoaddress(const Array& params, bool fHelp)
514 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
516 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
517 "<amount> is a real and is rounded to the nearest 0.00000001\n"
518 "requires wallet passphrase to be set with walletpassphrase first");
519 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
521 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
522 "<amount> is a real and is rounded to the nearest 0.00000001");
524 CBitcoinAddress address(params[0].get_str());
525 if (!address.IsValid())
526 throw JSONRPCError(-5, "Invalid bitcoin address");
529 int64_t nAmount = AmountFromValue(params[1]);
533 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
534 wtx.mapValue["comment"] = params[2].get_str();
535 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
536 wtx.mapValue["to"] = params[3].get_str();
538 if (pwalletMain->IsLocked())
539 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
541 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
543 throw JSONRPCError(-4, strError);
545 return wtx.GetHash().GetHex();
548 static const string strMessageMagic = "Bitcoin Signed Message:\n";
550 Value signmessage(const Array& params, bool fHelp)
552 if (fHelp || params.size() != 2)
554 "signmessage <bitcoinaddress> <message>\n"
555 "Sign a message with the private key of an address");
557 if (pwalletMain->IsLocked())
558 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
560 string strAddress = params[0].get_str();
561 string strMessage = params[1].get_str();
563 CBitcoinAddress addr(strAddress);
565 throw JSONRPCError(-3, "Invalid address");
568 if (!pwalletMain->GetKey(addr, key))
569 throw JSONRPCError(-4, "Private key not available");
571 CDataStream ss(SER_GETHASH);
572 ss << strMessageMagic;
575 vector<unsigned char> vchSig;
576 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
577 throw JSONRPCError(-5, "Sign failed");
579 return EncodeBase64(&vchSig[0], vchSig.size());
582 Value verifymessage(const Array& params, bool fHelp)
584 if (fHelp || params.size() != 3)
586 "verifymessage <bitcoinaddress> <signature> <message>\n"
587 "Verify a signed message");
589 string strAddress = params[0].get_str();
590 string strSign = params[1].get_str();
591 string strMessage = params[2].get_str();
593 CBitcoinAddress addr(strAddress);
595 throw JSONRPCError(-3, "Invalid address");
597 bool fInvalid = false;
598 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
601 throw JSONRPCError(-5, "Malformed base64 encoding");
603 CDataStream ss(SER_GETHASH);
604 ss << strMessageMagic;
608 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
611 return (CBitcoinAddress(key.GetPubKey()) == addr);
615 Value getreceivedbyaddress(const Array& params, bool fHelp)
617 if (fHelp || params.size() < 1 || params.size() > 2)
619 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
620 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
623 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
624 CScript scriptPubKey;
625 if (!address.IsValid())
626 throw JSONRPCError(-5, "Invalid bitcoin address");
627 scriptPubKey.SetBitcoinAddress(address);
628 if (!IsMine(*pwalletMain,scriptPubKey))
631 // Minimum confirmations
633 if (params.size() > 1)
634 nMinDepth = params[1].get_int();
638 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
640 const CWalletTx& wtx = (*it).second;
641 if (wtx.IsCoinBase() || !wtx.IsFinal())
644 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
645 if (txout.scriptPubKey == scriptPubKey)
646 if (wtx.GetDepthInMainChain() >= nMinDepth)
647 nAmount += txout.nValue;
650 return ValueFromAmount(nAmount);
654 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
656 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
658 const CBitcoinAddress& address = item.first;
659 const string& strName = item.second;
660 if (strName == strAccount)
661 setAddress.insert(address);
666 Value getreceivedbyaccount(const Array& params, bool fHelp)
668 if (fHelp || params.size() < 1 || params.size() > 2)
670 "getreceivedbyaccount <account> [minconf=1]\n"
671 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
673 // Minimum confirmations
675 if (params.size() > 1)
676 nMinDepth = params[1].get_int();
678 // Get the set of pub keys assigned to account
679 string strAccount = AccountFromValue(params[0]);
680 set<CBitcoinAddress> setAddress;
681 GetAccountAddresses(strAccount, setAddress);
685 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
687 const CWalletTx& wtx = (*it).second;
688 if (wtx.IsCoinBase() || !wtx.IsFinal())
691 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
693 CBitcoinAddress address;
694 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
695 if (wtx.GetDepthInMainChain() >= nMinDepth)
696 nAmount += txout.nValue;
700 return (double)nAmount / (double)COIN;
704 int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
706 int64_t nBalance = 0;
708 // Tally wallet transactions
709 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
711 const CWalletTx& wtx = (*it).second;
715 int64_t nGenerated, nReceived, nSent, nFee;
716 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
718 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
719 nBalance += nReceived;
720 nBalance += nGenerated - nSent - nFee;
723 // Tally internal accounting entries
724 nBalance += walletdb.GetAccountCreditDebit(strAccount);
729 int64_t GetAccountBalance(const string& strAccount, int nMinDepth)
731 CWalletDB walletdb(pwalletMain->strWalletFile);
732 return GetAccountBalance(walletdb, strAccount, nMinDepth);
736 Value getbalance(const Array& params, bool fHelp)
738 if (fHelp || params.size() > 2)
740 "getbalance [account] [minconf=1]\n"
741 "If [account] is not specified, returns the server's total available balance.\n"
742 "If [account] is specified, returns the balance in the account.");
744 if (params.size() == 0)
745 return ValueFromAmount(pwalletMain->GetBalance());
748 if (params.size() > 1)
749 nMinDepth = params[1].get_int();
751 if (params[0].get_str() == "*") {
752 // Calculate total balance a different way from GetBalance()
753 // (GetBalance() sums up all unspent TxOuts)
754 // getbalance and getbalance '*' should always return the same number.
755 int64_t nBalance = 0;
756 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
758 const CWalletTx& wtx = (*it).second;
762 int64_t allGeneratedImmature, allGeneratedMature, allFee;
763 allGeneratedImmature = allGeneratedMature = allFee = 0;
764 string strSentAccount;
765 list<pair<CBitcoinAddress, int64_t> > listReceived;
766 list<pair<CBitcoinAddress, int64_t> > listSent;
767 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
768 if (wtx.GetDepthInMainChain() >= nMinDepth)
769 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64_t)& r, listReceived)
770 nBalance += r.second;
771 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64_t)& r, listSent)
772 nBalance -= r.second;
774 nBalance += allGeneratedMature;
776 return ValueFromAmount(nBalance);
779 string strAccount = AccountFromValue(params[0]);
781 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
783 return ValueFromAmount(nBalance);
787 Value movecmd(const Array& params, bool fHelp)
789 if (fHelp || params.size() < 3 || params.size() > 5)
791 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
792 "Move from one account in your wallet to another.");
794 string strFrom = AccountFromValue(params[0]);
795 string strTo = AccountFromValue(params[1]);
796 int64_t nAmount = AmountFromValue(params[2]);
797 if (params.size() > 3)
798 // unused parameter, used to be nMinDepth, keep type-checking it though
799 (void)params[3].get_int();
801 if (params.size() > 4)
802 strComment = params[4].get_str();
804 CWalletDB walletdb(pwalletMain->strWalletFile);
807 int64_t nNow = GetAdjustedTime();
810 CAccountingEntry debit;
811 debit.strAccount = strFrom;
812 debit.nCreditDebit = -nAmount;
814 debit.strOtherAccount = strTo;
815 debit.strComment = strComment;
816 walletdb.WriteAccountingEntry(debit);
819 CAccountingEntry credit;
820 credit.strAccount = strTo;
821 credit.nCreditDebit = nAmount;
823 credit.strOtherAccount = strFrom;
824 credit.strComment = strComment;
825 walletdb.WriteAccountingEntry(credit);
827 walletdb.TxnCommit();
833 Value sendfrom(const Array& params, bool fHelp)
835 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
837 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
838 "<amount> is a real and is rounded to the nearest 0.00000001\n"
839 "requires wallet passphrase to be set with walletpassphrase first");
840 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
842 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
843 "<amount> is a real and is rounded to the nearest 0.00000001");
845 string strAccount = AccountFromValue(params[0]);
846 CBitcoinAddress address(params[1].get_str());
847 if (!address.IsValid())
848 throw JSONRPCError(-5, "Invalid bitcoin address");
849 int64_t nAmount = AmountFromValue(params[2]);
851 if (params.size() > 3)
852 nMinDepth = params[3].get_int();
855 wtx.strFromAccount = strAccount;
856 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
857 wtx.mapValue["comment"] = params[4].get_str();
858 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
859 wtx.mapValue["to"] = params[5].get_str();
861 if (pwalletMain->IsLocked())
862 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
865 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
866 if (nAmount > nBalance)
867 throw JSONRPCError(-6, "Account has insufficient funds");
870 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
872 throw JSONRPCError(-4, strError);
874 return wtx.GetHash().GetHex();
878 Value sendmany(const Array& params, bool fHelp)
880 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
882 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
883 "amounts are double-precision floating point numbers\n"
884 "requires wallet passphrase to be set with walletpassphrase first");
885 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
887 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
888 "amounts are double-precision floating point numbers");
890 string strAccount = AccountFromValue(params[0]);
891 Object sendTo = params[1].get_obj();
893 if (params.size() > 2)
894 nMinDepth = params[2].get_int();
897 wtx.strFromAccount = strAccount;
898 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
899 wtx.mapValue["comment"] = params[3].get_str();
901 set<CBitcoinAddress> setAddress;
902 vector<pair<CScript, int64_t> > vecSend;
904 int64_t totalAmount = 0;
905 BOOST_FOREACH(const Pair& s, sendTo)
907 CBitcoinAddress address(s.name_);
908 if (!address.IsValid())
909 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
911 if (setAddress.count(address))
912 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
913 setAddress.insert(address);
915 CScript scriptPubKey;
916 scriptPubKey.SetBitcoinAddress(address);
917 int64_t nAmount = AmountFromValue(s.value_);
918 totalAmount += nAmount;
920 vecSend.push_back(make_pair(scriptPubKey, nAmount));
923 if (pwalletMain->IsLocked())
924 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
927 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
928 if (totalAmount > nBalance)
929 throw JSONRPCError(-6, "Account has insufficient funds");
932 CReserveKey keyChange(pwalletMain);
933 int64_t nFeeRequired = 0;
934 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
937 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
938 throw JSONRPCError(-6, "Insufficient funds");
939 throw JSONRPCError(-4, "Transaction creation failed");
941 if (!pwalletMain->CommitTransaction(wtx, keyChange))
942 throw JSONRPCError(-4, "Transaction commit failed");
944 return wtx.GetHash().GetHex();
947 Value addmultisigaddress(const Array& params, bool fHelp)
949 if (fHelp || params.size() < 2 || params.size() > 3)
951 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
952 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
953 "each key is a bitcoin address, hex or base58 public key\n"
954 "If [account] is specified, assign address to [account].";
955 throw runtime_error(msg);
958 throw runtime_error("addmultisigaddress available only when running -testnet\n");
960 int nRequired = params[0].get_int();
961 const Array& keys = params[1].get_array();
963 if (params.size() > 2)
964 strAccount = AccountFromValue(params[2]);
966 // Gather public keys
967 if (keys.size() < nRequired)
969 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
970 std::vector<CKey> pubkeys;
971 pubkeys.resize(keys.size());
972 for (int i = 0; i < keys.size(); i++)
974 const std::string& ks = keys[i].get_str();
975 if (ks.size() == 130) // hex public key
976 pubkeys[i].SetPubKey(ParseHex(ks));
977 else if (ks.size() > 34) // base58-encoded
979 std::vector<unsigned char> vchPubKey;
980 if (DecodeBase58(ks, vchPubKey))
981 pubkeys[i].SetPubKey(vchPubKey);
983 throw runtime_error("Error base58 decoding key: "+ks);
985 else // bitcoin address for key in this wallet
987 CBitcoinAddress address(ks);
988 if (!pwalletMain->GetKey(address, pubkeys[i]))
990 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
994 // Construct using OP_EVAL
996 inner.SetMultisig(nRequired, pubkeys);
998 uint160 scriptHash = Hash160(inner);
999 CScript scriptPubKey;
1000 scriptPubKey.SetEval(inner);
1001 pwalletMain->AddCScript(scriptHash, inner);
1002 CBitcoinAddress address;
1003 address.SetScriptHash160(scriptHash);
1005 pwalletMain->SetAddressBookName(address, strAccount);
1006 return address.ToString();
1017 nConf = std::numeric_limits<int>::max();
1021 Value ListReceived(const Array& params, bool fByAccounts)
1023 // Minimum confirmations
1025 if (params.size() > 0)
1026 nMinDepth = params[0].get_int();
1028 // Whether to include empty accounts
1029 bool fIncludeEmpty = false;
1030 if (params.size() > 1)
1031 fIncludeEmpty = params[1].get_bool();
1034 map<CBitcoinAddress, tallyitem> mapTally;
1035 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1037 const CWalletTx& wtx = (*it).second;
1038 if (wtx.IsCoinBase() || !wtx.IsFinal())
1041 int nDepth = wtx.GetDepthInMainChain();
1042 if (nDepth < nMinDepth)
1045 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1047 CBitcoinAddress address;
1048 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
1051 tallyitem& item = mapTally[address];
1052 item.nAmount += txout.nValue;
1053 item.nConf = min(item.nConf, nDepth);
1059 map<string, tallyitem> mapAccountTally;
1060 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1062 const CBitcoinAddress& address = item.first;
1063 const string& strAccount = item.second;
1064 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1065 if (it == mapTally.end() && !fIncludeEmpty)
1068 int64_t nAmount = 0;
1069 int nConf = std::numeric_limits<int>::max();
1070 if (it != mapTally.end())
1072 nAmount = (*it).second.nAmount;
1073 nConf = (*it).second.nConf;
1078 tallyitem& item = mapAccountTally[strAccount];
1079 item.nAmount += nAmount;
1080 item.nConf = min(item.nConf, nConf);
1085 obj.push_back(Pair("address", address.ToString()));
1086 obj.push_back(Pair("account", strAccount));
1087 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1088 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1095 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1097 int64_t nAmount = (*it).second.nAmount;
1098 int nConf = (*it).second.nConf;
1100 obj.push_back(Pair("account", (*it).first));
1101 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1102 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1110 Value listreceivedbyaddress(const Array& params, bool fHelp)
1112 if (fHelp || params.size() > 2)
1113 throw runtime_error(
1114 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1115 "[minconf] is the minimum number of confirmations before payments are included.\n"
1116 "[includeempty] whether to include addresses that haven't received any payments.\n"
1117 "Returns an array of objects containing:\n"
1118 " \"address\" : receiving address\n"
1119 " \"account\" : the account of the receiving address\n"
1120 " \"amount\" : total amount received by the address\n"
1121 " \"confirmations\" : number of confirmations of the most recent transaction included");
1123 return ListReceived(params, false);
1126 Value listreceivedbyaccount(const Array& params, bool fHelp)
1128 if (fHelp || params.size() > 2)
1129 throw runtime_error(
1130 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1131 "[minconf] is the minimum number of confirmations before payments are included.\n"
1132 "[includeempty] whether to include accounts that haven't received any payments.\n"
1133 "Returns an array of objects containing:\n"
1134 " \"account\" : the account of the receiving addresses\n"
1135 " \"amount\" : total amount received by addresses with this account\n"
1136 " \"confirmations\" : number of confirmations of the most recent transaction included");
1138 return ListReceived(params, true);
1141 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1143 int64_t nGeneratedImmature, nGeneratedMature, nFee;
1144 string strSentAccount;
1145 list<pair<CBitcoinAddress, int64_t> > listReceived;
1146 list<pair<CBitcoinAddress, int64_t> > listSent;
1147 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1149 bool fAllAccounts = (strAccount == string("*"));
1151 // Generated blocks assigned to account ""
1152 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1155 entry.push_back(Pair("account", string("")));
1156 if (nGeneratedImmature)
1158 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1159 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1163 entry.push_back(Pair("category", "generate"));
1164 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1167 WalletTxToJSON(wtx, entry);
1168 ret.push_back(entry);
1172 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1174 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64_t)& s, listSent)
1177 entry.push_back(Pair("account", strSentAccount));
1178 entry.push_back(Pair("address", s.first.ToString()));
1179 entry.push_back(Pair("category", "send"));
1180 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1181 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1183 WalletTxToJSON(wtx, entry);
1184 ret.push_back(entry);
1189 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1190 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64_t)& r, listReceived)
1193 if (pwalletMain->mapAddressBook.count(r.first))
1194 account = pwalletMain->mapAddressBook[r.first];
1195 if (fAllAccounts || (account == strAccount))
1198 entry.push_back(Pair("account", account));
1199 entry.push_back(Pair("address", r.first.ToString()));
1200 entry.push_back(Pair("category", "receive"));
1201 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1203 WalletTxToJSON(wtx, entry);
1204 ret.push_back(entry);
1209 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1211 bool fAllAccounts = (strAccount == string("*"));
1213 if (fAllAccounts || acentry.strAccount == strAccount)
1216 entry.push_back(Pair("account", acentry.strAccount));
1217 entry.push_back(Pair("category", "move"));
1218 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1219 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1220 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1221 entry.push_back(Pair("comment", acentry.strComment));
1222 ret.push_back(entry);
1226 Value listtransactions(const Array& params, bool fHelp)
1228 if (fHelp || params.size() > 3)
1229 throw runtime_error(
1230 "listtransactions [account] [count=10] [from=0]\n"
1231 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1233 string strAccount = "*";
1234 if (params.size() > 0)
1235 strAccount = params[0].get_str();
1237 if (params.size() > 1)
1238 nCount = params[1].get_int();
1240 if (params.size() > 2)
1241 nFrom = params[2].get_int();
1244 CWalletDB walletdb(pwalletMain->strWalletFile);
1246 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1247 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1248 typedef multimap<int64_t, TxPair > TxItems;
1251 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1253 CWalletTx* wtx = &((*it).second);
1254 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1256 list<CAccountingEntry> acentries;
1257 walletdb.ListAccountCreditDebit(strAccount, acentries);
1258 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1260 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1263 // Now: iterate backwards until we have nCount items to return:
1264 TxItems::reverse_iterator it = txByTime.rbegin();
1265 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1266 for (; it != txByTime.rend(); ++it)
1268 CWalletTx *const pwtx = (*it).second.first;
1270 ListTransactions(*pwtx, strAccount, 0, true, ret);
1271 CAccountingEntry *const pacentry = (*it).second.second;
1273 AcentryToJSON(*pacentry, strAccount, ret);
1275 if (ret.size() >= nCount) break;
1277 // ret is now newest to oldest
1279 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1280 if (ret.size() > nCount)
1282 Array::iterator last = ret.begin();
1283 std::advance(last, nCount);
1284 ret.erase(last, ret.end());
1286 std::reverse(ret.begin(), ret.end()); // oldest to newest
1291 Value listaccounts(const Array& params, bool fHelp)
1293 if (fHelp || params.size() > 1)
1294 throw runtime_error(
1295 "listaccounts [minconf=1]\n"
1296 "Returns Object that has account names as keys, account balances as values.");
1299 if (params.size() > 0)
1300 nMinDepth = params[0].get_int();
1302 map<string, int64_t> mapAccountBalances;
1303 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1304 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1305 mapAccountBalances[entry.second] = 0;
1308 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1310 const CWalletTx& wtx = (*it).second;
1311 int64_t nGeneratedImmature, nGeneratedMature, nFee;
1312 string strSentAccount;
1313 list<pair<CBitcoinAddress, int64_t> > listReceived;
1314 list<pair<CBitcoinAddress, int64_t> > listSent;
1315 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1316 mapAccountBalances[strSentAccount] -= nFee;
1317 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64_t)& s, listSent)
1318 mapAccountBalances[strSentAccount] -= s.second;
1319 if (wtx.GetDepthInMainChain() >= nMinDepth)
1321 mapAccountBalances[""] += nGeneratedMature;
1322 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64_t)& r, listReceived)
1323 if (pwalletMain->mapAddressBook.count(r.first))
1324 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1326 mapAccountBalances[""] += r.second;
1330 list<CAccountingEntry> acentries;
1331 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1332 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1333 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1336 BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) {
1337 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1342 Value listsinceblock(const Array& params, bool fHelp)
1345 throw runtime_error(
1346 "listsinceblock [blockid] [target-confirmations]\n"
1347 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1349 CBlockIndex *pindex = NULL;
1350 int target_confirms = 1;
1352 if (params.size() > 0)
1354 uint256 blockId = 0;
1356 blockId.SetHex(params[0].get_str());
1357 pindex = CBlockLocator(blockId).GetBlockIndex();
1360 if (params.size() > 1)
1362 target_confirms = params[1].get_int();
1364 if (target_confirms < 1)
1365 throw JSONRPCError(-8, "Invalid parameter");
1368 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1372 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1374 CWalletTx tx = (*it).second;
1376 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1377 ListTransactions(tx, "*", 0, true, transactions);
1382 if (target_confirms == 1)
1385 lastblock = hashBestChain;
1389 int target_height = pindexBest->nHeight + 1 - target_confirms;
1392 for (block = pindexBest;
1393 block && block->nHeight > target_height;
1394 block = block->pprev);
1396 lastblock = block ? block->GetBlockHash() : 0;
1400 ret.push_back(Pair("transactions", transactions));
1401 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1406 Value gettransaction(const Array& params, bool fHelp)
1408 if (fHelp || params.size() != 1)
1409 throw runtime_error(
1410 "gettransaction <txid>\n"
1411 "Get detailed information about <txid>");
1414 hash.SetHex(params[0].get_str());
1418 if (!pwalletMain->mapWallet.count(hash))
1419 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1420 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1422 int64_t nCredit = wtx.GetCredit();
1423 int64_t nDebit = wtx.GetDebit();
1424 int64_t nNet = nCredit - nDebit;
1425 int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1427 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1429 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1431 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1434 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1435 entry.push_back(Pair("details", details));
1441 Value backupwallet(const Array& params, bool fHelp)
1443 if (fHelp || params.size() != 1)
1444 throw runtime_error(
1445 "backupwallet <destination>\n"
1446 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1448 string strDest = params[0].get_str();
1449 BackupWallet(*pwalletMain, strDest);
1455 Value keypoolrefill(const Array& params, bool fHelp)
1457 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1458 throw runtime_error(
1460 "Fills the keypool, requires wallet passphrase to be set.");
1461 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1462 throw runtime_error(
1464 "Fills the keypool.");
1466 if (pwalletMain->IsLocked())
1467 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1469 pwalletMain->TopUpKeyPool();
1471 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1472 throw JSONRPCError(-4, "Error refreshing keypool.");
1478 void ThreadTopUpKeyPool(void* parg)
1480 pwalletMain->TopUpKeyPool();
1483 void ThreadCleanWalletPassphrase(void* parg)
1485 int64_t nMyWakeTime = GetTime() + *((int*)parg);
1487 if (nWalletUnlockTime == 0)
1489 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1491 nWalletUnlockTime = nMyWakeTime;
1494 while (GetTime() < nWalletUnlockTime)
1495 Sleep(GetTime() - nWalletUnlockTime);
1497 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1499 nWalletUnlockTime = 0;
1504 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1506 if (nWalletUnlockTime < nMyWakeTime)
1507 nWalletUnlockTime = nMyWakeTime;
1513 pwalletMain->Lock();
1518 Value walletpassphrase(const Array& params, bool fHelp)
1520 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1521 throw runtime_error(
1522 "walletpassphrase <passphrase> <timeout>\n"
1523 "Stores the wallet decryption key in memory for <timeout> seconds.");
1526 if (!pwalletMain->IsCrypted())
1527 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1529 if (!pwalletMain->IsLocked())
1530 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1532 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1533 SecureString strWalletPass;
1534 strWalletPass.reserve(100);
1535 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1536 // Alternately, find a way to make params[0] mlock()'d to begin with.
1537 strWalletPass = params[0].get_str().c_str();
1539 if (strWalletPass.length() > 0)
1541 if (!pwalletMain->Unlock(strWalletPass))
1542 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1545 throw runtime_error(
1546 "walletpassphrase <passphrase> <timeout>\n"
1547 "Stores the wallet decryption key in memory for <timeout> seconds.");
1549 CreateThread(ThreadTopUpKeyPool, NULL);
1550 int* pnSleepTime = new int(params[1].get_int());
1551 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1557 Value walletpassphrasechange(const Array& params, bool fHelp)
1559 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1560 throw runtime_error(
1561 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1562 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1565 if (!pwalletMain->IsCrypted())
1566 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1568 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1569 // Alternately, find a way to make params[0] mlock()'d to begin with.
1570 SecureString strOldWalletPass;
1571 strOldWalletPass.reserve(100);
1572 strOldWalletPass = params[0].get_str().c_str();
1574 SecureString strNewWalletPass;
1575 strNewWalletPass.reserve(100);
1576 strNewWalletPass = params[1].get_str().c_str();
1578 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1579 throw runtime_error(
1580 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1581 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1583 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1584 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1590 Value walletlock(const Array& params, bool fHelp)
1592 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1593 throw runtime_error(
1595 "Removes the wallet encryption key from memory, locking the wallet.\n"
1596 "After calling this method, you will need to call walletpassphrase again\n"
1597 "before being able to call any methods which require the wallet to be unlocked.");
1600 if (!pwalletMain->IsCrypted())
1601 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1603 pwalletMain->Lock();
1604 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1606 nWalletUnlockTime = 0;
1613 Value encryptwallet(const Array& params, bool fHelp)
1615 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1616 throw runtime_error(
1617 "encryptwallet <passphrase>\n"
1618 "Encrypts the wallet with <passphrase>.");
1621 if (pwalletMain->IsCrypted())
1622 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1625 // shutting down via RPC while the GUI is running does not work (yet):
1626 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1629 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1630 // Alternately, find a way to make params[0] mlock()'d to begin with.
1631 SecureString strWalletPass;
1632 strWalletPass.reserve(100);
1633 strWalletPass = params[0].get_str().c_str();
1635 if (strWalletPass.length() < 1)
1636 throw runtime_error(
1637 "encryptwallet <passphrase>\n"
1638 "Encrypts the wallet with <passphrase>.");
1640 if (!pwalletMain->EncryptWallet(strWalletPass))
1641 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1643 // BDB seems to have a bad habit of writing old data into
1644 // slack space in .dat files; that is bad if the old data is
1645 // unencrypted private keys. So:
1646 CreateThread(Shutdown, NULL);
1647 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1651 Value validateaddress(const Array& params, bool fHelp)
1653 if (fHelp || params.size() != 1)
1654 throw runtime_error(
1655 "validateaddress <bitcoinaddress>\n"
1656 "Return information about <bitcoinaddress>.");
1658 CBitcoinAddress address(params[0].get_str());
1659 bool isValid = address.IsValid();
1662 ret.push_back(Pair("isvalid", isValid));
1665 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1666 // version of the address:
1667 string currentAddress = address.ToString();
1668 ret.push_back(Pair("address", currentAddress));
1669 if (pwalletMain->HaveKey(address))
1671 ret.push_back(Pair("ismine", true));
1672 std::vector<unsigned char> vchPubKey;
1673 pwalletMain->GetPubKey(address, vchPubKey);
1674 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1675 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1676 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1678 else if (pwalletMain->HaveCScript(address.GetHash160()))
1680 ret.push_back(Pair("isscript", true));
1682 pwalletMain->GetCScript(address.GetHash160(), subscript);
1683 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1684 std::vector<CBitcoinAddress> addresses;
1685 txnouttype whichType;
1687 ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
1688 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1690 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1691 a.push_back(addr.ToString());
1692 ret.push_back(Pair("addresses", a));
1693 if (whichType == TX_MULTISIG)
1694 ret.push_back(Pair("sigsrequired", nRequired));
1697 ret.push_back(Pair("ismine", false));
1698 if (pwalletMain->mapAddressBook.count(address))
1699 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1704 Value getwork(const Array& params, bool fHelp)
1706 if (fHelp || params.size() > 1)
1707 throw runtime_error(
1709 "If [data] is not specified, returns formatted hash data to work on:\n"
1710 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1711 " \"data\" : block data\n"
1712 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1713 " \"target\" : little endian hash target\n"
1714 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1717 throw JSONRPCError(-9, "Bitcoin is not connected!");
1719 if (IsInitialBlockDownload())
1720 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1722 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1723 static mapNewBlock_t mapNewBlock;
1724 static vector<CBlock*> vNewBlock;
1725 static CReserveKey reservekey(pwalletMain);
1727 if (params.size() == 0)
1730 static unsigned int nTransactionsUpdatedLast;
1731 static CBlockIndex* pindexPrev;
1732 static int64_t nStart;
1733 static CBlock* pblock;
1734 if (pindexPrev != pindexBest ||
1735 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1737 if (pindexPrev != pindexBest)
1739 // Deallocate old blocks since they're obsolete now
1740 mapNewBlock.clear();
1741 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1745 nTransactionsUpdatedLast = nTransactionsUpdated;
1746 pindexPrev = pindexBest;
1750 pblock = CreateNewBlock(reservekey);
1752 throw JSONRPCError(-7, "Out of memory");
1753 vNewBlock.push_back(pblock);
1757 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1760 // Update nExtraNonce
1761 static unsigned int nExtraNonce = 0;
1762 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1765 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1767 // Prebuild hash buffers
1771 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1773 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1776 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1777 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1778 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1779 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1785 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1786 if (vchData.size() != 128)
1787 throw JSONRPCError(-8, "Invalid parameter");
1788 CBlock* pdata = (CBlock*)&vchData[0];
1791 for (int i = 0; i < 128/4; i++)
1792 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1795 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1797 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1799 pblock->nTime = pdata->nTime;
1800 pblock->nNonce = pdata->nNonce;
1801 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1802 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1804 return CheckWork(pblock, *pwalletMain, reservekey);
1809 Value getmemorypool(const Array& params, bool fHelp)
1811 if (fHelp || params.size() > 1)
1812 throw runtime_error(
1813 "getmemorypool [data]\n"
1814 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1815 " \"version\" : block version\n"
1816 " \"previousblockhash\" : hash of current highest block\n"
1817 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1818 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1819 " \"time\" : timestamp appropriate for next block\n"
1820 " \"bits\" : compressed target of next block\n"
1821 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1823 if (params.size() == 0)
1826 throw JSONRPCError(-9, "Bitcoin is not connected!");
1828 if (IsInitialBlockDownload())
1829 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1831 static CReserveKey reservekey(pwalletMain);
1834 static unsigned int nTransactionsUpdatedLast;
1835 static CBlockIndex* pindexPrev;
1836 static int64_t nStart;
1837 static CBlock* pblock;
1838 if (pindexPrev != pindexBest ||
1839 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1841 nTransactionsUpdatedLast = nTransactionsUpdated;
1842 pindexPrev = pindexBest;
1848 pblock = CreateNewBlock(reservekey);
1850 throw JSONRPCError(-7, "Out of memory");
1854 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1858 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1865 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1869 result.push_back(Pair("version", pblock->nVersion));
1870 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1871 result.push_back(Pair("transactions", transactions));
1872 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1873 result.push_back(Pair("time", (int64_t)pblock->nTime));
1879 uBits.nBits = htonl((int32_t)pblock->nBits);
1880 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1887 CDataStream ssBlock(ParseHex(params[0].get_str()));
1891 return ProcessBlock(NULL, &pblock);
1909 pair<string, rpcfn_type> pCallTable[] =
1911 make_pair("help", &help),
1912 make_pair("stop", &stop),
1913 make_pair("getblockcount", &getblockcount),
1914 make_pair("getblocknumber", &getblocknumber),
1915 make_pair("getconnectioncount", &getconnectioncount),
1916 make_pair("getdifficulty", &getdifficulty),
1917 make_pair("getgenerate", &getgenerate),
1918 make_pair("setgenerate", &setgenerate),
1919 make_pair("gethashespersec", &gethashespersec),
1920 make_pair("getinfo", &getinfo),
1921 make_pair("getnewaddress", &getnewaddress),
1922 make_pair("getaccountaddress", &getaccountaddress),
1923 make_pair("setaccount", &setaccount),
1924 make_pair("getaccount", &getaccount),
1925 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1926 make_pair("sendtoaddress", &sendtoaddress),
1927 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1928 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1929 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1930 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1931 make_pair("backupwallet", &backupwallet),
1932 make_pair("keypoolrefill", &keypoolrefill),
1933 make_pair("walletpassphrase", &walletpassphrase),
1934 make_pair("walletpassphrasechange", &walletpassphrasechange),
1935 make_pair("walletlock", &walletlock),
1936 make_pair("encryptwallet", &encryptwallet),
1937 make_pair("validateaddress", &validateaddress),
1938 make_pair("getbalance", &getbalance),
1939 make_pair("move", &movecmd),
1940 make_pair("sendfrom", &sendfrom),
1941 make_pair("sendmany", &sendmany),
1942 make_pair("addmultisigaddress", &addmultisigaddress),
1943 make_pair("gettransaction", &gettransaction),
1944 make_pair("listtransactions", &listtransactions),
1945 make_pair("signmessage", &signmessage),
1946 make_pair("verifymessage", &verifymessage),
1947 make_pair("getwork", &getwork),
1948 make_pair("listaccounts", &listaccounts),
1949 make_pair("settxfee", &settxfee),
1950 make_pair("getmemorypool", &getmemorypool),
1951 make_pair("listsinceblock", &listsinceblock),
1952 make_pair("dumpprivkey", &dumpprivkey),
1953 make_pair("importprivkey", &importprivkey)
1955 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1957 string pAllowInSafeMode[] =
1962 "getblocknumber", // deprecated
1963 "getconnectioncount",
1970 "getaccountaddress",
1972 "getaddressesbyaccount",
1981 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1989 // This ain't Apache. We're just using HTTP header for the length field
1990 // and to be compatible with other JSON-RPC implementations.
1993 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1996 s << "POST / HTTP/1.1\r\n"
1997 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1998 << "Host: 127.0.0.1\r\n"
1999 << "Content-Type: application/json\r\n"
2000 << "Content-Length: " << strMsg.size() << "\r\n"
2001 << "Connection: close\r\n"
2002 << "Accept: application/json\r\n";
2003 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2004 s << item.first << ": " << item.second << "\r\n";
2005 s << "\r\n" << strMsg;
2010 string rfc1123Time()
2015 struct tm* now_gmt = gmtime(&now);
2016 string locale(setlocale(LC_TIME, NULL));
2017 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2018 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2019 setlocale(LC_TIME, locale.c_str());
2020 return string(buffer);
2023 static string HTTPReply(int nStatus, const string& strMsg)
2026 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2028 "Server: bitcoin-json-rpc/%s\r\n"
2029 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2030 "Content-Type: text/html\r\n"
2031 "Content-Length: 296\r\n"
2033 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2034 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2037 "<TITLE>Error</TITLE>\r\n"
2038 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2040 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2041 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2042 const char *cStatus;
2043 if (nStatus == 200) cStatus = "OK";
2044 else if (nStatus == 400) cStatus = "Bad Request";
2045 else if (nStatus == 403) cStatus = "Forbidden";
2046 else if (nStatus == 404) cStatus = "Not Found";
2047 else if (nStatus == 500) cStatus = "Internal Server Error";
2050 "HTTP/1.1 %d %s\r\n"
2052 "Connection: close\r\n"
2053 "Content-Length: %d\r\n"
2054 "Content-Type: application/json\r\n"
2055 "Server: bitcoin-json-rpc/%s\r\n"
2060 rfc1123Time().c_str(),
2062 FormatFullVersion().c_str(),
2066 int ReadHTTPStatus(std::basic_istream<char>& stream)
2069 getline(stream, str);
2070 vector<string> vWords;
2071 boost::split(vWords, str, boost::is_any_of(" "));
2072 if (vWords.size() < 2)
2074 return atoi(vWords[1].c_str());
2077 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2083 std::getline(stream, str);
2084 if (str.empty() || str == "\r")
2086 string::size_type nColon = str.find(":");
2087 if (nColon != string::npos)
2089 string strHeader = str.substr(0, nColon);
2090 boost::trim(strHeader);
2091 boost::to_lower(strHeader);
2092 string strValue = str.substr(nColon+1);
2093 boost::trim(strValue);
2094 mapHeadersRet[strHeader] = strValue;
2095 if (strHeader == "content-length")
2096 nLen = atoi(strValue.c_str());
2102 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2104 mapHeadersRet.clear();
2108 int nStatus = ReadHTTPStatus(stream);
2111 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2112 if (nLen < 0 || nLen > MAX_SIZE)
2118 vector<char> vch(nLen);
2119 stream.read(&vch[0], nLen);
2120 strMessageRet = string(vch.begin(), vch.end());
2126 bool HTTPAuthorized(map<string, string>& mapHeaders)
2128 string strAuth = mapHeaders["authorization"];
2129 if (strAuth.substr(0,6) != "Basic ")
2131 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2132 string strUserPass = DecodeBase64(strUserPass64);
2133 return strUserPass == strRPCUserColonPass;
2137 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2138 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2139 // unspecified (HTTP errors and contents of 'error').
2141 // 1.0 spec: http://json-rpc.org/wiki/specification
2142 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2143 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2146 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2149 request.push_back(Pair("method", strMethod));
2150 request.push_back(Pair("params", params));
2151 request.push_back(Pair("id", id));
2152 return write_string(Value(request), false) + "\n";
2155 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2158 if (error.type() != null_type)
2159 reply.push_back(Pair("result", Value::null));
2161 reply.push_back(Pair("result", result));
2162 reply.push_back(Pair("error", error));
2163 reply.push_back(Pair("id", id));
2164 return write_string(Value(reply), false) + "\n";
2167 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2169 // Send error reply from json-rpc error object
2171 int code = find_value(objError, "code").get_int();
2172 if (code == -32600) nStatus = 400;
2173 else if (code == -32601) nStatus = 404;
2174 string strReply = JSONRPCReply(Value::null, objError, id);
2175 stream << HTTPReply(nStatus, strReply) << std::flush;
2178 bool ClientAllowed(const string& strAddress)
2180 if (strAddress == asio::ip::address_v4::loopback().to_string())
2182 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2183 BOOST_FOREACH(string strAllow, vAllow)
2184 if (WildcardMatch(strAddress, strAllow))
2191 // IOStream device that speaks SSL but can also speak non-SSL
2193 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2195 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2197 fUseSSL = fUseSSLIn;
2198 fNeedHandshake = fUseSSLIn;
2201 void handshake(ssl::stream_base::handshake_type role)
2203 if (!fNeedHandshake) return;
2204 fNeedHandshake = false;
2205 stream.handshake(role);
2207 std::streamsize read(char* s, std::streamsize n)
2209 handshake(ssl::stream_base::server); // HTTPS servers read first
2210 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2211 return stream.next_layer().read_some(asio::buffer(s, n));
2213 std::streamsize write(const char* s, std::streamsize n)
2215 handshake(ssl::stream_base::client); // HTTPS clients write first
2216 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2217 return asio::write(stream.next_layer(), asio::buffer(s, n));
2219 bool connect(const std::string& server, const std::string& port)
2221 ip::tcp::resolver resolver(stream.get_io_service());
2222 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2223 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2224 ip::tcp::resolver::iterator end;
2225 boost::system::error_code error = asio::error::host_not_found;
2226 while (error && endpoint_iterator != end)
2228 stream.lowest_layer().close();
2229 stream.lowest_layer().connect(*endpoint_iterator++, error);
2237 bool fNeedHandshake;
2243 void ThreadRPCServer(void* parg)
2245 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2248 vnThreadsRunning[4]++;
2249 ThreadRPCServer2(parg);
2250 vnThreadsRunning[4]--;
2252 catch (std::exception& e) {
2253 vnThreadsRunning[4]--;
2254 PrintException(&e, "ThreadRPCServer()");
2256 vnThreadsRunning[4]--;
2257 PrintException(NULL, "ThreadRPCServer()");
2259 printf("ThreadRPCServer exiting\n");
2262 void ThreadRPCServer2(void* parg)
2264 printf("ThreadRPCServer started\n");
2266 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2267 if (strRPCUserColonPass == ":")
2269 string strWhatAmI = "To use bitcoind";
2270 if (mapArgs.count("-server"))
2271 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2272 else if (mapArgs.count("-daemon"))
2273 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2275 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2276 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2278 GetConfigFile().c_str());
2280 CreateThread(Shutdown, NULL);
2285 bool fUseSSL = GetBoolArg("-rpcssl");
2286 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2288 asio::io_service io_service;
2289 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2290 ip::tcp::acceptor acceptor(io_service, endpoint);
2292 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2295 ssl::context context(io_service, ssl::context::sslv23);
2298 context.set_options(ssl::context::no_sslv2);
2299 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2300 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2301 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2302 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2303 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2304 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2305 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2306 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2308 string ciphers = GetArg("-rpcsslciphers",
2309 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2310 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2314 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2319 // Accept connection
2321 SSLStream sslStream(io_service, context);
2322 SSLIOStreamDevice d(sslStream, fUseSSL);
2323 iostreams::stream<SSLIOStreamDevice> stream(d);
2325 ip::tcp::iostream stream;
2328 ip::tcp::endpoint peer;
2329 vnThreadsRunning[4]--;
2331 acceptor.accept(sslStream.lowest_layer(), peer);
2333 acceptor.accept(*stream.rdbuf(), peer);
2335 vnThreadsRunning[4]++;
2339 // Restrict callers by IP
2340 if (!ClientAllowed(peer.address().to_string()))
2342 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2344 stream << HTTPReply(403, "") << std::flush;
2348 map<string, string> mapHeaders;
2351 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2352 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2355 printf("ThreadRPCServer ReadHTTP timeout\n");
2359 // Check authorization
2360 if (mapHeaders.count("authorization") == 0)
2362 stream << HTTPReply(401, "") << std::flush;
2365 if (!HTTPAuthorized(mapHeaders))
2367 // Deter brute-forcing short passwords
2368 if (mapArgs["-rpcpassword"].size() < 15)
2371 stream << HTTPReply(401, "") << std::flush;
2372 printf("ThreadRPCServer incorrect password attempt\n");
2376 Value id = Value::null;
2381 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2382 throw JSONRPCError(-32700, "Parse error");
2383 const Object& request = valRequest.get_obj();
2385 // Parse id now so errors from here on will have the id
2386 id = find_value(request, "id");
2389 Value valMethod = find_value(request, "method");
2390 if (valMethod.type() == null_type)
2391 throw JSONRPCError(-32600, "Missing method");
2392 if (valMethod.type() != str_type)
2393 throw JSONRPCError(-32600, "Method must be a string");
2394 string strMethod = valMethod.get_str();
2395 if (strMethod != "getwork" && strMethod != "getmemorypool")
2396 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2399 Value valParams = find_value(request, "params");
2401 if (valParams.type() == array_type)
2402 params = valParams.get_array();
2403 else if (valParams.type() == null_type)
2406 throw JSONRPCError(-32600, "Params must be an array");
2409 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2410 if (mi == mapCallTable.end())
2411 throw JSONRPCError(-32601, "Method not found");
2413 // Observe safe mode
2414 string strWarning = GetWarnings("rpc");
2415 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2416 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2422 CRITICAL_BLOCK(cs_main)
2423 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2424 result = (*(*mi).second)(params, false);
2427 string strReply = JSONRPCReply(result, Value::null, id);
2428 stream << HTTPReply(200, strReply) << std::flush;
2430 catch (std::exception& e)
2432 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2435 catch (Object& objError)
2437 ErrorReply(stream, objError, id);
2439 catch (std::exception& e)
2441 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2449 Object CallRPC(const string& strMethod, const Array& params)
2451 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2452 throw runtime_error(strprintf(
2453 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2454 "If the file does not exist, create it with owner-readable-only file permissions."),
2455 GetConfigFile().c_str()));
2457 // Connect to localhost
2458 bool fUseSSL = GetBoolArg("-rpcssl");
2460 asio::io_service io_service;
2461 ssl::context context(io_service, ssl::context::sslv23);
2462 context.set_options(ssl::context::no_sslv2);
2463 SSLStream sslStream(io_service, context);
2464 SSLIOStreamDevice d(sslStream, fUseSSL);
2465 iostreams::stream<SSLIOStreamDevice> stream(d);
2466 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2467 throw runtime_error("couldn't connect to server");
2470 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2472 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2474 throw runtime_error("couldn't connect to server");
2478 // HTTP basic authentication
2479 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2480 map<string, string> mapRequestHeaders;
2481 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2484 string strRequest = JSONRPCRequest(strMethod, params, 1);
2485 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2486 stream << strPost << std::flush;
2489 map<string, string> mapHeaders;
2491 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2493 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2494 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2495 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2496 else if (strReply.empty())
2497 throw runtime_error("no response from server");
2501 if (!read_string(strReply, valReply))
2502 throw runtime_error("couldn't parse reply from server");
2503 const Object& reply = valReply.get_obj();
2505 throw runtime_error("expected reply to have result, error and id properties");
2513 template<typename T>
2514 void ConvertTo(Value& value)
2516 if (value.type() == str_type)
2518 // reinterpret string as unquoted json value
2520 if (!read_string(value.get_str(), value2))
2521 throw runtime_error("type mismatch");
2522 value = value2.get_value<T>();
2526 value = value.get_value<T>();
2530 int CommandLineRPC(int argc, char *argv[])
2537 while (argc > 1 && IsSwitchChar(argv[1][0]))
2545 throw runtime_error("too few parameters");
2546 string strMethod = argv[1];
2548 // Parameters default to strings
2550 for (int i = 2; i < argc; i++)
2551 params.push_back(argv[i]);
2552 int n = params.size();
2555 // Special case non-string parameter types
2557 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2558 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2559 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2560 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2561 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2562 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2563 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2564 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2565 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2566 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2567 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2568 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2569 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2570 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2571 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2572 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2573 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2574 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2575 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2576 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2577 if (strMethod == "sendmany" && n > 1)
2579 string s = params[1].get_str();
2581 if (!read_string(s, v) || v.type() != obj_type)
2582 throw runtime_error("type mismatch");
2583 params[1] = v.get_obj();
2585 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2586 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2587 if (strMethod == "addmultisigaddress" && n > 1)
2589 string s = params[1].get_str();
2591 if (!read_string(s, v) || v.type() != array_type)
2592 throw runtime_error("addmultisigaddress: type mismatch "+s);
2593 params[1] = v.get_array();
2597 Object reply = CallRPC(strMethod, params);
2600 const Value& result = find_value(reply, "result");
2601 const Value& error = find_value(reply, "error");
2603 if (error.type() != null_type)
2606 strPrint = "error: " + write_string(error, false);
2607 int code = find_value(error.get_obj(), "code").get_int();
2613 if (result.type() == null_type)
2615 else if (result.type() == str_type)
2616 strPrint = result.get_str();
2618 strPrint = write_string(result, true);
2621 catch (std::exception& e)
2623 strPrint = string("error: ") + e.what();
2628 PrintException(NULL, "CommandLineRPC()");
2633 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2642 int main(int argc, char *argv[])
2645 // Turn off microsoft heap dump noise
2646 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2647 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2649 setbuf(stdin, NULL);
2650 setbuf(stdout, NULL);
2651 setbuf(stderr, NULL);
2655 if (argc >= 2 && string(argv[1]) == "-server")
2657 printf("server ready\n");
2658 ThreadRPCServer(NULL);
2662 return CommandLineRPC(argc, argv);
2665 catch (std::exception& e) {
2666 PrintException(&e, "main()");
2668 PrintException(NULL, "main()");