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("currentblocksize",(uint64_t)nLastBlockSize));
372 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
373 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
374 obj.push_back(Pair("errors", GetWarnings("statusbar")));
375 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
376 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
377 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
378 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
379 obj.push_back(Pair("testnet", fTestNet));
384 Value getnewaddress(const Array& params, bool fHelp)
386 if (fHelp || params.size() > 1)
388 "getnewaddress [account]\n"
389 "Returns a new bitcoin address for receiving payments. "
390 "If [account] is specified (recommended), it is added to the address book "
391 "so payments received with the address will be credited to [account].");
393 // Parse the account first so we don't generate a key if there's an error
395 if (params.size() > 0)
396 strAccount = AccountFromValue(params[0]);
398 if (!pwalletMain->IsLocked())
399 pwalletMain->TopUpKeyPool();
401 // Generate a new key that is added to wallet
402 std::vector<unsigned char> newKey;
403 if (!pwalletMain->GetKeyFromPool(newKey, false))
404 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
405 CBitcoinAddress address(newKey);
407 pwalletMain->SetAddressBookName(address, strAccount);
409 return address.ToString();
413 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
415 CWalletDB walletdb(pwalletMain->strWalletFile);
418 walletdb.ReadAccount(strAccount, account);
420 bool bKeyUsed = false;
422 // Check if the current key has been used
423 if (!account.vchPubKey.empty())
425 CScript scriptPubKey;
426 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
427 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
428 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
431 const CWalletTx& wtx = (*it).second;
432 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
433 if (txout.scriptPubKey == scriptPubKey)
438 // Generate a new key
439 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
441 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
442 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
444 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
445 walletdb.WriteAccount(strAccount, account);
448 return CBitcoinAddress(account.vchPubKey);
451 Value getaccountaddress(const Array& params, bool fHelp)
453 if (fHelp || params.size() != 1)
455 "getaccountaddress <account>\n"
456 "Returns the current bitcoin address for receiving payments to this account.");
458 // Parse the account first so we don't generate a key if there's an error
459 string strAccount = AccountFromValue(params[0]);
463 ret = GetAccountAddress(strAccount).ToString();
470 Value setaccount(const Array& params, bool fHelp)
472 if (fHelp || params.size() < 1 || params.size() > 2)
474 "setaccount <bitcoinaddress> <account>\n"
475 "Sets the account associated with the given address.");
477 CBitcoinAddress address(params[0].get_str());
478 if (!address.IsValid())
479 throw JSONRPCError(-5, "Invalid bitcoin address");
483 if (params.size() > 1)
484 strAccount = AccountFromValue(params[1]);
486 // Detect when changing the account of an address that is the 'unused current key' of another account:
487 if (pwalletMain->mapAddressBook.count(address))
489 string strOldAccount = pwalletMain->mapAddressBook[address];
490 if (address == GetAccountAddress(strOldAccount))
491 GetAccountAddress(strOldAccount, true);
494 pwalletMain->SetAddressBookName(address, strAccount);
500 Value getaccount(const Array& params, bool fHelp)
502 if (fHelp || params.size() != 1)
504 "getaccount <bitcoinaddress>\n"
505 "Returns the account associated with the given address.");
507 CBitcoinAddress address(params[0].get_str());
508 if (!address.IsValid())
509 throw JSONRPCError(-5, "Invalid bitcoin address");
512 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
513 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
514 strAccount = (*mi).second;
519 Value getaddressesbyaccount(const Array& params, bool fHelp)
521 if (fHelp || params.size() != 1)
523 "getaddressesbyaccount <account>\n"
524 "Returns the list of addresses for the given account.");
526 string strAccount = AccountFromValue(params[0]);
528 // Find all addresses that have the given account
530 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
532 const CBitcoinAddress& address = item.first;
533 const string& strName = item.second;
534 if (strName == strAccount)
535 ret.push_back(address.ToString());
540 Value settxfee(const Array& params, bool fHelp)
542 if (fHelp || params.size() < 1 || params.size() > 1)
544 "settxfee <amount>\n"
545 "<amount> is a real and is rounded to the nearest 0.00000001");
549 if (params[0].get_real() != 0.0)
550 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
552 nTransactionFee = nAmount;
556 Value sendtoaddress(const Array& params, bool fHelp)
558 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
560 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
561 "<amount> is a real and is rounded to the nearest 0.00000001\n"
562 "requires wallet passphrase to be set with walletpassphrase first");
563 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
565 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
566 "<amount> is a real and is rounded to the nearest 0.00000001");
568 CBitcoinAddress address(params[0].get_str());
569 if (!address.IsValid())
570 throw JSONRPCError(-5, "Invalid bitcoin address");
573 int64 nAmount = AmountFromValue(params[1]);
577 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
578 wtx.mapValue["comment"] = params[2].get_str();
579 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
580 wtx.mapValue["to"] = params[3].get_str();
582 if (pwalletMain->IsLocked())
583 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
585 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
587 throw JSONRPCError(-4, strError);
589 return wtx.GetHash().GetHex();
592 Value signmessage(const Array& params, bool fHelp)
594 if (fHelp || params.size() != 2)
596 "signmessage <bitcoinaddress> <message>\n"
597 "Sign a message with the private key of an address");
599 if (pwalletMain->IsLocked())
600 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
602 string strAddress = params[0].get_str();
603 string strMessage = params[1].get_str();
605 CBitcoinAddress addr(strAddress);
607 throw JSONRPCError(-3, "Invalid address");
610 if (!pwalletMain->GetKey(addr, key))
611 throw JSONRPCError(-4, "Private key not available");
613 CDataStream ss(SER_GETHASH);
614 ss << strMessageMagic;
617 vector<unsigned char> vchSig;
618 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
619 throw JSONRPCError(-5, "Sign failed");
621 return EncodeBase64(&vchSig[0], vchSig.size());
624 Value verifymessage(const Array& params, bool fHelp)
626 if (fHelp || params.size() != 3)
628 "verifymessage <bitcoinaddress> <signature> <message>\n"
629 "Verify a signed message");
631 string strAddress = params[0].get_str();
632 string strSign = params[1].get_str();
633 string strMessage = params[2].get_str();
635 CBitcoinAddress addr(strAddress);
637 throw JSONRPCError(-3, "Invalid address");
639 bool fInvalid = false;
640 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
643 throw JSONRPCError(-5, "Malformed base64 encoding");
645 CDataStream ss(SER_GETHASH);
646 ss << strMessageMagic;
650 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
653 return (CBitcoinAddress(key.GetPubKey()) == addr);
657 Value getreceivedbyaddress(const Array& params, bool fHelp)
659 if (fHelp || params.size() < 1 || params.size() > 2)
661 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
662 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
665 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
666 CScript scriptPubKey;
667 if (!address.IsValid())
668 throw JSONRPCError(-5, "Invalid bitcoin address");
669 scriptPubKey.SetBitcoinAddress(address);
670 if (!IsMine(*pwalletMain,scriptPubKey))
673 // Minimum confirmations
675 if (params.size() > 1)
676 nMinDepth = params[1].get_int();
680 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
682 const CWalletTx& wtx = (*it).second;
683 if (wtx.IsCoinBase() || !wtx.IsFinal())
686 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
687 if (txout.scriptPubKey == scriptPubKey)
688 if (wtx.GetDepthInMainChain() >= nMinDepth)
689 nAmount += txout.nValue;
692 return ValueFromAmount(nAmount);
696 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
698 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
700 const CBitcoinAddress& address = item.first;
701 const string& strName = item.second;
702 if (strName == strAccount)
703 setAddress.insert(address);
708 Value getreceivedbyaccount(const Array& params, bool fHelp)
710 if (fHelp || params.size() < 1 || params.size() > 2)
712 "getreceivedbyaccount <account> [minconf=1]\n"
713 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
715 // Minimum confirmations
717 if (params.size() > 1)
718 nMinDepth = params[1].get_int();
720 // Get the set of pub keys assigned to account
721 string strAccount = AccountFromValue(params[0]);
722 set<CBitcoinAddress> setAddress;
723 GetAccountAddresses(strAccount, setAddress);
727 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
729 const CWalletTx& wtx = (*it).second;
730 if (wtx.IsCoinBase() || !wtx.IsFinal())
733 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
735 CBitcoinAddress address;
736 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
737 if (wtx.GetDepthInMainChain() >= nMinDepth)
738 nAmount += txout.nValue;
742 return (double)nAmount / (double)COIN;
746 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
750 // Tally wallet transactions
751 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
753 const CWalletTx& wtx = (*it).second;
757 int64 nGenerated, nReceived, nSent, nFee;
758 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
760 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
761 nBalance += nReceived;
762 nBalance += nGenerated - nSent - nFee;
765 // Tally internal accounting entries
766 nBalance += walletdb.GetAccountCreditDebit(strAccount);
771 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
773 CWalletDB walletdb(pwalletMain->strWalletFile);
774 return GetAccountBalance(walletdb, strAccount, nMinDepth);
778 Value getbalance(const Array& params, bool fHelp)
780 if (fHelp || params.size() > 2)
782 "getbalance [account] [minconf=1]\n"
783 "If [account] is not specified, returns the server's total available balance.\n"
784 "If [account] is specified, returns the balance in the account.");
786 if (params.size() == 0)
787 return ValueFromAmount(pwalletMain->GetBalance());
790 if (params.size() > 1)
791 nMinDepth = params[1].get_int();
793 if (params[0].get_str() == "*") {
794 // Calculate total balance a different way from GetBalance()
795 // (GetBalance() sums up all unspent TxOuts)
796 // getbalance and getbalance '*' should always return the same number.
798 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
800 const CWalletTx& wtx = (*it).second;
804 int64 allGeneratedImmature, allGeneratedMature, allFee;
805 allGeneratedImmature = allGeneratedMature = allFee = 0;
806 string strSentAccount;
807 list<pair<CBitcoinAddress, int64> > listReceived;
808 list<pair<CBitcoinAddress, int64> > listSent;
809 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
810 if (wtx.GetDepthInMainChain() >= nMinDepth)
811 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
812 nBalance += r.second;
813 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
814 nBalance -= r.second;
816 nBalance += allGeneratedMature;
818 return ValueFromAmount(nBalance);
821 string strAccount = AccountFromValue(params[0]);
823 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
825 return ValueFromAmount(nBalance);
829 Value movecmd(const Array& params, bool fHelp)
831 if (fHelp || params.size() < 3 || params.size() > 5)
833 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
834 "Move from one account in your wallet to another.");
836 string strFrom = AccountFromValue(params[0]);
837 string strTo = AccountFromValue(params[1]);
838 int64 nAmount = AmountFromValue(params[2]);
839 if (params.size() > 3)
840 // unused parameter, used to be nMinDepth, keep type-checking it though
841 (void)params[3].get_int();
843 if (params.size() > 4)
844 strComment = params[4].get_str();
846 CWalletDB walletdb(pwalletMain->strWalletFile);
849 int64 nNow = GetAdjustedTime();
852 CAccountingEntry debit;
853 debit.strAccount = strFrom;
854 debit.nCreditDebit = -nAmount;
856 debit.strOtherAccount = strTo;
857 debit.strComment = strComment;
858 walletdb.WriteAccountingEntry(debit);
861 CAccountingEntry credit;
862 credit.strAccount = strTo;
863 credit.nCreditDebit = nAmount;
865 credit.strOtherAccount = strFrom;
866 credit.strComment = strComment;
867 walletdb.WriteAccountingEntry(credit);
869 walletdb.TxnCommit();
875 Value sendfrom(const Array& params, bool fHelp)
877 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
879 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
880 "<amount> is a real and is rounded to the nearest 0.00000001\n"
881 "requires wallet passphrase to be set with walletpassphrase first");
882 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
884 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
885 "<amount> is a real and is rounded to the nearest 0.00000001");
887 string strAccount = AccountFromValue(params[0]);
888 CBitcoinAddress address(params[1].get_str());
889 if (!address.IsValid())
890 throw JSONRPCError(-5, "Invalid bitcoin address");
891 int64 nAmount = AmountFromValue(params[2]);
893 if (params.size() > 3)
894 nMinDepth = params[3].get_int();
897 wtx.strFromAccount = strAccount;
898 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
899 wtx.mapValue["comment"] = params[4].get_str();
900 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
901 wtx.mapValue["to"] = params[5].get_str();
903 if (pwalletMain->IsLocked())
904 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
907 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
908 if (nAmount > nBalance)
909 throw JSONRPCError(-6, "Account has insufficient funds");
912 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
914 throw JSONRPCError(-4, strError);
916 return wtx.GetHash().GetHex();
920 Value sendmany(const Array& params, bool fHelp)
922 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
924 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
925 "amounts are double-precision floating point numbers\n"
926 "requires wallet passphrase to be set with walletpassphrase first");
927 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
929 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
930 "amounts are double-precision floating point numbers");
932 string strAccount = AccountFromValue(params[0]);
933 Object sendTo = params[1].get_obj();
935 if (params.size() > 2)
936 nMinDepth = params[2].get_int();
939 wtx.strFromAccount = strAccount;
940 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
941 wtx.mapValue["comment"] = params[3].get_str();
943 set<CBitcoinAddress> setAddress;
944 vector<pair<CScript, int64> > vecSend;
946 int64 totalAmount = 0;
947 BOOST_FOREACH(const Pair& s, sendTo)
949 CBitcoinAddress address(s.name_);
950 if (!address.IsValid())
951 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
953 if (setAddress.count(address))
954 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
955 setAddress.insert(address);
957 CScript scriptPubKey;
958 scriptPubKey.SetBitcoinAddress(address);
959 int64 nAmount = AmountFromValue(s.value_);
960 totalAmount += nAmount;
962 vecSend.push_back(make_pair(scriptPubKey, nAmount));
965 if (pwalletMain->IsLocked())
966 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
969 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
970 if (totalAmount > nBalance)
971 throw JSONRPCError(-6, "Account has insufficient funds");
974 CReserveKey keyChange(pwalletMain);
975 int64 nFeeRequired = 0;
976 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
979 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
980 throw JSONRPCError(-6, "Insufficient funds");
981 throw JSONRPCError(-4, "Transaction creation failed");
983 if (!pwalletMain->CommitTransaction(wtx, keyChange))
984 throw JSONRPCError(-4, "Transaction commit failed");
986 return wtx.GetHash().GetHex();
989 Value addmultisigaddress(const Array& params, bool fHelp)
991 if (fHelp || params.size() < 2 || params.size() > 3)
993 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
994 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
995 "each key is a bitcoin address or hex-encoded public key\n"
996 "If [account] is specified, assign address to [account].";
997 throw runtime_error(msg);
1000 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1002 int nRequired = params[0].get_int();
1003 const Array& keys = params[1].get_array();
1005 if (params.size() > 2)
1006 strAccount = AccountFromValue(params[2]);
1008 // Gather public keys
1009 if (nRequired < 1 || keys.size() < nRequired)
1010 throw runtime_error(
1011 strprintf("wrong number of keys"
1012 "(got %d, need at least %d)", keys.size(), nRequired));
1013 std::vector<CKey> pubkeys;
1014 pubkeys.resize(keys.size());
1015 for (int i = 0; i < keys.size(); i++)
1017 const std::string& ks = keys[i].get_str();
1019 // Case 1: bitcoin address and we have full public key:
1020 CBitcoinAddress address(ks);
1021 if (address.IsValid())
1023 if (address.IsScript())
1024 throw runtime_error(
1025 strprintf("%s is a pay-to-script address",ks.c_str()));
1026 std::vector<unsigned char> vchPubKey;
1027 if (!pwalletMain->GetPubKey(address, vchPubKey))
1028 throw runtime_error(
1029 strprintf("no full public key for address %s",ks.c_str()));
1030 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1031 throw runtime_error(" Invalid public key: "+ks);
1034 // Case 2: hex public key
1037 vector<unsigned char> vchPubKey = ParseHex(ks);
1038 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1039 throw runtime_error(" Invalid public key: "+ks);
1043 throw runtime_error(" Invalid public key: "+ks);
1047 // Construct using pay-to-script-hash:
1049 inner.SetMultisig(nRequired, pubkeys);
1051 uint160 scriptHash = Hash160(inner);
1052 CScript scriptPubKey;
1053 scriptPubKey.SetPayToScriptHash(inner);
1054 pwalletMain->AddCScript(inner);
1055 CBitcoinAddress address;
1056 address.SetScriptHash160(scriptHash);
1058 pwalletMain->SetAddressBookName(address, strAccount);
1059 return address.ToString();
1070 nConf = std::numeric_limits<int>::max();
1074 Value ListReceived(const Array& params, bool fByAccounts)
1076 // Minimum confirmations
1078 if (params.size() > 0)
1079 nMinDepth = params[0].get_int();
1081 // Whether to include empty accounts
1082 bool fIncludeEmpty = false;
1083 if (params.size() > 1)
1084 fIncludeEmpty = params[1].get_bool();
1087 map<CBitcoinAddress, tallyitem> mapTally;
1088 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1090 const CWalletTx& wtx = (*it).second;
1092 if (wtx.IsCoinBase() || !wtx.IsFinal())
1095 int nDepth = wtx.GetDepthInMainChain();
1096 if (nDepth < nMinDepth)
1099 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1101 CBitcoinAddress address;
1102 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1105 tallyitem& item = mapTally[address];
1106 item.nAmount += txout.nValue;
1107 item.nConf = min(item.nConf, nDepth);
1113 map<string, tallyitem> mapAccountTally;
1114 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1116 const CBitcoinAddress& address = item.first;
1117 const string& strAccount = item.second;
1118 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1119 if (it == mapTally.end() && !fIncludeEmpty)
1123 int nConf = std::numeric_limits<int>::max();
1124 if (it != mapTally.end())
1126 nAmount = (*it).second.nAmount;
1127 nConf = (*it).second.nConf;
1132 tallyitem& item = mapAccountTally[strAccount];
1133 item.nAmount += nAmount;
1134 item.nConf = min(item.nConf, nConf);
1139 obj.push_back(Pair("address", address.ToString()));
1140 obj.push_back(Pair("account", strAccount));
1141 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1142 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1149 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1151 int64 nAmount = (*it).second.nAmount;
1152 int nConf = (*it).second.nConf;
1154 obj.push_back(Pair("account", (*it).first));
1155 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1156 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1164 Value listreceivedbyaddress(const Array& params, bool fHelp)
1166 if (fHelp || params.size() > 2)
1167 throw runtime_error(
1168 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1169 "[minconf] is the minimum number of confirmations before payments are included.\n"
1170 "[includeempty] whether to include addresses that haven't received any payments.\n"
1171 "Returns an array of objects containing:\n"
1172 " \"address\" : receiving address\n"
1173 " \"account\" : the account of the receiving address\n"
1174 " \"amount\" : total amount received by the address\n"
1175 " \"confirmations\" : number of confirmations of the most recent transaction included");
1177 return ListReceived(params, false);
1180 Value listreceivedbyaccount(const Array& params, bool fHelp)
1182 if (fHelp || params.size() > 2)
1183 throw runtime_error(
1184 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1185 "[minconf] is the minimum number of confirmations before payments are included.\n"
1186 "[includeempty] whether to include accounts that haven't received any payments.\n"
1187 "Returns an array of objects containing:\n"
1188 " \"account\" : the account of the receiving addresses\n"
1189 " \"amount\" : total amount received by addresses with this account\n"
1190 " \"confirmations\" : number of confirmations of the most recent transaction included");
1192 return ListReceived(params, true);
1195 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1197 int64 nGeneratedImmature, nGeneratedMature, nFee;
1198 string strSentAccount;
1199 list<pair<CBitcoinAddress, int64> > listReceived;
1200 list<pair<CBitcoinAddress, int64> > listSent;
1202 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1204 bool fAllAccounts = (strAccount == string("*"));
1206 // Generated blocks assigned to account ""
1207 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1210 entry.push_back(Pair("account", string("")));
1211 if (nGeneratedImmature)
1213 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1214 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1218 entry.push_back(Pair("category", "generate"));
1219 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1222 WalletTxToJSON(wtx, entry);
1223 ret.push_back(entry);
1227 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1229 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1232 entry.push_back(Pair("account", strSentAccount));
1233 entry.push_back(Pair("address", s.first.ToString()));
1234 entry.push_back(Pair("category", "send"));
1235 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1236 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1238 WalletTxToJSON(wtx, entry);
1239 ret.push_back(entry);
1244 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1245 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1248 if (pwalletMain->mapAddressBook.count(r.first))
1249 account = pwalletMain->mapAddressBook[r.first];
1250 if (fAllAccounts || (account == strAccount))
1253 entry.push_back(Pair("account", account));
1254 entry.push_back(Pair("address", r.first.ToString()));
1255 entry.push_back(Pair("category", "receive"));
1256 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1258 WalletTxToJSON(wtx, entry);
1259 ret.push_back(entry);
1264 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1266 bool fAllAccounts = (strAccount == string("*"));
1268 if (fAllAccounts || acentry.strAccount == strAccount)
1271 entry.push_back(Pair("account", acentry.strAccount));
1272 entry.push_back(Pair("category", "move"));
1273 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1274 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1275 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1276 entry.push_back(Pair("comment", acentry.strComment));
1277 ret.push_back(entry);
1281 Value listtransactions(const Array& params, bool fHelp)
1283 if (fHelp || params.size() > 3)
1284 throw runtime_error(
1285 "listtransactions [account] [count=10] [from=0]\n"
1286 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1288 string strAccount = "*";
1289 if (params.size() > 0)
1290 strAccount = params[0].get_str();
1292 if (params.size() > 1)
1293 nCount = params[1].get_int();
1295 if (params.size() > 2)
1296 nFrom = params[2].get_int();
1299 CWalletDB walletdb(pwalletMain->strWalletFile);
1301 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1302 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1303 typedef multimap<int64, TxPair > TxItems;
1306 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1308 CWalletTx* wtx = &((*it).second);
1309 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1311 list<CAccountingEntry> acentries;
1312 walletdb.ListAccountCreditDebit(strAccount, acentries);
1313 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1315 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1318 // Now: iterate backwards until we have nCount items to return:
1319 TxItems::reverse_iterator it = txByTime.rbegin();
1320 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1321 for (; it != txByTime.rend(); ++it)
1323 CWalletTx *const pwtx = (*it).second.first;
1325 ListTransactions(*pwtx, strAccount, 0, true, ret);
1326 CAccountingEntry *const pacentry = (*it).second.second;
1328 AcentryToJSON(*pacentry, strAccount, ret);
1330 if (ret.size() >= nCount) break;
1332 // ret is now newest to oldest
1334 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1335 if (ret.size() > nCount)
1337 Array::iterator last = ret.begin();
1338 std::advance(last, nCount);
1339 ret.erase(last, ret.end());
1341 std::reverse(ret.begin(), ret.end()); // oldest to newest
1346 Value listaccounts(const Array& params, bool fHelp)
1348 if (fHelp || params.size() > 1)
1349 throw runtime_error(
1350 "listaccounts [minconf=1]\n"
1351 "Returns Object that has account names as keys, account balances as values.");
1354 if (params.size() > 0)
1355 nMinDepth = params[0].get_int();
1357 map<string, int64> mapAccountBalances;
1358 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1359 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1360 mapAccountBalances[entry.second] = 0;
1363 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1365 const CWalletTx& wtx = (*it).second;
1366 int64 nGeneratedImmature, nGeneratedMature, nFee;
1367 string strSentAccount;
1368 list<pair<CBitcoinAddress, int64> > listReceived;
1369 list<pair<CBitcoinAddress, int64> > listSent;
1370 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1371 mapAccountBalances[strSentAccount] -= nFee;
1372 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1373 mapAccountBalances[strSentAccount] -= s.second;
1374 if (wtx.GetDepthInMainChain() >= nMinDepth)
1376 mapAccountBalances[""] += nGeneratedMature;
1377 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1378 if (pwalletMain->mapAddressBook.count(r.first))
1379 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1381 mapAccountBalances[""] += r.second;
1385 list<CAccountingEntry> acentries;
1386 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1387 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1388 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1391 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1392 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1397 Value listsinceblock(const Array& params, bool fHelp)
1400 throw runtime_error(
1401 "listsinceblock [blockid] [target-confirmations]\n"
1402 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1404 CBlockIndex *pindex = NULL;
1405 int target_confirms = 1;
1407 if (params.size() > 0)
1409 uint256 blockId = 0;
1411 blockId.SetHex(params[0].get_str());
1412 pindex = CBlockLocator(blockId).GetBlockIndex();
1415 if (params.size() > 1)
1417 target_confirms = params[1].get_int();
1419 if (target_confirms < 1)
1420 throw JSONRPCError(-8, "Invalid parameter");
1423 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1427 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1429 CWalletTx tx = (*it).second;
1431 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1432 ListTransactions(tx, "*", 0, true, transactions);
1437 if (target_confirms == 1)
1440 lastblock = hashBestChain;
1444 int target_height = pindexBest->nHeight + 1 - target_confirms;
1447 for (block = pindexBest;
1448 block && block->nHeight > target_height;
1449 block = block->pprev) { }
1451 lastblock = block ? block->GetBlockHash() : 0;
1455 ret.push_back(Pair("transactions", transactions));
1456 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1461 Value gettransaction(const Array& params, bool fHelp)
1463 if (fHelp || params.size() != 1)
1464 throw runtime_error(
1465 "gettransaction <txid>\n"
1466 "Get detailed information about <txid>");
1469 hash.SetHex(params[0].get_str());
1473 if (!pwalletMain->mapWallet.count(hash))
1474 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1475 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1477 int64 nCredit = wtx.GetCredit();
1478 int64 nDebit = wtx.GetDebit();
1479 int64 nNet = nCredit - nDebit;
1480 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1482 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1484 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1486 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1489 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1490 entry.push_back(Pair("details", details));
1496 Value backupwallet(const Array& params, bool fHelp)
1498 if (fHelp || params.size() != 1)
1499 throw runtime_error(
1500 "backupwallet <destination>\n"
1501 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1503 string strDest = params[0].get_str();
1504 BackupWallet(*pwalletMain, strDest);
1510 Value keypoolrefill(const Array& params, bool fHelp)
1512 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1513 throw runtime_error(
1515 "Fills the keypool, requires wallet passphrase to be set.");
1516 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1517 throw runtime_error(
1519 "Fills the keypool.");
1521 if (pwalletMain->IsLocked())
1522 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1524 pwalletMain->TopUpKeyPool();
1526 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1527 throw JSONRPCError(-4, "Error refreshing keypool.");
1533 void ThreadTopUpKeyPool(void* parg)
1535 pwalletMain->TopUpKeyPool();
1538 void ThreadCleanWalletPassphrase(void* parg)
1540 int64 nMyWakeTime = GetTime() + *((int*)parg);
1542 if (nWalletUnlockTime == 0)
1544 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1546 nWalletUnlockTime = nMyWakeTime;
1549 while (GetTime() < nWalletUnlockTime)
1550 Sleep(GetTime() - nWalletUnlockTime);
1552 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1554 nWalletUnlockTime = 0;
1559 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1561 if (nWalletUnlockTime < nMyWakeTime)
1562 nWalletUnlockTime = nMyWakeTime;
1568 pwalletMain->Lock();
1573 Value walletpassphrase(const Array& params, bool fHelp)
1575 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1576 throw runtime_error(
1577 "walletpassphrase <passphrase> <timeout>\n"
1578 "Stores the wallet decryption key in memory for <timeout> seconds.");
1581 if (!pwalletMain->IsCrypted())
1582 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1584 if (!pwalletMain->IsLocked())
1585 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1587 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1588 SecureString strWalletPass;
1589 strWalletPass.reserve(100);
1590 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1591 // Alternately, find a way to make params[0] mlock()'d to begin with.
1592 strWalletPass = params[0].get_str().c_str();
1594 if (strWalletPass.length() > 0)
1596 if (!pwalletMain->Unlock(strWalletPass))
1597 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1600 throw runtime_error(
1601 "walletpassphrase <passphrase> <timeout>\n"
1602 "Stores the wallet decryption key in memory for <timeout> seconds.");
1604 CreateThread(ThreadTopUpKeyPool, NULL);
1605 int* pnSleepTime = new int(params[1].get_int());
1606 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1612 Value walletpassphrasechange(const Array& params, bool fHelp)
1614 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1615 throw runtime_error(
1616 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1617 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1620 if (!pwalletMain->IsCrypted())
1621 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1623 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1624 // Alternately, find a way to make params[0] mlock()'d to begin with.
1625 SecureString strOldWalletPass;
1626 strOldWalletPass.reserve(100);
1627 strOldWalletPass = params[0].get_str().c_str();
1629 SecureString strNewWalletPass;
1630 strNewWalletPass.reserve(100);
1631 strNewWalletPass = params[1].get_str().c_str();
1633 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1634 throw runtime_error(
1635 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1636 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1638 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1639 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1645 Value walletlock(const Array& params, bool fHelp)
1647 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1648 throw runtime_error(
1650 "Removes the wallet encryption key from memory, locking the wallet.\n"
1651 "After calling this method, you will need to call walletpassphrase again\n"
1652 "before being able to call any methods which require the wallet to be unlocked.");
1655 if (!pwalletMain->IsCrypted())
1656 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1658 pwalletMain->Lock();
1659 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1661 nWalletUnlockTime = 0;
1668 Value encryptwallet(const Array& params, bool fHelp)
1670 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1671 throw runtime_error(
1672 "encryptwallet <passphrase>\n"
1673 "Encrypts the wallet with <passphrase>.");
1676 if (pwalletMain->IsCrypted())
1677 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1680 // shutting down via RPC while the GUI is running does not work (yet):
1681 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1684 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1685 // Alternately, find a way to make params[0] mlock()'d to begin with.
1686 SecureString strWalletPass;
1687 strWalletPass.reserve(100);
1688 strWalletPass = params[0].get_str().c_str();
1690 if (strWalletPass.length() < 1)
1691 throw runtime_error(
1692 "encryptwallet <passphrase>\n"
1693 "Encrypts the wallet with <passphrase>.");
1695 if (!pwalletMain->EncryptWallet(strWalletPass))
1696 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1698 // BDB seems to have a bad habit of writing old data into
1699 // slack space in .dat files; that is bad if the old data is
1700 // unencrypted private keys. So:
1701 CreateThread(Shutdown, NULL);
1702 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1706 Value validateaddress(const Array& params, bool fHelp)
1708 if (fHelp || params.size() != 1)
1709 throw runtime_error(
1710 "validateaddress <bitcoinaddress>\n"
1711 "Return information about <bitcoinaddress>.");
1713 CBitcoinAddress address(params[0].get_str());
1714 bool isValid = address.IsValid();
1717 ret.push_back(Pair("isvalid", isValid));
1720 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1721 // version of the address:
1722 string currentAddress = address.ToString();
1723 ret.push_back(Pair("address", currentAddress));
1724 if (pwalletMain->HaveKey(address))
1726 ret.push_back(Pair("ismine", true));
1727 std::vector<unsigned char> vchPubKey;
1728 pwalletMain->GetPubKey(address, vchPubKey);
1729 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1731 key.SetPubKey(vchPubKey);
1732 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1734 else if (pwalletMain->HaveCScript(address.GetHash160()))
1736 ret.push_back(Pair("isscript", true));
1738 pwalletMain->GetCScript(address.GetHash160(), subscript);
1739 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1740 std::vector<CBitcoinAddress> addresses;
1741 txnouttype whichType;
1743 ExtractAddresses(subscript, whichType, addresses, nRequired);
1744 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1746 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1747 a.push_back(addr.ToString());
1748 ret.push_back(Pair("addresses", a));
1749 if (whichType == TX_MULTISIG)
1750 ret.push_back(Pair("sigsrequired", nRequired));
1753 ret.push_back(Pair("ismine", false));
1754 if (pwalletMain->mapAddressBook.count(address))
1755 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1760 Value getwork(const Array& params, bool fHelp)
1762 if (fHelp || params.size() > 1)
1763 throw runtime_error(
1765 "If [data] is not specified, returns formatted hash data to work on:\n"
1766 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1767 " \"data\" : block data\n"
1768 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1769 " \"target\" : little endian hash target\n"
1770 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1773 throw JSONRPCError(-9, "Bitcoin is not connected!");
1775 if (IsInitialBlockDownload())
1776 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1778 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1779 static mapNewBlock_t mapNewBlock;
1780 static vector<CBlock*> vNewBlock;
1781 static CReserveKey reservekey(pwalletMain);
1783 if (params.size() == 0)
1786 static unsigned int nTransactionsUpdatedLast;
1787 static CBlockIndex* pindexPrev;
1788 static int64 nStart;
1789 static CBlock* pblock;
1790 if (pindexPrev != pindexBest ||
1791 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1793 if (pindexPrev != pindexBest)
1795 // Deallocate old blocks since they're obsolete now
1796 mapNewBlock.clear();
1797 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1801 nTransactionsUpdatedLast = nTransactionsUpdated;
1802 pindexPrev = pindexBest;
1806 pblock = CreateNewBlock(reservekey);
1808 throw JSONRPCError(-7, "Out of memory");
1809 vNewBlock.push_back(pblock);
1813 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1816 // Update nExtraNonce
1817 static unsigned int nExtraNonce = 0;
1818 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1821 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1823 // Prebuild hash buffers
1827 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1829 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1832 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1833 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1834 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1835 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1841 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1842 if (vchData.size() != 128)
1843 throw JSONRPCError(-8, "Invalid parameter");
1844 CBlock* pdata = (CBlock*)&vchData[0];
1847 for (int i = 0; i < 128/4; i++)
1848 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1851 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1853 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1855 pblock->nTime = pdata->nTime;
1856 pblock->nNonce = pdata->nNonce;
1857 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1858 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1860 return CheckWork(pblock, *pwalletMain, reservekey);
1865 Value getmemorypool(const Array& params, bool fHelp)
1867 if (fHelp || params.size() > 1)
1868 throw runtime_error(
1869 "getmemorypool [data]\n"
1870 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1871 " \"version\" : block version\n"
1872 " \"previousblockhash\" : hash of current highest block\n"
1873 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1874 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1875 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1876 " \"time\" : timestamp appropriate for next block\n"
1877 " \"mintime\" : minimum timestamp appropriate for next block\n"
1878 " \"curtime\" : current timestamp\n"
1879 " \"bits\" : compressed target of next block\n"
1880 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1882 if (params.size() == 0)
1885 throw JSONRPCError(-9, "Bitcoin is not connected!");
1887 if (IsInitialBlockDownload())
1888 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1890 static CReserveKey reservekey(pwalletMain);
1893 static unsigned int nTransactionsUpdatedLast;
1894 static CBlockIndex* pindexPrev;
1895 static int64 nStart;
1896 static CBlock* pblock;
1897 if (pindexPrev != pindexBest ||
1898 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1900 nTransactionsUpdatedLast = nTransactionsUpdated;
1901 pindexPrev = pindexBest;
1907 pblock = CreateNewBlock(reservekey);
1909 throw JSONRPCError(-7, "Out of memory");
1913 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1917 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1924 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1928 result.push_back(Pair("version", pblock->nVersion));
1929 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1930 result.push_back(Pair("transactions", transactions));
1931 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1932 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1933 result.push_back(Pair("time", (int64_t)pblock->nTime));
1934 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1935 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1941 uBits.nBits = htonl((int32_t)pblock->nBits);
1942 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1949 CDataStream ssBlock(ParseHex(params[0].get_str()));
1953 return ProcessBlock(NULL, &pblock);
1957 Value getblockhash(const Array& params, bool fHelp)
1959 if (fHelp || params.size() != 1)
1960 throw runtime_error(
1961 "getblockhash <index>\n"
1962 "Returns hash of block in best-block-chain at <index>.");
1964 int nHeight = params[0].get_int();
1965 if (nHeight < 0 || nHeight > nBestHeight)
1966 throw runtime_error("Block number out of range.");
1969 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1970 while (pblockindex->nHeight > nHeight)
1971 pblockindex = pblockindex->pprev;
1972 return pblockindex->phashBlock->GetHex();
1975 Value getblock(const Array& params, bool fHelp)
1977 if (fHelp || params.size() != 1)
1978 throw runtime_error(
1980 "Returns details of a block with given block-hash.");
1982 std::string strHash = params[0].get_str();
1983 uint256 hash(strHash);
1985 if (mapBlockIndex.count(hash) == 0)
1986 throw JSONRPCError(-5, "Block not found");
1989 CBlockIndex* pblockindex = mapBlockIndex[hash];
1990 block.ReadFromDisk(pblockindex, true);
1992 return blockToJSON(block, pblockindex);
2009 pair<string, rpcfn_type> pCallTable[] =
2011 make_pair("help", &help),
2012 make_pair("stop", &stop),
2013 make_pair("getblockcount", &getblockcount),
2014 make_pair("getblocknumber", &getblocknumber),
2015 make_pair("getconnectioncount", &getconnectioncount),
2016 make_pair("getdifficulty", &getdifficulty),
2017 make_pair("getgenerate", &getgenerate),
2018 make_pair("setgenerate", &setgenerate),
2019 make_pair("gethashespersec", &gethashespersec),
2020 make_pair("getinfo", &getinfo),
2021 make_pair("getmininginfo", &getmininginfo),
2022 make_pair("getnewaddress", &getnewaddress),
2023 make_pair("getaccountaddress", &getaccountaddress),
2024 make_pair("setaccount", &setaccount),
2025 make_pair("getaccount", &getaccount),
2026 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2027 make_pair("sendtoaddress", &sendtoaddress),
2028 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2029 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2030 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2031 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2032 make_pair("backupwallet", &backupwallet),
2033 make_pair("keypoolrefill", &keypoolrefill),
2034 make_pair("walletpassphrase", &walletpassphrase),
2035 make_pair("walletpassphrasechange", &walletpassphrasechange),
2036 make_pair("walletlock", &walletlock),
2037 make_pair("encryptwallet", &encryptwallet),
2038 make_pair("validateaddress", &validateaddress),
2039 make_pair("getbalance", &getbalance),
2040 make_pair("move", &movecmd),
2041 make_pair("sendfrom", &sendfrom),
2042 make_pair("sendmany", &sendmany),
2043 make_pair("addmultisigaddress", &addmultisigaddress),
2044 make_pair("getblock", &getblock),
2045 make_pair("getblockhash", &getblockhash),
2046 make_pair("gettransaction", &gettransaction),
2047 make_pair("listtransactions", &listtransactions),
2048 make_pair("signmessage", &signmessage),
2049 make_pair("verifymessage", &verifymessage),
2050 make_pair("getwork", &getwork),
2051 make_pair("listaccounts", &listaccounts),
2052 make_pair("settxfee", &settxfee),
2053 make_pair("getmemorypool", &getmemorypool),
2054 make_pair("listsinceblock", &listsinceblock),
2055 make_pair("dumpprivkey", &dumpprivkey),
2056 make_pair("importprivkey", &importprivkey)
2058 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2060 string pAllowInSafeMode[] =
2065 "getblocknumber", // deprecated
2066 "getconnectioncount",
2074 "getaccountaddress",
2076 "getaddressesbyaccount",
2085 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2093 // This ain't Apache. We're just using HTTP header for the length field
2094 // and to be compatible with other JSON-RPC implementations.
2097 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2100 s << "POST / HTTP/1.1\r\n"
2101 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2102 << "Host: 127.0.0.1\r\n"
2103 << "Content-Type: application/json\r\n"
2104 << "Content-Length: " << strMsg.size() << "\r\n"
2105 << "Connection: close\r\n"
2106 << "Accept: application/json\r\n";
2107 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2108 s << item.first << ": " << item.second << "\r\n";
2109 s << "\r\n" << strMsg;
2114 string rfc1123Time()
2119 struct tm* now_gmt = gmtime(&now);
2120 string locale(setlocale(LC_TIME, NULL));
2121 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2122 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2123 setlocale(LC_TIME, locale.c_str());
2124 return string(buffer);
2127 static string HTTPReply(int nStatus, const string& strMsg)
2130 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2132 "Server: bitcoin-json-rpc/%s\r\n"
2133 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2134 "Content-Type: text/html\r\n"
2135 "Content-Length: 296\r\n"
2137 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2138 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2141 "<TITLE>Error</TITLE>\r\n"
2142 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2144 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2145 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2146 const char *cStatus;
2147 if (nStatus == 200) cStatus = "OK";
2148 else if (nStatus == 400) cStatus = "Bad Request";
2149 else if (nStatus == 403) cStatus = "Forbidden";
2150 else if (nStatus == 404) cStatus = "Not Found";
2151 else if (nStatus == 500) cStatus = "Internal Server Error";
2154 "HTTP/1.1 %d %s\r\n"
2156 "Connection: close\r\n"
2157 "Content-Length: %d\r\n"
2158 "Content-Type: application/json\r\n"
2159 "Server: bitcoin-json-rpc/%s\r\n"
2164 rfc1123Time().c_str(),
2166 FormatFullVersion().c_str(),
2170 int ReadHTTPStatus(std::basic_istream<char>& stream)
2173 getline(stream, str);
2174 vector<string> vWords;
2175 boost::split(vWords, str, boost::is_any_of(" "));
2176 if (vWords.size() < 2)
2178 return atoi(vWords[1].c_str());
2181 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2187 std::getline(stream, str);
2188 if (str.empty() || str == "\r")
2190 string::size_type nColon = str.find(":");
2191 if (nColon != string::npos)
2193 string strHeader = str.substr(0, nColon);
2194 boost::trim(strHeader);
2195 boost::to_lower(strHeader);
2196 string strValue = str.substr(nColon+1);
2197 boost::trim(strValue);
2198 mapHeadersRet[strHeader] = strValue;
2199 if (strHeader == "content-length")
2200 nLen = atoi(strValue.c_str());
2206 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2208 mapHeadersRet.clear();
2212 int nStatus = ReadHTTPStatus(stream);
2215 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2216 if (nLen < 0 || nLen > MAX_SIZE)
2222 vector<char> vch(nLen);
2223 stream.read(&vch[0], nLen);
2224 strMessageRet = string(vch.begin(), vch.end());
2230 bool HTTPAuthorized(map<string, string>& mapHeaders)
2232 string strAuth = mapHeaders["authorization"];
2233 if (strAuth.substr(0,6) != "Basic ")
2235 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2236 string strUserPass = DecodeBase64(strUserPass64);
2237 return strUserPass == strRPCUserColonPass;
2241 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2242 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2243 // unspecified (HTTP errors and contents of 'error').
2245 // 1.0 spec: http://json-rpc.org/wiki/specification
2246 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2247 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2250 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2253 request.push_back(Pair("method", strMethod));
2254 request.push_back(Pair("params", params));
2255 request.push_back(Pair("id", id));
2256 return write_string(Value(request), false) + "\n";
2259 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2262 if (error.type() != null_type)
2263 reply.push_back(Pair("result", Value::null));
2265 reply.push_back(Pair("result", result));
2266 reply.push_back(Pair("error", error));
2267 reply.push_back(Pair("id", id));
2268 return write_string(Value(reply), false) + "\n";
2271 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2273 // Send error reply from json-rpc error object
2275 int code = find_value(objError, "code").get_int();
2276 if (code == -32600) nStatus = 400;
2277 else if (code == -32601) nStatus = 404;
2278 string strReply = JSONRPCReply(Value::null, objError, id);
2279 stream << HTTPReply(nStatus, strReply) << std::flush;
2282 bool ClientAllowed(const string& strAddress)
2284 if (strAddress == asio::ip::address_v4::loopback().to_string())
2286 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2287 BOOST_FOREACH(string strAllow, vAllow)
2288 if (WildcardMatch(strAddress, strAllow))
2295 // IOStream device that speaks SSL but can also speak non-SSL
2297 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2299 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2301 fUseSSL = fUseSSLIn;
2302 fNeedHandshake = fUseSSLIn;
2305 void handshake(ssl::stream_base::handshake_type role)
2307 if (!fNeedHandshake) return;
2308 fNeedHandshake = false;
2309 stream.handshake(role);
2311 std::streamsize read(char* s, std::streamsize n)
2313 handshake(ssl::stream_base::server); // HTTPS servers read first
2314 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2315 return stream.next_layer().read_some(asio::buffer(s, n));
2317 std::streamsize write(const char* s, std::streamsize n)
2319 handshake(ssl::stream_base::client); // HTTPS clients write first
2320 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2321 return asio::write(stream.next_layer(), asio::buffer(s, n));
2323 bool connect(const std::string& server, const std::string& port)
2325 ip::tcp::resolver resolver(stream.get_io_service());
2326 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2327 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2328 ip::tcp::resolver::iterator end;
2329 boost::system::error_code error = asio::error::host_not_found;
2330 while (error && endpoint_iterator != end)
2332 stream.lowest_layer().close();
2333 stream.lowest_layer().connect(*endpoint_iterator++, error);
2341 bool fNeedHandshake;
2347 void ThreadRPCServer(void* parg)
2349 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2352 vnThreadsRunning[4]++;
2353 ThreadRPCServer2(parg);
2354 vnThreadsRunning[4]--;
2356 catch (std::exception& e) {
2357 vnThreadsRunning[4]--;
2358 PrintException(&e, "ThreadRPCServer()");
2360 vnThreadsRunning[4]--;
2361 PrintException(NULL, "ThreadRPCServer()");
2363 printf("ThreadRPCServer exiting\n");
2366 void ThreadRPCServer2(void* parg)
2368 printf("ThreadRPCServer started\n");
2370 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2371 if (mapArgs["-rpcpassword"] == "")
2373 unsigned char rand_pwd[32];
2374 RAND_bytes(rand_pwd, 32);
2375 string strWhatAmI = "To use bitcoind";
2376 if (mapArgs.count("-server"))
2377 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2378 else if (mapArgs.count("-daemon"))
2379 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2381 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2382 "It is recommended you use the following random password:\n"
2383 "rpcuser=bitcoinrpc\n"
2385 "(you do not need to remember this password)\n"
2386 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2388 GetConfigFile().c_str(),
2389 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2391 CreateThread(Shutdown, NULL);
2396 bool fUseSSL = GetBoolArg("-rpcssl");
2397 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2399 asio::io_service io_service;
2400 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2401 ip::tcp::acceptor acceptor(io_service, endpoint);
2403 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2406 ssl::context context(io_service, ssl::context::sslv23);
2409 context.set_options(ssl::context::no_sslv2);
2410 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2411 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2412 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2413 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2414 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2415 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2416 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2417 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2419 string ciphers = GetArg("-rpcsslciphers",
2420 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2421 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2425 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2430 // Accept connection
2432 SSLStream sslStream(io_service, context);
2433 SSLIOStreamDevice d(sslStream, fUseSSL);
2434 iostreams::stream<SSLIOStreamDevice> stream(d);
2436 ip::tcp::iostream stream;
2439 ip::tcp::endpoint peer;
2440 vnThreadsRunning[4]--;
2442 acceptor.accept(sslStream.lowest_layer(), peer);
2444 acceptor.accept(*stream.rdbuf(), peer);
2446 vnThreadsRunning[4]++;
2450 // Restrict callers by IP
2451 if (!ClientAllowed(peer.address().to_string()))
2453 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2455 stream << HTTPReply(403, "") << std::flush;
2459 map<string, string> mapHeaders;
2462 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2463 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2466 printf("ThreadRPCServer ReadHTTP timeout\n");
2470 // Check authorization
2471 if (mapHeaders.count("authorization") == 0)
2473 stream << HTTPReply(401, "") << std::flush;
2476 if (!HTTPAuthorized(mapHeaders))
2478 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2479 /* Deter brute-forcing short passwords.
2480 If this results in a DOS the user really
2481 shouldn't have their RPC port exposed.*/
2482 if (mapArgs["-rpcpassword"].size() < 20)
2485 stream << HTTPReply(401, "") << std::flush;
2489 Value id = Value::null;
2494 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2495 throw JSONRPCError(-32700, "Parse error");
2496 const Object& request = valRequest.get_obj();
2498 // Parse id now so errors from here on will have the id
2499 id = find_value(request, "id");
2502 Value valMethod = find_value(request, "method");
2503 if (valMethod.type() == null_type)
2504 throw JSONRPCError(-32600, "Missing method");
2505 if (valMethod.type() != str_type)
2506 throw JSONRPCError(-32600, "Method must be a string");
2507 string strMethod = valMethod.get_str();
2508 if (strMethod != "getwork" && strMethod != "getmemorypool")
2509 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2512 Value valParams = find_value(request, "params");
2514 if (valParams.type() == array_type)
2515 params = valParams.get_array();
2516 else if (valParams.type() == null_type)
2519 throw JSONRPCError(-32600, "Params must be an array");
2522 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2523 if (mi == mapCallTable.end())
2524 throw JSONRPCError(-32601, "Method not found");
2526 // Observe safe mode
2527 string strWarning = GetWarnings("rpc");
2528 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2529 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2535 CRITICAL_BLOCK(cs_main)
2536 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2537 result = (*(*mi).second)(params, false);
2540 string strReply = JSONRPCReply(result, Value::null, id);
2541 stream << HTTPReply(200, strReply) << std::flush;
2543 catch (std::exception& e)
2545 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2548 catch (Object& objError)
2550 ErrorReply(stream, objError, id);
2552 catch (std::exception& e)
2554 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2562 Object CallRPC(const string& strMethod, const Array& params)
2564 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2565 throw runtime_error(strprintf(
2566 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2567 "If the file does not exist, create it with owner-readable-only file permissions."),
2568 GetConfigFile().c_str()));
2570 // Connect to localhost
2571 bool fUseSSL = GetBoolArg("-rpcssl");
2573 asio::io_service io_service;
2574 ssl::context context(io_service, ssl::context::sslv23);
2575 context.set_options(ssl::context::no_sslv2);
2576 SSLStream sslStream(io_service, context);
2577 SSLIOStreamDevice d(sslStream, fUseSSL);
2578 iostreams::stream<SSLIOStreamDevice> stream(d);
2579 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2580 throw runtime_error("couldn't connect to server");
2583 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2585 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2587 throw runtime_error("couldn't connect to server");
2591 // HTTP basic authentication
2592 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2593 map<string, string> mapRequestHeaders;
2594 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2597 string strRequest = JSONRPCRequest(strMethod, params, 1);
2598 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2599 stream << strPost << std::flush;
2602 map<string, string> mapHeaders;
2604 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2606 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2607 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2608 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2609 else if (strReply.empty())
2610 throw runtime_error("no response from server");
2614 if (!read_string(strReply, valReply))
2615 throw runtime_error("couldn't parse reply from server");
2616 const Object& reply = valReply.get_obj();
2618 throw runtime_error("expected reply to have result, error and id properties");
2626 template<typename T>
2627 void ConvertTo(Value& value)
2629 if (value.type() == str_type)
2631 // reinterpret string as unquoted json value
2633 if (!read_string(value.get_str(), value2))
2634 throw runtime_error("type mismatch");
2635 value = value2.get_value<T>();
2639 value = value.get_value<T>();
2643 int CommandLineRPC(int argc, char *argv[])
2650 while (argc > 1 && IsSwitchChar(argv[1][0]))
2658 throw runtime_error("too few parameters");
2659 string strMethod = argv[1];
2661 // Parameters default to strings
2663 for (int i = 2; i < argc; i++)
2664 params.push_back(argv[i]);
2665 int n = params.size();
2668 // Special case non-string parameter types
2670 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2671 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2672 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2673 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2674 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2676 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2677 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2678 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2680 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2681 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2682 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2683 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2684 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2685 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2686 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2687 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2688 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2689 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2690 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2691 if (strMethod == "sendmany" && n > 1)
2693 string s = params[1].get_str();
2695 if (!read_string(s, v) || v.type() != obj_type)
2696 throw runtime_error("type mismatch");
2697 params[1] = v.get_obj();
2699 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2700 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2701 if (strMethod == "addmultisigaddress" && n > 1)
2703 string s = params[1].get_str();
2705 if (!read_string(s, v) || v.type() != array_type)
2706 throw runtime_error("type mismatch "+s);
2707 params[1] = v.get_array();
2711 Object reply = CallRPC(strMethod, params);
2714 const Value& result = find_value(reply, "result");
2715 const Value& error = find_value(reply, "error");
2717 if (error.type() != null_type)
2720 strPrint = "error: " + write_string(error, false);
2721 int code = find_value(error.get_obj(), "code").get_int();
2727 if (result.type() == null_type)
2729 else if (result.type() == str_type)
2730 strPrint = result.get_str();
2732 strPrint = write_string(result, true);
2735 catch (std::exception& e)
2737 strPrint = string("error: ") + e.what();
2742 PrintException(NULL, "CommandLineRPC()");
2747 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2756 int main(int argc, char *argv[])
2759 // Turn off microsoft heap dump noise
2760 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2761 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2763 setbuf(stdin, NULL);
2764 setbuf(stdout, NULL);
2765 setbuf(stderr, NULL);
2769 if (argc >= 2 && string(argv[1]) == "-server")
2771 printf("server ready\n");
2772 ThreadRPCServer(NULL);
2776 return CommandLineRPC(argc, argv);
2779 catch (std::exception& e) {
2780 PrintException(&e, "main()");
2782 PrintException(NULL, "main()");