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);
75 double GetDifficulty(const CBlockIndex* blockindex = NULL)
77 // Floating point number that is a multiple of the minimum difficulty,
78 // minimum difficulty = 1.0.
79 if (blockindex == NULL)
81 if (pindexBest == NULL)
84 blockindex = pindexBest;
87 int nShift = (blockindex->nBits >> 24) & 0xff;
90 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
107 int64 AmountFromValue(const Value& value)
109 double dAmount = value.get_real();
110 if (dAmount <= 0.0 || dAmount > 21000000.0)
111 throw JSONRPCError(-3, "Invalid amount");
112 int64 nAmount = roundint64(dAmount * COIN);
113 if (!MoneyRange(nAmount))
114 throw JSONRPCError(-3, "Invalid amount");
118 Value ValueFromAmount(int64 amount)
120 return (double)amount / (double)COIN;
123 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
125 int confirms = wtx.GetDepthInMainChain();
126 entry.push_back(Pair("confirmations", confirms));
129 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
130 entry.push_back(Pair("blockindex", wtx.nIndex));
132 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
133 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
134 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
135 entry.push_back(Pair(item.first, item.second));
138 string AccountFromValue(const Value& value)
140 string strAccount = value.get_str();
141 if (strAccount == "*")
142 throw JSONRPCError(-11, "Invalid account name");
146 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
149 result.push_back(Pair("hash", block.GetHash().GetHex()));
150 result.push_back(Pair("blockcount", blockindex->nHeight));
151 result.push_back(Pair("version", block.nVersion));
152 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
153 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
154 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
155 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
157 BOOST_FOREACH (const CTransaction&tx, block.vtx)
158 txhashes.push_back(tx.GetHash().GetHex());
159 result.push_back(Pair("tx", txhashes));
161 if (blockindex->pprev)
162 result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex()));
163 if (blockindex->pnext)
164 result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex()));
171 /// Note: This interface may still be subject to change.
175 Value help(const Array& params, bool fHelp)
177 if (fHelp || params.size() > 1)
180 "List commands, or get help for a command.");
183 if (params.size() > 0)
184 strCommand = params[0].get_str();
187 set<rpcfn_type> setDone;
188 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
190 string strMethod = (*mi).first;
191 // We already filter duplicates, but these deprecated screw up the sort order
192 if (strMethod == "getamountreceived" ||
193 strMethod == "getallreceived" ||
194 strMethod == "getblocknumber" || // deprecated
195 (strMethod.find("label") != string::npos))
197 if (strCommand != "" && strMethod != strCommand)
202 rpcfn_type pfn = (*mi).second;
203 if (setDone.insert(pfn).second)
204 (*pfn)(params, true);
206 catch (std::exception& e)
208 // Help text is returned in an exception
209 string strHelp = string(e.what());
210 if (strCommand == "")
211 if (strHelp.find('\n') != -1)
212 strHelp = strHelp.substr(0, strHelp.find('\n'));
213 strRet += strHelp + "\n";
217 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
218 strRet = strRet.substr(0,strRet.size()-1);
223 Value stop(const Array& params, bool fHelp)
225 if (fHelp || params.size() != 0)
228 "Stop bitcoin server.");
230 // Shutdown will take long enough that the response should get back
231 CreateThread(Shutdown, NULL);
232 return "bitcoin server stopping";
234 throw runtime_error("NYI: cannot shut down GUI with RPC command");
239 Value getblockcount(const Array& params, bool fHelp)
241 if (fHelp || params.size() != 0)
244 "Returns the number of blocks in the longest block chain.");
251 Value getblocknumber(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Deprecated. Use getblockcount.");
262 Value getconnectioncount(const Array& params, bool fHelp)
264 if (fHelp || params.size() != 0)
266 "getconnectioncount\n"
267 "Returns the number of connections to other nodes.");
269 return (int)vNodes.size();
273 Value getdifficulty(const Array& params, bool fHelp)
275 if (fHelp || params.size() != 0)
278 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
280 return GetDifficulty();
284 Value getgenerate(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns true or false.");
291 return (bool)fGenerateBitcoins;
295 Value setgenerate(const Array& params, bool fHelp)
297 if (fHelp || params.size() < 1 || params.size() > 2)
299 "setgenerate <generate> [genproclimit]\n"
300 "<generate> is true or false to turn generation on or off.\n"
301 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
303 bool fGenerate = true;
304 if (params.size() > 0)
305 fGenerate = params[0].get_bool();
307 if (params.size() > 1)
309 int nGenProcLimit = params[1].get_int();
310 fLimitProcessors = (nGenProcLimit != -1);
311 WriteSetting("fLimitProcessors", fLimitProcessors);
312 if (nGenProcLimit != -1)
313 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
314 if (nGenProcLimit == 0)
318 GenerateBitcoins(fGenerate, pwalletMain);
323 Value gethashespersec(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 0)
328 "Returns a recent hashes per second performance measurement while generating.");
330 if (GetTimeMillis() - nHPSTimerStart > 8000)
331 return (boost::int64_t)0;
332 return (boost::int64_t)dHashesPerSec;
336 Value getinfo(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 0)
341 "Returns an object containing various state info.");
344 obj.push_back(Pair("version", (int)CLIENT_VERSION));
345 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
346 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
347 obj.push_back(Pair("blocks", (int)nBestHeight));
348 obj.push_back(Pair("connections", (int)vNodes.size()));
349 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
350 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
351 obj.push_back(Pair("testnet", fTestNet));
352 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
353 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
354 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
355 if (pwalletMain->IsCrypted())
356 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
357 obj.push_back(Pair("errors", GetWarnings("statusbar")));
362 Value getmininginfo(const Array& params, bool fHelp)
364 if (fHelp || params.size() != 0)
367 "Returns an object containing mining-related information.");
370 obj.push_back(Pair("blocks", (int)nBestHeight));
371 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
372 obj.push_back(Pair("errors", GetWarnings("statusbar")));
373 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
374 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
375 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
376 obj.push_back(Pair("testnet", fTestNet));
381 Value getnewaddress(const Array& params, bool fHelp)
383 if (fHelp || params.size() > 1)
385 "getnewaddress [account]\n"
386 "Returns a new bitcoin address for receiving payments. "
387 "If [account] is specified (recommended), it is added to the address book "
388 "so payments received with the address will be credited to [account].");
390 // Parse the account first so we don't generate a key if there's an error
392 if (params.size() > 0)
393 strAccount = AccountFromValue(params[0]);
395 if (!pwalletMain->IsLocked())
396 pwalletMain->TopUpKeyPool();
398 // Generate a new key that is added to wallet
399 std::vector<unsigned char> newKey;
400 if (!pwalletMain->GetKeyFromPool(newKey, false))
401 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
402 CBitcoinAddress address(newKey);
404 pwalletMain->SetAddressBookName(address, strAccount);
406 return address.ToString();
410 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
412 CWalletDB walletdb(pwalletMain->strWalletFile);
415 walletdb.ReadAccount(strAccount, account);
417 bool bKeyUsed = false;
419 // Check if the current key has been used
420 if (!account.vchPubKey.empty())
422 CScript scriptPubKey;
423 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
424 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
425 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
428 const CWalletTx& wtx = (*it).second;
429 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
430 if (txout.scriptPubKey == scriptPubKey)
435 // Generate a new key
436 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
438 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
439 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
441 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
442 walletdb.WriteAccount(strAccount, account);
445 return CBitcoinAddress(account.vchPubKey);
448 Value getaccountaddress(const Array& params, bool fHelp)
450 if (fHelp || params.size() != 1)
452 "getaccountaddress <account>\n"
453 "Returns the current bitcoin address for receiving payments to this account.");
455 // Parse the account first so we don't generate a key if there's an error
456 string strAccount = AccountFromValue(params[0]);
460 ret = GetAccountAddress(strAccount).ToString();
467 Value setaccount(const Array& params, bool fHelp)
469 if (fHelp || params.size() < 1 || params.size() > 2)
471 "setaccount <bitcoinaddress> <account>\n"
472 "Sets the account associated with the given address.");
474 CBitcoinAddress address(params[0].get_str());
475 if (!address.IsValid())
476 throw JSONRPCError(-5, "Invalid bitcoin address");
480 if (params.size() > 1)
481 strAccount = AccountFromValue(params[1]);
483 // Detect when changing the account of an address that is the 'unused current key' of another account:
484 if (pwalletMain->mapAddressBook.count(address))
486 string strOldAccount = pwalletMain->mapAddressBook[address];
487 if (address == GetAccountAddress(strOldAccount))
488 GetAccountAddress(strOldAccount, true);
491 pwalletMain->SetAddressBookName(address, strAccount);
497 Value getaccount(const Array& params, bool fHelp)
499 if (fHelp || params.size() != 1)
501 "getaccount <bitcoinaddress>\n"
502 "Returns the account associated with the given address.");
504 CBitcoinAddress address(params[0].get_str());
505 if (!address.IsValid())
506 throw JSONRPCError(-5, "Invalid bitcoin address");
509 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
510 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
511 strAccount = (*mi).second;
516 Value getaddressesbyaccount(const Array& params, bool fHelp)
518 if (fHelp || params.size() != 1)
520 "getaddressesbyaccount <account>\n"
521 "Returns the list of addresses for the given account.");
523 string strAccount = AccountFromValue(params[0]);
525 // Find all addresses that have the given account
527 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
529 const CBitcoinAddress& address = item.first;
530 const string& strName = item.second;
531 if (strName == strAccount)
532 ret.push_back(address.ToString());
537 Value settxfee(const Array& params, bool fHelp)
539 if (fHelp || params.size() < 1 || params.size() > 1)
541 "settxfee <amount>\n"
542 "<amount> is a real and is rounded to the nearest 0.00000001");
546 if (params[0].get_real() != 0.0)
547 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
549 nTransactionFee = nAmount;
553 Value sendtoaddress(const Array& params, bool fHelp)
555 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
557 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
558 "<amount> is a real and is rounded to the nearest 0.00000001\n"
559 "requires wallet passphrase to be set with walletpassphrase first");
560 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
562 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
563 "<amount> is a real and is rounded to the nearest 0.00000001");
565 CBitcoinAddress address(params[0].get_str());
566 if (!address.IsValid())
567 throw JSONRPCError(-5, "Invalid bitcoin address");
570 int64 nAmount = AmountFromValue(params[1]);
574 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
575 wtx.mapValue["comment"] = params[2].get_str();
576 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
577 wtx.mapValue["to"] = params[3].get_str();
579 if (pwalletMain->IsLocked())
580 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
582 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
584 throw JSONRPCError(-4, strError);
586 return wtx.GetHash().GetHex();
589 static const string strMessageMagic = "Bitcoin Signed Message:\n";
591 Value signmessage(const Array& params, bool fHelp)
593 if (fHelp || params.size() != 2)
595 "signmessage <bitcoinaddress> <message>\n"
596 "Sign a message with the private key of an address");
598 if (pwalletMain->IsLocked())
599 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
601 string strAddress = params[0].get_str();
602 string strMessage = params[1].get_str();
604 CBitcoinAddress addr(strAddress);
606 throw JSONRPCError(-3, "Invalid address");
609 if (!pwalletMain->GetKey(addr, key))
610 throw JSONRPCError(-4, "Private key not available");
612 CDataStream ss(SER_GETHASH);
613 ss << strMessageMagic;
616 vector<unsigned char> vchSig;
617 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
618 throw JSONRPCError(-5, "Sign failed");
620 return EncodeBase64(&vchSig[0], vchSig.size());
623 Value verifymessage(const Array& params, bool fHelp)
625 if (fHelp || params.size() != 3)
627 "verifymessage <bitcoinaddress> <signature> <message>\n"
628 "Verify a signed message");
630 string strAddress = params[0].get_str();
631 string strSign = params[1].get_str();
632 string strMessage = params[2].get_str();
634 CBitcoinAddress addr(strAddress);
636 throw JSONRPCError(-3, "Invalid address");
638 bool fInvalid = false;
639 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
642 throw JSONRPCError(-5, "Malformed base64 encoding");
644 CDataStream ss(SER_GETHASH);
645 ss << strMessageMagic;
649 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
652 return (CBitcoinAddress(key.GetPubKey()) == addr);
656 Value getreceivedbyaddress(const Array& params, bool fHelp)
658 if (fHelp || params.size() < 1 || params.size() > 2)
660 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
661 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
664 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
665 CScript scriptPubKey;
666 if (!address.IsValid())
667 throw JSONRPCError(-5, "Invalid bitcoin address");
668 scriptPubKey.SetBitcoinAddress(address);
669 if (!IsMine(*pwalletMain,scriptPubKey))
672 // Minimum confirmations
674 if (params.size() > 1)
675 nMinDepth = params[1].get_int();
679 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
681 const CWalletTx& wtx = (*it).second;
682 if (wtx.IsCoinBase() || !wtx.IsFinal())
685 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
686 if (txout.scriptPubKey == scriptPubKey)
687 if (wtx.GetDepthInMainChain() >= nMinDepth)
688 nAmount += txout.nValue;
691 return ValueFromAmount(nAmount);
695 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
697 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
699 const CBitcoinAddress& address = item.first;
700 const string& strName = item.second;
701 if (strName == strAccount)
702 setAddress.insert(address);
707 Value getreceivedbyaccount(const Array& params, bool fHelp)
709 if (fHelp || params.size() < 1 || params.size() > 2)
711 "getreceivedbyaccount <account> [minconf=1]\n"
712 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
714 // Minimum confirmations
716 if (params.size() > 1)
717 nMinDepth = params[1].get_int();
719 // Get the set of pub keys assigned to account
720 string strAccount = AccountFromValue(params[0]);
721 set<CBitcoinAddress> setAddress;
722 GetAccountAddresses(strAccount, setAddress);
726 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
728 const CWalletTx& wtx = (*it).second;
729 if (wtx.IsCoinBase() || !wtx.IsFinal())
732 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
734 CBitcoinAddress address;
735 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
736 if (wtx.GetDepthInMainChain() >= nMinDepth)
737 nAmount += txout.nValue;
741 return (double)nAmount / (double)COIN;
745 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
749 // Tally wallet transactions
750 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
752 const CWalletTx& wtx = (*it).second;
756 int64 nGenerated, nReceived, nSent, nFee;
757 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
759 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
760 nBalance += nReceived;
761 nBalance += nGenerated - nSent - nFee;
764 // Tally internal accounting entries
765 nBalance += walletdb.GetAccountCreditDebit(strAccount);
770 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
772 CWalletDB walletdb(pwalletMain->strWalletFile);
773 return GetAccountBalance(walletdb, strAccount, nMinDepth);
777 Value getbalance(const Array& params, bool fHelp)
779 if (fHelp || params.size() > 2)
781 "getbalance [account] [minconf=1]\n"
782 "If [account] is not specified, returns the server's total available balance.\n"
783 "If [account] is specified, returns the balance in the account.");
785 if (params.size() == 0)
786 return ValueFromAmount(pwalletMain->GetBalance());
789 if (params.size() > 1)
790 nMinDepth = params[1].get_int();
792 if (params[0].get_str() == "*") {
793 // Calculate total balance a different way from GetBalance()
794 // (GetBalance() sums up all unspent TxOuts)
795 // getbalance and getbalance '*' should always return the same number.
797 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
799 const CWalletTx& wtx = (*it).second;
803 int64 allGeneratedImmature, allGeneratedMature, allFee;
804 allGeneratedImmature = allGeneratedMature = allFee = 0;
805 string strSentAccount;
806 list<pair<CBitcoinAddress, int64> > listReceived;
807 list<pair<CBitcoinAddress, int64> > listSent;
808 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
809 if (wtx.GetDepthInMainChain() >= nMinDepth)
810 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
811 nBalance += r.second;
812 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
813 nBalance -= r.second;
815 nBalance += allGeneratedMature;
817 return ValueFromAmount(nBalance);
820 string strAccount = AccountFromValue(params[0]);
822 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
824 return ValueFromAmount(nBalance);
828 Value movecmd(const Array& params, bool fHelp)
830 if (fHelp || params.size() < 3 || params.size() > 5)
832 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
833 "Move from one account in your wallet to another.");
835 string strFrom = AccountFromValue(params[0]);
836 string strTo = AccountFromValue(params[1]);
837 int64 nAmount = AmountFromValue(params[2]);
838 if (params.size() > 3)
839 // unused parameter, used to be nMinDepth, keep type-checking it though
840 (void)params[3].get_int();
842 if (params.size() > 4)
843 strComment = params[4].get_str();
845 CWalletDB walletdb(pwalletMain->strWalletFile);
848 int64 nNow = GetAdjustedTime();
851 CAccountingEntry debit;
852 debit.strAccount = strFrom;
853 debit.nCreditDebit = -nAmount;
855 debit.strOtherAccount = strTo;
856 debit.strComment = strComment;
857 walletdb.WriteAccountingEntry(debit);
860 CAccountingEntry credit;
861 credit.strAccount = strTo;
862 credit.nCreditDebit = nAmount;
864 credit.strOtherAccount = strFrom;
865 credit.strComment = strComment;
866 walletdb.WriteAccountingEntry(credit);
868 walletdb.TxnCommit();
874 Value sendfrom(const Array& params, bool fHelp)
876 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
878 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
879 "<amount> is a real and is rounded to the nearest 0.00000001\n"
880 "requires wallet passphrase to be set with walletpassphrase first");
881 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
883 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
884 "<amount> is a real and is rounded to the nearest 0.00000001");
886 string strAccount = AccountFromValue(params[0]);
887 CBitcoinAddress address(params[1].get_str());
888 if (!address.IsValid())
889 throw JSONRPCError(-5, "Invalid bitcoin address");
890 int64 nAmount = AmountFromValue(params[2]);
892 if (params.size() > 3)
893 nMinDepth = params[3].get_int();
896 wtx.strFromAccount = strAccount;
897 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
898 wtx.mapValue["comment"] = params[4].get_str();
899 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
900 wtx.mapValue["to"] = params[5].get_str();
902 if (pwalletMain->IsLocked())
903 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
906 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
907 if (nAmount > nBalance)
908 throw JSONRPCError(-6, "Account has insufficient funds");
911 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
913 throw JSONRPCError(-4, strError);
915 return wtx.GetHash().GetHex();
919 Value sendmany(const Array& params, bool fHelp)
921 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
923 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
924 "amounts are double-precision floating point numbers\n"
925 "requires wallet passphrase to be set with walletpassphrase first");
926 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
928 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
929 "amounts are double-precision floating point numbers");
931 string strAccount = AccountFromValue(params[0]);
932 Object sendTo = params[1].get_obj();
934 if (params.size() > 2)
935 nMinDepth = params[2].get_int();
938 wtx.strFromAccount = strAccount;
939 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
940 wtx.mapValue["comment"] = params[3].get_str();
942 set<CBitcoinAddress> setAddress;
943 vector<pair<CScript, int64> > vecSend;
945 int64 totalAmount = 0;
946 BOOST_FOREACH(const Pair& s, sendTo)
948 CBitcoinAddress address(s.name_);
949 if (!address.IsValid())
950 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
952 if (setAddress.count(address))
953 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
954 setAddress.insert(address);
956 CScript scriptPubKey;
957 scriptPubKey.SetBitcoinAddress(address);
958 int64 nAmount = AmountFromValue(s.value_);
959 totalAmount += nAmount;
961 vecSend.push_back(make_pair(scriptPubKey, nAmount));
964 if (pwalletMain->IsLocked())
965 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
968 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
969 if (totalAmount > nBalance)
970 throw JSONRPCError(-6, "Account has insufficient funds");
973 CReserveKey keyChange(pwalletMain);
974 int64 nFeeRequired = 0;
975 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
978 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
979 throw JSONRPCError(-6, "Insufficient funds");
980 throw JSONRPCError(-4, "Transaction creation failed");
982 if (!pwalletMain->CommitTransaction(wtx, keyChange))
983 throw JSONRPCError(-4, "Transaction commit failed");
985 return wtx.GetHash().GetHex();
988 Value addmultisigaddress(const Array& params, bool fHelp)
990 if (fHelp || params.size() < 2 || params.size() > 3)
992 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
993 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
994 "each key is a bitcoin address, hex or base58 public key\n"
995 "If [account] is specified, assign address to [account].";
996 throw runtime_error(msg);
999 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1001 int nRequired = params[0].get_int();
1002 const Array& keys = params[1].get_array();
1004 if (params.size() > 2)
1005 strAccount = AccountFromValue(params[2]);
1007 // Gather public keys
1008 if (keys.size() < nRequired)
1009 throw runtime_error(
1010 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
1011 std::vector<CKey> pubkeys;
1012 pubkeys.resize(keys.size());
1013 for (int i = 0; i < keys.size(); i++)
1015 const std::string& ks = keys[i].get_str();
1016 if (ks.size() == 130) // hex public key
1017 pubkeys[i].SetPubKey(ParseHex(ks));
1018 else if (ks.size() > 34) // base58-encoded
1020 std::vector<unsigned char> vchPubKey;
1021 if (DecodeBase58(ks, vchPubKey))
1022 pubkeys[i].SetPubKey(vchPubKey);
1024 throw runtime_error("Error base58 decoding key: "+ks);
1026 else // bitcoin address for key in this wallet
1028 CBitcoinAddress address(ks);
1029 if (!pwalletMain->GetKey(address, pubkeys[i]))
1030 throw runtime_error(
1031 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
1035 // Construct using OP_EVAL
1037 inner.SetMultisig(nRequired, pubkeys);
1039 uint160 scriptHash = Hash160(inner);
1040 CScript scriptPubKey;
1041 scriptPubKey.SetEval(inner);
1042 pwalletMain->AddCScript(scriptHash, inner);
1043 CBitcoinAddress address;
1044 address.SetScriptHash160(scriptHash);
1046 pwalletMain->SetAddressBookName(address, strAccount);
1047 return address.ToString();
1058 nConf = std::numeric_limits<int>::max();
1062 Value ListReceived(const Array& params, bool fByAccounts)
1064 // Minimum confirmations
1066 if (params.size() > 0)
1067 nMinDepth = params[0].get_int();
1069 // Whether to include empty accounts
1070 bool fIncludeEmpty = false;
1071 if (params.size() > 1)
1072 fIncludeEmpty = params[1].get_bool();
1075 map<CBitcoinAddress, tallyitem> mapTally;
1076 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1078 const CWalletTx& wtx = (*it).second;
1080 if (wtx.IsCoinBase() || !wtx.IsFinal())
1083 int nDepth = wtx.GetDepthInMainChain();
1084 if (nDepth < nMinDepth)
1087 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1089 CBitcoinAddress address;
1090 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1093 tallyitem& item = mapTally[address];
1094 item.nAmount += txout.nValue;
1095 item.nConf = min(item.nConf, nDepth);
1101 map<string, tallyitem> mapAccountTally;
1102 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1104 const CBitcoinAddress& address = item.first;
1105 const string& strAccount = item.second;
1106 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1107 if (it == mapTally.end() && !fIncludeEmpty)
1111 int nConf = std::numeric_limits<int>::max();
1112 if (it != mapTally.end())
1114 nAmount = (*it).second.nAmount;
1115 nConf = (*it).second.nConf;
1120 tallyitem& item = mapAccountTally[strAccount];
1121 item.nAmount += nAmount;
1122 item.nConf = min(item.nConf, nConf);
1127 obj.push_back(Pair("address", address.ToString()));
1128 obj.push_back(Pair("account", strAccount));
1129 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1130 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1137 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1139 int64 nAmount = (*it).second.nAmount;
1140 int nConf = (*it).second.nConf;
1142 obj.push_back(Pair("account", (*it).first));
1143 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1144 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1152 Value listreceivedbyaddress(const Array& params, bool fHelp)
1154 if (fHelp || params.size() > 2)
1155 throw runtime_error(
1156 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1157 "[minconf] is the minimum number of confirmations before payments are included.\n"
1158 "[includeempty] whether to include addresses that haven't received any payments.\n"
1159 "Returns an array of objects containing:\n"
1160 " \"address\" : receiving address\n"
1161 " \"account\" : the account of the receiving address\n"
1162 " \"amount\" : total amount received by the address\n"
1163 " \"confirmations\" : number of confirmations of the most recent transaction included");
1165 return ListReceived(params, false);
1168 Value listreceivedbyaccount(const Array& params, bool fHelp)
1170 if (fHelp || params.size() > 2)
1171 throw runtime_error(
1172 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1173 "[minconf] is the minimum number of confirmations before payments are included.\n"
1174 "[includeempty] whether to include accounts that haven't received any payments.\n"
1175 "Returns an array of objects containing:\n"
1176 " \"account\" : the account of the receiving addresses\n"
1177 " \"amount\" : total amount received by addresses with this account\n"
1178 " \"confirmations\" : number of confirmations of the most recent transaction included");
1180 return ListReceived(params, true);
1183 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1185 int64 nGeneratedImmature, nGeneratedMature, nFee;
1186 string strSentAccount;
1187 list<pair<CBitcoinAddress, int64> > listReceived;
1188 list<pair<CBitcoinAddress, int64> > listSent;
1190 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1192 bool fAllAccounts = (strAccount == string("*"));
1194 // Generated blocks assigned to account ""
1195 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1198 entry.push_back(Pair("account", string("")));
1199 if (nGeneratedImmature)
1201 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1202 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1206 entry.push_back(Pair("category", "generate"));
1207 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1210 WalletTxToJSON(wtx, entry);
1211 ret.push_back(entry);
1215 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1217 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1220 entry.push_back(Pair("account", strSentAccount));
1221 entry.push_back(Pair("address", s.first.ToString()));
1222 entry.push_back(Pair("category", "send"));
1223 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1224 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1226 WalletTxToJSON(wtx, entry);
1227 ret.push_back(entry);
1232 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1233 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1236 if (pwalletMain->mapAddressBook.count(r.first))
1237 account = pwalletMain->mapAddressBook[r.first];
1238 if (fAllAccounts || (account == strAccount))
1241 entry.push_back(Pair("account", account));
1242 entry.push_back(Pair("address", r.first.ToString()));
1243 entry.push_back(Pair("category", "receive"));
1244 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1246 WalletTxToJSON(wtx, entry);
1247 ret.push_back(entry);
1252 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1254 bool fAllAccounts = (strAccount == string("*"));
1256 if (fAllAccounts || acentry.strAccount == strAccount)
1259 entry.push_back(Pair("account", acentry.strAccount));
1260 entry.push_back(Pair("category", "move"));
1261 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1262 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1263 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1264 entry.push_back(Pair("comment", acentry.strComment));
1265 ret.push_back(entry);
1269 Value listtransactions(const Array& params, bool fHelp)
1271 if (fHelp || params.size() > 3)
1272 throw runtime_error(
1273 "listtransactions [account] [count=10] [from=0]\n"
1274 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1276 string strAccount = "*";
1277 if (params.size() > 0)
1278 strAccount = params[0].get_str();
1280 if (params.size() > 1)
1281 nCount = params[1].get_int();
1283 if (params.size() > 2)
1284 nFrom = params[2].get_int();
1287 CWalletDB walletdb(pwalletMain->strWalletFile);
1289 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1290 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1291 typedef multimap<int64, TxPair > TxItems;
1294 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1296 CWalletTx* wtx = &((*it).second);
1297 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1299 list<CAccountingEntry> acentries;
1300 walletdb.ListAccountCreditDebit(strAccount, acentries);
1301 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1303 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1306 // Now: iterate backwards until we have nCount items to return:
1307 TxItems::reverse_iterator it = txByTime.rbegin();
1308 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1309 for (; it != txByTime.rend(); ++it)
1311 CWalletTx *const pwtx = (*it).second.first;
1313 ListTransactions(*pwtx, strAccount, 0, true, ret);
1314 CAccountingEntry *const pacentry = (*it).second.second;
1316 AcentryToJSON(*pacentry, strAccount, ret);
1318 if (ret.size() >= nCount) break;
1320 // ret is now newest to oldest
1322 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1323 if (ret.size() > nCount)
1325 Array::iterator last = ret.begin();
1326 std::advance(last, nCount);
1327 ret.erase(last, ret.end());
1329 std::reverse(ret.begin(), ret.end()); // oldest to newest
1334 Value listaccounts(const Array& params, bool fHelp)
1336 if (fHelp || params.size() > 1)
1337 throw runtime_error(
1338 "listaccounts [minconf=1]\n"
1339 "Returns Object that has account names as keys, account balances as values.");
1342 if (params.size() > 0)
1343 nMinDepth = params[0].get_int();
1345 map<string, int64> mapAccountBalances;
1346 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1347 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1348 mapAccountBalances[entry.second] = 0;
1351 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1353 const CWalletTx& wtx = (*it).second;
1354 int64 nGeneratedImmature, nGeneratedMature, nFee;
1355 string strSentAccount;
1356 list<pair<CBitcoinAddress, int64> > listReceived;
1357 list<pair<CBitcoinAddress, int64> > listSent;
1358 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1359 mapAccountBalances[strSentAccount] -= nFee;
1360 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1361 mapAccountBalances[strSentAccount] -= s.second;
1362 if (wtx.GetDepthInMainChain() >= nMinDepth)
1364 mapAccountBalances[""] += nGeneratedMature;
1365 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1366 if (pwalletMain->mapAddressBook.count(r.first))
1367 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1369 mapAccountBalances[""] += r.second;
1373 list<CAccountingEntry> acentries;
1374 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1375 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1376 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1379 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1380 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1385 Value listsinceblock(const Array& params, bool fHelp)
1388 throw runtime_error(
1389 "listsinceblock [blockid] [target-confirmations]\n"
1390 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1392 CBlockIndex *pindex = NULL;
1393 int target_confirms = 1;
1395 if (params.size() > 0)
1397 uint256 blockId = 0;
1399 blockId.SetHex(params[0].get_str());
1400 pindex = CBlockLocator(blockId).GetBlockIndex();
1403 if (params.size() > 1)
1405 target_confirms = params[1].get_int();
1407 if (target_confirms < 1)
1408 throw JSONRPCError(-8, "Invalid parameter");
1411 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1415 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1417 CWalletTx tx = (*it).second;
1419 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1420 ListTransactions(tx, "*", 0, true, transactions);
1425 if (target_confirms == 1)
1428 lastblock = hashBestChain;
1432 int target_height = pindexBest->nHeight + 1 - target_confirms;
1435 for (block = pindexBest;
1436 block && block->nHeight > target_height;
1437 block = block->pprev);
1439 lastblock = block ? block->GetBlockHash() : 0;
1443 ret.push_back(Pair("transactions", transactions));
1444 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1449 Value gettransaction(const Array& params, bool fHelp)
1451 if (fHelp || params.size() != 1)
1452 throw runtime_error(
1453 "gettransaction <txid>\n"
1454 "Get detailed information about <txid>");
1457 hash.SetHex(params[0].get_str());
1461 if (!pwalletMain->mapWallet.count(hash))
1462 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1463 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1465 int64 nCredit = wtx.GetCredit();
1466 int64 nDebit = wtx.GetDebit();
1467 int64 nNet = nCredit - nDebit;
1468 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1470 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1472 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1474 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1477 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1478 entry.push_back(Pair("details", details));
1484 Value backupwallet(const Array& params, bool fHelp)
1486 if (fHelp || params.size() != 1)
1487 throw runtime_error(
1488 "backupwallet <destination>\n"
1489 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1491 string strDest = params[0].get_str();
1492 BackupWallet(*pwalletMain, strDest);
1498 Value keypoolrefill(const Array& params, bool fHelp)
1500 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1501 throw runtime_error(
1503 "Fills the keypool, requires wallet passphrase to be set.");
1504 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1505 throw runtime_error(
1507 "Fills the keypool.");
1509 if (pwalletMain->IsLocked())
1510 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1512 pwalletMain->TopUpKeyPool();
1514 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1515 throw JSONRPCError(-4, "Error refreshing keypool.");
1521 void ThreadTopUpKeyPool(void* parg)
1523 pwalletMain->TopUpKeyPool();
1526 void ThreadCleanWalletPassphrase(void* parg)
1528 int64 nMyWakeTime = GetTime() + *((int*)parg);
1530 if (nWalletUnlockTime == 0)
1532 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1534 nWalletUnlockTime = nMyWakeTime;
1537 while (GetTime() < nWalletUnlockTime)
1538 Sleep(GetTime() - nWalletUnlockTime);
1540 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1542 nWalletUnlockTime = 0;
1547 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1549 if (nWalletUnlockTime < nMyWakeTime)
1550 nWalletUnlockTime = nMyWakeTime;
1556 pwalletMain->Lock();
1561 Value walletpassphrase(const Array& params, bool fHelp)
1563 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1564 throw runtime_error(
1565 "walletpassphrase <passphrase> <timeout>\n"
1566 "Stores the wallet decryption key in memory for <timeout> seconds.");
1569 if (!pwalletMain->IsCrypted())
1570 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1572 if (!pwalletMain->IsLocked())
1573 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1575 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1576 SecureString strWalletPass;
1577 strWalletPass.reserve(100);
1578 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1579 // Alternately, find a way to make params[0] mlock()'d to begin with.
1580 strWalletPass = params[0].get_str().c_str();
1582 if (strWalletPass.length() > 0)
1584 if (!pwalletMain->Unlock(strWalletPass))
1585 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1588 throw runtime_error(
1589 "walletpassphrase <passphrase> <timeout>\n"
1590 "Stores the wallet decryption key in memory for <timeout> seconds.");
1592 CreateThread(ThreadTopUpKeyPool, NULL);
1593 int* pnSleepTime = new int(params[1].get_int());
1594 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1600 Value walletpassphrasechange(const Array& params, bool fHelp)
1602 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1603 throw runtime_error(
1604 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1605 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1608 if (!pwalletMain->IsCrypted())
1609 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1611 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1612 // Alternately, find a way to make params[0] mlock()'d to begin with.
1613 SecureString strOldWalletPass;
1614 strOldWalletPass.reserve(100);
1615 strOldWalletPass = params[0].get_str().c_str();
1617 SecureString strNewWalletPass;
1618 strNewWalletPass.reserve(100);
1619 strNewWalletPass = params[1].get_str().c_str();
1621 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1622 throw runtime_error(
1623 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1624 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1626 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1627 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1633 Value walletlock(const Array& params, bool fHelp)
1635 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1636 throw runtime_error(
1638 "Removes the wallet encryption key from memory, locking the wallet.\n"
1639 "After calling this method, you will need to call walletpassphrase again\n"
1640 "before being able to call any methods which require the wallet to be unlocked.");
1643 if (!pwalletMain->IsCrypted())
1644 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1646 pwalletMain->Lock();
1647 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1649 nWalletUnlockTime = 0;
1656 Value encryptwallet(const Array& params, bool fHelp)
1658 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1659 throw runtime_error(
1660 "encryptwallet <passphrase>\n"
1661 "Encrypts the wallet with <passphrase>.");
1664 if (pwalletMain->IsCrypted())
1665 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1668 // shutting down via RPC while the GUI is running does not work (yet):
1669 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1672 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1673 // Alternately, find a way to make params[0] mlock()'d to begin with.
1674 SecureString strWalletPass;
1675 strWalletPass.reserve(100);
1676 strWalletPass = params[0].get_str().c_str();
1678 if (strWalletPass.length() < 1)
1679 throw runtime_error(
1680 "encryptwallet <passphrase>\n"
1681 "Encrypts the wallet with <passphrase>.");
1683 if (!pwalletMain->EncryptWallet(strWalletPass))
1684 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1686 // BDB seems to have a bad habit of writing old data into
1687 // slack space in .dat files; that is bad if the old data is
1688 // unencrypted private keys. So:
1689 CreateThread(Shutdown, NULL);
1690 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1694 Value validateaddress(const Array& params, bool fHelp)
1696 if (fHelp || params.size() != 1)
1697 throw runtime_error(
1698 "validateaddress <bitcoinaddress>\n"
1699 "Return information about <bitcoinaddress>.");
1701 CBitcoinAddress address(params[0].get_str());
1702 bool isValid = address.IsValid();
1705 ret.push_back(Pair("isvalid", isValid));
1708 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1709 // version of the address:
1710 string currentAddress = address.ToString();
1711 ret.push_back(Pair("address", currentAddress));
1712 if (pwalletMain->HaveKey(address))
1714 ret.push_back(Pair("ismine", true));
1715 std::vector<unsigned char> vchPubKey;
1716 pwalletMain->GetPubKey(address, vchPubKey);
1717 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1718 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1719 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1721 key.SetPubKey(vchPubKey);
1722 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1724 else if (pwalletMain->HaveCScript(address.GetHash160()))
1726 ret.push_back(Pair("isscript", true));
1728 pwalletMain->GetCScript(address.GetHash160(), subscript);
1729 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1730 std::vector<CBitcoinAddress> addresses;
1731 txnouttype whichType;
1733 ExtractAddresses(subscript, whichType, addresses, nRequired);
1734 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1736 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1737 a.push_back(addr.ToString());
1738 ret.push_back(Pair("addresses", a));
1739 if (whichType == TX_MULTISIG)
1740 ret.push_back(Pair("sigsrequired", nRequired));
1743 ret.push_back(Pair("ismine", false));
1744 if (pwalletMain->mapAddressBook.count(address))
1745 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1750 Value getwork(const Array& params, bool fHelp)
1752 if (fHelp || params.size() > 1)
1753 throw runtime_error(
1755 "If [data] is not specified, returns formatted hash data to work on:\n"
1756 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1757 " \"data\" : block data\n"
1758 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1759 " \"target\" : little endian hash target\n"
1760 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1763 throw JSONRPCError(-9, "Bitcoin is not connected!");
1765 if (IsInitialBlockDownload())
1766 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1768 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1769 static mapNewBlock_t mapNewBlock;
1770 static vector<CBlock*> vNewBlock;
1771 static CReserveKey reservekey(pwalletMain);
1773 if (params.size() == 0)
1776 static unsigned int nTransactionsUpdatedLast;
1777 static CBlockIndex* pindexPrev;
1778 static int64 nStart;
1779 static CBlock* pblock;
1780 if (pindexPrev != pindexBest ||
1781 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1783 if (pindexPrev != pindexBest)
1785 // Deallocate old blocks since they're obsolete now
1786 mapNewBlock.clear();
1787 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1791 nTransactionsUpdatedLast = nTransactionsUpdated;
1792 pindexPrev = pindexBest;
1796 pblock = CreateNewBlock(reservekey);
1798 throw JSONRPCError(-7, "Out of memory");
1799 vNewBlock.push_back(pblock);
1803 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1806 // Update nExtraNonce
1807 static unsigned int nExtraNonce = 0;
1808 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1811 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1813 // Prebuild hash buffers
1817 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1819 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1822 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1823 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1824 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1825 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1831 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1832 if (vchData.size() != 128)
1833 throw JSONRPCError(-8, "Invalid parameter");
1834 CBlock* pdata = (CBlock*)&vchData[0];
1837 for (int i = 0; i < 128/4; i++)
1838 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1841 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1843 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1845 pblock->nTime = pdata->nTime;
1846 pblock->nNonce = pdata->nNonce;
1847 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1848 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1850 return CheckWork(pblock, *pwalletMain, reservekey);
1855 Value getmemorypool(const Array& params, bool fHelp)
1857 if (fHelp || params.size() > 1)
1858 throw runtime_error(
1859 "getmemorypool [data]\n"
1860 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1861 " \"version\" : block version\n"
1862 " \"previousblockhash\" : hash of current highest block\n"
1863 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1864 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1865 " \"time\" : timestamp appropriate for next block\n"
1866 " \"bits\" : compressed target of next block\n"
1867 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1869 if (params.size() == 0)
1872 throw JSONRPCError(-9, "Bitcoin is not connected!");
1874 if (IsInitialBlockDownload())
1875 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1877 static CReserveKey reservekey(pwalletMain);
1880 static unsigned int nTransactionsUpdatedLast;
1881 static CBlockIndex* pindexPrev;
1882 static int64 nStart;
1883 static CBlock* pblock;
1884 if (pindexPrev != pindexBest ||
1885 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1887 nTransactionsUpdatedLast = nTransactionsUpdated;
1888 pindexPrev = pindexBest;
1894 pblock = CreateNewBlock(reservekey);
1896 throw JSONRPCError(-7, "Out of memory");
1900 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1904 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1911 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1915 result.push_back(Pair("version", pblock->nVersion));
1916 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1917 result.push_back(Pair("transactions", transactions));
1918 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1919 result.push_back(Pair("time", (int64_t)pblock->nTime));
1925 uBits.nBits = htonl((int32_t)pblock->nBits);
1926 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1933 CDataStream ssBlock(ParseHex(params[0].get_str()));
1937 return ProcessBlock(NULL, &pblock);
1941 Value getblockhash(const Array& params, bool fHelp)
1943 if (fHelp || params.size() != 1)
1944 throw runtime_error(
1945 "getblockhash <index>\n"
1946 "Returns hash of block in best-block-chain at <index>.");
1948 int nHeight = params[0].get_int();
1949 if (nHeight < 0 || nHeight > nBestHeight)
1950 throw runtime_error("Block number out of range.");
1953 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1954 while (pblockindex->nHeight > nHeight)
1955 pblockindex = pblockindex->pprev;
1956 return pblockindex->phashBlock->GetHex();
1959 Value getblock(const Array& params, bool fHelp)
1961 if (fHelp || params.size() != 1)
1962 throw runtime_error(
1964 "Returns details of a block with given block-hash.");
1966 std::string strHash = params[0].get_str();
1967 uint256 hash(strHash);
1969 if (mapBlockIndex.count(hash) == 0)
1970 throw JSONRPCError(-5, "Block not found");
1973 CBlockIndex* pblockindex = mapBlockIndex[hash];
1974 block.ReadFromDisk(pblockindex, true);
1976 return blockToJSON(block, pblockindex);
1993 pair<string, rpcfn_type> pCallTable[] =
1995 make_pair("help", &help),
1996 make_pair("stop", &stop),
1997 make_pair("getblockcount", &getblockcount),
1998 make_pair("getblocknumber", &getblocknumber),
1999 make_pair("getconnectioncount", &getconnectioncount),
2000 make_pair("getdifficulty", &getdifficulty),
2001 make_pair("getgenerate", &getgenerate),
2002 make_pair("setgenerate", &setgenerate),
2003 make_pair("gethashespersec", &gethashespersec),
2004 make_pair("getinfo", &getinfo),
2005 make_pair("getmininginfo", &getmininginfo),
2006 make_pair("getnewaddress", &getnewaddress),
2007 make_pair("getaccountaddress", &getaccountaddress),
2008 make_pair("setaccount", &setaccount),
2009 make_pair("getaccount", &getaccount),
2010 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2011 make_pair("sendtoaddress", &sendtoaddress),
2012 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2013 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2014 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2015 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2016 make_pair("backupwallet", &backupwallet),
2017 make_pair("keypoolrefill", &keypoolrefill),
2018 make_pair("walletpassphrase", &walletpassphrase),
2019 make_pair("walletpassphrasechange", &walletpassphrasechange),
2020 make_pair("walletlock", &walletlock),
2021 make_pair("encryptwallet", &encryptwallet),
2022 make_pair("validateaddress", &validateaddress),
2023 make_pair("getbalance", &getbalance),
2024 make_pair("move", &movecmd),
2025 make_pair("sendfrom", &sendfrom),
2026 make_pair("sendmany", &sendmany),
2027 make_pair("addmultisigaddress", &addmultisigaddress),
2028 make_pair("getblock", &getblock),
2029 make_pair("getblockhash", &getblockhash),
2030 make_pair("gettransaction", &gettransaction),
2031 make_pair("listtransactions", &listtransactions),
2032 make_pair("signmessage", &signmessage),
2033 make_pair("verifymessage", &verifymessage),
2034 make_pair("getwork", &getwork),
2035 make_pair("listaccounts", &listaccounts),
2036 make_pair("settxfee", &settxfee),
2037 make_pair("getmemorypool", &getmemorypool),
2038 make_pair("listsinceblock", &listsinceblock),
2039 make_pair("dumpprivkey", &dumpprivkey),
2040 make_pair("importprivkey", &importprivkey)
2042 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2044 string pAllowInSafeMode[] =
2049 "getblocknumber", // deprecated
2050 "getconnectioncount",
2058 "getaccountaddress",
2060 "getaddressesbyaccount",
2069 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2077 // This ain't Apache. We're just using HTTP header for the length field
2078 // and to be compatible with other JSON-RPC implementations.
2081 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2084 s << "POST / HTTP/1.1\r\n"
2085 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2086 << "Host: 127.0.0.1\r\n"
2087 << "Content-Type: application/json\r\n"
2088 << "Content-Length: " << strMsg.size() << "\r\n"
2089 << "Connection: close\r\n"
2090 << "Accept: application/json\r\n";
2091 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2092 s << item.first << ": " << item.second << "\r\n";
2093 s << "\r\n" << strMsg;
2098 string rfc1123Time()
2103 struct tm* now_gmt = gmtime(&now);
2104 string locale(setlocale(LC_TIME, NULL));
2105 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2106 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2107 setlocale(LC_TIME, locale.c_str());
2108 return string(buffer);
2111 static string HTTPReply(int nStatus, const string& strMsg)
2114 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2116 "Server: bitcoin-json-rpc/%s\r\n"
2117 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2118 "Content-Type: text/html\r\n"
2119 "Content-Length: 296\r\n"
2121 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2122 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2125 "<TITLE>Error</TITLE>\r\n"
2126 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2128 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2129 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2130 const char *cStatus;
2131 if (nStatus == 200) cStatus = "OK";
2132 else if (nStatus == 400) cStatus = "Bad Request";
2133 else if (nStatus == 403) cStatus = "Forbidden";
2134 else if (nStatus == 404) cStatus = "Not Found";
2135 else if (nStatus == 500) cStatus = "Internal Server Error";
2138 "HTTP/1.1 %d %s\r\n"
2140 "Connection: close\r\n"
2141 "Content-Length: %d\r\n"
2142 "Content-Type: application/json\r\n"
2143 "Server: bitcoin-json-rpc/%s\r\n"
2148 rfc1123Time().c_str(),
2150 FormatFullVersion().c_str(),
2154 int ReadHTTPStatus(std::basic_istream<char>& stream)
2157 getline(stream, str);
2158 vector<string> vWords;
2159 boost::split(vWords, str, boost::is_any_of(" "));
2160 if (vWords.size() < 2)
2162 return atoi(vWords[1].c_str());
2165 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2171 std::getline(stream, str);
2172 if (str.empty() || str == "\r")
2174 string::size_type nColon = str.find(":");
2175 if (nColon != string::npos)
2177 string strHeader = str.substr(0, nColon);
2178 boost::trim(strHeader);
2179 boost::to_lower(strHeader);
2180 string strValue = str.substr(nColon+1);
2181 boost::trim(strValue);
2182 mapHeadersRet[strHeader] = strValue;
2183 if (strHeader == "content-length")
2184 nLen = atoi(strValue.c_str());
2190 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2192 mapHeadersRet.clear();
2196 int nStatus = ReadHTTPStatus(stream);
2199 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2200 if (nLen < 0 || nLen > MAX_SIZE)
2206 vector<char> vch(nLen);
2207 stream.read(&vch[0], nLen);
2208 strMessageRet = string(vch.begin(), vch.end());
2214 bool HTTPAuthorized(map<string, string>& mapHeaders)
2216 string strAuth = mapHeaders["authorization"];
2217 if (strAuth.substr(0,6) != "Basic ")
2219 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2220 string strUserPass = DecodeBase64(strUserPass64);
2221 return strUserPass == strRPCUserColonPass;
2225 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2226 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2227 // unspecified (HTTP errors and contents of 'error').
2229 // 1.0 spec: http://json-rpc.org/wiki/specification
2230 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2231 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2234 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2237 request.push_back(Pair("method", strMethod));
2238 request.push_back(Pair("params", params));
2239 request.push_back(Pair("id", id));
2240 return write_string(Value(request), false) + "\n";
2243 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2246 if (error.type() != null_type)
2247 reply.push_back(Pair("result", Value::null));
2249 reply.push_back(Pair("result", result));
2250 reply.push_back(Pair("error", error));
2251 reply.push_back(Pair("id", id));
2252 return write_string(Value(reply), false) + "\n";
2255 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2257 // Send error reply from json-rpc error object
2259 int code = find_value(objError, "code").get_int();
2260 if (code == -32600) nStatus = 400;
2261 else if (code == -32601) nStatus = 404;
2262 string strReply = JSONRPCReply(Value::null, objError, id);
2263 stream << HTTPReply(nStatus, strReply) << std::flush;
2266 bool ClientAllowed(const string& strAddress)
2268 if (strAddress == asio::ip::address_v4::loopback().to_string())
2270 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2271 BOOST_FOREACH(string strAllow, vAllow)
2272 if (WildcardMatch(strAddress, strAllow))
2279 // IOStream device that speaks SSL but can also speak non-SSL
2281 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2283 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2285 fUseSSL = fUseSSLIn;
2286 fNeedHandshake = fUseSSLIn;
2289 void handshake(ssl::stream_base::handshake_type role)
2291 if (!fNeedHandshake) return;
2292 fNeedHandshake = false;
2293 stream.handshake(role);
2295 std::streamsize read(char* s, std::streamsize n)
2297 handshake(ssl::stream_base::server); // HTTPS servers read first
2298 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2299 return stream.next_layer().read_some(asio::buffer(s, n));
2301 std::streamsize write(const char* s, std::streamsize n)
2303 handshake(ssl::stream_base::client); // HTTPS clients write first
2304 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2305 return asio::write(stream.next_layer(), asio::buffer(s, n));
2307 bool connect(const std::string& server, const std::string& port)
2309 ip::tcp::resolver resolver(stream.get_io_service());
2310 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2311 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2312 ip::tcp::resolver::iterator end;
2313 boost::system::error_code error = asio::error::host_not_found;
2314 while (error && endpoint_iterator != end)
2316 stream.lowest_layer().close();
2317 stream.lowest_layer().connect(*endpoint_iterator++, error);
2325 bool fNeedHandshake;
2331 void ThreadRPCServer(void* parg)
2333 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2336 vnThreadsRunning[4]++;
2337 ThreadRPCServer2(parg);
2338 vnThreadsRunning[4]--;
2340 catch (std::exception& e) {
2341 vnThreadsRunning[4]--;
2342 PrintException(&e, "ThreadRPCServer()");
2344 vnThreadsRunning[4]--;
2345 PrintException(NULL, "ThreadRPCServer()");
2347 printf("ThreadRPCServer exiting\n");
2350 void ThreadRPCServer2(void* parg)
2352 printf("ThreadRPCServer started\n");
2354 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2355 if (strRPCUserColonPass == ":")
2357 string strWhatAmI = "To use bitcoind";
2358 if (mapArgs.count("-server"))
2359 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2360 else if (mapArgs.count("-daemon"))
2361 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2363 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2364 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2366 GetConfigFile().c_str());
2368 CreateThread(Shutdown, NULL);
2373 bool fUseSSL = GetBoolArg("-rpcssl");
2374 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2376 asio::io_service io_service;
2377 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2378 ip::tcp::acceptor acceptor(io_service, endpoint);
2380 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2383 ssl::context context(io_service, ssl::context::sslv23);
2386 context.set_options(ssl::context::no_sslv2);
2387 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2388 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2389 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2390 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2391 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2392 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2393 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2394 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2396 string ciphers = GetArg("-rpcsslciphers",
2397 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2398 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2402 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2407 // Accept connection
2409 SSLStream sslStream(io_service, context);
2410 SSLIOStreamDevice d(sslStream, fUseSSL);
2411 iostreams::stream<SSLIOStreamDevice> stream(d);
2413 ip::tcp::iostream stream;
2416 ip::tcp::endpoint peer;
2417 vnThreadsRunning[4]--;
2419 acceptor.accept(sslStream.lowest_layer(), peer);
2421 acceptor.accept(*stream.rdbuf(), peer);
2423 vnThreadsRunning[4]++;
2427 // Restrict callers by IP
2428 if (!ClientAllowed(peer.address().to_string()))
2430 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2432 stream << HTTPReply(403, "") << std::flush;
2436 map<string, string> mapHeaders;
2439 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2440 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2443 printf("ThreadRPCServer ReadHTTP timeout\n");
2447 // Check authorization
2448 if (mapHeaders.count("authorization") == 0)
2450 stream << HTTPReply(401, "") << std::flush;
2453 if (!HTTPAuthorized(mapHeaders))
2455 // Deter brute-forcing short passwords
2456 if (mapArgs["-rpcpassword"].size() < 15)
2459 stream << HTTPReply(401, "") << std::flush;
2460 printf("ThreadRPCServer incorrect password attempt\n");
2464 Value id = Value::null;
2469 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2470 throw JSONRPCError(-32700, "Parse error");
2471 const Object& request = valRequest.get_obj();
2473 // Parse id now so errors from here on will have the id
2474 id = find_value(request, "id");
2477 Value valMethod = find_value(request, "method");
2478 if (valMethod.type() == null_type)
2479 throw JSONRPCError(-32600, "Missing method");
2480 if (valMethod.type() != str_type)
2481 throw JSONRPCError(-32600, "Method must be a string");
2482 string strMethod = valMethod.get_str();
2483 if (strMethod != "getwork" && strMethod != "getmemorypool")
2484 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2487 Value valParams = find_value(request, "params");
2489 if (valParams.type() == array_type)
2490 params = valParams.get_array();
2491 else if (valParams.type() == null_type)
2494 throw JSONRPCError(-32600, "Params must be an array");
2497 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2498 if (mi == mapCallTable.end())
2499 throw JSONRPCError(-32601, "Method not found");
2501 // Observe safe mode
2502 string strWarning = GetWarnings("rpc");
2503 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2504 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2510 CRITICAL_BLOCK(cs_main)
2511 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2512 result = (*(*mi).second)(params, false);
2515 string strReply = JSONRPCReply(result, Value::null, id);
2516 stream << HTTPReply(200, strReply) << std::flush;
2518 catch (std::exception& e)
2520 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2523 catch (Object& objError)
2525 ErrorReply(stream, objError, id);
2527 catch (std::exception& e)
2529 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2537 Object CallRPC(const string& strMethod, const Array& params)
2539 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2540 throw runtime_error(strprintf(
2541 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2542 "If the file does not exist, create it with owner-readable-only file permissions."),
2543 GetConfigFile().c_str()));
2545 // Connect to localhost
2546 bool fUseSSL = GetBoolArg("-rpcssl");
2548 asio::io_service io_service;
2549 ssl::context context(io_service, ssl::context::sslv23);
2550 context.set_options(ssl::context::no_sslv2);
2551 SSLStream sslStream(io_service, context);
2552 SSLIOStreamDevice d(sslStream, fUseSSL);
2553 iostreams::stream<SSLIOStreamDevice> stream(d);
2554 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2555 throw runtime_error("couldn't connect to server");
2558 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2560 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2562 throw runtime_error("couldn't connect to server");
2566 // HTTP basic authentication
2567 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2568 map<string, string> mapRequestHeaders;
2569 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2572 string strRequest = JSONRPCRequest(strMethod, params, 1);
2573 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2574 stream << strPost << std::flush;
2577 map<string, string> mapHeaders;
2579 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2581 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2582 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2583 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2584 else if (strReply.empty())
2585 throw runtime_error("no response from server");
2589 if (!read_string(strReply, valReply))
2590 throw runtime_error("couldn't parse reply from server");
2591 const Object& reply = valReply.get_obj();
2593 throw runtime_error("expected reply to have result, error and id properties");
2601 template<typename T>
2602 void ConvertTo(Value& value)
2604 if (value.type() == str_type)
2606 // reinterpret string as unquoted json value
2608 if (!read_string(value.get_str(), value2))
2609 throw runtime_error("type mismatch");
2610 value = value2.get_value<T>();
2614 value = value.get_value<T>();
2618 int CommandLineRPC(int argc, char *argv[])
2625 while (argc > 1 && IsSwitchChar(argv[1][0]))
2633 throw runtime_error("too few parameters");
2634 string strMethod = argv[1];
2636 // Parameters default to strings
2638 for (int i = 2; i < argc; i++)
2639 params.push_back(argv[i]);
2640 int n = params.size();
2643 // Special case non-string parameter types
2645 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2646 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2647 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2648 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2649 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2650 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2651 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2652 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2653 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2654 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2655 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2657 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2658 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2659 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2660 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2661 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2662 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2663 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2664 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2666 if (strMethod == "sendmany" && n > 1)
2668 string s = params[1].get_str();
2670 if (!read_string(s, v) || v.type() != obj_type)
2671 throw runtime_error("type mismatch");
2672 params[1] = v.get_obj();
2674 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2675 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2676 if (strMethod == "addmultisigaddress" && n > 1)
2678 string s = params[1].get_str();
2680 if (!read_string(s, v) || v.type() != array_type)
2681 throw runtime_error("addmultisigaddress: type mismatch "+s);
2682 params[1] = v.get_array();
2686 Object reply = CallRPC(strMethod, params);
2689 const Value& result = find_value(reply, "result");
2690 const Value& error = find_value(reply, "error");
2692 if (error.type() != null_type)
2695 strPrint = "error: " + write_string(error, false);
2696 int code = find_value(error.get_obj(), "code").get_int();
2702 if (result.type() == null_type)
2704 else if (result.type() == str_type)
2705 strPrint = result.get_str();
2707 strPrint = write_string(result, true);
2710 catch (std::exception& e)
2712 strPrint = string("error: ") + e.what();
2717 PrintException(NULL, "CommandLineRPC()");
2722 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2731 int main(int argc, char *argv[])
2734 // Turn off microsoft heap dump noise
2735 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2736 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2738 setbuf(stdin, NULL);
2739 setbuf(stdout, NULL);
2740 setbuf(stderr, NULL);
2744 if (argc >= 2 && string(argv[1]) == "-server")
2746 printf("server ready\n");
2747 ThreadRPCServer(NULL);
2751 return CommandLineRPC(argc, argv);
2754 catch (std::exception& e) {
2755 PrintException(&e, "main()");
2757 PrintException(NULL, "main()");