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 int confirms = wtx.GetDepthInMainChain();
95 entry.push_back(Pair("confirmations", confirms));
98 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
99 entry.push_back(Pair("blockindex", wtx.nIndex));
101 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
102 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
103 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
104 entry.push_back(Pair(item.first, item.second));
107 string AccountFromValue(const Value& value)
109 string strAccount = value.get_str();
110 if (strAccount == "*")
111 throw JSONRPCError(-11, "Invalid account name");
118 /// Note: This interface may still be subject to change.
122 Value help(const Array& params, bool fHelp)
124 if (fHelp || params.size() > 1)
127 "List commands, or get help for a command.");
130 if (params.size() > 0)
131 strCommand = params[0].get_str();
134 set<rpcfn_type> setDone;
135 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
137 string strMethod = (*mi).first;
138 // We already filter duplicates, but these deprecated screw up the sort order
139 if (strMethod == "getamountreceived" ||
140 strMethod == "getallreceived" ||
141 strMethod == "getblocknumber" || // deprecated
142 (strMethod.find("label") != string::npos))
144 if (strCommand != "" && strMethod != strCommand)
149 rpcfn_type pfn = (*mi).second;
150 if (setDone.insert(pfn).second)
151 (*pfn)(params, true);
153 catch (std::exception& e)
155 // Help text is returned in an exception
156 string strHelp = string(e.what());
157 if (strCommand == "")
158 if (strHelp.find('\n') != -1)
159 strHelp = strHelp.substr(0, strHelp.find('\n'));
160 strRet += strHelp + "\n";
164 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
165 strRet = strRet.substr(0,strRet.size()-1);
170 Value stop(const Array& params, bool fHelp)
172 if (fHelp || params.size() != 0)
175 "Stop bitcoin server.");
177 // Shutdown will take long enough that the response should get back
178 CreateThread(Shutdown, NULL);
179 return "bitcoin server stopping";
181 throw runtime_error("NYI: cannot shut down GUI with RPC command");
186 Value getblockcount(const Array& params, bool fHelp)
188 if (fHelp || params.size() != 0)
191 "Returns the number of blocks in the longest block chain.");
198 Value getblocknumber(const Array& params, bool fHelp)
200 if (fHelp || params.size() != 0)
203 "Deprecated. Use getblockcount.");
209 Value getconnectioncount(const Array& params, bool fHelp)
211 if (fHelp || params.size() != 0)
213 "getconnectioncount\n"
214 "Returns the number of connections to other nodes.");
216 return (int)vNodes.size();
220 double GetDifficulty()
222 // Floating point number that is a multiple of the minimum difficulty,
223 // minimum difficulty = 1.0.
225 if (pindexBest == NULL)
227 int nShift = (pindexBest->nBits >> 24) & 0xff;
230 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
246 Value getdifficulty(const Array& params, bool fHelp)
248 if (fHelp || params.size() != 0)
251 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
253 return GetDifficulty();
257 Value getgenerate(const Array& params, bool fHelp)
259 if (fHelp || params.size() != 0)
262 "Returns true or false.");
264 return (bool)fGenerateBitcoins;
268 Value setgenerate(const Array& params, bool fHelp)
270 if (fHelp || params.size() < 1 || params.size() > 2)
272 "setgenerate <generate> [genproclimit]\n"
273 "<generate> is true or false to turn generation on or off.\n"
274 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
276 bool fGenerate = true;
277 if (params.size() > 0)
278 fGenerate = params[0].get_bool();
280 if (params.size() > 1)
282 int nGenProcLimit = params[1].get_int();
283 fLimitProcessors = (nGenProcLimit != -1);
284 WriteSetting("fLimitProcessors", fLimitProcessors);
285 if (nGenProcLimit != -1)
286 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
287 if (nGenProcLimit == 0)
291 GenerateBitcoins(fGenerate, pwalletMain);
296 Value gethashespersec(const Array& params, bool fHelp)
298 if (fHelp || params.size() != 0)
301 "Returns a recent hashes per second performance measurement while generating.");
303 if (GetTimeMillis() - nHPSTimerStart > 8000)
304 return (boost::int64_t)0;
305 return (boost::int64_t)dHashesPerSec;
309 Value getinfo(const Array& params, bool fHelp)
311 if (fHelp || params.size() != 0)
314 "Returns an object containing various state info.");
317 obj.push_back(Pair("version", (int)CLIENT_VERSION));
318 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
319 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
320 obj.push_back(Pair("blocks", (int)nBestHeight));
321 obj.push_back(Pair("connections", (int)vNodes.size()));
322 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
323 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
324 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
325 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
326 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
327 obj.push_back(Pair("testnet", fTestNet));
328 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
329 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
330 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
331 if (pwalletMain->IsCrypted())
332 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
333 obj.push_back(Pair("errors", GetWarnings("statusbar")));
338 Value getnewaddress(const Array& params, bool fHelp)
340 if (fHelp || params.size() > 1)
342 "getnewaddress [account]\n"
343 "Returns a new bitcoin address for receiving payments. "
344 "If [account] is specified (recommended), it is added to the address book "
345 "so payments received with the address will be credited to [account].");
347 // Parse the account first so we don't generate a key if there's an error
349 if (params.size() > 0)
350 strAccount = AccountFromValue(params[0]);
352 if (!pwalletMain->IsLocked())
353 pwalletMain->TopUpKeyPool();
355 // Generate a new key that is added to wallet
356 std::vector<unsigned char> newKey;
357 if (!pwalletMain->GetKeyFromPool(newKey, false))
358 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
359 CBitcoinAddress address(newKey);
361 pwalletMain->SetAddressBookName(address, strAccount);
363 return address.ToString();
367 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
369 CWalletDB walletdb(pwalletMain->strWalletFile);
372 walletdb.ReadAccount(strAccount, account);
374 bool bKeyUsed = false;
376 // Check if the current key has been used
377 if (!account.vchPubKey.empty())
379 CScript scriptPubKey;
380 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
381 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
382 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
385 const CWalletTx& wtx = (*it).second;
386 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
387 if (txout.scriptPubKey == scriptPubKey)
392 // Generate a new key
393 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
395 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
396 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
398 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
399 walletdb.WriteAccount(strAccount, account);
402 return CBitcoinAddress(account.vchPubKey);
405 Value getaccountaddress(const Array& params, bool fHelp)
407 if (fHelp || params.size() != 1)
409 "getaccountaddress <account>\n"
410 "Returns the current bitcoin address for receiving payments to this account.");
412 // Parse the account first so we don't generate a key if there's an error
413 string strAccount = AccountFromValue(params[0]);
417 ret = GetAccountAddress(strAccount).ToString();
424 Value setaccount(const Array& params, bool fHelp)
426 if (fHelp || params.size() < 1 || params.size() > 2)
428 "setaccount <bitcoinaddress> <account>\n"
429 "Sets the account associated with the given address.");
431 CBitcoinAddress address(params[0].get_str());
432 if (!address.IsValid())
433 throw JSONRPCError(-5, "Invalid bitcoin address");
437 if (params.size() > 1)
438 strAccount = AccountFromValue(params[1]);
440 // Detect when changing the account of an address that is the 'unused current key' of another account:
441 if (pwalletMain->mapAddressBook.count(address))
443 string strOldAccount = pwalletMain->mapAddressBook[address];
444 if (address == GetAccountAddress(strOldAccount))
445 GetAccountAddress(strOldAccount, true);
448 pwalletMain->SetAddressBookName(address, strAccount);
454 Value getaccount(const Array& params, bool fHelp)
456 if (fHelp || params.size() != 1)
458 "getaccount <bitcoinaddress>\n"
459 "Returns the account associated with the given address.");
461 CBitcoinAddress address(params[0].get_str());
462 if (!address.IsValid())
463 throw JSONRPCError(-5, "Invalid bitcoin address");
466 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
467 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
468 strAccount = (*mi).second;
473 Value getaddressesbyaccount(const Array& params, bool fHelp)
475 if (fHelp || params.size() != 1)
477 "getaddressesbyaccount <account>\n"
478 "Returns the list of addresses for the given account.");
480 string strAccount = AccountFromValue(params[0]);
482 // Find all addresses that have the given account
484 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
486 const CBitcoinAddress& address = item.first;
487 const string& strName = item.second;
488 if (strName == strAccount)
489 ret.push_back(address.ToString());
494 Value settxfee(const Array& params, bool fHelp)
496 if (fHelp || params.size() < 1 || params.size() > 1)
498 "settxfee <amount>\n"
499 "<amount> is a real and is rounded to the nearest 0.00000001");
503 if (params[0].get_real() != 0.0)
504 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
506 nTransactionFee = nAmount;
510 Value sendtoaddress(const Array& params, bool fHelp)
512 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
514 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
515 "<amount> is a real and is rounded to the nearest 0.00000001\n"
516 "requires wallet passphrase to be set with walletpassphrase first");
517 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
519 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
520 "<amount> is a real and is rounded to the nearest 0.00000001");
522 CBitcoinAddress address(params[0].get_str());
523 if (!address.IsValid())
524 throw JSONRPCError(-5, "Invalid bitcoin address");
527 int64 nAmount = AmountFromValue(params[1]);
531 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
532 wtx.mapValue["comment"] = params[2].get_str();
533 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
534 wtx.mapValue["to"] = params[3].get_str();
536 if (pwalletMain->IsLocked())
537 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
539 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
541 throw JSONRPCError(-4, strError);
543 return wtx.GetHash().GetHex();
546 static const string strMessageMagic = "Bitcoin Signed Message:\n";
548 Value signmessage(const Array& params, bool fHelp)
550 if (fHelp || params.size() != 2)
552 "signmessage <bitcoinaddress> <message>\n"
553 "Sign a message with the private key of an address");
555 if (pwalletMain->IsLocked())
556 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
558 string strAddress = params[0].get_str();
559 string strMessage = params[1].get_str();
561 CBitcoinAddress addr(strAddress);
563 throw JSONRPCError(-3, "Invalid address");
566 if (!pwalletMain->GetKey(addr, key))
567 throw JSONRPCError(-4, "Private key not available");
569 CDataStream ss(SER_GETHASH);
570 ss << strMessageMagic;
573 vector<unsigned char> vchSig;
574 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
575 throw JSONRPCError(-5, "Sign failed");
577 return EncodeBase64(&vchSig[0], vchSig.size());
580 Value verifymessage(const Array& params, bool fHelp)
582 if (fHelp || params.size() != 3)
584 "verifymessage <bitcoinaddress> <signature> <message>\n"
585 "Verify a signed message");
587 string strAddress = params[0].get_str();
588 string strSign = params[1].get_str();
589 string strMessage = params[2].get_str();
591 CBitcoinAddress addr(strAddress);
593 throw JSONRPCError(-3, "Invalid address");
595 bool fInvalid = false;
596 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
599 throw JSONRPCError(-5, "Malformed base64 encoding");
601 CDataStream ss(SER_GETHASH);
602 ss << strMessageMagic;
606 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
609 return (CBitcoinAddress(key.GetPubKey()) == addr);
613 Value getreceivedbyaddress(const Array& params, bool fHelp)
615 if (fHelp || params.size() < 1 || params.size() > 2)
617 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
618 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
621 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
622 CScript scriptPubKey;
623 if (!address.IsValid())
624 throw JSONRPCError(-5, "Invalid bitcoin address");
625 scriptPubKey.SetBitcoinAddress(address);
626 if (!IsMine(*pwalletMain,scriptPubKey))
629 // Minimum confirmations
631 if (params.size() > 1)
632 nMinDepth = params[1].get_int();
636 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
638 const CWalletTx& wtx = (*it).second;
639 if (wtx.IsCoinBase() || !wtx.IsFinal())
642 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
643 if (txout.scriptPubKey == scriptPubKey)
644 if (wtx.GetDepthInMainChain() >= nMinDepth)
645 nAmount += txout.nValue;
648 return ValueFromAmount(nAmount);
652 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
654 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
656 const CBitcoinAddress& address = item.first;
657 const string& strName = item.second;
658 if (strName == strAccount)
659 setAddress.insert(address);
664 Value getreceivedbyaccount(const Array& params, bool fHelp)
666 if (fHelp || params.size() < 1 || params.size() > 2)
668 "getreceivedbyaccount <account> [minconf=1]\n"
669 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
671 // Minimum confirmations
673 if (params.size() > 1)
674 nMinDepth = params[1].get_int();
676 // Get the set of pub keys assigned to account
677 string strAccount = AccountFromValue(params[0]);
678 set<CBitcoinAddress> setAddress;
679 GetAccountAddresses(strAccount, setAddress);
683 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
685 const CWalletTx& wtx = (*it).second;
686 if (wtx.IsCoinBase() || !wtx.IsFinal())
689 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
691 CBitcoinAddress address;
692 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
693 if (wtx.GetDepthInMainChain() >= nMinDepth)
694 nAmount += txout.nValue;
698 return (double)nAmount / (double)COIN;
702 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
706 // Tally wallet transactions
707 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
709 const CWalletTx& wtx = (*it).second;
713 int64 nGenerated, nReceived, nSent, nFee;
714 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
716 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
717 nBalance += nReceived;
718 nBalance += nGenerated - nSent - nFee;
721 // Tally internal accounting entries
722 nBalance += walletdb.GetAccountCreditDebit(strAccount);
727 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
729 CWalletDB walletdb(pwalletMain->strWalletFile);
730 return GetAccountBalance(walletdb, strAccount, nMinDepth);
734 Value getbalance(const Array& params, bool fHelp)
736 if (fHelp || params.size() > 2)
738 "getbalance [account] [minconf=1]\n"
739 "If [account] is not specified, returns the server's total available balance.\n"
740 "If [account] is specified, returns the balance in the account.");
742 if (params.size() == 0)
743 return ValueFromAmount(pwalletMain->GetBalance());
746 if (params.size() > 1)
747 nMinDepth = params[1].get_int();
749 if (params[0].get_str() == "*") {
750 // Calculate total balance a different way from GetBalance()
751 // (GetBalance() sums up all unspent TxOuts)
752 // getbalance and getbalance '*' should always return the same number.
754 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
756 const CWalletTx& wtx = (*it).second;
760 int64 allGeneratedImmature, allGeneratedMature, allFee;
761 allGeneratedImmature = allGeneratedMature = allFee = 0;
762 string strSentAccount;
763 list<pair<CBitcoinAddress, int64> > listReceived;
764 list<pair<CBitcoinAddress, int64> > listSent;
765 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
766 if (wtx.GetDepthInMainChain() >= nMinDepth)
767 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
768 nBalance += r.second;
769 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
770 nBalance -= r.second;
772 nBalance += allGeneratedMature;
774 return ValueFromAmount(nBalance);
777 string strAccount = AccountFromValue(params[0]);
779 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
781 return ValueFromAmount(nBalance);
785 Value movecmd(const Array& params, bool fHelp)
787 if (fHelp || params.size() < 3 || params.size() > 5)
789 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
790 "Move from one account in your wallet to another.");
792 string strFrom = AccountFromValue(params[0]);
793 string strTo = AccountFromValue(params[1]);
794 int64 nAmount = AmountFromValue(params[2]);
795 if (params.size() > 3)
796 // unused parameter, used to be nMinDepth, keep type-checking it though
797 (void)params[3].get_int();
799 if (params.size() > 4)
800 strComment = params[4].get_str();
802 CWalletDB walletdb(pwalletMain->strWalletFile);
805 int64 nNow = GetAdjustedTime();
808 CAccountingEntry debit;
809 debit.strAccount = strFrom;
810 debit.nCreditDebit = -nAmount;
812 debit.strOtherAccount = strTo;
813 debit.strComment = strComment;
814 walletdb.WriteAccountingEntry(debit);
817 CAccountingEntry credit;
818 credit.strAccount = strTo;
819 credit.nCreditDebit = nAmount;
821 credit.strOtherAccount = strFrom;
822 credit.strComment = strComment;
823 walletdb.WriteAccountingEntry(credit);
825 walletdb.TxnCommit();
831 Value sendfrom(const Array& params, bool fHelp)
833 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
835 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
836 "<amount> is a real and is rounded to the nearest 0.00000001\n"
837 "requires wallet passphrase to be set with walletpassphrase first");
838 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
840 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
841 "<amount> is a real and is rounded to the nearest 0.00000001");
843 string strAccount = AccountFromValue(params[0]);
844 CBitcoinAddress address(params[1].get_str());
845 if (!address.IsValid())
846 throw JSONRPCError(-5, "Invalid bitcoin address");
847 int64 nAmount = AmountFromValue(params[2]);
849 if (params.size() > 3)
850 nMinDepth = params[3].get_int();
853 wtx.strFromAccount = strAccount;
854 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
855 wtx.mapValue["comment"] = params[4].get_str();
856 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
857 wtx.mapValue["to"] = params[5].get_str();
859 if (pwalletMain->IsLocked())
860 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
863 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
864 if (nAmount > nBalance)
865 throw JSONRPCError(-6, "Account has insufficient funds");
868 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
870 throw JSONRPCError(-4, strError);
872 return wtx.GetHash().GetHex();
876 Value sendmany(const Array& params, bool fHelp)
878 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
880 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
881 "amounts are double-precision floating point numbers\n"
882 "requires wallet passphrase to be set with walletpassphrase first");
883 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
885 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
886 "amounts are double-precision floating point numbers");
888 string strAccount = AccountFromValue(params[0]);
889 Object sendTo = params[1].get_obj();
891 if (params.size() > 2)
892 nMinDepth = params[2].get_int();
895 wtx.strFromAccount = strAccount;
896 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
897 wtx.mapValue["comment"] = params[3].get_str();
899 set<CBitcoinAddress> setAddress;
900 vector<pair<CScript, int64> > vecSend;
902 int64 totalAmount = 0;
903 BOOST_FOREACH(const Pair& s, sendTo)
905 CBitcoinAddress address(s.name_);
906 if (!address.IsValid())
907 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
909 if (setAddress.count(address))
910 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
911 setAddress.insert(address);
913 CScript scriptPubKey;
914 scriptPubKey.SetBitcoinAddress(address);
915 int64 nAmount = AmountFromValue(s.value_);
916 totalAmount += nAmount;
918 vecSend.push_back(make_pair(scriptPubKey, nAmount));
921 if (pwalletMain->IsLocked())
922 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
925 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
926 if (totalAmount > nBalance)
927 throw JSONRPCError(-6, "Account has insufficient funds");
930 CReserveKey keyChange(pwalletMain);
931 int64 nFeeRequired = 0;
932 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
935 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
936 throw JSONRPCError(-6, "Insufficient funds");
937 throw JSONRPCError(-4, "Transaction creation failed");
939 if (!pwalletMain->CommitTransaction(wtx, keyChange))
940 throw JSONRPCError(-4, "Transaction commit failed");
942 return wtx.GetHash().GetHex();
945 Value addmultisigaddress(const Array& params, bool fHelp)
947 if (fHelp || params.size() < 2 || params.size() > 3)
949 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
950 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
951 "each key is a bitcoin address, hex or base58 public key\n"
952 "If [account] is specified, assign address to [account].";
953 throw runtime_error(msg);
956 throw runtime_error("addmultisigaddress available only when running -testnet\n");
958 int nRequired = params[0].get_int();
959 const Array& keys = params[1].get_array();
961 if (params.size() > 2)
962 strAccount = AccountFromValue(params[2]);
964 // Gather public keys
965 if (keys.size() < nRequired)
967 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
968 std::vector<CKey> pubkeys;
969 pubkeys.resize(keys.size());
970 for (int i = 0; i < keys.size(); i++)
972 const std::string& ks = keys[i].get_str();
973 if (ks.size() == 130) // hex public key
974 pubkeys[i].SetPubKey(ParseHex(ks));
975 else if (ks.size() > 34) // base58-encoded
977 std::vector<unsigned char> vchPubKey;
978 if (DecodeBase58(ks, vchPubKey))
979 pubkeys[i].SetPubKey(vchPubKey);
981 throw runtime_error("Error base58 decoding key: "+ks);
983 else // bitcoin address for key in this wallet
985 CBitcoinAddress address(ks);
986 if (!pwalletMain->GetKey(address, pubkeys[i]))
988 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
992 // Construct using OP_EVAL
994 inner.SetMultisig(nRequired, pubkeys);
996 uint160 scriptHash = Hash160(inner);
997 CScript scriptPubKey;
998 scriptPubKey.SetEval(inner);
999 pwalletMain->AddCScript(scriptHash, inner);
1000 CBitcoinAddress address;
1001 address.SetScriptHash160(scriptHash);
1003 pwalletMain->SetAddressBookName(address, strAccount);
1004 return address.ToString();
1015 nConf = std::numeric_limits<int>::max();
1019 Value ListReceived(const Array& params, bool fByAccounts)
1021 // Minimum confirmations
1023 if (params.size() > 0)
1024 nMinDepth = params[0].get_int();
1026 // Whether to include empty accounts
1027 bool fIncludeEmpty = false;
1028 if (params.size() > 1)
1029 fIncludeEmpty = params[1].get_bool();
1032 map<CBitcoinAddress, tallyitem> mapTally;
1033 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1035 const CWalletTx& wtx = (*it).second;
1036 if (wtx.IsCoinBase() || !wtx.IsFinal())
1039 int nDepth = wtx.GetDepthInMainChain();
1040 if (nDepth < nMinDepth)
1043 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1045 CBitcoinAddress address;
1046 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
1049 tallyitem& item = mapTally[address];
1050 item.nAmount += txout.nValue;
1051 item.nConf = min(item.nConf, nDepth);
1057 map<string, tallyitem> mapAccountTally;
1058 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1060 const CBitcoinAddress& address = item.first;
1061 const string& strAccount = item.second;
1062 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1063 if (it == mapTally.end() && !fIncludeEmpty)
1067 int nConf = std::numeric_limits<int>::max();
1068 if (it != mapTally.end())
1070 nAmount = (*it).second.nAmount;
1071 nConf = (*it).second.nConf;
1076 tallyitem& item = mapAccountTally[strAccount];
1077 item.nAmount += nAmount;
1078 item.nConf = min(item.nConf, nConf);
1083 obj.push_back(Pair("address", address.ToString()));
1084 obj.push_back(Pair("account", strAccount));
1085 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1086 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1093 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1095 int64 nAmount = (*it).second.nAmount;
1096 int nConf = (*it).second.nConf;
1098 obj.push_back(Pair("account", (*it).first));
1099 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1100 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1108 Value listreceivedbyaddress(const Array& params, bool fHelp)
1110 if (fHelp || params.size() > 2)
1111 throw runtime_error(
1112 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1113 "[minconf] is the minimum number of confirmations before payments are included.\n"
1114 "[includeempty] whether to include addresses that haven't received any payments.\n"
1115 "Returns an array of objects containing:\n"
1116 " \"address\" : receiving address\n"
1117 " \"account\" : the account of the receiving address\n"
1118 " \"amount\" : total amount received by the address\n"
1119 " \"confirmations\" : number of confirmations of the most recent transaction included");
1121 return ListReceived(params, false);
1124 Value listreceivedbyaccount(const Array& params, bool fHelp)
1126 if (fHelp || params.size() > 2)
1127 throw runtime_error(
1128 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1129 "[minconf] is the minimum number of confirmations before payments are included.\n"
1130 "[includeempty] whether to include accounts that haven't received any payments.\n"
1131 "Returns an array of objects containing:\n"
1132 " \"account\" : the account of the receiving addresses\n"
1133 " \"amount\" : total amount received by addresses with this account\n"
1134 " \"confirmations\" : number of confirmations of the most recent transaction included");
1136 return ListReceived(params, true);
1139 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1141 int64 nGeneratedImmature, nGeneratedMature, nFee;
1142 string strSentAccount;
1143 list<pair<CBitcoinAddress, int64> > listReceived;
1144 list<pair<CBitcoinAddress, int64> > listSent;
1145 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1147 bool fAllAccounts = (strAccount == string("*"));
1149 // Generated blocks assigned to account ""
1150 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1153 entry.push_back(Pair("account", string("")));
1154 if (nGeneratedImmature)
1156 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1157 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1161 entry.push_back(Pair("category", "generate"));
1162 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1165 WalletTxToJSON(wtx, entry);
1166 ret.push_back(entry);
1170 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1172 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1175 entry.push_back(Pair("account", strSentAccount));
1176 entry.push_back(Pair("address", s.first.ToString()));
1177 entry.push_back(Pair("category", "send"));
1178 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1179 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1181 WalletTxToJSON(wtx, entry);
1182 ret.push_back(entry);
1187 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1188 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1191 if (pwalletMain->mapAddressBook.count(r.first))
1192 account = pwalletMain->mapAddressBook[r.first];
1193 if (fAllAccounts || (account == strAccount))
1196 entry.push_back(Pair("account", account));
1197 entry.push_back(Pair("address", r.first.ToString()));
1198 entry.push_back(Pair("category", "receive"));
1199 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1201 WalletTxToJSON(wtx, entry);
1202 ret.push_back(entry);
1207 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1209 bool fAllAccounts = (strAccount == string("*"));
1211 if (fAllAccounts || acentry.strAccount == strAccount)
1214 entry.push_back(Pair("account", acentry.strAccount));
1215 entry.push_back(Pair("category", "move"));
1216 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1217 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1218 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1219 entry.push_back(Pair("comment", acentry.strComment));
1220 ret.push_back(entry);
1224 Value listtransactions(const Array& params, bool fHelp)
1226 if (fHelp || params.size() > 3)
1227 throw runtime_error(
1228 "listtransactions [account] [count=10] [from=0]\n"
1229 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1231 string strAccount = "*";
1232 if (params.size() > 0)
1233 strAccount = params[0].get_str();
1235 if (params.size() > 1)
1236 nCount = params[1].get_int();
1238 if (params.size() > 2)
1239 nFrom = params[2].get_int();
1242 CWalletDB walletdb(pwalletMain->strWalletFile);
1244 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1245 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1246 typedef multimap<int64, TxPair > TxItems;
1249 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1251 CWalletTx* wtx = &((*it).second);
1252 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1254 list<CAccountingEntry> acentries;
1255 walletdb.ListAccountCreditDebit(strAccount, acentries);
1256 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1258 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1261 // Now: iterate backwards until we have nCount items to return:
1262 TxItems::reverse_iterator it = txByTime.rbegin();
1263 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1264 for (; it != txByTime.rend(); ++it)
1266 CWalletTx *const pwtx = (*it).second.first;
1268 ListTransactions(*pwtx, strAccount, 0, true, ret);
1269 CAccountingEntry *const pacentry = (*it).second.second;
1271 AcentryToJSON(*pacentry, strAccount, ret);
1273 if (ret.size() >= nCount) break;
1275 // ret is now newest to oldest
1277 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1278 if (ret.size() > nCount)
1280 Array::iterator last = ret.begin();
1281 std::advance(last, nCount);
1282 ret.erase(last, ret.end());
1284 std::reverse(ret.begin(), ret.end()); // oldest to newest
1289 Value listaccounts(const Array& params, bool fHelp)
1291 if (fHelp || params.size() > 1)
1292 throw runtime_error(
1293 "listaccounts [minconf=1]\n"
1294 "Returns Object that has account names as keys, account balances as values.");
1297 if (params.size() > 0)
1298 nMinDepth = params[0].get_int();
1300 map<string, int64> mapAccountBalances;
1301 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1302 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1303 mapAccountBalances[entry.second] = 0;
1306 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1308 const CWalletTx& wtx = (*it).second;
1309 int64 nGeneratedImmature, nGeneratedMature, nFee;
1310 string strSentAccount;
1311 list<pair<CBitcoinAddress, int64> > listReceived;
1312 list<pair<CBitcoinAddress, int64> > listSent;
1313 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1314 mapAccountBalances[strSentAccount] -= nFee;
1315 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1316 mapAccountBalances[strSentAccount] -= s.second;
1317 if (wtx.GetDepthInMainChain() >= nMinDepth)
1319 mapAccountBalances[""] += nGeneratedMature;
1320 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1321 if (pwalletMain->mapAddressBook.count(r.first))
1322 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1324 mapAccountBalances[""] += r.second;
1328 list<CAccountingEntry> acentries;
1329 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1330 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1331 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1334 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1335 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1340 Value listsinceblock(const Array& params, bool fHelp)
1343 throw runtime_error(
1344 "listsinceblock [blockid] [target-confirmations]\n"
1345 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1347 CBlockIndex *pindex = NULL;
1348 int target_confirms = 1;
1350 if (params.size() > 0)
1352 uint256 blockId = 0;
1354 blockId.SetHex(params[0].get_str());
1355 pindex = CBlockLocator(blockId).GetBlockIndex();
1358 if (params.size() > 1)
1360 target_confirms = params[1].get_int();
1362 if (target_confirms < 1)
1363 throw JSONRPCError(-8, "Invalid parameter");
1366 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1370 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1372 CWalletTx tx = (*it).second;
1374 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1375 ListTransactions(tx, "*", 0, true, transactions);
1380 if (target_confirms == 1)
1383 lastblock = hashBestChain;
1387 int target_height = pindexBest->nHeight + 1 - target_confirms;
1390 for (block = pindexBest;
1391 block && block->nHeight > target_height;
1392 block = block->pprev);
1394 lastblock = block ? block->GetBlockHash() : 0;
1398 ret.push_back(Pair("transactions", transactions));
1399 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1404 Value gettransaction(const Array& params, bool fHelp)
1406 if (fHelp || params.size() != 1)
1407 throw runtime_error(
1408 "gettransaction <txid>\n"
1409 "Get detailed information about <txid>");
1412 hash.SetHex(params[0].get_str());
1416 if (!pwalletMain->mapWallet.count(hash))
1417 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1418 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1420 int64 nCredit = wtx.GetCredit();
1421 int64 nDebit = wtx.GetDebit();
1422 int64 nNet = nCredit - nDebit;
1423 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1425 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1427 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1429 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1432 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1433 entry.push_back(Pair("details", details));
1439 Value backupwallet(const Array& params, bool fHelp)
1441 if (fHelp || params.size() != 1)
1442 throw runtime_error(
1443 "backupwallet <destination>\n"
1444 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1446 string strDest = params[0].get_str();
1447 BackupWallet(*pwalletMain, strDest);
1453 Value keypoolrefill(const Array& params, bool fHelp)
1455 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1456 throw runtime_error(
1458 "Fills the keypool, requires wallet passphrase to be set.");
1459 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1460 throw runtime_error(
1462 "Fills the keypool.");
1464 if (pwalletMain->IsLocked())
1465 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1467 pwalletMain->TopUpKeyPool();
1469 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1470 throw JSONRPCError(-4, "Error refreshing keypool.");
1476 void ThreadTopUpKeyPool(void* parg)
1478 pwalletMain->TopUpKeyPool();
1481 void ThreadCleanWalletPassphrase(void* parg)
1483 int64 nMyWakeTime = GetTime() + *((int*)parg);
1485 if (nWalletUnlockTime == 0)
1487 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1489 nWalletUnlockTime = nMyWakeTime;
1492 while (GetTime() < nWalletUnlockTime)
1493 Sleep(GetTime() - nWalletUnlockTime);
1495 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1497 nWalletUnlockTime = 0;
1502 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1504 if (nWalletUnlockTime < nMyWakeTime)
1505 nWalletUnlockTime = nMyWakeTime;
1511 pwalletMain->Lock();
1516 Value walletpassphrase(const Array& params, bool fHelp)
1518 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1519 throw runtime_error(
1520 "walletpassphrase <passphrase> <timeout>\n"
1521 "Stores the wallet decryption key in memory for <timeout> seconds.");
1524 if (!pwalletMain->IsCrypted())
1525 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1527 if (!pwalletMain->IsLocked())
1528 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1530 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1531 SecureString strWalletPass;
1532 strWalletPass.reserve(100);
1533 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1534 // Alternately, find a way to make params[0] mlock()'d to begin with.
1535 strWalletPass = params[0].get_str().c_str();
1537 if (strWalletPass.length() > 0)
1539 if (!pwalletMain->Unlock(strWalletPass))
1540 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1543 throw runtime_error(
1544 "walletpassphrase <passphrase> <timeout>\n"
1545 "Stores the wallet decryption key in memory for <timeout> seconds.");
1547 CreateThread(ThreadTopUpKeyPool, NULL);
1548 int* pnSleepTime = new int(params[1].get_int());
1549 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1555 Value walletpassphrasechange(const Array& params, bool fHelp)
1557 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1558 throw runtime_error(
1559 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1560 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1563 if (!pwalletMain->IsCrypted())
1564 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1566 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1567 // Alternately, find a way to make params[0] mlock()'d to begin with.
1568 SecureString strOldWalletPass;
1569 strOldWalletPass.reserve(100);
1570 strOldWalletPass = params[0].get_str().c_str();
1572 SecureString strNewWalletPass;
1573 strNewWalletPass.reserve(100);
1574 strNewWalletPass = params[1].get_str().c_str();
1576 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1577 throw runtime_error(
1578 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1579 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1581 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1582 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1588 Value walletlock(const Array& params, bool fHelp)
1590 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1591 throw runtime_error(
1593 "Removes the wallet encryption key from memory, locking the wallet.\n"
1594 "After calling this method, you will need to call walletpassphrase again\n"
1595 "before being able to call any methods which require the wallet to be unlocked.");
1598 if (!pwalletMain->IsCrypted())
1599 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1601 pwalletMain->Lock();
1602 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1604 nWalletUnlockTime = 0;
1611 Value encryptwallet(const Array& params, bool fHelp)
1613 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1614 throw runtime_error(
1615 "encryptwallet <passphrase>\n"
1616 "Encrypts the wallet with <passphrase>.");
1619 if (pwalletMain->IsCrypted())
1620 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1623 // shutting down via RPC while the GUI is running does not work (yet):
1624 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1627 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1628 // Alternately, find a way to make params[0] mlock()'d to begin with.
1629 SecureString strWalletPass;
1630 strWalletPass.reserve(100);
1631 strWalletPass = params[0].get_str().c_str();
1633 if (strWalletPass.length() < 1)
1634 throw runtime_error(
1635 "encryptwallet <passphrase>\n"
1636 "Encrypts the wallet with <passphrase>.");
1638 if (!pwalletMain->EncryptWallet(strWalletPass))
1639 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1641 // BDB seems to have a bad habit of writing old data into
1642 // slack space in .dat files; that is bad if the old data is
1643 // unencrypted private keys. So:
1644 CreateThread(Shutdown, NULL);
1645 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1649 Value validateaddress(const Array& params, bool fHelp)
1651 if (fHelp || params.size() != 1)
1652 throw runtime_error(
1653 "validateaddress <bitcoinaddress>\n"
1654 "Return information about <bitcoinaddress>.");
1656 CBitcoinAddress address(params[0].get_str());
1657 bool isValid = address.IsValid();
1660 ret.push_back(Pair("isvalid", isValid));
1663 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1664 // version of the address:
1665 string currentAddress = address.ToString();
1666 ret.push_back(Pair("address", currentAddress));
1667 if (pwalletMain->HaveKey(address))
1669 ret.push_back(Pair("ismine", true));
1670 std::vector<unsigned char> vchPubKey;
1671 pwalletMain->GetPubKey(address, vchPubKey);
1672 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1673 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1674 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1676 else if (pwalletMain->HaveCScript(address.GetHash160()))
1678 ret.push_back(Pair("isscript", true));
1680 pwalletMain->GetCScript(address.GetHash160(), subscript);
1681 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1682 std::vector<CBitcoinAddress> addresses;
1683 txnouttype whichType;
1685 ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
1686 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1688 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1689 a.push_back(addr.ToString());
1690 ret.push_back(Pair("addresses", a));
1691 if (whichType == TX_MULTISIG)
1692 ret.push_back(Pair("sigsrequired", nRequired));
1695 ret.push_back(Pair("ismine", false));
1696 if (pwalletMain->mapAddressBook.count(address))
1697 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1702 Value getwork(const Array& params, bool fHelp)
1704 if (fHelp || params.size() > 1)
1705 throw runtime_error(
1707 "If [data] is not specified, returns formatted hash data to work on:\n"
1708 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1709 " \"data\" : block data\n"
1710 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1711 " \"target\" : little endian hash target\n"
1712 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1715 throw JSONRPCError(-9, "Bitcoin is not connected!");
1717 if (IsInitialBlockDownload())
1718 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1720 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1721 static mapNewBlock_t mapNewBlock;
1722 static vector<CBlock*> vNewBlock;
1723 static CReserveKey reservekey(pwalletMain);
1725 if (params.size() == 0)
1728 static unsigned int nTransactionsUpdatedLast;
1729 static CBlockIndex* pindexPrev;
1730 static int64 nStart;
1731 static CBlock* pblock;
1732 if (pindexPrev != pindexBest ||
1733 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1735 if (pindexPrev != pindexBest)
1737 // Deallocate old blocks since they're obsolete now
1738 mapNewBlock.clear();
1739 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1743 nTransactionsUpdatedLast = nTransactionsUpdated;
1744 pindexPrev = pindexBest;
1748 pblock = CreateNewBlock(reservekey);
1750 throw JSONRPCError(-7, "Out of memory");
1751 vNewBlock.push_back(pblock);
1755 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1758 // Update nExtraNonce
1759 static unsigned int nExtraNonce = 0;
1760 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1763 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1765 // Prebuild hash buffers
1769 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1771 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1774 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1775 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1776 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1777 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1783 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1784 if (vchData.size() != 128)
1785 throw JSONRPCError(-8, "Invalid parameter");
1786 CBlock* pdata = (CBlock*)&vchData[0];
1789 for (int i = 0; i < 128/4; i++)
1790 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1793 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1795 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1797 pblock->nTime = pdata->nTime;
1798 pblock->nNonce = pdata->nNonce;
1799 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1800 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1802 return CheckWork(pblock, *pwalletMain, reservekey);
1807 Value getmemorypool(const Array& params, bool fHelp)
1809 if (fHelp || params.size() > 1)
1810 throw runtime_error(
1811 "getmemorypool [data]\n"
1812 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1813 " \"version\" : block version\n"
1814 " \"previousblockhash\" : hash of current highest block\n"
1815 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1816 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1817 " \"time\" : timestamp appropriate for next block\n"
1818 " \"bits\" : compressed target of next block\n"
1819 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1821 if (params.size() == 0)
1824 throw JSONRPCError(-9, "Bitcoin is not connected!");
1826 if (IsInitialBlockDownload())
1827 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1829 static CReserveKey reservekey(pwalletMain);
1832 static unsigned int nTransactionsUpdatedLast;
1833 static CBlockIndex* pindexPrev;
1834 static int64 nStart;
1835 static CBlock* pblock;
1836 if (pindexPrev != pindexBest ||
1837 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1839 nTransactionsUpdatedLast = nTransactionsUpdated;
1840 pindexPrev = pindexBest;
1846 pblock = CreateNewBlock(reservekey);
1848 throw JSONRPCError(-7, "Out of memory");
1852 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1856 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1863 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1867 result.push_back(Pair("version", pblock->nVersion));
1868 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1869 result.push_back(Pair("transactions", transactions));
1870 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1871 result.push_back(Pair("time", (int64_t)pblock->nTime));
1877 uBits.nBits = htonl((int32_t)pblock->nBits);
1878 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1885 CDataStream ssBlock(ParseHex(params[0].get_str()));
1889 return ProcessBlock(NULL, &pblock);
1907 pair<string, rpcfn_type> pCallTable[] =
1909 make_pair("help", &help),
1910 make_pair("stop", &stop),
1911 make_pair("getblockcount", &getblockcount),
1912 make_pair("getblocknumber", &getblocknumber),
1913 make_pair("getconnectioncount", &getconnectioncount),
1914 make_pair("getdifficulty", &getdifficulty),
1915 make_pair("getgenerate", &getgenerate),
1916 make_pair("setgenerate", &setgenerate),
1917 make_pair("gethashespersec", &gethashespersec),
1918 make_pair("getinfo", &getinfo),
1919 make_pair("getnewaddress", &getnewaddress),
1920 make_pair("getaccountaddress", &getaccountaddress),
1921 make_pair("setaccount", &setaccount),
1922 make_pair("getaccount", &getaccount),
1923 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1924 make_pair("sendtoaddress", &sendtoaddress),
1925 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1926 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1927 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1928 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1929 make_pair("backupwallet", &backupwallet),
1930 make_pair("keypoolrefill", &keypoolrefill),
1931 make_pair("walletpassphrase", &walletpassphrase),
1932 make_pair("walletpassphrasechange", &walletpassphrasechange),
1933 make_pair("walletlock", &walletlock),
1934 make_pair("encryptwallet", &encryptwallet),
1935 make_pair("validateaddress", &validateaddress),
1936 make_pair("getbalance", &getbalance),
1937 make_pair("move", &movecmd),
1938 make_pair("sendfrom", &sendfrom),
1939 make_pair("sendmany", &sendmany),
1940 make_pair("addmultisigaddress", &addmultisigaddress),
1941 make_pair("gettransaction", &gettransaction),
1942 make_pair("listtransactions", &listtransactions),
1943 make_pair("signmessage", &signmessage),
1944 make_pair("verifymessage", &verifymessage),
1945 make_pair("getwork", &getwork),
1946 make_pair("listaccounts", &listaccounts),
1947 make_pair("settxfee", &settxfee),
1948 make_pair("getmemorypool", &getmemorypool),
1949 make_pair("listsinceblock", &listsinceblock),
1950 make_pair("dumpprivkey", &dumpprivkey),
1951 make_pair("importprivkey", &importprivkey)
1953 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1955 string pAllowInSafeMode[] =
1960 "getblocknumber", // deprecated
1961 "getconnectioncount",
1968 "getaccountaddress",
1970 "getaddressesbyaccount",
1979 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1987 // This ain't Apache. We're just using HTTP header for the length field
1988 // and to be compatible with other JSON-RPC implementations.
1991 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1994 s << "POST / HTTP/1.1\r\n"
1995 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1996 << "Host: 127.0.0.1\r\n"
1997 << "Content-Type: application/json\r\n"
1998 << "Content-Length: " << strMsg.size() << "\r\n"
1999 << "Connection: close\r\n"
2000 << "Accept: application/json\r\n";
2001 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2002 s << item.first << ": " << item.second << "\r\n";
2003 s << "\r\n" << strMsg;
2008 string rfc1123Time()
2013 struct tm* now_gmt = gmtime(&now);
2014 string locale(setlocale(LC_TIME, NULL));
2015 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2016 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2017 setlocale(LC_TIME, locale.c_str());
2018 return string(buffer);
2021 static string HTTPReply(int nStatus, const string& strMsg)
2024 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2026 "Server: bitcoin-json-rpc/%s\r\n"
2027 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2028 "Content-Type: text/html\r\n"
2029 "Content-Length: 296\r\n"
2031 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2032 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2035 "<TITLE>Error</TITLE>\r\n"
2036 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2038 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2039 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2040 const char *cStatus;
2041 if (nStatus == 200) cStatus = "OK";
2042 else if (nStatus == 400) cStatus = "Bad Request";
2043 else if (nStatus == 403) cStatus = "Forbidden";
2044 else if (nStatus == 404) cStatus = "Not Found";
2045 else if (nStatus == 500) cStatus = "Internal Server Error";
2048 "HTTP/1.1 %d %s\r\n"
2050 "Connection: close\r\n"
2051 "Content-Length: %d\r\n"
2052 "Content-Type: application/json\r\n"
2053 "Server: bitcoin-json-rpc/%s\r\n"
2058 rfc1123Time().c_str(),
2060 FormatFullVersion().c_str(),
2064 int ReadHTTPStatus(std::basic_istream<char>& stream)
2067 getline(stream, str);
2068 vector<string> vWords;
2069 boost::split(vWords, str, boost::is_any_of(" "));
2070 if (vWords.size() < 2)
2072 return atoi(vWords[1].c_str());
2075 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2081 std::getline(stream, str);
2082 if (str.empty() || str == "\r")
2084 string::size_type nColon = str.find(":");
2085 if (nColon != string::npos)
2087 string strHeader = str.substr(0, nColon);
2088 boost::trim(strHeader);
2089 boost::to_lower(strHeader);
2090 string strValue = str.substr(nColon+1);
2091 boost::trim(strValue);
2092 mapHeadersRet[strHeader] = strValue;
2093 if (strHeader == "content-length")
2094 nLen = atoi(strValue.c_str());
2100 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2102 mapHeadersRet.clear();
2106 int nStatus = ReadHTTPStatus(stream);
2109 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2110 if (nLen < 0 || nLen > MAX_SIZE)
2116 vector<char> vch(nLen);
2117 stream.read(&vch[0], nLen);
2118 strMessageRet = string(vch.begin(), vch.end());
2124 bool HTTPAuthorized(map<string, string>& mapHeaders)
2126 string strAuth = mapHeaders["authorization"];
2127 if (strAuth.substr(0,6) != "Basic ")
2129 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2130 string strUserPass = DecodeBase64(strUserPass64);
2131 return strUserPass == strRPCUserColonPass;
2135 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2136 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2137 // unspecified (HTTP errors and contents of 'error').
2139 // 1.0 spec: http://json-rpc.org/wiki/specification
2140 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2141 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2144 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2147 request.push_back(Pair("method", strMethod));
2148 request.push_back(Pair("params", params));
2149 request.push_back(Pair("id", id));
2150 return write_string(Value(request), false) + "\n";
2153 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2156 if (error.type() != null_type)
2157 reply.push_back(Pair("result", Value::null));
2159 reply.push_back(Pair("result", result));
2160 reply.push_back(Pair("error", error));
2161 reply.push_back(Pair("id", id));
2162 return write_string(Value(reply), false) + "\n";
2165 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2167 // Send error reply from json-rpc error object
2169 int code = find_value(objError, "code").get_int();
2170 if (code == -32600) nStatus = 400;
2171 else if (code == -32601) nStatus = 404;
2172 string strReply = JSONRPCReply(Value::null, objError, id);
2173 stream << HTTPReply(nStatus, strReply) << std::flush;
2176 bool ClientAllowed(const string& strAddress)
2178 if (strAddress == asio::ip::address_v4::loopback().to_string())
2180 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2181 BOOST_FOREACH(string strAllow, vAllow)
2182 if (WildcardMatch(strAddress, strAllow))
2189 // IOStream device that speaks SSL but can also speak non-SSL
2191 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2193 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2195 fUseSSL = fUseSSLIn;
2196 fNeedHandshake = fUseSSLIn;
2199 void handshake(ssl::stream_base::handshake_type role)
2201 if (!fNeedHandshake) return;
2202 fNeedHandshake = false;
2203 stream.handshake(role);
2205 std::streamsize read(char* s, std::streamsize n)
2207 handshake(ssl::stream_base::server); // HTTPS servers read first
2208 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2209 return stream.next_layer().read_some(asio::buffer(s, n));
2211 std::streamsize write(const char* s, std::streamsize n)
2213 handshake(ssl::stream_base::client); // HTTPS clients write first
2214 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2215 return asio::write(stream.next_layer(), asio::buffer(s, n));
2217 bool connect(const std::string& server, const std::string& port)
2219 ip::tcp::resolver resolver(stream.get_io_service());
2220 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2221 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2222 ip::tcp::resolver::iterator end;
2223 boost::system::error_code error = asio::error::host_not_found;
2224 while (error && endpoint_iterator != end)
2226 stream.lowest_layer().close();
2227 stream.lowest_layer().connect(*endpoint_iterator++, error);
2235 bool fNeedHandshake;
2241 void ThreadRPCServer(void* parg)
2243 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2246 vnThreadsRunning[4]++;
2247 ThreadRPCServer2(parg);
2248 vnThreadsRunning[4]--;
2250 catch (std::exception& e) {
2251 vnThreadsRunning[4]--;
2252 PrintException(&e, "ThreadRPCServer()");
2254 vnThreadsRunning[4]--;
2255 PrintException(NULL, "ThreadRPCServer()");
2257 printf("ThreadRPCServer exiting\n");
2260 void ThreadRPCServer2(void* parg)
2262 printf("ThreadRPCServer started\n");
2264 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2265 if (strRPCUserColonPass == ":")
2267 string strWhatAmI = "To use bitcoind";
2268 if (mapArgs.count("-server"))
2269 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2270 else if (mapArgs.count("-daemon"))
2271 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2273 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2274 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2276 GetConfigFile().c_str());
2278 CreateThread(Shutdown, NULL);
2283 bool fUseSSL = GetBoolArg("-rpcssl");
2284 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2286 asio::io_service io_service;
2287 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2288 ip::tcp::acceptor acceptor(io_service, endpoint);
2290 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2293 ssl::context context(io_service, ssl::context::sslv23);
2296 context.set_options(ssl::context::no_sslv2);
2297 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2298 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2299 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2300 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2301 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2302 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2303 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2304 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2306 string ciphers = GetArg("-rpcsslciphers",
2307 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2308 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2312 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2317 // Accept connection
2319 SSLStream sslStream(io_service, context);
2320 SSLIOStreamDevice d(sslStream, fUseSSL);
2321 iostreams::stream<SSLIOStreamDevice> stream(d);
2323 ip::tcp::iostream stream;
2326 ip::tcp::endpoint peer;
2327 vnThreadsRunning[4]--;
2329 acceptor.accept(sslStream.lowest_layer(), peer);
2331 acceptor.accept(*stream.rdbuf(), peer);
2333 vnThreadsRunning[4]++;
2337 // Restrict callers by IP
2338 if (!ClientAllowed(peer.address().to_string()))
2340 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2342 stream << HTTPReply(403, "") << std::flush;
2346 map<string, string> mapHeaders;
2349 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2350 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2353 printf("ThreadRPCServer ReadHTTP timeout\n");
2357 // Check authorization
2358 if (mapHeaders.count("authorization") == 0)
2360 stream << HTTPReply(401, "") << std::flush;
2363 if (!HTTPAuthorized(mapHeaders))
2365 // Deter brute-forcing short passwords
2366 if (mapArgs["-rpcpassword"].size() < 15)
2369 stream << HTTPReply(401, "") << std::flush;
2370 printf("ThreadRPCServer incorrect password attempt\n");
2374 Value id = Value::null;
2379 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2380 throw JSONRPCError(-32700, "Parse error");
2381 const Object& request = valRequest.get_obj();
2383 // Parse id now so errors from here on will have the id
2384 id = find_value(request, "id");
2387 Value valMethod = find_value(request, "method");
2388 if (valMethod.type() == null_type)
2389 throw JSONRPCError(-32600, "Missing method");
2390 if (valMethod.type() != str_type)
2391 throw JSONRPCError(-32600, "Method must be a string");
2392 string strMethod = valMethod.get_str();
2393 if (strMethod != "getwork" && strMethod != "getmemorypool")
2394 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2397 Value valParams = find_value(request, "params");
2399 if (valParams.type() == array_type)
2400 params = valParams.get_array();
2401 else if (valParams.type() == null_type)
2404 throw JSONRPCError(-32600, "Params must be an array");
2407 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2408 if (mi == mapCallTable.end())
2409 throw JSONRPCError(-32601, "Method not found");
2411 // Observe safe mode
2412 string strWarning = GetWarnings("rpc");
2413 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2414 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2420 CRITICAL_BLOCK(cs_main)
2421 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2422 result = (*(*mi).second)(params, false);
2425 string strReply = JSONRPCReply(result, Value::null, id);
2426 stream << HTTPReply(200, strReply) << std::flush;
2428 catch (std::exception& e)
2430 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2433 catch (Object& objError)
2435 ErrorReply(stream, objError, id);
2437 catch (std::exception& e)
2439 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2447 Object CallRPC(const string& strMethod, const Array& params)
2449 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2450 throw runtime_error(strprintf(
2451 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2452 "If the file does not exist, create it with owner-readable-only file permissions."),
2453 GetConfigFile().c_str()));
2455 // Connect to localhost
2456 bool fUseSSL = GetBoolArg("-rpcssl");
2458 asio::io_service io_service;
2459 ssl::context context(io_service, ssl::context::sslv23);
2460 context.set_options(ssl::context::no_sslv2);
2461 SSLStream sslStream(io_service, context);
2462 SSLIOStreamDevice d(sslStream, fUseSSL);
2463 iostreams::stream<SSLIOStreamDevice> stream(d);
2464 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2465 throw runtime_error("couldn't connect to server");
2468 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2470 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2472 throw runtime_error("couldn't connect to server");
2476 // HTTP basic authentication
2477 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2478 map<string, string> mapRequestHeaders;
2479 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2482 string strRequest = JSONRPCRequest(strMethod, params, 1);
2483 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2484 stream << strPost << std::flush;
2487 map<string, string> mapHeaders;
2489 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2491 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2492 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2493 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2494 else if (strReply.empty())
2495 throw runtime_error("no response from server");
2499 if (!read_string(strReply, valReply))
2500 throw runtime_error("couldn't parse reply from server");
2501 const Object& reply = valReply.get_obj();
2503 throw runtime_error("expected reply to have result, error and id properties");
2511 template<typename T>
2512 void ConvertTo(Value& value)
2514 if (value.type() == str_type)
2516 // reinterpret string as unquoted json value
2518 if (!read_string(value.get_str(), value2))
2519 throw runtime_error("type mismatch");
2520 value = value2.get_value<T>();
2524 value = value.get_value<T>();
2528 int CommandLineRPC(int argc, char *argv[])
2535 while (argc > 1 && IsSwitchChar(argv[1][0]))
2543 throw runtime_error("too few parameters");
2544 string strMethod = argv[1];
2546 // Parameters default to strings
2548 for (int i = 2; i < argc; i++)
2549 params.push_back(argv[i]);
2550 int n = params.size();
2553 // Special case non-string parameter types
2555 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2556 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2557 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2558 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2559 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2560 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2561 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2562 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2563 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2564 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2565 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2566 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2567 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2568 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2569 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2570 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2571 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2572 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2573 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2574 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2575 if (strMethod == "sendmany" && n > 1)
2577 string s = params[1].get_str();
2579 if (!read_string(s, v) || v.type() != obj_type)
2580 throw runtime_error("type mismatch");
2581 params[1] = v.get_obj();
2583 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2584 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2585 if (strMethod == "addmultisigaddress" && n > 1)
2587 string s = params[1].get_str();
2589 if (!read_string(s, v) || v.type() != array_type)
2590 throw runtime_error("addmultisigaddress: type mismatch "+s);
2591 params[1] = v.get_array();
2595 Object reply = CallRPC(strMethod, params);
2598 const Value& result = find_value(reply, "result");
2599 const Value& error = find_value(reply, "error");
2601 if (error.type() != null_type)
2604 strPrint = "error: " + write_string(error, false);
2605 int code = find_value(error.get_obj(), "code").get_int();
2611 if (result.type() == null_type)
2613 else if (result.type() == str_type)
2614 strPrint = result.get_str();
2616 strPrint = write_string(result, true);
2619 catch (std::exception& e)
2621 strPrint = string("error: ") + e.what();
2626 PrintException(NULL, "CommandLineRPC()");
2631 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2640 int main(int argc, char *argv[])
2643 // Turn off microsoft heap dump noise
2644 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2645 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2647 setbuf(stdin, NULL);
2648 setbuf(stdout, NULL);
2649 setbuf(stderr, NULL);
2653 if (argc >= 2 && string(argv[1]) == "-server")
2655 printf("server ready\n");
2656 ThreadRPCServer(NULL);
2660 return CommandLineRPC(argc, argv);
2663 catch (std::exception& e) {
2664 PrintException(&e, "main()");
2666 PrintException(NULL, "main()");