1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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;
124 HexBits(unsigned int nBits)
130 uBits.nBits = htonl((int32_t)nBits);
131 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
134 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
136 int confirms = wtx.GetDepthInMainChain();
137 entry.push_back(Pair("confirmations", confirms));
140 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
141 entry.push_back(Pair("blockindex", wtx.nIndex));
143 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
144 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
145 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
146 entry.push_back(Pair(item.first, item.second));
149 string AccountFromValue(const Value& value)
151 string strAccount = value.get_str();
152 if (strAccount == "*")
153 throw JSONRPCError(-11, "Invalid account name");
157 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
160 result.push_back(Pair("hash", block.GetHash().GetHex()));
161 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
162 result.push_back(Pair("height", blockindex->nHeight));
163 result.push_back(Pair("version", block.nVersion));
164 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
165 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
166 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
167 result.push_back(Pair("bits", HexBits(block.nBits)));
168 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
170 BOOST_FOREACH (const CTransaction&tx, block.vtx)
171 txhashes.push_back(tx.GetHash().GetHex());
172 result.push_back(Pair("tx", txhashes));
174 if (blockindex->pprev)
175 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
176 if (blockindex->pnext)
177 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
184 /// Note: This interface may still be subject to change.
188 Value help(const Array& params, bool fHelp)
190 if (fHelp || params.size() > 1)
193 "List commands, or get help for a command.");
196 if (params.size() > 0)
197 strCommand = params[0].get_str();
200 set<rpcfn_type> setDone;
201 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
203 string strMethod = (*mi).first;
204 // We already filter duplicates, but these deprecated screw up the sort order
205 if (strMethod == "getamountreceived" ||
206 strMethod == "getallreceived" ||
207 strMethod == "getblocknumber" || // deprecated
208 (strMethod.find("label") != string::npos))
210 if (strCommand != "" && strMethod != strCommand)
215 rpcfn_type pfn = (*mi).second;
216 if (setDone.insert(pfn).second)
217 (*pfn)(params, true);
219 catch (std::exception& e)
221 // Help text is returned in an exception
222 string strHelp = string(e.what());
223 if (strCommand == "")
224 if (strHelp.find('\n') != -1)
225 strHelp = strHelp.substr(0, strHelp.find('\n'));
226 strRet += strHelp + "\n";
230 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
231 strRet = strRet.substr(0,strRet.size()-1);
236 Value stop(const Array& params, bool fHelp)
238 if (fHelp || params.size() != 0)
241 "Stop bitcoin server.");
243 // Shutdown will take long enough that the response should get back
244 CreateThread(Shutdown, NULL);
245 return "bitcoin server stopping";
247 throw runtime_error("NYI: cannot shut down GUI with RPC command");
252 Value getblockcount(const Array& params, bool fHelp)
254 if (fHelp || params.size() != 0)
257 "Returns the number of blocks in the longest block chain.");
264 Value getblocknumber(const Array& params, bool fHelp)
266 if (fHelp || params.size() != 0)
269 "Deprecated. Use getblockcount.");
275 Value getconnectioncount(const Array& params, bool fHelp)
277 if (fHelp || params.size() != 0)
279 "getconnectioncount\n"
280 "Returns the number of connections to other nodes.");
282 return (int)vNodes.size();
286 Value getdifficulty(const Array& params, bool fHelp)
288 if (fHelp || params.size() != 0)
291 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
293 return GetDifficulty();
297 Value getgenerate(const Array& params, bool fHelp)
299 if (fHelp || params.size() != 0)
302 "Returns true or false.");
304 return (bool)fGenerateBitcoins;
308 Value setgenerate(const Array& params, bool fHelp)
310 if (fHelp || params.size() < 1 || params.size() > 2)
312 "setgenerate <generate> [genproclimit]\n"
313 "<generate> is true or false to turn generation on or off.\n"
314 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
316 bool fGenerate = true;
317 if (params.size() > 0)
318 fGenerate = params[0].get_bool();
320 if (params.size() > 1)
322 int nGenProcLimit = params[1].get_int();
323 fLimitProcessors = (nGenProcLimit != -1);
324 WriteSetting("fLimitProcessors", fLimitProcessors);
325 if (nGenProcLimit != -1)
326 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
327 if (nGenProcLimit == 0)
331 GenerateBitcoins(fGenerate, pwalletMain);
336 Value gethashespersec(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 0)
341 "Returns a recent hashes per second performance measurement while generating.");
343 if (GetTimeMillis() - nHPSTimerStart > 8000)
344 return (boost::int64_t)0;
345 return (boost::int64_t)dHashesPerSec;
349 Value getinfo(const Array& params, bool fHelp)
351 if (fHelp || params.size() != 0)
354 "Returns an object containing various state info.");
357 obj.push_back(Pair("version", (int)CLIENT_VERSION));
358 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
359 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
360 obj.push_back(Pair("blocks", (int)nBestHeight));
361 obj.push_back(Pair("connections", (int)vNodes.size()));
362 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
363 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
364 obj.push_back(Pair("testnet", fTestNet));
365 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
366 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
367 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
368 if (pwalletMain->IsCrypted())
369 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
370 obj.push_back(Pair("errors", GetWarnings("statusbar")));
375 Value getmininginfo(const Array& params, bool fHelp)
377 if (fHelp || params.size() != 0)
380 "Returns an object containing mining-related information.");
383 obj.push_back(Pair("blocks", (int)nBestHeight));
384 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
385 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
386 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
387 obj.push_back(Pair("errors", GetWarnings("statusbar")));
388 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
389 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
390 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
391 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
392 obj.push_back(Pair("testnet", fTestNet));
397 Value getnewaddress(const Array& params, bool fHelp)
399 if (fHelp || params.size() > 1)
401 "getnewaddress [account]\n"
402 "Returns a new bitcoin address for receiving payments. "
403 "If [account] is specified (recommended), it is added to the address book "
404 "so payments received with the address will be credited to [account].");
406 // Parse the account first so we don't generate a key if there's an error
408 if (params.size() > 0)
409 strAccount = AccountFromValue(params[0]);
411 if (!pwalletMain->IsLocked())
412 pwalletMain->TopUpKeyPool();
414 // Generate a new key that is added to wallet
415 std::vector<unsigned char> newKey;
416 if (!pwalletMain->GetKeyFromPool(newKey, false))
417 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
418 CBitcoinAddress address(newKey);
420 pwalletMain->SetAddressBookName(address, strAccount);
422 return address.ToString();
426 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
428 CWalletDB walletdb(pwalletMain->strWalletFile);
431 walletdb.ReadAccount(strAccount, account);
433 bool bKeyUsed = false;
435 // Check if the current key has been used
436 if (!account.vchPubKey.empty())
438 CScript scriptPubKey;
439 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
440 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
441 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
444 const CWalletTx& wtx = (*it).second;
445 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
446 if (txout.scriptPubKey == scriptPubKey)
451 // Generate a new key
452 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
454 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
455 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
457 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
458 walletdb.WriteAccount(strAccount, account);
461 return CBitcoinAddress(account.vchPubKey);
464 Value getaccountaddress(const Array& params, bool fHelp)
466 if (fHelp || params.size() != 1)
468 "getaccountaddress <account>\n"
469 "Returns the current bitcoin address for receiving payments to this account.");
471 // Parse the account first so we don't generate a key if there's an error
472 string strAccount = AccountFromValue(params[0]);
476 ret = GetAccountAddress(strAccount).ToString();
483 Value setaccount(const Array& params, bool fHelp)
485 if (fHelp || params.size() < 1 || params.size() > 2)
487 "setaccount <bitcoinaddress> <account>\n"
488 "Sets the account associated with the given address.");
490 CBitcoinAddress address(params[0].get_str());
491 if (!address.IsValid())
492 throw JSONRPCError(-5, "Invalid bitcoin address");
496 if (params.size() > 1)
497 strAccount = AccountFromValue(params[1]);
499 // Detect when changing the account of an address that is the 'unused current key' of another account:
500 if (pwalletMain->mapAddressBook.count(address))
502 string strOldAccount = pwalletMain->mapAddressBook[address];
503 if (address == GetAccountAddress(strOldAccount))
504 GetAccountAddress(strOldAccount, true);
507 pwalletMain->SetAddressBookName(address, strAccount);
513 Value getaccount(const Array& params, bool fHelp)
515 if (fHelp || params.size() != 1)
517 "getaccount <bitcoinaddress>\n"
518 "Returns the account associated with the given address.");
520 CBitcoinAddress address(params[0].get_str());
521 if (!address.IsValid())
522 throw JSONRPCError(-5, "Invalid bitcoin address");
525 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
526 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
527 strAccount = (*mi).second;
532 Value getaddressesbyaccount(const Array& params, bool fHelp)
534 if (fHelp || params.size() != 1)
536 "getaddressesbyaccount <account>\n"
537 "Returns the list of addresses for the given account.");
539 string strAccount = AccountFromValue(params[0]);
541 // Find all addresses that have the given account
543 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
545 const CBitcoinAddress& address = item.first;
546 const string& strName = item.second;
547 if (strName == strAccount)
548 ret.push_back(address.ToString());
553 Value settxfee(const Array& params, bool fHelp)
555 if (fHelp || params.size() < 1 || params.size() > 1)
557 "settxfee <amount>\n"
558 "<amount> is a real and is rounded to the nearest 0.00000001");
562 if (params[0].get_real() != 0.0)
563 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
565 nTransactionFee = nAmount;
569 Value sendtoaddress(const Array& params, bool fHelp)
571 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
573 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
574 "<amount> is a real and is rounded to the nearest 0.00000001\n"
575 "requires wallet passphrase to be set with walletpassphrase first");
576 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
578 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
579 "<amount> is a real and is rounded to the nearest 0.00000001");
581 CBitcoinAddress address(params[0].get_str());
582 if (!address.IsValid())
583 throw JSONRPCError(-5, "Invalid bitcoin address");
586 int64 nAmount = AmountFromValue(params[1]);
590 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
591 wtx.mapValue["comment"] = params[2].get_str();
592 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
593 wtx.mapValue["to"] = params[3].get_str();
595 if (pwalletMain->IsLocked())
596 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
598 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
600 throw JSONRPCError(-4, strError);
602 return wtx.GetHash().GetHex();
605 Value signmessage(const Array& params, bool fHelp)
607 if (fHelp || params.size() != 2)
609 "signmessage <bitcoinaddress> <message>\n"
610 "Sign a message with the private key of an address");
612 if (pwalletMain->IsLocked())
613 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
615 string strAddress = params[0].get_str();
616 string strMessage = params[1].get_str();
618 CBitcoinAddress addr(strAddress);
620 throw JSONRPCError(-3, "Invalid address");
623 if (!pwalletMain->GetKey(addr, key))
624 throw JSONRPCError(-4, "Private key not available");
626 CDataStream ss(SER_GETHASH);
627 ss << strMessageMagic;
630 vector<unsigned char> vchSig;
631 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
632 throw JSONRPCError(-5, "Sign failed");
634 return EncodeBase64(&vchSig[0], vchSig.size());
637 Value verifymessage(const Array& params, bool fHelp)
639 if (fHelp || params.size() != 3)
641 "verifymessage <bitcoinaddress> <signature> <message>\n"
642 "Verify a signed message");
644 string strAddress = params[0].get_str();
645 string strSign = params[1].get_str();
646 string strMessage = params[2].get_str();
648 CBitcoinAddress addr(strAddress);
650 throw JSONRPCError(-3, "Invalid address");
652 bool fInvalid = false;
653 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
656 throw JSONRPCError(-5, "Malformed base64 encoding");
658 CDataStream ss(SER_GETHASH);
659 ss << strMessageMagic;
663 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
666 return (CBitcoinAddress(key.GetPubKey()) == addr);
670 Value getreceivedbyaddress(const Array& params, bool fHelp)
672 if (fHelp || params.size() < 1 || params.size() > 2)
674 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
675 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
678 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
679 CScript scriptPubKey;
680 if (!address.IsValid())
681 throw JSONRPCError(-5, "Invalid bitcoin address");
682 scriptPubKey.SetBitcoinAddress(address);
683 if (!IsMine(*pwalletMain,scriptPubKey))
686 // Minimum confirmations
688 if (params.size() > 1)
689 nMinDepth = params[1].get_int();
693 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
695 const CWalletTx& wtx = (*it).second;
696 if (wtx.IsCoinBase() || !wtx.IsFinal())
699 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
700 if (txout.scriptPubKey == scriptPubKey)
701 if (wtx.GetDepthInMainChain() >= nMinDepth)
702 nAmount += txout.nValue;
705 return ValueFromAmount(nAmount);
709 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
711 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
713 const CBitcoinAddress& address = item.first;
714 const string& strName = item.second;
715 if (strName == strAccount)
716 setAddress.insert(address);
721 Value getreceivedbyaccount(const Array& params, bool fHelp)
723 if (fHelp || params.size() < 1 || params.size() > 2)
725 "getreceivedbyaccount <account> [minconf=1]\n"
726 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
728 // Minimum confirmations
730 if (params.size() > 1)
731 nMinDepth = params[1].get_int();
733 // Get the set of pub keys assigned to account
734 string strAccount = AccountFromValue(params[0]);
735 set<CBitcoinAddress> setAddress;
736 GetAccountAddresses(strAccount, setAddress);
740 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
742 const CWalletTx& wtx = (*it).second;
743 if (wtx.IsCoinBase() || !wtx.IsFinal())
746 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
748 CBitcoinAddress address;
749 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
750 if (wtx.GetDepthInMainChain() >= nMinDepth)
751 nAmount += txout.nValue;
755 return (double)nAmount / (double)COIN;
759 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
763 // Tally wallet transactions
764 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
766 const CWalletTx& wtx = (*it).second;
770 int64 nGenerated, nReceived, nSent, nFee;
771 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
773 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
774 nBalance += nReceived;
775 nBalance += nGenerated - nSent - nFee;
778 // Tally internal accounting entries
779 nBalance += walletdb.GetAccountCreditDebit(strAccount);
784 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
786 CWalletDB walletdb(pwalletMain->strWalletFile);
787 return GetAccountBalance(walletdb, strAccount, nMinDepth);
791 Value getbalance(const Array& params, bool fHelp)
793 if (fHelp || params.size() > 2)
795 "getbalance [account] [minconf=1]\n"
796 "If [account] is not specified, returns the server's total available balance.\n"
797 "If [account] is specified, returns the balance in the account.");
799 if (params.size() == 0)
800 return ValueFromAmount(pwalletMain->GetBalance());
803 if (params.size() > 1)
804 nMinDepth = params[1].get_int();
806 if (params[0].get_str() == "*") {
807 // Calculate total balance a different way from GetBalance()
808 // (GetBalance() sums up all unspent TxOuts)
809 // getbalance and getbalance '*' should always return the same number.
811 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
813 const CWalletTx& wtx = (*it).second;
817 int64 allGeneratedImmature, allGeneratedMature, allFee;
818 allGeneratedImmature = allGeneratedMature = allFee = 0;
819 string strSentAccount;
820 list<pair<CBitcoinAddress, int64> > listReceived;
821 list<pair<CBitcoinAddress, int64> > listSent;
822 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
823 if (wtx.GetDepthInMainChain() >= nMinDepth)
824 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
825 nBalance += r.second;
826 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
827 nBalance -= r.second;
829 nBalance += allGeneratedMature;
831 return ValueFromAmount(nBalance);
834 string strAccount = AccountFromValue(params[0]);
836 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
838 return ValueFromAmount(nBalance);
842 Value movecmd(const Array& params, bool fHelp)
844 if (fHelp || params.size() < 3 || params.size() > 5)
846 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
847 "Move from one account in your wallet to another.");
849 string strFrom = AccountFromValue(params[0]);
850 string strTo = AccountFromValue(params[1]);
851 int64 nAmount = AmountFromValue(params[2]);
852 if (params.size() > 3)
853 // unused parameter, used to be nMinDepth, keep type-checking it though
854 (void)params[3].get_int();
856 if (params.size() > 4)
857 strComment = params[4].get_str();
859 CWalletDB walletdb(pwalletMain->strWalletFile);
862 int64 nNow = GetAdjustedTime();
865 CAccountingEntry debit;
866 debit.strAccount = strFrom;
867 debit.nCreditDebit = -nAmount;
869 debit.strOtherAccount = strTo;
870 debit.strComment = strComment;
871 walletdb.WriteAccountingEntry(debit);
874 CAccountingEntry credit;
875 credit.strAccount = strTo;
876 credit.nCreditDebit = nAmount;
878 credit.strOtherAccount = strFrom;
879 credit.strComment = strComment;
880 walletdb.WriteAccountingEntry(credit);
882 walletdb.TxnCommit();
888 Value sendfrom(const Array& params, bool fHelp)
890 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
892 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
893 "<amount> is a real and is rounded to the nearest 0.00000001\n"
894 "requires wallet passphrase to be set with walletpassphrase first");
895 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
897 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
898 "<amount> is a real and is rounded to the nearest 0.00000001");
900 string strAccount = AccountFromValue(params[0]);
901 CBitcoinAddress address(params[1].get_str());
902 if (!address.IsValid())
903 throw JSONRPCError(-5, "Invalid bitcoin address");
904 int64 nAmount = AmountFromValue(params[2]);
906 if (params.size() > 3)
907 nMinDepth = params[3].get_int();
910 wtx.strFromAccount = strAccount;
911 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
912 wtx.mapValue["comment"] = params[4].get_str();
913 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
914 wtx.mapValue["to"] = params[5].get_str();
916 if (pwalletMain->IsLocked())
917 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
920 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
921 if (nAmount > nBalance)
922 throw JSONRPCError(-6, "Account has insufficient funds");
925 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
927 throw JSONRPCError(-4, strError);
929 return wtx.GetHash().GetHex();
933 Value sendmany(const Array& params, bool fHelp)
935 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
937 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
938 "amounts are double-precision floating point numbers\n"
939 "requires wallet passphrase to be set with walletpassphrase first");
940 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
942 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
943 "amounts are double-precision floating point numbers");
945 string strAccount = AccountFromValue(params[0]);
946 Object sendTo = params[1].get_obj();
948 if (params.size() > 2)
949 nMinDepth = params[2].get_int();
952 wtx.strFromAccount = strAccount;
953 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
954 wtx.mapValue["comment"] = params[3].get_str();
956 set<CBitcoinAddress> setAddress;
957 vector<pair<CScript, int64> > vecSend;
959 int64 totalAmount = 0;
960 BOOST_FOREACH(const Pair& s, sendTo)
962 CBitcoinAddress address(s.name_);
963 if (!address.IsValid())
964 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
966 if (setAddress.count(address))
967 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
968 setAddress.insert(address);
970 CScript scriptPubKey;
971 scriptPubKey.SetBitcoinAddress(address);
972 int64 nAmount = AmountFromValue(s.value_);
973 totalAmount += nAmount;
975 vecSend.push_back(make_pair(scriptPubKey, nAmount));
978 if (pwalletMain->IsLocked())
979 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
982 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
983 if (totalAmount > nBalance)
984 throw JSONRPCError(-6, "Account has insufficient funds");
987 CReserveKey keyChange(pwalletMain);
988 int64 nFeeRequired = 0;
989 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
992 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
993 throw JSONRPCError(-6, "Insufficient funds");
994 throw JSONRPCError(-4, "Transaction creation failed");
996 if (!pwalletMain->CommitTransaction(wtx, keyChange))
997 throw JSONRPCError(-4, "Transaction commit failed");
999 return wtx.GetHash().GetHex();
1002 Value addmultisigaddress(const Array& params, bool fHelp)
1004 if (fHelp || params.size() < 2 || params.size() > 3)
1006 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
1007 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
1008 "each key is a bitcoin address or hex-encoded public key\n"
1009 "If [account] is specified, assign address to [account].";
1010 throw runtime_error(msg);
1013 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1015 int nRequired = params[0].get_int();
1016 const Array& keys = params[1].get_array();
1018 if (params.size() > 2)
1019 strAccount = AccountFromValue(params[2]);
1021 // Gather public keys
1022 if (nRequired < 1 || keys.size() < nRequired)
1023 throw runtime_error(
1024 strprintf("wrong number of keys"
1025 "(got %d, need at least %d)", keys.size(), nRequired));
1026 std::vector<CKey> pubkeys;
1027 pubkeys.resize(keys.size());
1028 for (int i = 0; i < keys.size(); i++)
1030 const std::string& ks = keys[i].get_str();
1032 // Case 1: bitcoin address and we have full public key:
1033 CBitcoinAddress address(ks);
1034 if (address.IsValid())
1036 if (address.IsScript())
1037 throw runtime_error(
1038 strprintf("%s is a pay-to-script address",ks.c_str()));
1039 std::vector<unsigned char> vchPubKey;
1040 if (!pwalletMain->GetPubKey(address, vchPubKey))
1041 throw runtime_error(
1042 strprintf("no full public key for address %s",ks.c_str()));
1043 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1044 throw runtime_error(" Invalid public key: "+ks);
1047 // Case 2: hex public key
1050 vector<unsigned char> vchPubKey = ParseHex(ks);
1051 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1052 throw runtime_error(" Invalid public key: "+ks);
1056 throw runtime_error(" Invalid public key: "+ks);
1060 // Construct using pay-to-script-hash:
1062 inner.SetMultisig(nRequired, pubkeys);
1064 uint160 scriptHash = Hash160(inner);
1065 CScript scriptPubKey;
1066 scriptPubKey.SetPayToScriptHash(inner);
1067 pwalletMain->AddCScript(inner);
1068 CBitcoinAddress address;
1069 address.SetScriptHash160(scriptHash);
1071 pwalletMain->SetAddressBookName(address, strAccount);
1072 return address.ToString();
1083 nConf = std::numeric_limits<int>::max();
1087 Value ListReceived(const Array& params, bool fByAccounts)
1089 // Minimum confirmations
1091 if (params.size() > 0)
1092 nMinDepth = params[0].get_int();
1094 // Whether to include empty accounts
1095 bool fIncludeEmpty = false;
1096 if (params.size() > 1)
1097 fIncludeEmpty = params[1].get_bool();
1100 map<CBitcoinAddress, tallyitem> mapTally;
1101 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1103 const CWalletTx& wtx = (*it).second;
1105 if (wtx.IsCoinBase() || !wtx.IsFinal())
1108 int nDepth = wtx.GetDepthInMainChain();
1109 if (nDepth < nMinDepth)
1112 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1114 CBitcoinAddress address;
1115 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1118 tallyitem& item = mapTally[address];
1119 item.nAmount += txout.nValue;
1120 item.nConf = min(item.nConf, nDepth);
1126 map<string, tallyitem> mapAccountTally;
1127 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1129 const CBitcoinAddress& address = item.first;
1130 const string& strAccount = item.second;
1131 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1132 if (it == mapTally.end() && !fIncludeEmpty)
1136 int nConf = std::numeric_limits<int>::max();
1137 if (it != mapTally.end())
1139 nAmount = (*it).second.nAmount;
1140 nConf = (*it).second.nConf;
1145 tallyitem& item = mapAccountTally[strAccount];
1146 item.nAmount += nAmount;
1147 item.nConf = min(item.nConf, nConf);
1152 obj.push_back(Pair("address", address.ToString()));
1153 obj.push_back(Pair("account", strAccount));
1154 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1155 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1162 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1164 int64 nAmount = (*it).second.nAmount;
1165 int nConf = (*it).second.nConf;
1167 obj.push_back(Pair("account", (*it).first));
1168 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1169 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1177 Value listreceivedbyaddress(const Array& params, bool fHelp)
1179 if (fHelp || params.size() > 2)
1180 throw runtime_error(
1181 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1182 "[minconf] is the minimum number of confirmations before payments are included.\n"
1183 "[includeempty] whether to include addresses that haven't received any payments.\n"
1184 "Returns an array of objects containing:\n"
1185 " \"address\" : receiving address\n"
1186 " \"account\" : the account of the receiving address\n"
1187 " \"amount\" : total amount received by the address\n"
1188 " \"confirmations\" : number of confirmations of the most recent transaction included");
1190 return ListReceived(params, false);
1193 Value listreceivedbyaccount(const Array& params, bool fHelp)
1195 if (fHelp || params.size() > 2)
1196 throw runtime_error(
1197 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1198 "[minconf] is the minimum number of confirmations before payments are included.\n"
1199 "[includeempty] whether to include accounts that haven't received any payments.\n"
1200 "Returns an array of objects containing:\n"
1201 " \"account\" : the account of the receiving addresses\n"
1202 " \"amount\" : total amount received by addresses with this account\n"
1203 " \"confirmations\" : number of confirmations of the most recent transaction included");
1205 return ListReceived(params, true);
1208 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1210 int64 nGeneratedImmature, nGeneratedMature, nFee;
1211 string strSentAccount;
1212 list<pair<CBitcoinAddress, int64> > listReceived;
1213 list<pair<CBitcoinAddress, int64> > listSent;
1215 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1217 bool fAllAccounts = (strAccount == string("*"));
1219 // Generated blocks assigned to account ""
1220 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1223 entry.push_back(Pair("account", string("")));
1224 if (nGeneratedImmature)
1226 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1227 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1231 entry.push_back(Pair("category", "generate"));
1232 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1235 WalletTxToJSON(wtx, entry);
1236 ret.push_back(entry);
1240 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1242 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1245 entry.push_back(Pair("account", strSentAccount));
1246 entry.push_back(Pair("address", s.first.ToString()));
1247 entry.push_back(Pair("category", "send"));
1248 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1249 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1251 WalletTxToJSON(wtx, entry);
1252 ret.push_back(entry);
1257 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1258 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1261 if (pwalletMain->mapAddressBook.count(r.first))
1262 account = pwalletMain->mapAddressBook[r.first];
1263 if (fAllAccounts || (account == strAccount))
1266 entry.push_back(Pair("account", account));
1267 entry.push_back(Pair("address", r.first.ToString()));
1268 entry.push_back(Pair("category", "receive"));
1269 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1271 WalletTxToJSON(wtx, entry);
1272 ret.push_back(entry);
1277 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1279 bool fAllAccounts = (strAccount == string("*"));
1281 if (fAllAccounts || acentry.strAccount == strAccount)
1284 entry.push_back(Pair("account", acentry.strAccount));
1285 entry.push_back(Pair("category", "move"));
1286 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1287 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1288 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1289 entry.push_back(Pair("comment", acentry.strComment));
1290 ret.push_back(entry);
1294 Value listtransactions(const Array& params, bool fHelp)
1296 if (fHelp || params.size() > 3)
1297 throw runtime_error(
1298 "listtransactions [account] [count=10] [from=0]\n"
1299 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1301 string strAccount = "*";
1302 if (params.size() > 0)
1303 strAccount = params[0].get_str();
1305 if (params.size() > 1)
1306 nCount = params[1].get_int();
1308 if (params.size() > 2)
1309 nFrom = params[2].get_int();
1312 CWalletDB walletdb(pwalletMain->strWalletFile);
1314 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1315 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1316 typedef multimap<int64, TxPair > TxItems;
1319 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1321 CWalletTx* wtx = &((*it).second);
1322 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1324 list<CAccountingEntry> acentries;
1325 walletdb.ListAccountCreditDebit(strAccount, acentries);
1326 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1328 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1331 // Now: iterate backwards until we have nCount items to return:
1332 TxItems::reverse_iterator it = txByTime.rbegin();
1333 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1334 for (; it != txByTime.rend(); ++it)
1336 CWalletTx *const pwtx = (*it).second.first;
1338 ListTransactions(*pwtx, strAccount, 0, true, ret);
1339 CAccountingEntry *const pacentry = (*it).second.second;
1341 AcentryToJSON(*pacentry, strAccount, ret);
1343 if (ret.size() >= nCount) break;
1345 // ret is now newest to oldest
1347 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1348 if (ret.size() > nCount)
1350 Array::iterator last = ret.begin();
1351 std::advance(last, nCount);
1352 ret.erase(last, ret.end());
1354 std::reverse(ret.begin(), ret.end()); // oldest to newest
1359 Value listaccounts(const Array& params, bool fHelp)
1361 if (fHelp || params.size() > 1)
1362 throw runtime_error(
1363 "listaccounts [minconf=1]\n"
1364 "Returns Object that has account names as keys, account balances as values.");
1367 if (params.size() > 0)
1368 nMinDepth = params[0].get_int();
1370 map<string, int64> mapAccountBalances;
1371 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1372 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1373 mapAccountBalances[entry.second] = 0;
1376 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1378 const CWalletTx& wtx = (*it).second;
1379 int64 nGeneratedImmature, nGeneratedMature, nFee;
1380 string strSentAccount;
1381 list<pair<CBitcoinAddress, int64> > listReceived;
1382 list<pair<CBitcoinAddress, int64> > listSent;
1383 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1384 mapAccountBalances[strSentAccount] -= nFee;
1385 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1386 mapAccountBalances[strSentAccount] -= s.second;
1387 if (wtx.GetDepthInMainChain() >= nMinDepth)
1389 mapAccountBalances[""] += nGeneratedMature;
1390 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1391 if (pwalletMain->mapAddressBook.count(r.first))
1392 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1394 mapAccountBalances[""] += r.second;
1398 list<CAccountingEntry> acentries;
1399 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1400 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1401 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1404 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1405 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1410 Value listsinceblock(const Array& params, bool fHelp)
1413 throw runtime_error(
1414 "listsinceblock [blockid] [target-confirmations]\n"
1415 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1417 CBlockIndex *pindex = NULL;
1418 int target_confirms = 1;
1420 if (params.size() > 0)
1422 uint256 blockId = 0;
1424 blockId.SetHex(params[0].get_str());
1425 pindex = CBlockLocator(blockId).GetBlockIndex();
1428 if (params.size() > 1)
1430 target_confirms = params[1].get_int();
1432 if (target_confirms < 1)
1433 throw JSONRPCError(-8, "Invalid parameter");
1436 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1440 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1442 CWalletTx tx = (*it).second;
1444 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1445 ListTransactions(tx, "*", 0, true, transactions);
1450 if (target_confirms == 1)
1453 lastblock = hashBestChain;
1457 int target_height = pindexBest->nHeight + 1 - target_confirms;
1460 for (block = pindexBest;
1461 block && block->nHeight > target_height;
1462 block = block->pprev) { }
1464 lastblock = block ? block->GetBlockHash() : 0;
1468 ret.push_back(Pair("transactions", transactions));
1469 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1474 Value gettransaction(const Array& params, bool fHelp)
1476 if (fHelp || params.size() != 1)
1477 throw runtime_error(
1478 "gettransaction <txid>\n"
1479 "Get detailed information about <txid>");
1482 hash.SetHex(params[0].get_str());
1486 if (!pwalletMain->mapWallet.count(hash))
1487 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1488 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1490 int64 nCredit = wtx.GetCredit();
1491 int64 nDebit = wtx.GetDebit();
1492 int64 nNet = nCredit - nDebit;
1493 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1495 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1497 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1499 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1502 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1503 entry.push_back(Pair("details", details));
1509 Value backupwallet(const Array& params, bool fHelp)
1511 if (fHelp || params.size() != 1)
1512 throw runtime_error(
1513 "backupwallet <destination>\n"
1514 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1516 string strDest = params[0].get_str();
1517 BackupWallet(*pwalletMain, strDest);
1523 Value keypoolrefill(const Array& params, bool fHelp)
1525 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1526 throw runtime_error(
1528 "Fills the keypool, requires wallet passphrase to be set.");
1529 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1530 throw runtime_error(
1532 "Fills the keypool.");
1534 if (pwalletMain->IsLocked())
1535 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1537 pwalletMain->TopUpKeyPool();
1539 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1540 throw JSONRPCError(-4, "Error refreshing keypool.");
1546 void ThreadTopUpKeyPool(void* parg)
1548 pwalletMain->TopUpKeyPool();
1551 void ThreadCleanWalletPassphrase(void* parg)
1553 int64 nMyWakeTime = GetTimeMillis() + *((int*)parg) * 1000;
1555 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1557 if (nWalletUnlockTime == 0)
1559 nWalletUnlockTime = nMyWakeTime;
1563 if (nWalletUnlockTime==0)
1565 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1569 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1571 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1575 if (nWalletUnlockTime)
1577 nWalletUnlockTime = 0;
1578 pwalletMain->Lock();
1583 if (nWalletUnlockTime < nMyWakeTime)
1584 nWalletUnlockTime = nMyWakeTime;
1587 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1592 Value walletpassphrase(const Array& params, bool fHelp)
1594 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1595 throw runtime_error(
1596 "walletpassphrase <passphrase> <timeout>\n"
1597 "Stores the wallet decryption key in memory for <timeout> seconds.");
1600 if (!pwalletMain->IsCrypted())
1601 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1603 if (!pwalletMain->IsLocked())
1604 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1606 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1607 SecureString strWalletPass;
1608 strWalletPass.reserve(100);
1609 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1610 // Alternately, find a way to make params[0] mlock()'d to begin with.
1611 strWalletPass = params[0].get_str().c_str();
1613 if (strWalletPass.length() > 0)
1615 if (!pwalletMain->Unlock(strWalletPass))
1616 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1619 throw runtime_error(
1620 "walletpassphrase <passphrase> <timeout>\n"
1621 "Stores the wallet decryption key in memory for <timeout> seconds.");
1623 CreateThread(ThreadTopUpKeyPool, NULL);
1624 int* pnSleepTime = new int(params[1].get_int());
1625 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1631 Value walletpassphrasechange(const Array& params, bool fHelp)
1633 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1634 throw runtime_error(
1635 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1636 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1639 if (!pwalletMain->IsCrypted())
1640 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1642 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1643 // Alternately, find a way to make params[0] mlock()'d to begin with.
1644 SecureString strOldWalletPass;
1645 strOldWalletPass.reserve(100);
1646 strOldWalletPass = params[0].get_str().c_str();
1648 SecureString strNewWalletPass;
1649 strNewWalletPass.reserve(100);
1650 strNewWalletPass = params[1].get_str().c_str();
1652 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1653 throw runtime_error(
1654 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1655 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1657 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1658 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1664 Value walletlock(const Array& params, bool fHelp)
1666 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1667 throw runtime_error(
1669 "Removes the wallet encryption key from memory, locking the wallet.\n"
1670 "After calling this method, you will need to call walletpassphrase again\n"
1671 "before being able to call any methods which require the wallet to be unlocked.");
1674 if (!pwalletMain->IsCrypted())
1675 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1677 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1679 pwalletMain->Lock();
1680 nWalletUnlockTime = 0;
1687 Value encryptwallet(const Array& params, bool fHelp)
1689 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1690 throw runtime_error(
1691 "encryptwallet <passphrase>\n"
1692 "Encrypts the wallet with <passphrase>.");
1695 if (pwalletMain->IsCrypted())
1696 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1699 // shutting down via RPC while the GUI is running does not work (yet):
1700 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1703 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1704 // Alternately, find a way to make params[0] mlock()'d to begin with.
1705 SecureString strWalletPass;
1706 strWalletPass.reserve(100);
1707 strWalletPass = params[0].get_str().c_str();
1709 if (strWalletPass.length() < 1)
1710 throw runtime_error(
1711 "encryptwallet <passphrase>\n"
1712 "Encrypts the wallet with <passphrase>.");
1714 if (!pwalletMain->EncryptWallet(strWalletPass))
1715 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1717 // BDB seems to have a bad habit of writing old data into
1718 // slack space in .dat files; that is bad if the old data is
1719 // unencrypted private keys. So:
1720 CreateThread(Shutdown, NULL);
1721 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1725 Value validateaddress(const Array& params, bool fHelp)
1727 if (fHelp || params.size() != 1)
1728 throw runtime_error(
1729 "validateaddress <bitcoinaddress>\n"
1730 "Return information about <bitcoinaddress>.");
1732 CBitcoinAddress address(params[0].get_str());
1733 bool isValid = address.IsValid();
1736 ret.push_back(Pair("isvalid", isValid));
1739 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1740 // version of the address:
1741 string currentAddress = address.ToString();
1742 ret.push_back(Pair("address", currentAddress));
1743 if (pwalletMain->HaveKey(address))
1745 ret.push_back(Pair("ismine", true));
1746 std::vector<unsigned char> vchPubKey;
1747 pwalletMain->GetPubKey(address, vchPubKey);
1748 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1750 key.SetPubKey(vchPubKey);
1751 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1753 else if (pwalletMain->HaveCScript(address.GetHash160()))
1755 ret.push_back(Pair("isscript", true));
1757 pwalletMain->GetCScript(address.GetHash160(), subscript);
1758 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1759 std::vector<CBitcoinAddress> addresses;
1760 txnouttype whichType;
1762 ExtractAddresses(subscript, whichType, addresses, nRequired);
1763 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1765 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1766 a.push_back(addr.ToString());
1767 ret.push_back(Pair("addresses", a));
1768 if (whichType == TX_MULTISIG)
1769 ret.push_back(Pair("sigsrequired", nRequired));
1772 ret.push_back(Pair("ismine", false));
1773 if (pwalletMain->mapAddressBook.count(address))
1774 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1779 Value getwork(const Array& params, bool fHelp)
1781 if (fHelp || params.size() > 1)
1782 throw runtime_error(
1784 "If [data] is not specified, returns formatted hash data to work on:\n"
1785 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1786 " \"data\" : block data\n"
1787 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1788 " \"target\" : little endian hash target\n"
1789 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1792 throw JSONRPCError(-9, "Bitcoin is not connected!");
1794 if (IsInitialBlockDownload())
1795 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1797 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1798 static mapNewBlock_t mapNewBlock;
1799 static vector<CBlock*> vNewBlock;
1800 static CReserveKey reservekey(pwalletMain);
1802 if (params.size() == 0)
1805 static unsigned int nTransactionsUpdatedLast;
1806 static CBlockIndex* pindexPrev;
1807 static int64 nStart;
1808 static CBlock* pblock;
1809 if (pindexPrev != pindexBest ||
1810 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1812 if (pindexPrev != pindexBest)
1814 // Deallocate old blocks since they're obsolete now
1815 mapNewBlock.clear();
1816 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1820 nTransactionsUpdatedLast = nTransactionsUpdated;
1821 pindexPrev = pindexBest;
1825 pblock = CreateNewBlock(reservekey);
1827 throw JSONRPCError(-7, "Out of memory");
1828 vNewBlock.push_back(pblock);
1832 pblock->UpdateTime(pindexPrev);
1835 // Update nExtraNonce
1836 static unsigned int nExtraNonce = 0;
1837 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1840 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1842 // Prebuild hash buffers
1846 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1848 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1851 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1852 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1853 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1854 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1860 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1861 if (vchData.size() != 128)
1862 throw JSONRPCError(-8, "Invalid parameter");
1863 CBlock* pdata = (CBlock*)&vchData[0];
1866 for (int i = 0; i < 128/4; i++)
1867 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1870 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1872 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1874 pblock->nTime = pdata->nTime;
1875 pblock->nNonce = pdata->nNonce;
1876 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1877 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1879 return CheckWork(pblock, *pwalletMain, reservekey);
1884 Value getmemorypool(const Array& params, bool fHelp)
1886 if (fHelp || params.size() > 1)
1887 throw runtime_error(
1888 "getmemorypool [data]\n"
1889 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1890 " \"version\" : block version\n"
1891 " \"previousblockhash\" : hash of current highest block\n"
1892 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1893 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1894 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1895 " \"time\" : timestamp appropriate for next block\n"
1896 " \"mintime\" : minimum timestamp appropriate for next block\n"
1897 " \"curtime\" : current timestamp\n"
1898 " \"bits\" : compressed target of next block\n"
1899 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1901 if (params.size() == 0)
1904 throw JSONRPCError(-9, "Bitcoin is not connected!");
1906 if (IsInitialBlockDownload())
1907 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1909 static CReserveKey reservekey(pwalletMain);
1912 static unsigned int nTransactionsUpdatedLast;
1913 static CBlockIndex* pindexPrev;
1914 static int64 nStart;
1915 static CBlock* pblock;
1916 if (pindexPrev != pindexBest ||
1917 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1919 nTransactionsUpdatedLast = nTransactionsUpdated;
1920 pindexPrev = pindexBest;
1926 pblock = CreateNewBlock(reservekey);
1928 throw JSONRPCError(-7, "Out of memory");
1932 pblock->UpdateTime(pindexPrev);
1936 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1943 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1947 result.push_back(Pair("version", pblock->nVersion));
1948 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1949 result.push_back(Pair("transactions", transactions));
1950 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1951 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1952 result.push_back(Pair("time", (int64_t)pblock->nTime));
1953 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1954 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1955 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1962 CDataStream ssBlock(ParseHex(params[0].get_str()));
1966 return ProcessBlock(NULL, &pblock);
1970 Value getblockhash(const Array& params, bool fHelp)
1972 if (fHelp || params.size() != 1)
1973 throw runtime_error(
1974 "getblockhash <index>\n"
1975 "Returns hash of block in best-block-chain at <index>.");
1977 int nHeight = params[0].get_int();
1978 if (nHeight < 0 || nHeight > nBestHeight)
1979 throw runtime_error("Block number out of range.");
1982 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1983 while (pblockindex->nHeight > nHeight)
1984 pblockindex = pblockindex->pprev;
1985 return pblockindex->phashBlock->GetHex();
1988 Value getblock(const Array& params, bool fHelp)
1990 if (fHelp || params.size() != 1)
1991 throw runtime_error(
1993 "Returns details of a block with given block-hash.");
1995 std::string strHash = params[0].get_str();
1996 uint256 hash(strHash);
1998 if (mapBlockIndex.count(hash) == 0)
1999 throw JSONRPCError(-5, "Block not found");
2002 CBlockIndex* pblockindex = mapBlockIndex[hash];
2003 block.ReadFromDisk(pblockindex, true);
2005 return blockToJSON(block, pblockindex);
2022 pair<string, rpcfn_type> pCallTable[] =
2024 make_pair("help", &help),
2025 make_pair("stop", &stop),
2026 make_pair("getblockcount", &getblockcount),
2027 make_pair("getblocknumber", &getblocknumber),
2028 make_pair("getconnectioncount", &getconnectioncount),
2029 make_pair("getdifficulty", &getdifficulty),
2030 make_pair("getgenerate", &getgenerate),
2031 make_pair("setgenerate", &setgenerate),
2032 make_pair("gethashespersec", &gethashespersec),
2033 make_pair("getinfo", &getinfo),
2034 make_pair("getmininginfo", &getmininginfo),
2035 make_pair("getnewaddress", &getnewaddress),
2036 make_pair("getaccountaddress", &getaccountaddress),
2037 make_pair("setaccount", &setaccount),
2038 make_pair("getaccount", &getaccount),
2039 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2040 make_pair("sendtoaddress", &sendtoaddress),
2041 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2042 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2043 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2044 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2045 make_pair("backupwallet", &backupwallet),
2046 make_pair("keypoolrefill", &keypoolrefill),
2047 make_pair("walletpassphrase", &walletpassphrase),
2048 make_pair("walletpassphrasechange", &walletpassphrasechange),
2049 make_pair("walletlock", &walletlock),
2050 make_pair("encryptwallet", &encryptwallet),
2051 make_pair("validateaddress", &validateaddress),
2052 make_pair("getbalance", &getbalance),
2053 make_pair("move", &movecmd),
2054 make_pair("sendfrom", &sendfrom),
2055 make_pair("sendmany", &sendmany),
2056 make_pair("addmultisigaddress", &addmultisigaddress),
2057 make_pair("getblock", &getblock),
2058 make_pair("getblockhash", &getblockhash),
2059 make_pair("gettransaction", &gettransaction),
2060 make_pair("listtransactions", &listtransactions),
2061 make_pair("signmessage", &signmessage),
2062 make_pair("verifymessage", &verifymessage),
2063 make_pair("getwork", &getwork),
2064 make_pair("listaccounts", &listaccounts),
2065 make_pair("settxfee", &settxfee),
2066 make_pair("getmemorypool", &getmemorypool),
2067 make_pair("listsinceblock", &listsinceblock),
2068 make_pair("dumpprivkey", &dumpprivkey),
2069 make_pair("importprivkey", &importprivkey)
2071 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2073 string pAllowInSafeMode[] =
2078 "getblocknumber", // deprecated
2079 "getconnectioncount",
2087 "getaccountaddress",
2089 "getaddressesbyaccount",
2098 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2106 // This ain't Apache. We're just using HTTP header for the length field
2107 // and to be compatible with other JSON-RPC implementations.
2110 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2113 s << "POST / HTTP/1.1\r\n"
2114 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2115 << "Host: 127.0.0.1\r\n"
2116 << "Content-Type: application/json\r\n"
2117 << "Content-Length: " << strMsg.size() << "\r\n"
2118 << "Connection: close\r\n"
2119 << "Accept: application/json\r\n";
2120 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2121 s << item.first << ": " << item.second << "\r\n";
2122 s << "\r\n" << strMsg;
2127 string rfc1123Time()
2132 struct tm* now_gmt = gmtime(&now);
2133 string locale(setlocale(LC_TIME, NULL));
2134 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2135 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2136 setlocale(LC_TIME, locale.c_str());
2137 return string(buffer);
2140 static string HTTPReply(int nStatus, const string& strMsg)
2143 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2145 "Server: bitcoin-json-rpc/%s\r\n"
2146 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2147 "Content-Type: text/html\r\n"
2148 "Content-Length: 296\r\n"
2150 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2151 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2154 "<TITLE>Error</TITLE>\r\n"
2155 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2157 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2158 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2159 const char *cStatus;
2160 if (nStatus == 200) cStatus = "OK";
2161 else if (nStatus == 400) cStatus = "Bad Request";
2162 else if (nStatus == 403) cStatus = "Forbidden";
2163 else if (nStatus == 404) cStatus = "Not Found";
2164 else if (nStatus == 500) cStatus = "Internal Server Error";
2167 "HTTP/1.1 %d %s\r\n"
2169 "Connection: close\r\n"
2170 "Content-Length: %d\r\n"
2171 "Content-Type: application/json\r\n"
2172 "Server: bitcoin-json-rpc/%s\r\n"
2177 rfc1123Time().c_str(),
2179 FormatFullVersion().c_str(),
2183 int ReadHTTPStatus(std::basic_istream<char>& stream)
2186 getline(stream, str);
2187 vector<string> vWords;
2188 boost::split(vWords, str, boost::is_any_of(" "));
2189 if (vWords.size() < 2)
2191 return atoi(vWords[1].c_str());
2194 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2200 std::getline(stream, str);
2201 if (str.empty() || str == "\r")
2203 string::size_type nColon = str.find(":");
2204 if (nColon != string::npos)
2206 string strHeader = str.substr(0, nColon);
2207 boost::trim(strHeader);
2208 boost::to_lower(strHeader);
2209 string strValue = str.substr(nColon+1);
2210 boost::trim(strValue);
2211 mapHeadersRet[strHeader] = strValue;
2212 if (strHeader == "content-length")
2213 nLen = atoi(strValue.c_str());
2219 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2221 mapHeadersRet.clear();
2225 int nStatus = ReadHTTPStatus(stream);
2228 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2229 if (nLen < 0 || nLen > MAX_SIZE)
2235 vector<char> vch(nLen);
2236 stream.read(&vch[0], nLen);
2237 strMessageRet = string(vch.begin(), vch.end());
2243 bool HTTPAuthorized(map<string, string>& mapHeaders)
2245 string strAuth = mapHeaders["authorization"];
2246 if (strAuth.substr(0,6) != "Basic ")
2248 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2249 string strUserPass = DecodeBase64(strUserPass64);
2250 return strUserPass == strRPCUserColonPass;
2254 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2255 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2256 // unspecified (HTTP errors and contents of 'error').
2258 // 1.0 spec: http://json-rpc.org/wiki/specification
2259 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2260 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2263 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2266 request.push_back(Pair("method", strMethod));
2267 request.push_back(Pair("params", params));
2268 request.push_back(Pair("id", id));
2269 return write_string(Value(request), false) + "\n";
2272 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2275 if (error.type() != null_type)
2276 reply.push_back(Pair("result", Value::null));
2278 reply.push_back(Pair("result", result));
2279 reply.push_back(Pair("error", error));
2280 reply.push_back(Pair("id", id));
2281 return write_string(Value(reply), false) + "\n";
2284 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2286 // Send error reply from json-rpc error object
2288 int code = find_value(objError, "code").get_int();
2289 if (code == -32600) nStatus = 400;
2290 else if (code == -32601) nStatus = 404;
2291 string strReply = JSONRPCReply(Value::null, objError, id);
2292 stream << HTTPReply(nStatus, strReply) << std::flush;
2295 bool ClientAllowed(const string& strAddress)
2297 if (strAddress == asio::ip::address_v4::loopback().to_string())
2299 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2300 BOOST_FOREACH(string strAllow, vAllow)
2301 if (WildcardMatch(strAddress, strAllow))
2308 // IOStream device that speaks SSL but can also speak non-SSL
2310 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2312 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2314 fUseSSL = fUseSSLIn;
2315 fNeedHandshake = fUseSSLIn;
2318 void handshake(ssl::stream_base::handshake_type role)
2320 if (!fNeedHandshake) return;
2321 fNeedHandshake = false;
2322 stream.handshake(role);
2324 std::streamsize read(char* s, std::streamsize n)
2326 handshake(ssl::stream_base::server); // HTTPS servers read first
2327 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2328 return stream.next_layer().read_some(asio::buffer(s, n));
2330 std::streamsize write(const char* s, std::streamsize n)
2332 handshake(ssl::stream_base::client); // HTTPS clients write first
2333 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2334 return asio::write(stream.next_layer(), asio::buffer(s, n));
2336 bool connect(const std::string& server, const std::string& port)
2338 ip::tcp::resolver resolver(stream.get_io_service());
2339 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2340 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2341 ip::tcp::resolver::iterator end;
2342 boost::system::error_code error = asio::error::host_not_found;
2343 while (error && endpoint_iterator != end)
2345 stream.lowest_layer().close();
2346 stream.lowest_layer().connect(*endpoint_iterator++, error);
2354 bool fNeedHandshake;
2360 void ThreadRPCServer(void* parg)
2362 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2365 vnThreadsRunning[THREAD_RPCSERVER]++;
2366 ThreadRPCServer2(parg);
2367 vnThreadsRunning[THREAD_RPCSERVER]--;
2369 catch (std::exception& e) {
2370 vnThreadsRunning[THREAD_RPCSERVER]--;
2371 PrintException(&e, "ThreadRPCServer()");
2373 vnThreadsRunning[THREAD_RPCSERVER]--;
2374 PrintException(NULL, "ThreadRPCServer()");
2376 printf("ThreadRPCServer exiting\n");
2379 void ThreadRPCServer2(void* parg)
2381 printf("ThreadRPCServer started\n");
2383 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2384 if (mapArgs["-rpcpassword"] == "")
2386 unsigned char rand_pwd[32];
2387 RAND_bytes(rand_pwd, 32);
2388 string strWhatAmI = "To use bitcoind";
2389 if (mapArgs.count("-server"))
2390 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2391 else if (mapArgs.count("-daemon"))
2392 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2394 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2395 "It is recommended you use the following random password:\n"
2396 "rpcuser=bitcoinrpc\n"
2398 "(you do not need to remember this password)\n"
2399 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2401 GetConfigFile().c_str(),
2402 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2404 CreateThread(Shutdown, NULL);
2409 bool fUseSSL = GetBoolArg("-rpcssl");
2410 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2412 asio::io_service io_service;
2413 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2414 ip::tcp::acceptor acceptor(io_service, endpoint);
2416 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2419 ssl::context context(io_service, ssl::context::sslv23);
2422 context.set_options(ssl::context::no_sslv2);
2423 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2424 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2425 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2426 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2427 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2428 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2429 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2430 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2432 string ciphers = GetArg("-rpcsslciphers",
2433 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2434 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2438 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2443 // Accept connection
2445 SSLStream sslStream(io_service, context);
2446 SSLIOStreamDevice d(sslStream, fUseSSL);
2447 iostreams::stream<SSLIOStreamDevice> stream(d);
2449 ip::tcp::iostream stream;
2452 ip::tcp::endpoint peer;
2453 vnThreadsRunning[THREAD_RPCSERVER]--;
2455 acceptor.accept(sslStream.lowest_layer(), peer);
2457 acceptor.accept(*stream.rdbuf(), peer);
2459 vnThreadsRunning[4]++;
2463 // Restrict callers by IP
2464 if (!ClientAllowed(peer.address().to_string()))
2466 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2468 stream << HTTPReply(403, "") << std::flush;
2472 map<string, string> mapHeaders;
2475 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2476 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2479 printf("ThreadRPCServer ReadHTTP timeout\n");
2483 // Check authorization
2484 if (mapHeaders.count("authorization") == 0)
2486 stream << HTTPReply(401, "") << std::flush;
2489 if (!HTTPAuthorized(mapHeaders))
2491 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2492 /* Deter brute-forcing short passwords.
2493 If this results in a DOS the user really
2494 shouldn't have their RPC port exposed.*/
2495 if (mapArgs["-rpcpassword"].size() < 20)
2498 stream << HTTPReply(401, "") << std::flush;
2502 Value id = Value::null;
2507 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2508 throw JSONRPCError(-32700, "Parse error");
2509 const Object& request = valRequest.get_obj();
2511 // Parse id now so errors from here on will have the id
2512 id = find_value(request, "id");
2515 Value valMethod = find_value(request, "method");
2516 if (valMethod.type() == null_type)
2517 throw JSONRPCError(-32600, "Missing method");
2518 if (valMethod.type() != str_type)
2519 throw JSONRPCError(-32600, "Method must be a string");
2520 string strMethod = valMethod.get_str();
2521 if (strMethod != "getwork" && strMethod != "getmemorypool")
2522 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2525 Value valParams = find_value(request, "params");
2527 if (valParams.type() == array_type)
2528 params = valParams.get_array();
2529 else if (valParams.type() == null_type)
2532 throw JSONRPCError(-32600, "Params must be an array");
2535 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2536 if (mi == mapCallTable.end())
2537 throw JSONRPCError(-32601, "Method not found");
2539 // Observe safe mode
2540 string strWarning = GetWarnings("rpc");
2541 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2542 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2548 CRITICAL_BLOCK(cs_main)
2549 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2550 result = (*(*mi).second)(params, false);
2553 string strReply = JSONRPCReply(result, Value::null, id);
2554 stream << HTTPReply(200, strReply) << std::flush;
2556 catch (std::exception& e)
2558 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2561 catch (Object& objError)
2563 ErrorReply(stream, objError, id);
2565 catch (std::exception& e)
2567 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2575 Object CallRPC(const string& strMethod, const Array& params)
2577 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2578 throw runtime_error(strprintf(
2579 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2580 "If the file does not exist, create it with owner-readable-only file permissions."),
2581 GetConfigFile().c_str()));
2583 // Connect to localhost
2584 bool fUseSSL = GetBoolArg("-rpcssl");
2586 asio::io_service io_service;
2587 ssl::context context(io_service, ssl::context::sslv23);
2588 context.set_options(ssl::context::no_sslv2);
2589 SSLStream sslStream(io_service, context);
2590 SSLIOStreamDevice d(sslStream, fUseSSL);
2591 iostreams::stream<SSLIOStreamDevice> stream(d);
2592 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2593 throw runtime_error("couldn't connect to server");
2596 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2598 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2600 throw runtime_error("couldn't connect to server");
2604 // HTTP basic authentication
2605 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2606 map<string, string> mapRequestHeaders;
2607 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2610 string strRequest = JSONRPCRequest(strMethod, params, 1);
2611 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2612 stream << strPost << std::flush;
2615 map<string, string> mapHeaders;
2617 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2619 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2620 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2621 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2622 else if (strReply.empty())
2623 throw runtime_error("no response from server");
2627 if (!read_string(strReply, valReply))
2628 throw runtime_error("couldn't parse reply from server");
2629 const Object& reply = valReply.get_obj();
2631 throw runtime_error("expected reply to have result, error and id properties");
2639 template<typename T>
2640 void ConvertTo(Value& value)
2642 if (value.type() == str_type)
2644 // reinterpret string as unquoted json value
2646 if (!read_string(value.get_str(), value2))
2647 throw runtime_error("type mismatch");
2648 value = value2.get_value<T>();
2652 value = value.get_value<T>();
2656 int CommandLineRPC(int argc, char *argv[])
2663 while (argc > 1 && IsSwitchChar(argv[1][0]))
2671 throw runtime_error("too few parameters");
2672 string strMethod = argv[1];
2674 // Parameters default to strings
2676 for (int i = 2; i < argc; i++)
2677 params.push_back(argv[i]);
2678 int n = params.size();
2681 // Special case non-string parameter types
2683 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2684 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2685 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2686 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2687 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2688 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2689 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2690 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2691 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2692 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2693 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2694 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2695 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2696 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2697 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2698 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2699 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2700 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2701 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2702 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2703 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2704 if (strMethod == "sendmany" && n > 1)
2706 string s = params[1].get_str();
2708 if (!read_string(s, v) || v.type() != obj_type)
2709 throw runtime_error("type mismatch");
2710 params[1] = v.get_obj();
2712 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2713 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2714 if (strMethod == "addmultisigaddress" && n > 1)
2716 string s = params[1].get_str();
2718 if (!read_string(s, v) || v.type() != array_type)
2719 throw runtime_error("type mismatch "+s);
2720 params[1] = v.get_array();
2724 Object reply = CallRPC(strMethod, params);
2727 const Value& result = find_value(reply, "result");
2728 const Value& error = find_value(reply, "error");
2730 if (error.type() != null_type)
2733 strPrint = "error: " + write_string(error, false);
2734 int code = find_value(error.get_obj(), "code").get_int();
2740 if (result.type() == null_type)
2742 else if (result.type() == str_type)
2743 strPrint = result.get_str();
2745 strPrint = write_string(result, true);
2748 catch (std::exception& e)
2750 strPrint = string("error: ") + e.what();
2755 PrintException(NULL, "CommandLineRPC()");
2760 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2769 int main(int argc, char *argv[])
2772 // Turn off microsoft heap dump noise
2773 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2774 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2776 setbuf(stdin, NULL);
2777 setbuf(stdout, NULL);
2778 setbuf(stderr, NULL);
2782 if (argc >= 2 && string(argv[1]) == "-server")
2784 printf("server ready\n");
2785 ThreadRPCServer(NULL);
2789 return CommandLineRPC(argc, argv);
2792 catch (std::exception& e) {
2793 PrintException(&e, "main()");
2795 PrintException(NULL, "main()");