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 throw runtime_error("addmultisigaddress available only when running -testnet\n");
952 int nRequired = params[0].get_int();
953 const Array& keys = params[1].get_array();
955 if (params.size() > 2)
956 strAccount = AccountFromValue(params[2]);
958 // Gather public keys
959 if (keys.size() < nRequired)
961 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
962 std::vector<CKey> pubkeys;
963 pubkeys.resize(keys.size());
964 for (int i = 0; i < keys.size(); i++)
966 const std::string& ks = keys[i].get_str();
967 if (ks.size() == 130) // hex public key
968 pubkeys[i].SetPubKey(ParseHex(ks));
969 else if (ks.size() > 34) // base58-encoded
971 std::vector<unsigned char> vchPubKey;
972 if (DecodeBase58(ks, vchPubKey))
973 pubkeys[i].SetPubKey(vchPubKey);
975 throw runtime_error("Error base58 decoding key: "+ks);
977 else // bitcoin address for key in this wallet
979 CBitcoinAddress address(ks);
980 if (!pwalletMain->GetKey(address, pubkeys[i]))
982 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
986 // Construct using OP_EVAL
988 inner.SetMultisig(nRequired, pubkeys);
990 uint160 scriptHash = Hash160(inner);
991 CScript scriptPubKey;
992 scriptPubKey.SetEval(inner);
993 pwalletMain->AddCScript(scriptHash, inner);
994 CBitcoinAddress address;
995 address.SetScriptHash160(scriptHash);
997 pwalletMain->SetAddressBookName(address, strAccount);
998 return address.ToString();
1013 Value ListReceived(const Array& params, bool fByAccounts)
1015 // Minimum confirmations
1017 if (params.size() > 0)
1018 nMinDepth = params[0].get_int();
1020 // Whether to include empty accounts
1021 bool fIncludeEmpty = false;
1022 if (params.size() > 1)
1023 fIncludeEmpty = params[1].get_bool();
1026 map<CBitcoinAddress, tallyitem> mapTally;
1027 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1029 const CWalletTx& wtx = (*it).second;
1030 if (wtx.IsCoinBase() || !wtx.IsFinal())
1033 int nDepth = wtx.GetDepthInMainChain();
1034 if (nDepth < nMinDepth)
1037 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1039 CBitcoinAddress address;
1040 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
1043 tallyitem& item = mapTally[address];
1044 item.nAmount += txout.nValue;
1045 item.nConf = min(item.nConf, nDepth);
1051 map<string, tallyitem> mapAccountTally;
1052 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1054 const CBitcoinAddress& address = item.first;
1055 const string& strAccount = item.second;
1056 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1057 if (it == mapTally.end() && !fIncludeEmpty)
1061 int nConf = INT_MAX;
1062 if (it != mapTally.end())
1064 nAmount = (*it).second.nAmount;
1065 nConf = (*it).second.nConf;
1070 tallyitem& item = mapAccountTally[strAccount];
1071 item.nAmount += nAmount;
1072 item.nConf = min(item.nConf, nConf);
1077 obj.push_back(Pair("address", address.ToString()));
1078 obj.push_back(Pair("account", strAccount));
1079 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1080 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1087 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1089 int64 nAmount = (*it).second.nAmount;
1090 int nConf = (*it).second.nConf;
1092 obj.push_back(Pair("account", (*it).first));
1093 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1094 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1102 Value listreceivedbyaddress(const Array& params, bool fHelp)
1104 if (fHelp || params.size() > 2)
1105 throw runtime_error(
1106 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1107 "[minconf] is the minimum number of confirmations before payments are included.\n"
1108 "[includeempty] whether to include addresses that haven't received any payments.\n"
1109 "Returns an array of objects containing:\n"
1110 " \"address\" : receiving address\n"
1111 " \"account\" : the account of the receiving address\n"
1112 " \"amount\" : total amount received by the address\n"
1113 " \"confirmations\" : number of confirmations of the most recent transaction included");
1115 return ListReceived(params, false);
1118 Value listreceivedbyaccount(const Array& params, bool fHelp)
1120 if (fHelp || params.size() > 2)
1121 throw runtime_error(
1122 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1123 "[minconf] is the minimum number of confirmations before payments are included.\n"
1124 "[includeempty] whether to include accounts that haven't received any payments.\n"
1125 "Returns an array of objects containing:\n"
1126 " \"account\" : the account of the receiving addresses\n"
1127 " \"amount\" : total amount received by addresses with this account\n"
1128 " \"confirmations\" : number of confirmations of the most recent transaction included");
1130 return ListReceived(params, true);
1133 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1135 int64 nGeneratedImmature, nGeneratedMature, nFee;
1136 string strSentAccount;
1137 list<pair<CBitcoinAddress, int64> > listReceived;
1138 list<pair<CBitcoinAddress, int64> > listSent;
1139 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1141 bool fAllAccounts = (strAccount == string("*"));
1143 // Generated blocks assigned to account ""
1144 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1147 entry.push_back(Pair("account", string("")));
1148 if (nGeneratedImmature)
1150 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1151 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1155 entry.push_back(Pair("category", "generate"));
1156 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1159 WalletTxToJSON(wtx, entry);
1160 ret.push_back(entry);
1164 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1166 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1169 entry.push_back(Pair("account", strSentAccount));
1170 entry.push_back(Pair("address", s.first.ToString()));
1171 entry.push_back(Pair("category", "send"));
1172 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1173 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1175 WalletTxToJSON(wtx, entry);
1176 ret.push_back(entry);
1181 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1182 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1185 if (pwalletMain->mapAddressBook.count(r.first))
1186 account = pwalletMain->mapAddressBook[r.first];
1187 if (fAllAccounts || (account == strAccount))
1190 entry.push_back(Pair("account", account));
1191 entry.push_back(Pair("address", r.first.ToString()));
1192 entry.push_back(Pair("category", "receive"));
1193 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1195 WalletTxToJSON(wtx, entry);
1196 ret.push_back(entry);
1201 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1203 bool fAllAccounts = (strAccount == string("*"));
1205 if (fAllAccounts || acentry.strAccount == strAccount)
1208 entry.push_back(Pair("account", acentry.strAccount));
1209 entry.push_back(Pair("category", "move"));
1210 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1211 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1212 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1213 entry.push_back(Pair("comment", acentry.strComment));
1214 ret.push_back(entry);
1218 Value listtransactions(const Array& params, bool fHelp)
1220 if (fHelp || params.size() > 3)
1221 throw runtime_error(
1222 "listtransactions [account] [count=10] [from=0]\n"
1223 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1225 string strAccount = "*";
1226 if (params.size() > 0)
1227 strAccount = params[0].get_str();
1229 if (params.size() > 1)
1230 nCount = params[1].get_int();
1232 if (params.size() > 2)
1233 nFrom = params[2].get_int();
1236 CWalletDB walletdb(pwalletMain->strWalletFile);
1238 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1239 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1240 typedef multimap<int64, TxPair > TxItems;
1243 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1245 CWalletTx* wtx = &((*it).second);
1246 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1248 list<CAccountingEntry> acentries;
1249 walletdb.ListAccountCreditDebit(strAccount, acentries);
1250 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1252 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1255 // Now: iterate backwards until we have nCount items to return:
1256 TxItems::reverse_iterator it = txByTime.rbegin();
1257 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1258 for (; it != txByTime.rend(); ++it)
1260 CWalletTx *const pwtx = (*it).second.first;
1262 ListTransactions(*pwtx, strAccount, 0, true, ret);
1263 CAccountingEntry *const pacentry = (*it).second.second;
1265 AcentryToJSON(*pacentry, strAccount, ret);
1267 if (ret.size() >= nCount) break;
1269 // ret is now newest to oldest
1271 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1272 if (ret.size() > nCount)
1274 Array::iterator last = ret.begin();
1275 std::advance(last, nCount);
1276 ret.erase(last, ret.end());
1278 std::reverse(ret.begin(), ret.end()); // oldest to newest
1283 Value listaccounts(const Array& params, bool fHelp)
1285 if (fHelp || params.size() > 1)
1286 throw runtime_error(
1287 "listaccounts [minconf=1]\n"
1288 "Returns Object that has account names as keys, account balances as values.");
1291 if (params.size() > 0)
1292 nMinDepth = params[0].get_int();
1294 map<string, int64> mapAccountBalances;
1295 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1296 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1297 mapAccountBalances[entry.second] = 0;
1300 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1302 const CWalletTx& wtx = (*it).second;
1303 int64 nGeneratedImmature, nGeneratedMature, nFee;
1304 string strSentAccount;
1305 list<pair<CBitcoinAddress, int64> > listReceived;
1306 list<pair<CBitcoinAddress, int64> > listSent;
1307 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1308 mapAccountBalances[strSentAccount] -= nFee;
1309 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1310 mapAccountBalances[strSentAccount] -= s.second;
1311 if (wtx.GetDepthInMainChain() >= nMinDepth)
1313 mapAccountBalances[""] += nGeneratedMature;
1314 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1315 if (pwalletMain->mapAddressBook.count(r.first))
1316 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1318 mapAccountBalances[""] += r.second;
1322 list<CAccountingEntry> acentries;
1323 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1324 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1325 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1328 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1329 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1334 Value listsinceblock(const Array& params, bool fHelp)
1337 throw runtime_error(
1338 "listsinceblock [blockid] [target-confirmations]\n"
1339 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1341 CBlockIndex *pindex = NULL;
1342 int target_confirms = 1;
1344 if (params.size() > 0)
1346 uint256 blockId = 0;
1348 blockId.SetHex(params[0].get_str());
1349 pindex = CBlockLocator(blockId).GetBlockIndex();
1352 if (params.size() > 1)
1354 target_confirms = params[1].get_int();
1356 if (target_confirms < 1)
1357 throw JSONRPCError(-8, "Invalid parameter");
1360 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1366 CWalletTx tx = (*it).second;
1368 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1369 ListTransactions(tx, "*", 0, true, transactions);
1374 if (target_confirms == 1)
1377 lastblock = hashBestChain;
1381 int target_height = pindexBest->nHeight + 1 - target_confirms;
1384 for (block = pindexBest;
1385 block && block->nHeight > target_height;
1386 block = block->pprev);
1388 lastblock = block ? block->GetBlockHash() : 0;
1392 ret.push_back(Pair("transactions", transactions));
1393 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1398 Value gettransaction(const Array& params, bool fHelp)
1400 if (fHelp || params.size() != 1)
1401 throw runtime_error(
1402 "gettransaction <txid>\n"
1403 "Get detailed information about <txid>");
1406 hash.SetHex(params[0].get_str());
1410 if (!pwalletMain->mapWallet.count(hash))
1411 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1412 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1414 int64 nCredit = wtx.GetCredit();
1415 int64 nDebit = wtx.GetDebit();
1416 int64 nNet = nCredit - nDebit;
1417 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1419 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1421 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1423 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1426 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1427 entry.push_back(Pair("details", details));
1433 Value backupwallet(const Array& params, bool fHelp)
1435 if (fHelp || params.size() != 1)
1436 throw runtime_error(
1437 "backupwallet <destination>\n"
1438 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1440 string strDest = params[0].get_str();
1441 BackupWallet(*pwalletMain, strDest);
1447 Value keypoolrefill(const Array& params, bool fHelp)
1449 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1450 throw runtime_error(
1452 "Fills the keypool, requires wallet passphrase to be set.");
1453 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1454 throw runtime_error(
1456 "Fills the keypool.");
1458 if (pwalletMain->IsLocked())
1459 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1461 pwalletMain->TopUpKeyPool();
1463 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1464 throw JSONRPCError(-4, "Error refreshing keypool.");
1470 void ThreadTopUpKeyPool(void* parg)
1472 pwalletMain->TopUpKeyPool();
1475 void ThreadCleanWalletPassphrase(void* parg)
1477 int64 nMyWakeTime = GetTime() + *((int*)parg);
1479 if (nWalletUnlockTime == 0)
1481 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1483 nWalletUnlockTime = nMyWakeTime;
1486 while (GetTime() < nWalletUnlockTime)
1487 Sleep(GetTime() - nWalletUnlockTime);
1489 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1491 nWalletUnlockTime = 0;
1496 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1498 if (nWalletUnlockTime < nMyWakeTime)
1499 nWalletUnlockTime = nMyWakeTime;
1505 pwalletMain->Lock();
1510 Value walletpassphrase(const Array& params, bool fHelp)
1512 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1513 throw runtime_error(
1514 "walletpassphrase <passphrase> <timeout>\n"
1515 "Stores the wallet decryption key in memory for <timeout> seconds.");
1518 if (!pwalletMain->IsCrypted())
1519 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1521 if (!pwalletMain->IsLocked())
1522 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1524 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1525 SecureString strWalletPass;
1526 strWalletPass.reserve(100);
1527 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1528 // Alternately, find a way to make params[0] mlock()'d to begin with.
1529 strWalletPass = params[0].get_str().c_str();
1531 if (strWalletPass.length() > 0)
1533 if (!pwalletMain->Unlock(strWalletPass))
1534 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1537 throw runtime_error(
1538 "walletpassphrase <passphrase> <timeout>\n"
1539 "Stores the wallet decryption key in memory for <timeout> seconds.");
1541 CreateThread(ThreadTopUpKeyPool, NULL);
1542 int* pnSleepTime = new int(params[1].get_int());
1543 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1549 Value walletpassphrasechange(const Array& params, bool fHelp)
1551 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1552 throw runtime_error(
1553 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1554 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1557 if (!pwalletMain->IsCrypted())
1558 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1560 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1561 // Alternately, find a way to make params[0] mlock()'d to begin with.
1562 SecureString strOldWalletPass;
1563 strOldWalletPass.reserve(100);
1564 strOldWalletPass = params[0].get_str().c_str();
1566 SecureString strNewWalletPass;
1567 strNewWalletPass.reserve(100);
1568 strNewWalletPass = params[1].get_str().c_str();
1570 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1571 throw runtime_error(
1572 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1573 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1575 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1576 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1582 Value walletlock(const Array& params, bool fHelp)
1584 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1585 throw runtime_error(
1587 "Removes the wallet encryption key from memory, locking the wallet.\n"
1588 "After calling this method, you will need to call walletpassphrase again\n"
1589 "before being able to call any methods which require the wallet to be unlocked.");
1592 if (!pwalletMain->IsCrypted())
1593 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1595 pwalletMain->Lock();
1596 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1598 nWalletUnlockTime = 0;
1605 Value encryptwallet(const Array& params, bool fHelp)
1607 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1608 throw runtime_error(
1609 "encryptwallet <passphrase>\n"
1610 "Encrypts the wallet with <passphrase>.");
1613 if (pwalletMain->IsCrypted())
1614 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1617 // shutting down via RPC while the GUI is running does not work (yet):
1618 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1621 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1622 // Alternately, find a way to make params[0] mlock()'d to begin with.
1623 SecureString strWalletPass;
1624 strWalletPass.reserve(100);
1625 strWalletPass = params[0].get_str().c_str();
1627 if (strWalletPass.length() < 1)
1628 throw runtime_error(
1629 "encryptwallet <passphrase>\n"
1630 "Encrypts the wallet with <passphrase>.");
1632 if (!pwalletMain->EncryptWallet(strWalletPass))
1633 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1635 // BDB seems to have a bad habit of writing old data into
1636 // slack space in .dat files; that is bad if the old data is
1637 // unencrypted private keys. So:
1638 CreateThread(Shutdown, NULL);
1639 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1643 Value validateaddress(const Array& params, bool fHelp)
1645 if (fHelp || params.size() != 1)
1646 throw runtime_error(
1647 "validateaddress <bitcoinaddress>\n"
1648 "Return information about <bitcoinaddress>.");
1650 CBitcoinAddress address(params[0].get_str());
1651 bool isValid = address.IsValid();
1654 ret.push_back(Pair("isvalid", isValid));
1657 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1658 // version of the address:
1659 string currentAddress = address.ToString();
1660 ret.push_back(Pair("address", currentAddress));
1661 if (pwalletMain->HaveKey(address))
1663 ret.push_back(Pair("ismine", true));
1664 std::vector<unsigned char> vchPubKey;
1665 pwalletMain->GetPubKey(address, vchPubKey);
1666 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1667 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1668 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1670 else if (pwalletMain->HaveCScript(address.GetHash160()))
1672 ret.push_back(Pair("isscript", true));
1674 pwalletMain->GetCScript(address.GetHash160(), subscript);
1675 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1676 std::vector<CBitcoinAddress> addresses;
1679 ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
1680 ret.push_back(Pair("script", GetTxnTypeName(whichType)));
1682 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1683 a.push_back(addr.ToString());
1684 ret.push_back(Pair("addresses", a));
1685 if (whichType == TX_MULTISIG)
1686 ret.push_back(Pair("sigsrequired", nRequired));
1689 ret.push_back(Pair("ismine", false));
1690 if (pwalletMain->mapAddressBook.count(address))
1691 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1696 Value getwork(const Array& params, bool fHelp)
1698 if (fHelp || params.size() > 1)
1699 throw runtime_error(
1701 "If [data] is not specified, returns formatted hash data to work on:\n"
1702 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1703 " \"data\" : block data\n"
1704 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1705 " \"target\" : little endian hash target\n"
1706 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1709 throw JSONRPCError(-9, "Bitcoin is not connected!");
1711 if (IsInitialBlockDownload())
1712 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1714 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1715 static mapNewBlock_t mapNewBlock;
1716 static vector<CBlock*> vNewBlock;
1717 static CReserveKey reservekey(pwalletMain);
1719 if (params.size() == 0)
1722 static unsigned int nTransactionsUpdatedLast;
1723 static CBlockIndex* pindexPrev;
1724 static int64 nStart;
1725 static CBlock* pblock;
1726 if (pindexPrev != pindexBest ||
1727 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1729 if (pindexPrev != pindexBest)
1731 // Deallocate old blocks since they're obsolete now
1732 mapNewBlock.clear();
1733 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1737 nTransactionsUpdatedLast = nTransactionsUpdated;
1738 pindexPrev = pindexBest;
1742 pblock = CreateNewBlock(reservekey);
1744 throw JSONRPCError(-7, "Out of memory");
1745 vNewBlock.push_back(pblock);
1749 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1752 // Update nExtraNonce
1753 static unsigned int nExtraNonce = 0;
1754 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1757 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1759 // Prebuild hash buffers
1763 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1765 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1768 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1769 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1770 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1771 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1777 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1778 if (vchData.size() != 128)
1779 throw JSONRPCError(-8, "Invalid parameter");
1780 CBlock* pdata = (CBlock*)&vchData[0];
1783 for (int i = 0; i < 128/4; i++)
1784 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1787 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1789 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1791 pblock->nTime = pdata->nTime;
1792 pblock->nNonce = pdata->nNonce;
1793 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1794 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1796 return CheckWork(pblock, *pwalletMain, reservekey);
1801 Value getmemorypool(const Array& params, bool fHelp)
1803 if (fHelp || params.size() > 1)
1804 throw runtime_error(
1805 "getmemorypool [data]\n"
1806 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1807 " \"version\" : block version\n"
1808 " \"previousblockhash\" : hash of current highest block\n"
1809 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1810 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1811 " \"time\" : timestamp appropriate for next block\n"
1812 " \"bits\" : compressed target of next block\n"
1813 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1815 if (params.size() == 0)
1818 throw JSONRPCError(-9, "Bitcoin is not connected!");
1820 if (IsInitialBlockDownload())
1821 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1823 static CReserveKey reservekey(pwalletMain);
1826 static unsigned int nTransactionsUpdatedLast;
1827 static CBlockIndex* pindexPrev;
1828 static int64 nStart;
1829 static CBlock* pblock;
1830 if (pindexPrev != pindexBest ||
1831 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1833 nTransactionsUpdatedLast = nTransactionsUpdated;
1834 pindexPrev = pindexBest;
1840 pblock = CreateNewBlock(reservekey);
1842 throw JSONRPCError(-7, "Out of memory");
1846 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1850 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1857 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1861 result.push_back(Pair("version", pblock->nVersion));
1862 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1863 result.push_back(Pair("transactions", transactions));
1864 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1865 result.push_back(Pair("time", (int64_t)pblock->nTime));
1871 uBits.nBits = htonl((int32_t)pblock->nBits);
1872 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1879 CDataStream ssBlock(ParseHex(params[0].get_str()));
1883 return ProcessBlock(NULL, &pblock);
1901 pair<string, rpcfn_type> pCallTable[] =
1903 make_pair("help", &help),
1904 make_pair("stop", &stop),
1905 make_pair("getblockcount", &getblockcount),
1906 make_pair("getblocknumber", &getblocknumber),
1907 make_pair("getconnectioncount", &getconnectioncount),
1908 make_pair("getdifficulty", &getdifficulty),
1909 make_pair("getgenerate", &getgenerate),
1910 make_pair("setgenerate", &setgenerate),
1911 make_pair("gethashespersec", &gethashespersec),
1912 make_pair("getinfo", &getinfo),
1913 make_pair("getnewaddress", &getnewaddress),
1914 make_pair("getaccountaddress", &getaccountaddress),
1915 make_pair("setaccount", &setaccount),
1916 make_pair("getaccount", &getaccount),
1917 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1918 make_pair("sendtoaddress", &sendtoaddress),
1919 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1920 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1921 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1922 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1923 make_pair("backupwallet", &backupwallet),
1924 make_pair("keypoolrefill", &keypoolrefill),
1925 make_pair("walletpassphrase", &walletpassphrase),
1926 make_pair("walletpassphrasechange", &walletpassphrasechange),
1927 make_pair("walletlock", &walletlock),
1928 make_pair("encryptwallet", &encryptwallet),
1929 make_pair("validateaddress", &validateaddress),
1930 make_pair("getbalance", &getbalance),
1931 make_pair("move", &movecmd),
1932 make_pair("sendfrom", &sendfrom),
1933 make_pair("sendmany", &sendmany),
1934 make_pair("addmultisigaddress", &addmultisigaddress),
1935 make_pair("gettransaction", &gettransaction),
1936 make_pair("listtransactions", &listtransactions),
1937 make_pair("signmessage", &signmessage),
1938 make_pair("verifymessage", &verifymessage),
1939 make_pair("getwork", &getwork),
1940 make_pair("listaccounts", &listaccounts),
1941 make_pair("settxfee", &settxfee),
1942 make_pair("getmemorypool", &getmemorypool),
1943 make_pair("listsinceblock", &listsinceblock),
1944 make_pair("dumpprivkey", &dumpprivkey),
1945 make_pair("importprivkey", &importprivkey)
1947 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1949 string pAllowInSafeMode[] =
1954 "getblocknumber", // deprecated
1955 "getconnectioncount",
1962 "getaccountaddress",
1964 "getaddressesbyaccount",
1973 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1981 // This ain't Apache. We're just using HTTP header for the length field
1982 // and to be compatible with other JSON-RPC implementations.
1985 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1988 s << "POST / HTTP/1.1\r\n"
1989 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1990 << "Host: 127.0.0.1\r\n"
1991 << "Content-Type: application/json\r\n"
1992 << "Content-Length: " << strMsg.size() << "\r\n"
1993 << "Connection: close\r\n"
1994 << "Accept: application/json\r\n";
1995 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1996 s << item.first << ": " << item.second << "\r\n";
1997 s << "\r\n" << strMsg;
2002 string rfc1123Time()
2007 struct tm* now_gmt = gmtime(&now);
2008 string locale(setlocale(LC_TIME, NULL));
2009 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2010 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2011 setlocale(LC_TIME, locale.c_str());
2012 return string(buffer);
2015 static string HTTPReply(int nStatus, const string& strMsg)
2018 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2020 "Server: bitcoin-json-rpc/%s\r\n"
2021 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2022 "Content-Type: text/html\r\n"
2023 "Content-Length: 296\r\n"
2025 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2026 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2029 "<TITLE>Error</TITLE>\r\n"
2030 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2032 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2033 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2034 const char *cStatus;
2035 if (nStatus == 200) cStatus = "OK";
2036 else if (nStatus == 400) cStatus = "Bad Request";
2037 else if (nStatus == 403) cStatus = "Forbidden";
2038 else if (nStatus == 404) cStatus = "Not Found";
2039 else if (nStatus == 500) cStatus = "Internal Server Error";
2042 "HTTP/1.1 %d %s\r\n"
2044 "Connection: close\r\n"
2045 "Content-Length: %d\r\n"
2046 "Content-Type: application/json\r\n"
2047 "Server: bitcoin-json-rpc/%s\r\n"
2052 rfc1123Time().c_str(),
2054 FormatFullVersion().c_str(),
2058 int ReadHTTPStatus(std::basic_istream<char>& stream)
2061 getline(stream, str);
2062 vector<string> vWords;
2063 boost::split(vWords, str, boost::is_any_of(" "));
2064 if (vWords.size() < 2)
2066 return atoi(vWords[1].c_str());
2069 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2075 std::getline(stream, str);
2076 if (str.empty() || str == "\r")
2078 string::size_type nColon = str.find(":");
2079 if (nColon != string::npos)
2081 string strHeader = str.substr(0, nColon);
2082 boost::trim(strHeader);
2083 boost::to_lower(strHeader);
2084 string strValue = str.substr(nColon+1);
2085 boost::trim(strValue);
2086 mapHeadersRet[strHeader] = strValue;
2087 if (strHeader == "content-length")
2088 nLen = atoi(strValue.c_str());
2094 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2096 mapHeadersRet.clear();
2100 int nStatus = ReadHTTPStatus(stream);
2103 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2104 if (nLen < 0 || nLen > MAX_SIZE)
2110 vector<char> vch(nLen);
2111 stream.read(&vch[0], nLen);
2112 strMessageRet = string(vch.begin(), vch.end());
2118 bool HTTPAuthorized(map<string, string>& mapHeaders)
2120 string strAuth = mapHeaders["authorization"];
2121 if (strAuth.substr(0,6) != "Basic ")
2123 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2124 string strUserPass = DecodeBase64(strUserPass64);
2125 return strUserPass == strRPCUserColonPass;
2129 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2130 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2131 // unspecified (HTTP errors and contents of 'error').
2133 // 1.0 spec: http://json-rpc.org/wiki/specification
2134 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2135 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2138 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2141 request.push_back(Pair("method", strMethod));
2142 request.push_back(Pair("params", params));
2143 request.push_back(Pair("id", id));
2144 return write_string(Value(request), false) + "\n";
2147 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2150 if (error.type() != null_type)
2151 reply.push_back(Pair("result", Value::null));
2153 reply.push_back(Pair("result", result));
2154 reply.push_back(Pair("error", error));
2155 reply.push_back(Pair("id", id));
2156 return write_string(Value(reply), false) + "\n";
2159 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2161 // Send error reply from json-rpc error object
2163 int code = find_value(objError, "code").get_int();
2164 if (code == -32600) nStatus = 400;
2165 else if (code == -32601) nStatus = 404;
2166 string strReply = JSONRPCReply(Value::null, objError, id);
2167 stream << HTTPReply(nStatus, strReply) << std::flush;
2170 bool ClientAllowed(const string& strAddress)
2172 if (strAddress == asio::ip::address_v4::loopback().to_string())
2174 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2175 BOOST_FOREACH(string strAllow, vAllow)
2176 if (WildcardMatch(strAddress, strAllow))
2183 // IOStream device that speaks SSL but can also speak non-SSL
2185 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2187 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2189 fUseSSL = fUseSSLIn;
2190 fNeedHandshake = fUseSSLIn;
2193 void handshake(ssl::stream_base::handshake_type role)
2195 if (!fNeedHandshake) return;
2196 fNeedHandshake = false;
2197 stream.handshake(role);
2199 std::streamsize read(char* s, std::streamsize n)
2201 handshake(ssl::stream_base::server); // HTTPS servers read first
2202 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2203 return stream.next_layer().read_some(asio::buffer(s, n));
2205 std::streamsize write(const char* s, std::streamsize n)
2207 handshake(ssl::stream_base::client); // HTTPS clients write first
2208 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2209 return asio::write(stream.next_layer(), asio::buffer(s, n));
2211 bool connect(const std::string& server, const std::string& port)
2213 ip::tcp::resolver resolver(stream.get_io_service());
2214 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2215 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2216 ip::tcp::resolver::iterator end;
2217 boost::system::error_code error = asio::error::host_not_found;
2218 while (error && endpoint_iterator != end)
2220 stream.lowest_layer().close();
2221 stream.lowest_layer().connect(*endpoint_iterator++, error);
2229 bool fNeedHandshake;
2235 void ThreadRPCServer(void* parg)
2237 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2240 vnThreadsRunning[4]++;
2241 ThreadRPCServer2(parg);
2242 vnThreadsRunning[4]--;
2244 catch (std::exception& e) {
2245 vnThreadsRunning[4]--;
2246 PrintException(&e, "ThreadRPCServer()");
2248 vnThreadsRunning[4]--;
2249 PrintException(NULL, "ThreadRPCServer()");
2251 printf("ThreadRPCServer exiting\n");
2254 void ThreadRPCServer2(void* parg)
2256 printf("ThreadRPCServer started\n");
2258 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2259 if (strRPCUserColonPass == ":")
2261 string strWhatAmI = "To use bitcoind";
2262 if (mapArgs.count("-server"))
2263 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2264 else if (mapArgs.count("-daemon"))
2265 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2267 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2268 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2270 GetConfigFile().c_str());
2272 CreateThread(Shutdown, NULL);
2277 bool fUseSSL = GetBoolArg("-rpcssl");
2278 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2280 asio::io_service io_service;
2281 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2282 ip::tcp::acceptor acceptor(io_service, endpoint);
2284 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2287 ssl::context context(io_service, ssl::context::sslv23);
2290 context.set_options(ssl::context::no_sslv2);
2291 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2292 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2293 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2294 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2295 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2296 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2297 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2298 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2300 string ciphers = GetArg("-rpcsslciphers",
2301 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2302 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2306 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2311 // Accept connection
2313 SSLStream sslStream(io_service, context);
2314 SSLIOStreamDevice d(sslStream, fUseSSL);
2315 iostreams::stream<SSLIOStreamDevice> stream(d);
2317 ip::tcp::iostream stream;
2320 ip::tcp::endpoint peer;
2321 vnThreadsRunning[4]--;
2323 acceptor.accept(sslStream.lowest_layer(), peer);
2325 acceptor.accept(*stream.rdbuf(), peer);
2327 vnThreadsRunning[4]++;
2331 // Restrict callers by IP
2332 if (!ClientAllowed(peer.address().to_string()))
2334 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2336 stream << HTTPReply(403, "") << std::flush;
2340 map<string, string> mapHeaders;
2343 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2344 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2347 printf("ThreadRPCServer ReadHTTP timeout\n");
2351 // Check authorization
2352 if (mapHeaders.count("authorization") == 0)
2354 stream << HTTPReply(401, "") << std::flush;
2357 if (!HTTPAuthorized(mapHeaders))
2359 // Deter brute-forcing short passwords
2360 if (mapArgs["-rpcpassword"].size() < 15)
2363 stream << HTTPReply(401, "") << std::flush;
2364 printf("ThreadRPCServer incorrect password attempt\n");
2368 Value id = Value::null;
2373 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2374 throw JSONRPCError(-32700, "Parse error");
2375 const Object& request = valRequest.get_obj();
2377 // Parse id now so errors from here on will have the id
2378 id = find_value(request, "id");
2381 Value valMethod = find_value(request, "method");
2382 if (valMethod.type() == null_type)
2383 throw JSONRPCError(-32600, "Missing method");
2384 if (valMethod.type() != str_type)
2385 throw JSONRPCError(-32600, "Method must be a string");
2386 string strMethod = valMethod.get_str();
2387 if (strMethod != "getwork" && strMethod != "getmemorypool")
2388 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2391 Value valParams = find_value(request, "params");
2393 if (valParams.type() == array_type)
2394 params = valParams.get_array();
2395 else if (valParams.type() == null_type)
2398 throw JSONRPCError(-32600, "Params must be an array");
2401 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2402 if (mi == mapCallTable.end())
2403 throw JSONRPCError(-32601, "Method not found");
2405 // Observe safe mode
2406 string strWarning = GetWarnings("rpc");
2407 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2408 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2414 CRITICAL_BLOCK(cs_main)
2415 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2416 result = (*(*mi).second)(params, false);
2419 string strReply = JSONRPCReply(result, Value::null, id);
2420 stream << HTTPReply(200, strReply) << std::flush;
2422 catch (std::exception& e)
2424 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2427 catch (Object& objError)
2429 ErrorReply(stream, objError, id);
2431 catch (std::exception& e)
2433 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2441 Object CallRPC(const string& strMethod, const Array& params)
2443 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2444 throw runtime_error(strprintf(
2445 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2446 "If the file does not exist, create it with owner-readable-only file permissions."),
2447 GetConfigFile().c_str()));
2449 // Connect to localhost
2450 bool fUseSSL = GetBoolArg("-rpcssl");
2452 asio::io_service io_service;
2453 ssl::context context(io_service, ssl::context::sslv23);
2454 context.set_options(ssl::context::no_sslv2);
2455 SSLStream sslStream(io_service, context);
2456 SSLIOStreamDevice d(sslStream, fUseSSL);
2457 iostreams::stream<SSLIOStreamDevice> stream(d);
2458 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2459 throw runtime_error("couldn't connect to server");
2462 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2464 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2466 throw runtime_error("couldn't connect to server");
2470 // HTTP basic authentication
2471 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2472 map<string, string> mapRequestHeaders;
2473 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2476 string strRequest = JSONRPCRequest(strMethod, params, 1);
2477 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2478 stream << strPost << std::flush;
2481 map<string, string> mapHeaders;
2483 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2485 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2486 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2487 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2488 else if (strReply.empty())
2489 throw runtime_error("no response from server");
2493 if (!read_string(strReply, valReply))
2494 throw runtime_error("couldn't parse reply from server");
2495 const Object& reply = valReply.get_obj();
2497 throw runtime_error("expected reply to have result, error and id properties");
2505 template<typename T>
2506 void ConvertTo(Value& value)
2508 if (value.type() == str_type)
2510 // reinterpret string as unquoted json value
2512 if (!read_string(value.get_str(), value2))
2513 throw runtime_error("type mismatch");
2514 value = value2.get_value<T>();
2518 value = value.get_value<T>();
2522 int CommandLineRPC(int argc, char *argv[])
2529 while (argc > 1 && IsSwitchChar(argv[1][0]))
2537 throw runtime_error("too few parameters");
2538 string strMethod = argv[1];
2540 // Parameters default to strings
2542 for (int i = 2; i < argc; i++)
2543 params.push_back(argv[i]);
2544 int n = params.size();
2547 // Special case non-string parameter types
2549 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2550 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2551 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2552 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2553 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2554 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2555 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2556 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2557 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2558 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2559 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2560 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2561 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2562 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2563 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2564 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2565 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2566 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2567 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2568 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2569 if (strMethod == "sendmany" && n > 1)
2571 string s = params[1].get_str();
2573 if (!read_string(s, v) || v.type() != obj_type)
2574 throw runtime_error("type mismatch");
2575 params[1] = v.get_obj();
2577 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2578 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2579 if (strMethod == "addmultisigaddress" && n > 1)
2581 string s = params[1].get_str();
2583 if (!read_string(s, v) || v.type() != array_type)
2584 throw runtime_error("addmultisigaddress: type mismatch "+s);
2585 params[1] = v.get_array();
2589 Object reply = CallRPC(strMethod, params);
2592 const Value& result = find_value(reply, "result");
2593 const Value& error = find_value(reply, "error");
2595 if (error.type() != null_type)
2598 strPrint = "error: " + write_string(error, false);
2599 int code = find_value(error.get_obj(), "code").get_int();
2605 if (result.type() == null_type)
2607 else if (result.type() == str_type)
2608 strPrint = result.get_str();
2610 strPrint = write_string(result, true);
2613 catch (std::exception& e)
2615 strPrint = string("error: ") + e.what();
2620 PrintException(NULL, "CommandLineRPC()");
2625 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2634 int main(int argc, char *argv[])
2637 // Turn off microsoft heap dump noise
2638 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2639 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2641 setbuf(stdin, NULL);
2642 setbuf(stdout, NULL);
2643 setbuf(stderr, NULL);
2647 if (argc >= 2 && string(argv[1]) == "-server")
2649 printf("server ready\n");
2650 ThreadRPCServer(NULL);
2654 return CommandLineRPC(argc, argv);
2657 catch (std::exception& e) {
2658 PrintException(&e, "main()");
2660 PrintException(NULL, "main()");