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.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
58 void PrintConsole(const std::string &format, ...)
61 int limit = sizeof(buffer);
63 va_start(arg_ptr, format);
64 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
66 if (ret < 0 || ret >= limit)
72 fprintf(stdout, "%s", buffer);
76 int64 AmountFromValue(const Value& value)
78 double dAmount = value.get_real();
79 if (dAmount <= 0.0 || dAmount > 21000000.0)
80 throw JSONRPCError(-3, "Invalid amount");
81 int64 nAmount = roundint64(dAmount * COIN);
82 if (!MoneyRange(nAmount))
83 throw JSONRPCError(-3, "Invalid amount");
87 Value ValueFromAmount(int64 amount)
89 return (double)amount / (double)COIN;
92 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
94 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
95 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
96 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
97 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
98 entry.push_back(Pair(item.first, item.second));
101 string AccountFromValue(const Value& value)
103 string strAccount = value.get_str();
104 if (strAccount == "*")
105 throw JSONRPCError(-11, "Invalid account name");
112 /// Note: This interface may still be subject to change.
116 Value help(const Array& params, bool fHelp)
118 if (fHelp || params.size() > 1)
121 "List commands, or get help for a command.");
124 if (params.size() > 0)
125 strCommand = params[0].get_str();
128 set<rpcfn_type> setDone;
129 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
131 string strMethod = (*mi).first;
132 // We already filter duplicates, but these deprecated screw up the sort order
133 if (strMethod == "getamountreceived" ||
134 strMethod == "getallreceived" ||
135 strMethod == "getblocknumber" || // deprecated
136 (strMethod.find("label") != string::npos))
138 if (strCommand != "" && strMethod != strCommand)
143 rpcfn_type pfn = (*mi).second;
144 if (setDone.insert(pfn).second)
145 (*pfn)(params, true);
147 catch (std::exception& e)
149 // Help text is returned in an exception
150 string strHelp = string(e.what());
151 if (strCommand == "")
152 if (strHelp.find('\n') != -1)
153 strHelp = strHelp.substr(0, strHelp.find('\n'));
154 strRet += strHelp + "\n";
158 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
159 strRet = strRet.substr(0,strRet.size()-1);
164 Value stop(const Array& params, bool fHelp)
166 if (fHelp || params.size() != 0)
169 "Stop bitcoin server.");
171 // Shutdown will take long enough that the response should get back
172 CreateThread(Shutdown, NULL);
173 return "bitcoin server stopping";
175 throw runtime_error("NYI: cannot shut down GUI with RPC command");
180 Value getblockcount(const Array& params, bool fHelp)
182 if (fHelp || params.size() != 0)
185 "Returns the number of blocks in the longest block chain.");
192 Value getblocknumber(const Array& params, bool fHelp)
194 if (fHelp || params.size() != 0)
197 "Deprecated. Use getblockcount.");
203 Value getconnectioncount(const Array& params, bool fHelp)
205 if (fHelp || params.size() != 0)
207 "getconnectioncount\n"
208 "Returns the number of connections to other nodes.");
210 return (int)vNodes.size();
214 double GetDifficulty()
216 // Floating point number that is a multiple of the minimum difficulty,
217 // minimum difficulty = 1.0.
219 if (pindexBest == NULL)
221 int nShift = (pindexBest->nBits >> 24) & 0xff;
224 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
240 Value getdifficulty(const Array& params, bool fHelp)
242 if (fHelp || params.size() != 0)
245 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
247 return GetDifficulty();
251 Value getgenerate(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Returns true or false.");
258 return (bool)fGenerateBitcoins;
262 Value setgenerate(const Array& params, bool fHelp)
264 if (fHelp || params.size() < 1 || params.size() > 2)
266 "setgenerate <generate> [genproclimit]\n"
267 "<generate> is true or false to turn generation on or off.\n"
268 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
270 bool fGenerate = true;
271 if (params.size() > 0)
272 fGenerate = params[0].get_bool();
274 if (params.size() > 1)
276 int nGenProcLimit = params[1].get_int();
277 fLimitProcessors = (nGenProcLimit != -1);
278 WriteSetting("fLimitProcessors", fLimitProcessors);
279 if (nGenProcLimit != -1)
280 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
281 if (nGenProcLimit == 0)
285 GenerateBitcoins(fGenerate, pwalletMain);
290 Value gethashespersec(const Array& params, bool fHelp)
292 if (fHelp || params.size() != 0)
295 "Returns a recent hashes per second performance measurement while generating.");
297 if (GetTimeMillis() - nHPSTimerStart > 8000)
298 return (boost::int64_t)0;
299 return (boost::int64_t)dHashesPerSec;
303 Value getinfo(const Array& params, bool fHelp)
305 if (fHelp || params.size() != 0)
308 "Returns an object containing various state info.");
311 obj.push_back(Pair("version", (int)CLIENT_VERSION));
312 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
313 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
314 obj.push_back(Pair("blocks", (int)nBestHeight));
315 obj.push_back(Pair("connections", (int)vNodes.size()));
316 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
317 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
318 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
319 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
320 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
321 obj.push_back(Pair("testnet", fTestNet));
322 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
323 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
324 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
325 if (pwalletMain->IsCrypted())
326 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
327 obj.push_back(Pair("errors", GetWarnings("statusbar")));
332 Value getnewaddress(const Array& params, bool fHelp)
334 if (fHelp || params.size() > 1)
336 "getnewaddress [account]\n"
337 "Returns a new bitcoin address for receiving payments. "
338 "If [account] is specified (recommended), it is added to the address book "
339 "so payments received with the address will be credited to [account].");
341 // Parse the account first so we don't generate a key if there's an error
343 if (params.size() > 0)
344 strAccount = AccountFromValue(params[0]);
346 if (!pwalletMain->IsLocked())
347 pwalletMain->TopUpKeyPool();
349 // Generate a new key that is added to wallet
350 std::vector<unsigned char> newKey;
351 if (!pwalletMain->GetKeyFromPool(newKey, false))
352 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
353 CBitcoinAddress address(newKey);
355 pwalletMain->SetAddressBookName(address, strAccount);
357 return address.ToString();
361 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
363 CWalletDB walletdb(pwalletMain->strWalletFile);
366 walletdb.ReadAccount(strAccount, account);
368 bool bKeyUsed = false;
370 // Check if the current key has been used
371 if (!account.vchPubKey.empty())
373 CScript scriptPubKey;
374 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
375 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
376 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
379 const CWalletTx& wtx = (*it).second;
380 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
381 if (txout.scriptPubKey == scriptPubKey)
386 // Generate a new key
387 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
389 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
390 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
392 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
393 walletdb.WriteAccount(strAccount, account);
396 return CBitcoinAddress(account.vchPubKey);
399 Value getaccountaddress(const Array& params, bool fHelp)
401 if (fHelp || params.size() != 1)
403 "getaccountaddress <account>\n"
404 "Returns the current bitcoin address for receiving payments to this account.");
406 // Parse the account first so we don't generate a key if there's an error
407 string strAccount = AccountFromValue(params[0]);
411 ret = GetAccountAddress(strAccount).ToString();
418 Value setaccount(const Array& params, bool fHelp)
420 if (fHelp || params.size() < 1 || params.size() > 2)
422 "setaccount <bitcoinaddress> <account>\n"
423 "Sets the account associated with the given address.");
425 CBitcoinAddress address(params[0].get_str());
426 if (!address.IsValid())
427 throw JSONRPCError(-5, "Invalid bitcoin address");
431 if (params.size() > 1)
432 strAccount = AccountFromValue(params[1]);
434 // Detect when changing the account of an address that is the 'unused current key' of another account:
435 if (pwalletMain->mapAddressBook.count(address))
437 string strOldAccount = pwalletMain->mapAddressBook[address];
438 if (address == GetAccountAddress(strOldAccount))
439 GetAccountAddress(strOldAccount, true);
442 pwalletMain->SetAddressBookName(address, strAccount);
448 Value getaccount(const Array& params, bool fHelp)
450 if (fHelp || params.size() != 1)
452 "getaccount <bitcoinaddress>\n"
453 "Returns the account associated with the given address.");
455 CBitcoinAddress address(params[0].get_str());
456 if (!address.IsValid())
457 throw JSONRPCError(-5, "Invalid bitcoin address");
460 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
461 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
462 strAccount = (*mi).second;
467 Value getaddressesbyaccount(const Array& params, bool fHelp)
469 if (fHelp || params.size() != 1)
471 "getaddressesbyaccount <account>\n"
472 "Returns the list of addresses for the given account.");
474 string strAccount = AccountFromValue(params[0]);
476 // Find all addresses that have the given account
478 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
480 const CBitcoinAddress& address = item.first;
481 const string& strName = item.second;
482 if (strName == strAccount)
483 ret.push_back(address.ToString());
488 Value settxfee(const Array& params, bool fHelp)
490 if (fHelp || params.size() < 1 || params.size() > 1)
492 "settxfee <amount>\n"
493 "<amount> is a real and is rounded to the nearest 0.00000001");
497 if (params[0].get_real() != 0.0)
498 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
500 nTransactionFee = nAmount;
504 Value sendtoaddress(const Array& params, bool fHelp)
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\n"
510 "requires wallet passphrase to be set with walletpassphrase first");
511 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
513 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
514 "<amount> is a real and is rounded to the nearest 0.00000001");
516 CBitcoinAddress address(params[0].get_str());
517 if (!address.IsValid())
518 throw JSONRPCError(-5, "Invalid bitcoin address");
521 int64 nAmount = AmountFromValue(params[1]);
525 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
526 wtx.mapValue["comment"] = params[2].get_str();
527 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
528 wtx.mapValue["to"] = params[3].get_str();
530 if (pwalletMain->IsLocked())
531 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
533 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
535 throw JSONRPCError(-4, strError);
537 return wtx.GetHash().GetHex();
540 static const string strMessageMagic = "Bitcoin Signed Message:\n";
542 Value signmessage(const Array& params, bool fHelp)
544 if (fHelp || params.size() != 2)
546 "signmessage <bitcoinaddress> <message>\n"
547 "Sign a message with the private key of an address");
549 if (pwalletMain->IsLocked())
550 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
552 string strAddress = params[0].get_str();
553 string strMessage = params[1].get_str();
555 CBitcoinAddress addr(strAddress);
557 throw JSONRPCError(-3, "Invalid address");
560 if (!pwalletMain->GetKey(addr, key))
561 throw JSONRPCError(-4, "Private key not available");
563 CDataStream ss(SER_GETHASH);
564 ss << strMessageMagic;
567 vector<unsigned char> vchSig;
568 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
569 throw JSONRPCError(-5, "Sign failed");
571 return EncodeBase64(&vchSig[0], vchSig.size());
574 Value verifymessage(const Array& params, bool fHelp)
576 if (fHelp || params.size() != 3)
578 "verifymessage <bitcoinaddress> <signature> <message>\n"
579 "Verify a signed message");
581 string strAddress = params[0].get_str();
582 string strSign = params[1].get_str();
583 string strMessage = params[2].get_str();
585 CBitcoinAddress addr(strAddress);
587 throw JSONRPCError(-3, "Invalid address");
589 bool fInvalid = false;
590 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
593 throw JSONRPCError(-5, "Malformed base64 encoding");
595 CDataStream ss(SER_GETHASH);
596 ss << strMessageMagic;
600 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
603 return (CBitcoinAddress(key.GetPubKey()) == addr);
607 Value getreceivedbyaddress(const Array& params, bool fHelp)
609 if (fHelp || params.size() < 1 || params.size() > 2)
611 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
612 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
615 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
616 CScript scriptPubKey;
617 if (!address.IsValid())
618 throw JSONRPCError(-5, "Invalid bitcoin address");
619 scriptPubKey.SetBitcoinAddress(address);
620 if (!IsMine(*pwalletMain,scriptPubKey))
623 // Minimum confirmations
625 if (params.size() > 1)
626 nMinDepth = params[1].get_int();
630 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
632 const CWalletTx& wtx = (*it).second;
633 if (wtx.IsCoinBase() || !wtx.IsFinal())
636 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
637 if (txout.scriptPubKey == scriptPubKey)
638 if (wtx.GetDepthInMainChain() >= nMinDepth)
639 nAmount += txout.nValue;
642 return ValueFromAmount(nAmount);
646 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
648 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
650 const CBitcoinAddress& address = item.first;
651 const string& strName = item.second;
652 if (strName == strAccount)
653 setAddress.insert(address);
658 Value getreceivedbyaccount(const Array& params, bool fHelp)
660 if (fHelp || params.size() < 1 || params.size() > 2)
662 "getreceivedbyaccount <account> [minconf=1]\n"
663 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
665 // Minimum confirmations
667 if (params.size() > 1)
668 nMinDepth = params[1].get_int();
670 // Get the set of pub keys assigned to account
671 string strAccount = AccountFromValue(params[0]);
672 set<CBitcoinAddress> setAddress;
673 GetAccountAddresses(strAccount, setAddress);
677 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
679 const CWalletTx& wtx = (*it).second;
680 if (wtx.IsCoinBase() || !wtx.IsFinal())
683 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
685 CBitcoinAddress address;
686 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
687 if (wtx.GetDepthInMainChain() >= nMinDepth)
688 nAmount += txout.nValue;
692 return (double)nAmount / (double)COIN;
696 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
700 // Tally wallet transactions
701 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
703 const CWalletTx& wtx = (*it).second;
707 int64 nGenerated, nReceived, nSent, nFee;
708 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
710 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
711 nBalance += nReceived;
712 nBalance += nGenerated - nSent - nFee;
715 // Tally internal accounting entries
716 nBalance += walletdb.GetAccountCreditDebit(strAccount);
721 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
723 CWalletDB walletdb(pwalletMain->strWalletFile);
724 return GetAccountBalance(walletdb, strAccount, nMinDepth);
728 Value getbalance(const Array& params, bool fHelp)
730 if (fHelp || params.size() > 2)
732 "getbalance [account] [minconf=1]\n"
733 "If [account] is not specified, returns the server's total available balance.\n"
734 "If [account] is specified, returns the balance in the account.");
736 if (params.size() == 0)
737 return ValueFromAmount(pwalletMain->GetBalance());
740 if (params.size() > 1)
741 nMinDepth = params[1].get_int();
743 if (params[0].get_str() == "*") {
744 // Calculate total balance a different way from GetBalance()
745 // (GetBalance() sums up all unspent TxOuts)
746 // getbalance and getbalance '*' should always return the same number.
748 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
750 const CWalletTx& wtx = (*it).second;
754 int64 allGeneratedImmature, allGeneratedMature, allFee;
755 allGeneratedImmature = allGeneratedMature = allFee = 0;
756 string strSentAccount;
757 list<pair<CBitcoinAddress, int64> > listReceived;
758 list<pair<CBitcoinAddress, int64> > listSent;
759 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
760 if (wtx.GetDepthInMainChain() >= nMinDepth)
761 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
762 nBalance += r.second;
763 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
764 nBalance -= r.second;
766 nBalance += allGeneratedMature;
768 return ValueFromAmount(nBalance);
771 string strAccount = AccountFromValue(params[0]);
773 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
775 return ValueFromAmount(nBalance);
779 Value movecmd(const Array& params, bool fHelp)
781 if (fHelp || params.size() < 3 || params.size() > 5)
783 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
784 "Move from one account in your wallet to another.");
786 string strFrom = AccountFromValue(params[0]);
787 string strTo = AccountFromValue(params[1]);
788 int64 nAmount = AmountFromValue(params[2]);
789 if (params.size() > 3)
790 // unused parameter, used to be nMinDepth, keep type-checking it though
791 (void)params[3].get_int();
793 if (params.size() > 4)
794 strComment = params[4].get_str();
796 CWalletDB walletdb(pwalletMain->strWalletFile);
799 int64 nNow = GetAdjustedTime();
802 CAccountingEntry debit;
803 debit.strAccount = strFrom;
804 debit.nCreditDebit = -nAmount;
806 debit.strOtherAccount = strTo;
807 debit.strComment = strComment;
808 walletdb.WriteAccountingEntry(debit);
811 CAccountingEntry credit;
812 credit.strAccount = strTo;
813 credit.nCreditDebit = nAmount;
815 credit.strOtherAccount = strFrom;
816 credit.strComment = strComment;
817 walletdb.WriteAccountingEntry(credit);
819 walletdb.TxnCommit();
825 Value sendfrom(const Array& params, bool fHelp)
827 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
829 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
830 "<amount> is a real and is rounded to the nearest 0.00000001\n"
831 "requires wallet passphrase to be set with walletpassphrase first");
832 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
834 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
835 "<amount> is a real and is rounded to the nearest 0.00000001");
837 string strAccount = AccountFromValue(params[0]);
838 CBitcoinAddress address(params[1].get_str());
839 if (!address.IsValid())
840 throw JSONRPCError(-5, "Invalid bitcoin address");
841 int64 nAmount = AmountFromValue(params[2]);
843 if (params.size() > 3)
844 nMinDepth = params[3].get_int();
847 wtx.strFromAccount = strAccount;
848 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
849 wtx.mapValue["comment"] = params[4].get_str();
850 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
851 wtx.mapValue["to"] = params[5].get_str();
853 if (pwalletMain->IsLocked())
854 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
857 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
858 if (nAmount > nBalance)
859 throw JSONRPCError(-6, "Account has insufficient funds");
862 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
864 throw JSONRPCError(-4, strError);
866 return wtx.GetHash().GetHex();
870 Value sendmany(const Array& params, bool fHelp)
872 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
874 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
875 "amounts are double-precision floating point numbers\n"
876 "requires wallet passphrase to be set with walletpassphrase first");
877 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
879 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
880 "amounts are double-precision floating point numbers");
882 string strAccount = AccountFromValue(params[0]);
883 Object sendTo = params[1].get_obj();
885 if (params.size() > 2)
886 nMinDepth = params[2].get_int();
889 wtx.strFromAccount = strAccount;
890 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
891 wtx.mapValue["comment"] = params[3].get_str();
893 set<CBitcoinAddress> setAddress;
894 vector<pair<CScript, int64> > vecSend;
896 int64 totalAmount = 0;
897 BOOST_FOREACH(const Pair& s, sendTo)
899 CBitcoinAddress address(s.name_);
900 if (!address.IsValid())
901 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
903 if (setAddress.count(address))
904 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
905 setAddress.insert(address);
907 CScript scriptPubKey;
908 scriptPubKey.SetBitcoinAddress(address);
909 int64 nAmount = AmountFromValue(s.value_);
910 totalAmount += nAmount;
912 vecSend.push_back(make_pair(scriptPubKey, nAmount));
915 if (pwalletMain->IsLocked())
916 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
919 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
920 if (totalAmount > nBalance)
921 throw JSONRPCError(-6, "Account has insufficient funds");
924 CReserveKey keyChange(pwalletMain);
925 int64 nFeeRequired = 0;
926 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
929 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
930 throw JSONRPCError(-6, "Insufficient funds");
931 throw JSONRPCError(-4, "Transaction creation failed");
933 if (!pwalletMain->CommitTransaction(wtx, keyChange))
934 throw JSONRPCError(-4, "Transaction commit failed");
936 return wtx.GetHash().GetHex();
939 Value addmultisigaddress(const Array& params, bool fHelp)
941 if (fHelp || params.size() < 2 || params.size() > 3)
943 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
944 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
945 "each key is a bitcoin address, hex or base58 public key\n"
946 "If [account] is specified, assign address to [account].";
947 throw runtime_error(msg);
950 int nRequired = params[0].get_int();
951 const Array& keys = params[1].get_array();
953 if (params.size() > 2)
954 strAccount = AccountFromValue(params[2]);
956 // Gather public keys
957 if (keys.size() < nRequired)
959 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
960 std::vector<CKey> pubkeys;
961 pubkeys.resize(keys.size());
962 for (int i = 0; i < keys.size(); i++)
964 const std::string& ks = keys[i].get_str();
965 if (ks.size() == 130) // hex public key
966 pubkeys[i].SetPubKey(ParseHex(ks));
967 else if (ks.size() > 34) // base58-encoded
969 std::vector<unsigned char> vchPubKey;
970 if (DecodeBase58(ks, vchPubKey))
971 pubkeys[i].SetPubKey(vchPubKey);
973 throw runtime_error("Error base58 decoding key: "+ks);
975 else // bitcoin address for key in this wallet
977 CBitcoinAddress address(ks);
978 if (!pwalletMain->GetKey(address, pubkeys[i]))
980 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
984 // Construct using OP_EVAL
986 inner.SetMultisig(nRequired, pubkeys);
988 uint160 scriptHash = Hash160(inner);
989 CScript scriptPubKey;
990 scriptPubKey.SetEval(inner);
991 pwalletMain->AddCScript(scriptHash, inner);
992 CBitcoinAddress address;
993 address.SetScriptHash160(scriptHash);
995 pwalletMain->SetAddressBookName(address, strAccount);
996 return address.ToString();
1011 Value ListReceived(const Array& params, bool fByAccounts)
1013 // Minimum confirmations
1015 if (params.size() > 0)
1016 nMinDepth = params[0].get_int();
1018 // Whether to include empty accounts
1019 bool fIncludeEmpty = false;
1020 if (params.size() > 1)
1021 fIncludeEmpty = params[1].get_bool();
1024 map<CBitcoinAddress, tallyitem> mapTally;
1025 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1027 const CWalletTx& wtx = (*it).second;
1028 if (wtx.IsCoinBase() || !wtx.IsFinal())
1031 int nDepth = wtx.GetDepthInMainChain();
1032 if (nDepth < nMinDepth)
1035 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1037 CBitcoinAddress address;
1038 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
1041 tallyitem& item = mapTally[address];
1042 item.nAmount += txout.nValue;
1043 item.nConf = min(item.nConf, nDepth);
1049 map<string, tallyitem> mapAccountTally;
1050 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1052 const CBitcoinAddress& address = item.first;
1053 const string& strAccount = item.second;
1054 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1055 if (it == mapTally.end() && !fIncludeEmpty)
1059 int nConf = INT_MAX;
1060 if (it != mapTally.end())
1062 nAmount = (*it).second.nAmount;
1063 nConf = (*it).second.nConf;
1068 tallyitem& item = mapAccountTally[strAccount];
1069 item.nAmount += nAmount;
1070 item.nConf = min(item.nConf, nConf);
1075 obj.push_back(Pair("address", address.ToString()));
1076 obj.push_back(Pair("account", strAccount));
1077 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1078 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1085 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1087 int64 nAmount = (*it).second.nAmount;
1088 int nConf = (*it).second.nConf;
1090 obj.push_back(Pair("account", (*it).first));
1091 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1092 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1100 Value listreceivedbyaddress(const Array& params, bool fHelp)
1102 if (fHelp || params.size() > 2)
1103 throw runtime_error(
1104 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1105 "[minconf] is the minimum number of confirmations before payments are included.\n"
1106 "[includeempty] whether to include addresses that haven't received any payments.\n"
1107 "Returns an array of objects containing:\n"
1108 " \"address\" : receiving address\n"
1109 " \"account\" : the account of the receiving address\n"
1110 " \"amount\" : total amount received by the address\n"
1111 " \"confirmations\" : number of confirmations of the most recent transaction included");
1113 return ListReceived(params, false);
1116 Value listreceivedbyaccount(const Array& params, bool fHelp)
1118 if (fHelp || params.size() > 2)
1119 throw runtime_error(
1120 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1121 "[minconf] is the minimum number of confirmations before payments are included.\n"
1122 "[includeempty] whether to include accounts that haven't received any payments.\n"
1123 "Returns an array of objects containing:\n"
1124 " \"account\" : the account of the receiving addresses\n"
1125 " \"amount\" : total amount received by addresses with this account\n"
1126 " \"confirmations\" : number of confirmations of the most recent transaction included");
1128 return ListReceived(params, true);
1131 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1133 int64 nGeneratedImmature, nGeneratedMature, nFee;
1134 string strSentAccount;
1135 list<pair<CBitcoinAddress, int64> > listReceived;
1136 list<pair<CBitcoinAddress, int64> > listSent;
1137 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1139 bool fAllAccounts = (strAccount == string("*"));
1141 // Generated blocks assigned to account ""
1142 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1145 entry.push_back(Pair("account", string("")));
1146 if (nGeneratedImmature)
1148 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1149 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1153 entry.push_back(Pair("category", "generate"));
1154 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1157 WalletTxToJSON(wtx, entry);
1158 ret.push_back(entry);
1162 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1164 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1167 entry.push_back(Pair("account", strSentAccount));
1168 entry.push_back(Pair("address", s.first.ToString()));
1169 entry.push_back(Pair("category", "send"));
1170 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1171 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1173 WalletTxToJSON(wtx, entry);
1174 ret.push_back(entry);
1179 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1180 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1183 if (pwalletMain->mapAddressBook.count(r.first))
1184 account = pwalletMain->mapAddressBook[r.first];
1185 if (fAllAccounts || (account == strAccount))
1188 entry.push_back(Pair("account", account));
1189 entry.push_back(Pair("address", r.first.ToString()));
1190 entry.push_back(Pair("category", "receive"));
1191 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1193 WalletTxToJSON(wtx, entry);
1194 ret.push_back(entry);
1199 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1201 bool fAllAccounts = (strAccount == string("*"));
1203 if (fAllAccounts || acentry.strAccount == strAccount)
1206 entry.push_back(Pair("account", acentry.strAccount));
1207 entry.push_back(Pair("category", "move"));
1208 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1209 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1210 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1211 entry.push_back(Pair("comment", acentry.strComment));
1212 ret.push_back(entry);
1216 Value listtransactions(const Array& params, bool fHelp)
1218 if (fHelp || params.size() > 3)
1219 throw runtime_error(
1220 "listtransactions [account] [count=10] [from=0]\n"
1221 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1223 string strAccount = "*";
1224 if (params.size() > 0)
1225 strAccount = params[0].get_str();
1227 if (params.size() > 1)
1228 nCount = params[1].get_int();
1230 if (params.size() > 2)
1231 nFrom = params[2].get_int();
1234 CWalletDB walletdb(pwalletMain->strWalletFile);
1236 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1237 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1238 typedef multimap<int64, TxPair > TxItems;
1241 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1243 CWalletTx* wtx = &((*it).second);
1244 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1246 list<CAccountingEntry> acentries;
1247 walletdb.ListAccountCreditDebit(strAccount, acentries);
1248 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1250 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1253 // Now: iterate backwards until we have nCount items to return:
1254 TxItems::reverse_iterator it = txByTime.rbegin();
1255 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1256 for (; it != txByTime.rend(); ++it)
1258 CWalletTx *const pwtx = (*it).second.first;
1260 ListTransactions(*pwtx, strAccount, 0, true, ret);
1261 CAccountingEntry *const pacentry = (*it).second.second;
1263 AcentryToJSON(*pacentry, strAccount, ret);
1265 if (ret.size() >= nCount) break;
1267 // ret is now newest to oldest
1269 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1270 if (ret.size() > nCount)
1272 Array::iterator last = ret.begin();
1273 std::advance(last, nCount);
1274 ret.erase(last, ret.end());
1276 std::reverse(ret.begin(), ret.end()); // oldest to newest
1281 Value listaccounts(const Array& params, bool fHelp)
1283 if (fHelp || params.size() > 1)
1284 throw runtime_error(
1285 "listaccounts [minconf=1]\n"
1286 "Returns Object that has account names as keys, account balances as values.");
1289 if (params.size() > 0)
1290 nMinDepth = params[0].get_int();
1292 map<string, int64> mapAccountBalances;
1293 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1294 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1295 mapAccountBalances[entry.second] = 0;
1298 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1300 const CWalletTx& wtx = (*it).second;
1301 int64 nGeneratedImmature, nGeneratedMature, nFee;
1302 string strSentAccount;
1303 list<pair<CBitcoinAddress, int64> > listReceived;
1304 list<pair<CBitcoinAddress, int64> > listSent;
1305 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1306 mapAccountBalances[strSentAccount] -= nFee;
1307 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1308 mapAccountBalances[strSentAccount] -= s.second;
1309 if (wtx.GetDepthInMainChain() >= nMinDepth)
1311 mapAccountBalances[""] += nGeneratedMature;
1312 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1313 if (pwalletMain->mapAddressBook.count(r.first))
1314 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1316 mapAccountBalances[""] += r.second;
1320 list<CAccountingEntry> acentries;
1321 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1322 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1323 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1326 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1327 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1332 Value listsinceblock(const Array& params, bool fHelp)
1335 throw runtime_error(
1336 "listsinceblock [blockid] [target-confirmations]\n"
1337 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1339 CBlockIndex *pindex = NULL;
1340 int target_confirms = 1;
1342 if (params.size() > 0)
1344 uint256 blockId = 0;
1346 blockId.SetHex(params[0].get_str());
1347 pindex = CBlockLocator(blockId).GetBlockIndex();
1350 if (params.size() > 1)
1352 target_confirms = params[1].get_int();
1354 if (target_confirms < 1)
1355 throw JSONRPCError(-8, "Invalid parameter");
1358 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1362 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1364 CWalletTx tx = (*it).second;
1366 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1367 ListTransactions(tx, "*", 0, true, transactions);
1372 if (target_confirms == 1)
1375 lastblock = hashBestChain;
1379 int target_height = pindexBest->nHeight + 1 - target_confirms;
1382 for (block = pindexBest;
1383 block && block->nHeight > target_height;
1384 block = block->pprev);
1386 lastblock = block ? block->GetBlockHash() : 0;
1390 ret.push_back(Pair("transactions", transactions));
1391 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1396 Value gettransaction(const Array& params, bool fHelp)
1398 if (fHelp || params.size() != 1)
1399 throw runtime_error(
1400 "gettransaction <txid>\n"
1401 "Get detailed information about <txid>");
1404 hash.SetHex(params[0].get_str());
1408 if (!pwalletMain->mapWallet.count(hash))
1409 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1410 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1412 int64 nCredit = wtx.GetCredit();
1413 int64 nDebit = wtx.GetDebit();
1414 int64 nNet = nCredit - nDebit;
1415 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1417 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1419 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1421 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1424 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1425 entry.push_back(Pair("details", details));
1431 Value backupwallet(const Array& params, bool fHelp)
1433 if (fHelp || params.size() != 1)
1434 throw runtime_error(
1435 "backupwallet <destination>\n"
1436 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1438 string strDest = params[0].get_str();
1439 BackupWallet(*pwalletMain, strDest);
1445 Value keypoolrefill(const Array& params, bool fHelp)
1447 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1448 throw runtime_error(
1450 "Fills the keypool, requires wallet passphrase to be set.");
1451 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1452 throw runtime_error(
1454 "Fills the keypool.");
1456 if (pwalletMain->IsLocked())
1457 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1459 pwalletMain->TopUpKeyPool();
1461 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1462 throw JSONRPCError(-4, "Error refreshing keypool.");
1468 void ThreadTopUpKeyPool(void* parg)
1470 pwalletMain->TopUpKeyPool();
1473 void ThreadCleanWalletPassphrase(void* parg)
1475 int64 nMyWakeTime = GetTime() + *((int*)parg);
1477 if (nWalletUnlockTime == 0)
1479 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1481 nWalletUnlockTime = nMyWakeTime;
1484 while (GetTime() < nWalletUnlockTime)
1485 Sleep(GetTime() - nWalletUnlockTime);
1487 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1489 nWalletUnlockTime = 0;
1494 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1496 if (nWalletUnlockTime < nMyWakeTime)
1497 nWalletUnlockTime = nMyWakeTime;
1503 pwalletMain->Lock();
1508 Value walletpassphrase(const Array& params, bool fHelp)
1510 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1511 throw runtime_error(
1512 "walletpassphrase <passphrase> <timeout>\n"
1513 "Stores the wallet decryption key in memory for <timeout> seconds.");
1516 if (!pwalletMain->IsCrypted())
1517 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1519 if (!pwalletMain->IsLocked())
1520 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1522 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1523 SecureString strWalletPass;
1524 strWalletPass.reserve(100);
1525 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1526 // Alternately, find a way to make params[0] mlock()'d to begin with.
1527 strWalletPass = params[0].get_str().c_str();
1529 if (strWalletPass.length() > 0)
1531 if (!pwalletMain->Unlock(strWalletPass))
1532 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1535 throw runtime_error(
1536 "walletpassphrase <passphrase> <timeout>\n"
1537 "Stores the wallet decryption key in memory for <timeout> seconds.");
1539 CreateThread(ThreadTopUpKeyPool, NULL);
1540 int* pnSleepTime = new int(params[1].get_int());
1541 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1547 Value walletpassphrasechange(const Array& params, bool fHelp)
1549 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1550 throw runtime_error(
1551 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1552 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1555 if (!pwalletMain->IsCrypted())
1556 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1558 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1559 // Alternately, find a way to make params[0] mlock()'d to begin with.
1560 SecureString strOldWalletPass;
1561 strOldWalletPass.reserve(100);
1562 strOldWalletPass = params[0].get_str().c_str();
1564 SecureString strNewWalletPass;
1565 strNewWalletPass.reserve(100);
1566 strNewWalletPass = params[1].get_str().c_str();
1568 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1569 throw runtime_error(
1570 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1571 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1573 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1574 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1580 Value walletlock(const Array& params, bool fHelp)
1582 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1583 throw runtime_error(
1585 "Removes the wallet encryption key from memory, locking the wallet.\n"
1586 "After calling this method, you will need to call walletpassphrase again\n"
1587 "before being able to call any methods which require the wallet to be unlocked.");
1590 if (!pwalletMain->IsCrypted())
1591 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1593 pwalletMain->Lock();
1594 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1596 nWalletUnlockTime = 0;
1603 Value encryptwallet(const Array& params, bool fHelp)
1605 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1606 throw runtime_error(
1607 "encryptwallet <passphrase>\n"
1608 "Encrypts the wallet with <passphrase>.");
1611 if (pwalletMain->IsCrypted())
1612 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1615 // shutting down via RPC while the GUI is running does not work (yet):
1616 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1619 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1620 // Alternately, find a way to make params[0] mlock()'d to begin with.
1621 SecureString strWalletPass;
1622 strWalletPass.reserve(100);
1623 strWalletPass = params[0].get_str().c_str();
1625 if (strWalletPass.length() < 1)
1626 throw runtime_error(
1627 "encryptwallet <passphrase>\n"
1628 "Encrypts the wallet with <passphrase>.");
1630 if (!pwalletMain->EncryptWallet(strWalletPass))
1631 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1633 // BDB seems to have a bad habit of writing old data into
1634 // slack space in .dat files; that is bad if the old data is
1635 // unencrypted private keys. So:
1636 CreateThread(Shutdown, NULL);
1637 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1641 Value validateaddress(const Array& params, bool fHelp)
1643 if (fHelp || params.size() != 1)
1644 throw runtime_error(
1645 "validateaddress <bitcoinaddress>\n"
1646 "Return information about <bitcoinaddress>.");
1648 CBitcoinAddress address(params[0].get_str());
1649 bool isValid = address.IsValid();
1652 ret.push_back(Pair("isvalid", isValid));
1655 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1656 // version of the address:
1657 string currentAddress = address.ToString();
1658 ret.push_back(Pair("address", currentAddress));
1659 if (pwalletMain->HaveKey(address))
1661 ret.push_back(Pair("ismine", true));
1662 std::vector<unsigned char> vchPubKey;
1663 pwalletMain->GetPubKey(address, vchPubKey);
1664 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1665 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1666 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1668 else if (pwalletMain->HaveCScript(address.GetHash160()))
1670 ret.push_back(Pair("isscript", true));
1672 pwalletMain->GetCScript(address.GetHash160(), subscript);
1673 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1674 std::vector<CBitcoinAddress> addresses;
1677 ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
1678 ret.push_back(Pair("script", GetTxnTypeName(whichType)));
1680 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1681 a.push_back(addr.ToString());
1682 ret.push_back(Pair("addresses", a));
1683 if (whichType == TX_MULTISIG)
1684 ret.push_back(Pair("sigsrequired", nRequired));
1687 ret.push_back(Pair("ismine", false));
1688 if (pwalletMain->mapAddressBook.count(address))
1689 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1694 Value getwork(const Array& params, bool fHelp)
1696 if (fHelp || params.size() > 1)
1697 throw runtime_error(
1699 "If [data] is not specified, returns formatted hash data to work on:\n"
1700 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1701 " \"data\" : block data\n"
1702 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1703 " \"target\" : little endian hash target\n"
1704 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1707 throw JSONRPCError(-9, "Bitcoin is not connected!");
1709 if (IsInitialBlockDownload())
1710 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1712 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1713 static mapNewBlock_t mapNewBlock;
1714 static vector<CBlock*> vNewBlock;
1715 static CReserveKey reservekey(pwalletMain);
1717 if (params.size() == 0)
1720 static unsigned int nTransactionsUpdatedLast;
1721 static CBlockIndex* pindexPrev;
1722 static int64 nStart;
1723 static CBlock* pblock;
1724 if (pindexPrev != pindexBest ||
1725 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1727 if (pindexPrev != pindexBest)
1729 // Deallocate old blocks since they're obsolete now
1730 mapNewBlock.clear();
1731 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1735 nTransactionsUpdatedLast = nTransactionsUpdated;
1736 pindexPrev = pindexBest;
1740 pblock = CreateNewBlock(reservekey);
1742 throw JSONRPCError(-7, "Out of memory");
1743 vNewBlock.push_back(pblock);
1747 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1750 // Update nExtraNonce
1751 static unsigned int nExtraNonce = 0;
1752 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1755 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1757 // Prebuild hash buffers
1761 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1763 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1766 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1767 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1768 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1769 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1775 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1776 if (vchData.size() != 128)
1777 throw JSONRPCError(-8, "Invalid parameter");
1778 CBlock* pdata = (CBlock*)&vchData[0];
1781 for (int i = 0; i < 128/4; i++)
1782 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1785 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1787 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1789 pblock->nTime = pdata->nTime;
1790 pblock->nNonce = pdata->nNonce;
1791 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1792 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1794 return CheckWork(pblock, *pwalletMain, reservekey);
1799 Value getmemorypool(const Array& params, bool fHelp)
1801 if (fHelp || params.size() > 1)
1802 throw runtime_error(
1803 "getmemorypool [data]\n"
1804 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1805 " \"version\" : block version\n"
1806 " \"previousblockhash\" : hash of current highest block\n"
1807 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1808 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1809 " \"time\" : timestamp appropriate for next block\n"
1810 " \"bits\" : compressed target of next block\n"
1811 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1813 if (params.size() == 0)
1816 throw JSONRPCError(-9, "Bitcoin is not connected!");
1818 if (IsInitialBlockDownload())
1819 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1821 static CReserveKey reservekey(pwalletMain);
1824 static unsigned int nTransactionsUpdatedLast;
1825 static CBlockIndex* pindexPrev;
1826 static int64 nStart;
1827 static CBlock* pblock;
1828 if (pindexPrev != pindexBest ||
1829 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1831 nTransactionsUpdatedLast = nTransactionsUpdated;
1832 pindexPrev = pindexBest;
1838 pblock = CreateNewBlock(reservekey);
1840 throw JSONRPCError(-7, "Out of memory");
1844 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1848 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1855 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1859 result.push_back(Pair("version", pblock->nVersion));
1860 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1861 result.push_back(Pair("transactions", transactions));
1862 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1863 result.push_back(Pair("time", (int64_t)pblock->nTime));
1869 uBits.nBits = htonl((int32_t)pblock->nBits);
1870 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1877 CDataStream ssBlock(ParseHex(params[0].get_str()));
1881 return ProcessBlock(NULL, &pblock);
1899 pair<string, rpcfn_type> pCallTable[] =
1901 make_pair("help", &help),
1902 make_pair("stop", &stop),
1903 make_pair("getblockcount", &getblockcount),
1904 make_pair("getblocknumber", &getblocknumber),
1905 make_pair("getconnectioncount", &getconnectioncount),
1906 make_pair("getdifficulty", &getdifficulty),
1907 make_pair("getgenerate", &getgenerate),
1908 make_pair("setgenerate", &setgenerate),
1909 make_pair("gethashespersec", &gethashespersec),
1910 make_pair("getinfo", &getinfo),
1911 make_pair("getnewaddress", &getnewaddress),
1912 make_pair("getaccountaddress", &getaccountaddress),
1913 make_pair("setaccount", &setaccount),
1914 make_pair("getaccount", &getaccount),
1915 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1916 make_pair("sendtoaddress", &sendtoaddress),
1917 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1918 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1919 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1920 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1921 make_pair("backupwallet", &backupwallet),
1922 make_pair("keypoolrefill", &keypoolrefill),
1923 make_pair("walletpassphrase", &walletpassphrase),
1924 make_pair("walletpassphrasechange", &walletpassphrasechange),
1925 make_pair("walletlock", &walletlock),
1926 make_pair("encryptwallet", &encryptwallet),
1927 make_pair("validateaddress", &validateaddress),
1928 make_pair("getbalance", &getbalance),
1929 make_pair("move", &movecmd),
1930 make_pair("sendfrom", &sendfrom),
1931 make_pair("sendmany", &sendmany),
1932 make_pair("addmultisigaddress", &addmultisigaddress),
1933 make_pair("gettransaction", &gettransaction),
1934 make_pair("listtransactions", &listtransactions),
1935 make_pair("signmessage", &signmessage),
1936 make_pair("verifymessage", &verifymessage),
1937 make_pair("getwork", &getwork),
1938 make_pair("listaccounts", &listaccounts),
1939 make_pair("settxfee", &settxfee),
1940 make_pair("getmemorypool", &getmemorypool),
1941 make_pair("listsinceblock", &listsinceblock),
1942 make_pair("dumpprivkey", &dumpprivkey),
1943 make_pair("importprivkey", &importprivkey)
1945 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1947 string pAllowInSafeMode[] =
1952 "getblocknumber", // deprecated
1953 "getconnectioncount",
1960 "getaccountaddress",
1962 "getaddressesbyaccount",
1971 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1979 // This ain't Apache. We're just using HTTP header for the length field
1980 // and to be compatible with other JSON-RPC implementations.
1983 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1986 s << "POST / HTTP/1.1\r\n"
1987 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1988 << "Host: 127.0.0.1\r\n"
1989 << "Content-Type: application/json\r\n"
1990 << "Content-Length: " << strMsg.size() << "\r\n"
1991 << "Connection: close\r\n"
1992 << "Accept: application/json\r\n";
1993 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1994 s << item.first << ": " << item.second << "\r\n";
1995 s << "\r\n" << strMsg;
2000 string rfc1123Time()
2005 struct tm* now_gmt = gmtime(&now);
2006 string locale(setlocale(LC_TIME, NULL));
2007 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2008 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2009 setlocale(LC_TIME, locale.c_str());
2010 return string(buffer);
2013 static string HTTPReply(int nStatus, const string& strMsg)
2016 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2018 "Server: bitcoin-json-rpc/%s\r\n"
2019 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2020 "Content-Type: text/html\r\n"
2021 "Content-Length: 296\r\n"
2023 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2024 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2027 "<TITLE>Error</TITLE>\r\n"
2028 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2030 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2031 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2032 const char *cStatus;
2033 if (nStatus == 200) cStatus = "OK";
2034 else if (nStatus == 400) cStatus = "Bad Request";
2035 else if (nStatus == 403) cStatus = "Forbidden";
2036 else if (nStatus == 404) cStatus = "Not Found";
2037 else if (nStatus == 500) cStatus = "Internal Server Error";
2040 "HTTP/1.1 %d %s\r\n"
2042 "Connection: close\r\n"
2043 "Content-Length: %d\r\n"
2044 "Content-Type: application/json\r\n"
2045 "Server: bitcoin-json-rpc/%s\r\n"
2050 rfc1123Time().c_str(),
2052 FormatFullVersion().c_str(),
2056 int ReadHTTPStatus(std::basic_istream<char>& stream)
2059 getline(stream, str);
2060 vector<string> vWords;
2061 boost::split(vWords, str, boost::is_any_of(" "));
2062 if (vWords.size() < 2)
2064 return atoi(vWords[1].c_str());
2067 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2073 std::getline(stream, str);
2074 if (str.empty() || str == "\r")
2076 string::size_type nColon = str.find(":");
2077 if (nColon != string::npos)
2079 string strHeader = str.substr(0, nColon);
2080 boost::trim(strHeader);
2081 boost::to_lower(strHeader);
2082 string strValue = str.substr(nColon+1);
2083 boost::trim(strValue);
2084 mapHeadersRet[strHeader] = strValue;
2085 if (strHeader == "content-length")
2086 nLen = atoi(strValue.c_str());
2092 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2094 mapHeadersRet.clear();
2098 int nStatus = ReadHTTPStatus(stream);
2101 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2102 if (nLen < 0 || nLen > MAX_SIZE)
2108 vector<char> vch(nLen);
2109 stream.read(&vch[0], nLen);
2110 strMessageRet = string(vch.begin(), vch.end());
2116 bool HTTPAuthorized(map<string, string>& mapHeaders)
2118 string strAuth = mapHeaders["authorization"];
2119 if (strAuth.substr(0,6) != "Basic ")
2121 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2122 string strUserPass = DecodeBase64(strUserPass64);
2123 return strUserPass == strRPCUserColonPass;
2127 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2128 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2129 // unspecified (HTTP errors and contents of 'error').
2131 // 1.0 spec: http://json-rpc.org/wiki/specification
2132 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2133 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2136 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2139 request.push_back(Pair("method", strMethod));
2140 request.push_back(Pair("params", params));
2141 request.push_back(Pair("id", id));
2142 return write_string(Value(request), false) + "\n";
2145 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2148 if (error.type() != null_type)
2149 reply.push_back(Pair("result", Value::null));
2151 reply.push_back(Pair("result", result));
2152 reply.push_back(Pair("error", error));
2153 reply.push_back(Pair("id", id));
2154 return write_string(Value(reply), false) + "\n";
2157 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2159 // Send error reply from json-rpc error object
2161 int code = find_value(objError, "code").get_int();
2162 if (code == -32600) nStatus = 400;
2163 else if (code == -32601) nStatus = 404;
2164 string strReply = JSONRPCReply(Value::null, objError, id);
2165 stream << HTTPReply(nStatus, strReply) << std::flush;
2168 bool ClientAllowed(const string& strAddress)
2170 if (strAddress == asio::ip::address_v4::loopback().to_string())
2172 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2173 BOOST_FOREACH(string strAllow, vAllow)
2174 if (WildcardMatch(strAddress, strAllow))
2181 // IOStream device that speaks SSL but can also speak non-SSL
2183 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2185 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2187 fUseSSL = fUseSSLIn;
2188 fNeedHandshake = fUseSSLIn;
2191 void handshake(ssl::stream_base::handshake_type role)
2193 if (!fNeedHandshake) return;
2194 fNeedHandshake = false;
2195 stream.handshake(role);
2197 std::streamsize read(char* s, std::streamsize n)
2199 handshake(ssl::stream_base::server); // HTTPS servers read first
2200 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2201 return stream.next_layer().read_some(asio::buffer(s, n));
2203 std::streamsize write(const char* s, std::streamsize n)
2205 handshake(ssl::stream_base::client); // HTTPS clients write first
2206 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2207 return asio::write(stream.next_layer(), asio::buffer(s, n));
2209 bool connect(const std::string& server, const std::string& port)
2211 ip::tcp::resolver resolver(stream.get_io_service());
2212 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2213 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2214 ip::tcp::resolver::iterator end;
2215 boost::system::error_code error = asio::error::host_not_found;
2216 while (error && endpoint_iterator != end)
2218 stream.lowest_layer().close();
2219 stream.lowest_layer().connect(*endpoint_iterator++, error);
2227 bool fNeedHandshake;
2233 void ThreadRPCServer(void* parg)
2235 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2238 vnThreadsRunning[4]++;
2239 ThreadRPCServer2(parg);
2240 vnThreadsRunning[4]--;
2242 catch (std::exception& e) {
2243 vnThreadsRunning[4]--;
2244 PrintException(&e, "ThreadRPCServer()");
2246 vnThreadsRunning[4]--;
2247 PrintException(NULL, "ThreadRPCServer()");
2249 printf("ThreadRPCServer exiting\n");
2252 void ThreadRPCServer2(void* parg)
2254 printf("ThreadRPCServer started\n");
2256 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2257 if (strRPCUserColonPass == ":")
2259 string strWhatAmI = "To use bitcoind";
2260 if (mapArgs.count("-server"))
2261 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2262 else if (mapArgs.count("-daemon"))
2263 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2265 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2266 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2268 GetConfigFile().c_str());
2270 CreateThread(Shutdown, NULL);
2275 bool fUseSSL = GetBoolArg("-rpcssl");
2276 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2278 asio::io_service io_service;
2279 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2280 ip::tcp::acceptor acceptor(io_service, endpoint);
2282 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2285 ssl::context context(io_service, ssl::context::sslv23);
2288 context.set_options(ssl::context::no_sslv2);
2289 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2290 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2291 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2292 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2293 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2294 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2295 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2296 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2298 string ciphers = GetArg("-rpcsslciphers",
2299 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2300 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2304 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2309 // Accept connection
2311 SSLStream sslStream(io_service, context);
2312 SSLIOStreamDevice d(sslStream, fUseSSL);
2313 iostreams::stream<SSLIOStreamDevice> stream(d);
2315 ip::tcp::iostream stream;
2318 ip::tcp::endpoint peer;
2319 vnThreadsRunning[4]--;
2321 acceptor.accept(sslStream.lowest_layer(), peer);
2323 acceptor.accept(*stream.rdbuf(), peer);
2325 vnThreadsRunning[4]++;
2329 // Restrict callers by IP
2330 if (!ClientAllowed(peer.address().to_string()))
2332 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2334 stream << HTTPReply(403, "") << std::flush;
2338 map<string, string> mapHeaders;
2341 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2342 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2345 printf("ThreadRPCServer ReadHTTP timeout\n");
2349 // Check authorization
2350 if (mapHeaders.count("authorization") == 0)
2352 stream << HTTPReply(401, "") << std::flush;
2355 if (!HTTPAuthorized(mapHeaders))
2357 // Deter brute-forcing short passwords
2358 if (mapArgs["-rpcpassword"].size() < 15)
2361 stream << HTTPReply(401, "") << std::flush;
2362 printf("ThreadRPCServer incorrect password attempt\n");
2366 Value id = Value::null;
2371 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2372 throw JSONRPCError(-32700, "Parse error");
2373 const Object& request = valRequest.get_obj();
2375 // Parse id now so errors from here on will have the id
2376 id = find_value(request, "id");
2379 Value valMethod = find_value(request, "method");
2380 if (valMethod.type() == null_type)
2381 throw JSONRPCError(-32600, "Missing method");
2382 if (valMethod.type() != str_type)
2383 throw JSONRPCError(-32600, "Method must be a string");
2384 string strMethod = valMethod.get_str();
2385 if (strMethod != "getwork" && strMethod != "getmemorypool")
2386 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2389 Value valParams = find_value(request, "params");
2391 if (valParams.type() == array_type)
2392 params = valParams.get_array();
2393 else if (valParams.type() == null_type)
2396 throw JSONRPCError(-32600, "Params must be an array");
2399 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2400 if (mi == mapCallTable.end())
2401 throw JSONRPCError(-32601, "Method not found");
2403 // Observe safe mode
2404 string strWarning = GetWarnings("rpc");
2405 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2406 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2412 CRITICAL_BLOCK(cs_main)
2413 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2414 result = (*(*mi).second)(params, false);
2417 string strReply = JSONRPCReply(result, Value::null, id);
2418 stream << HTTPReply(200, strReply) << std::flush;
2420 catch (std::exception& e)
2422 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2425 catch (Object& objError)
2427 ErrorReply(stream, objError, id);
2429 catch (std::exception& e)
2431 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2439 Object CallRPC(const string& strMethod, const Array& params)
2441 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2442 throw runtime_error(strprintf(
2443 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2444 "If the file does not exist, create it with owner-readable-only file permissions."),
2445 GetConfigFile().c_str()));
2447 // Connect to localhost
2448 bool fUseSSL = GetBoolArg("-rpcssl");
2450 asio::io_service io_service;
2451 ssl::context context(io_service, ssl::context::sslv23);
2452 context.set_options(ssl::context::no_sslv2);
2453 SSLStream sslStream(io_service, context);
2454 SSLIOStreamDevice d(sslStream, fUseSSL);
2455 iostreams::stream<SSLIOStreamDevice> stream(d);
2456 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2457 throw runtime_error("couldn't connect to server");
2460 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2462 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2464 throw runtime_error("couldn't connect to server");
2468 // HTTP basic authentication
2469 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2470 map<string, string> mapRequestHeaders;
2471 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2474 string strRequest = JSONRPCRequest(strMethod, params, 1);
2475 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2476 stream << strPost << std::flush;
2479 map<string, string> mapHeaders;
2481 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2483 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2484 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2485 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2486 else if (strReply.empty())
2487 throw runtime_error("no response from server");
2491 if (!read_string(strReply, valReply))
2492 throw runtime_error("couldn't parse reply from server");
2493 const Object& reply = valReply.get_obj();
2495 throw runtime_error("expected reply to have result, error and id properties");
2503 template<typename T>
2504 void ConvertTo(Value& value)
2506 if (value.type() == str_type)
2508 // reinterpret string as unquoted json value
2510 if (!read_string(value.get_str(), value2))
2511 throw runtime_error("type mismatch");
2512 value = value2.get_value<T>();
2516 value = value.get_value<T>();
2520 int CommandLineRPC(int argc, char *argv[])
2527 while (argc > 1 && IsSwitchChar(argv[1][0]))
2535 throw runtime_error("too few parameters");
2536 string strMethod = argv[1];
2538 // Parameters default to strings
2540 for (int i = 2; i < argc; i++)
2541 params.push_back(argv[i]);
2542 int n = params.size();
2545 // Special case non-string parameter types
2547 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2548 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2549 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2550 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2551 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2552 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2553 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2554 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2555 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2556 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2557 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2558 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2559 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2560 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2561 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2562 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2563 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2564 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2565 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2566 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2567 if (strMethod == "sendmany" && n > 1)
2569 string s = params[1].get_str();
2571 if (!read_string(s, v) || v.type() != obj_type)
2572 throw runtime_error("type mismatch");
2573 params[1] = v.get_obj();
2575 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2576 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2577 if (strMethod == "addmultisigaddress" && n > 1)
2579 string s = params[1].get_str();
2581 if (!read_string(s, v) || v.type() != array_type)
2582 throw runtime_error("addmultisigaddress: type mismatch "+s);
2583 params[1] = v.get_array();
2587 Object reply = CallRPC(strMethod, params);
2590 const Value& result = find_value(reply, "result");
2591 const Value& error = find_value(reply, "error");
2593 if (error.type() != null_type)
2596 strPrint = "error: " + write_string(error, false);
2597 int code = find_value(error.get_obj(), "code").get_int();
2603 if (result.type() == null_type)
2605 else if (result.type() == str_type)
2606 strPrint = result.get_str();
2608 strPrint = write_string(result, true);
2611 catch (std::exception& e)
2613 strPrint = string("error: ") + e.what();
2618 PrintException(NULL, "CommandLineRPC()");
2623 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2632 int main(int argc, char *argv[])
2635 // Turn off microsoft heap dump noise
2636 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2637 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2639 setbuf(stdin, NULL);
2640 setbuf(stdout, NULL);
2641 setbuf(stderr, NULL);
2645 if (argc >= 2 && string(argv[1]) == "-server")
2647 printf("server ready\n");
2648 ThreadRPCServer(NULL);
2652 return CommandLineRPC(argc, argv);
2655 catch (std::exception& e) {
2656 PrintException(&e, "main()");
2658 PrintException(NULL, "main()");