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));
57 double GetDifficulty(const CBlockIndex* blockindex = NULL)
59 // Floating point number that is a multiple of the minimum difficulty,
60 // minimum difficulty = 1.0.
61 if (blockindex == NULL)
63 if (pindexBest == NULL)
66 blockindex = pindexBest;
69 int nShift = (blockindex->nBits >> 24) & 0xff;
72 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
89 int64 AmountFromValue(const Value& value)
91 double dAmount = value.get_real();
92 if (dAmount <= 0.0 || dAmount > 21000000.0)
93 throw JSONRPCError(-3, "Invalid amount");
94 int64 nAmount = roundint64(dAmount * COIN);
95 if (!MoneyRange(nAmount))
96 throw JSONRPCError(-3, "Invalid amount");
100 Value ValueFromAmount(int64 amount)
102 return (double)amount / (double)COIN;
106 HexBits(unsigned int nBits)
112 uBits.nBits = htonl((int32_t)nBits);
113 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
116 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
118 int confirms = wtx.GetDepthInMainChain();
119 entry.push_back(Pair("confirmations", confirms));
122 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
123 entry.push_back(Pair("blockindex", wtx.nIndex));
125 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
126 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
127 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
128 entry.push_back(Pair(item.first, item.second));
131 string AccountFromValue(const Value& value)
133 string strAccount = value.get_str();
134 if (strAccount == "*")
135 throw JSONRPCError(-11, "Invalid account name");
139 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
142 result.push_back(Pair("hash", block.GetHash().GetHex()));
143 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
144 result.push_back(Pair("height", blockindex->nHeight));
145 result.push_back(Pair("version", block.nVersion));
146 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
147 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
148 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
149 result.push_back(Pair("bits", HexBits(block.nBits)));
150 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
152 BOOST_FOREACH (const CTransaction&tx, block.vtx)
153 txhashes.push_back(tx.GetHash().GetHex());
154 result.push_back(Pair("tx", txhashes));
156 if (blockindex->pprev)
157 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
158 if (blockindex->pnext)
159 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
166 /// Note: This interface may still be subject to change.
170 Value help(const Array& params, bool fHelp)
172 if (fHelp || params.size() > 1)
175 "List commands, or get help for a command.");
178 if (params.size() > 0)
179 strCommand = params[0].get_str();
182 set<rpcfn_type> setDone;
183 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
185 string strMethod = (*mi).first;
186 // We already filter duplicates, but these deprecated screw up the sort order
187 if (strMethod == "getamountreceived" ||
188 strMethod == "getallreceived" ||
189 strMethod == "getblocknumber" || // deprecated
190 (strMethod.find("label") != string::npos))
192 if (strCommand != "" && strMethod != strCommand)
197 rpcfn_type pfn = (*mi).second;
198 if (setDone.insert(pfn).second)
199 (*pfn)(params, true);
201 catch (std::exception& e)
203 // Help text is returned in an exception
204 string strHelp = string(e.what());
205 if (strCommand == "")
206 if (strHelp.find('\n') != -1)
207 strHelp = strHelp.substr(0, strHelp.find('\n'));
208 strRet += strHelp + "\n";
212 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
213 strRet = strRet.substr(0,strRet.size()-1);
218 Value stop(const Array& params, bool fHelp)
220 if (fHelp || params.size() != 0)
223 "Stop bitcoin server.");
225 // Shutdown will take long enough that the response should get back
226 CreateThread(Shutdown, NULL);
227 return "bitcoin server stopping";
229 throw runtime_error("NYI: cannot shut down GUI with RPC command");
234 Value getblockcount(const Array& params, bool fHelp)
236 if (fHelp || params.size() != 0)
239 "Returns the number of blocks in the longest block chain.");
246 Value getblocknumber(const Array& params, bool fHelp)
248 if (fHelp || params.size() != 0)
251 "Deprecated. Use getblockcount.");
257 Value getconnectioncount(const Array& params, bool fHelp)
259 if (fHelp || params.size() != 0)
261 "getconnectioncount\n"
262 "Returns the number of connections to other nodes.");
264 return (int)vNodes.size();
268 Value getdifficulty(const Array& params, bool fHelp)
270 if (fHelp || params.size() != 0)
273 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
275 return GetDifficulty();
279 Value getgenerate(const Array& params, bool fHelp)
281 if (fHelp || params.size() != 0)
284 "Returns true or false.");
286 return GetBoolArg("-gen");
290 Value setgenerate(const Array& params, bool fHelp)
292 if (fHelp || params.size() < 1 || params.size() > 2)
294 "setgenerate <generate> [genproclimit]\n"
295 "<generate> is true or false to turn generation on or off.\n"
296 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
298 bool fGenerate = true;
299 if (params.size() > 0)
300 fGenerate = params[0].get_bool();
302 if (params.size() > 1)
304 int nGenProcLimit = params[1].get_int();
305 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
306 if (nGenProcLimit == 0)
309 mapArgs["-gen"] = (fGenerate ? "1" : "0");
311 GenerateBitcoins(fGenerate, pwalletMain);
316 Value gethashespersec(const Array& params, bool fHelp)
318 if (fHelp || params.size() != 0)
321 "Returns a recent hashes per second performance measurement while generating.");
323 if (GetTimeMillis() - nHPSTimerStart > 8000)
324 return (boost::int64_t)0;
325 return (boost::int64_t)dHashesPerSec;
329 Value getinfo(const Array& params, bool fHelp)
331 if (fHelp || params.size() != 0)
334 "Returns an object containing various state info.");
337 obj.push_back(Pair("version", (int)CLIENT_VERSION));
338 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
339 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
340 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
341 obj.push_back(Pair("blocks", (int)nBestHeight));
342 obj.push_back(Pair("connections", (int)vNodes.size()));
343 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
344 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
345 obj.push_back(Pair("testnet", fTestNet));
346 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
347 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
348 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
349 if (pwalletMain->IsCrypted())
350 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
351 obj.push_back(Pair("errors", GetWarnings("statusbar")));
356 Value getmininginfo(const Array& params, bool fHelp)
358 if (fHelp || params.size() != 0)
361 "Returns an object containing mining-related information.");
364 obj.push_back(Pair("blocks", (int)nBestHeight));
365 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
366 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
367 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
368 obj.push_back(Pair("errors", GetWarnings("statusbar")));
369 obj.push_back(Pair("generate", GetBoolArg("-gen")));
370 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
371 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
372 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
373 obj.push_back(Pair("testnet", fTestNet));
378 Value getnewaddress(const Array& params, bool fHelp)
380 if (fHelp || params.size() > 1)
382 "getnewaddress [account]\n"
383 "Returns a new bitcoin address for receiving payments. "
384 "If [account] is specified (recommended), it is added to the address book "
385 "so payments received with the address will be credited to [account].");
387 // Parse the account first so we don't generate a key if there's an error
389 if (params.size() > 0)
390 strAccount = AccountFromValue(params[0]);
392 if (!pwalletMain->IsLocked())
393 pwalletMain->TopUpKeyPool();
395 // Generate a new key that is added to wallet
396 std::vector<unsigned char> newKey;
397 if (!pwalletMain->GetKeyFromPool(newKey, false))
398 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
399 CBitcoinAddress address(newKey);
401 pwalletMain->SetAddressBookName(address, strAccount);
403 return address.ToString();
407 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
409 CWalletDB walletdb(pwalletMain->strWalletFile);
412 walletdb.ReadAccount(strAccount, account);
414 bool bKeyUsed = false;
416 // Check if the current key has been used
417 if (!account.vchPubKey.empty())
419 CScript scriptPubKey;
420 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
421 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
422 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
425 const CWalletTx& wtx = (*it).second;
426 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
427 if (txout.scriptPubKey == scriptPubKey)
432 // Generate a new key
433 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
435 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
436 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
438 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
439 walletdb.WriteAccount(strAccount, account);
442 return CBitcoinAddress(account.vchPubKey);
445 Value getaccountaddress(const Array& params, bool fHelp)
447 if (fHelp || params.size() != 1)
449 "getaccountaddress <account>\n"
450 "Returns the current bitcoin address for receiving payments to this account.");
452 // Parse the account first so we don't generate a key if there's an error
453 string strAccount = AccountFromValue(params[0]);
457 ret = GetAccountAddress(strAccount).ToString();
464 Value setaccount(const Array& params, bool fHelp)
466 if (fHelp || params.size() < 1 || params.size() > 2)
468 "setaccount <bitcoinaddress> <account>\n"
469 "Sets the account associated with the given address.");
471 CBitcoinAddress address(params[0].get_str());
472 if (!address.IsValid())
473 throw JSONRPCError(-5, "Invalid bitcoin address");
477 if (params.size() > 1)
478 strAccount = AccountFromValue(params[1]);
480 // Detect when changing the account of an address that is the 'unused current key' of another account:
481 if (pwalletMain->mapAddressBook.count(address))
483 string strOldAccount = pwalletMain->mapAddressBook[address];
484 if (address == GetAccountAddress(strOldAccount))
485 GetAccountAddress(strOldAccount, true);
488 pwalletMain->SetAddressBookName(address, strAccount);
494 Value getaccount(const Array& params, bool fHelp)
496 if (fHelp || params.size() != 1)
498 "getaccount <bitcoinaddress>\n"
499 "Returns the account associated with the given address.");
501 CBitcoinAddress address(params[0].get_str());
502 if (!address.IsValid())
503 throw JSONRPCError(-5, "Invalid bitcoin address");
506 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
507 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
508 strAccount = (*mi).second;
513 Value getaddressesbyaccount(const Array& params, bool fHelp)
515 if (fHelp || params.size() != 1)
517 "getaddressesbyaccount <account>\n"
518 "Returns the list of addresses for the given account.");
520 string strAccount = AccountFromValue(params[0]);
522 // Find all addresses that have the given account
524 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
526 const CBitcoinAddress& address = item.first;
527 const string& strName = item.second;
528 if (strName == strAccount)
529 ret.push_back(address.ToString());
534 Value settxfee(const Array& params, bool fHelp)
536 if (fHelp || params.size() < 1 || params.size() > 1)
538 "settxfee <amount>\n"
539 "<amount> is a real and is rounded to the nearest 0.00000001");
543 if (params[0].get_real() != 0.0)
544 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
546 nTransactionFee = nAmount;
550 Value sendtoaddress(const Array& params, bool fHelp)
552 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
554 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
555 "<amount> is a real and is rounded to the nearest 0.00000001\n"
556 "requires wallet passphrase to be set with walletpassphrase first");
557 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
559 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
560 "<amount> is a real and is rounded to the nearest 0.00000001");
562 CBitcoinAddress address(params[0].get_str());
563 if (!address.IsValid())
564 throw JSONRPCError(-5, "Invalid bitcoin address");
567 int64 nAmount = AmountFromValue(params[1]);
571 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
572 wtx.mapValue["comment"] = params[2].get_str();
573 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
574 wtx.mapValue["to"] = params[3].get_str();
576 if (pwalletMain->IsLocked())
577 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
579 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
581 throw JSONRPCError(-4, strError);
583 return wtx.GetHash().GetHex();
586 Value signmessage(const Array& params, bool fHelp)
588 if (fHelp || params.size() != 2)
590 "signmessage <bitcoinaddress> <message>\n"
591 "Sign a message with the private key of an address");
593 if (pwalletMain->IsLocked())
594 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
596 string strAddress = params[0].get_str();
597 string strMessage = params[1].get_str();
599 CBitcoinAddress addr(strAddress);
601 throw JSONRPCError(-3, "Invalid address");
604 if (!pwalletMain->GetKey(addr, key))
605 throw JSONRPCError(-4, "Private key not available");
607 CDataStream ss(SER_GETHASH);
608 ss << strMessageMagic;
611 vector<unsigned char> vchSig;
612 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
613 throw JSONRPCError(-5, "Sign failed");
615 return EncodeBase64(&vchSig[0], vchSig.size());
618 Value verifymessage(const Array& params, bool fHelp)
620 if (fHelp || params.size() != 3)
622 "verifymessage <bitcoinaddress> <signature> <message>\n"
623 "Verify a signed message");
625 string strAddress = params[0].get_str();
626 string strSign = params[1].get_str();
627 string strMessage = params[2].get_str();
629 CBitcoinAddress addr(strAddress);
631 throw JSONRPCError(-3, "Invalid address");
633 bool fInvalid = false;
634 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
637 throw JSONRPCError(-5, "Malformed base64 encoding");
639 CDataStream ss(SER_GETHASH);
640 ss << strMessageMagic;
644 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
647 return (CBitcoinAddress(key.GetPubKey()) == addr);
651 Value getreceivedbyaddress(const Array& params, bool fHelp)
653 if (fHelp || params.size() < 1 || params.size() > 2)
655 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
656 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
659 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
660 CScript scriptPubKey;
661 if (!address.IsValid())
662 throw JSONRPCError(-5, "Invalid bitcoin address");
663 scriptPubKey.SetBitcoinAddress(address);
664 if (!IsMine(*pwalletMain,scriptPubKey))
667 // Minimum confirmations
669 if (params.size() > 1)
670 nMinDepth = params[1].get_int();
674 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
676 const CWalletTx& wtx = (*it).second;
677 if (wtx.IsCoinBase() || !wtx.IsFinal())
680 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
681 if (txout.scriptPubKey == scriptPubKey)
682 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 nAmount += txout.nValue;
686 return ValueFromAmount(nAmount);
690 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
692 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
694 const CBitcoinAddress& address = item.first;
695 const string& strName = item.second;
696 if (strName == strAccount)
697 setAddress.insert(address);
702 Value getreceivedbyaccount(const Array& params, bool fHelp)
704 if (fHelp || params.size() < 1 || params.size() > 2)
706 "getreceivedbyaccount <account> [minconf=1]\n"
707 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
709 // Minimum confirmations
711 if (params.size() > 1)
712 nMinDepth = params[1].get_int();
714 // Get the set of pub keys assigned to account
715 string strAccount = AccountFromValue(params[0]);
716 set<CBitcoinAddress> setAddress;
717 GetAccountAddresses(strAccount, setAddress);
721 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
723 const CWalletTx& wtx = (*it).second;
724 if (wtx.IsCoinBase() || !wtx.IsFinal())
727 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
729 CBitcoinAddress address;
730 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
731 if (wtx.GetDepthInMainChain() >= nMinDepth)
732 nAmount += txout.nValue;
736 return (double)nAmount / (double)COIN;
740 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
744 // Tally wallet transactions
745 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
747 const CWalletTx& wtx = (*it).second;
751 int64 nGenerated, nReceived, nSent, nFee;
752 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
754 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
755 nBalance += nReceived;
756 nBalance += nGenerated - nSent - nFee;
759 // Tally internal accounting entries
760 nBalance += walletdb.GetAccountCreditDebit(strAccount);
765 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
767 CWalletDB walletdb(pwalletMain->strWalletFile);
768 return GetAccountBalance(walletdb, strAccount, nMinDepth);
772 Value getbalance(const Array& params, bool fHelp)
774 if (fHelp || params.size() > 2)
776 "getbalance [account] [minconf=1]\n"
777 "If [account] is not specified, returns the server's total available balance.\n"
778 "If [account] is specified, returns the balance in the account.");
780 if (params.size() == 0)
781 return ValueFromAmount(pwalletMain->GetBalance());
784 if (params.size() > 1)
785 nMinDepth = params[1].get_int();
787 if (params[0].get_str() == "*") {
788 // Calculate total balance a different way from GetBalance()
789 // (GetBalance() sums up all unspent TxOuts)
790 // getbalance and getbalance '*' should always return the same number.
792 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
794 const CWalletTx& wtx = (*it).second;
798 int64 allGeneratedImmature, allGeneratedMature, allFee;
799 allGeneratedImmature = allGeneratedMature = allFee = 0;
800 string strSentAccount;
801 list<pair<CBitcoinAddress, int64> > listReceived;
802 list<pair<CBitcoinAddress, int64> > listSent;
803 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
804 if (wtx.GetDepthInMainChain() >= nMinDepth)
806 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
807 nBalance += r.second;
809 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
810 nBalance -= r.second;
812 nBalance += allGeneratedMature;
814 return ValueFromAmount(nBalance);
817 string strAccount = AccountFromValue(params[0]);
819 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
821 return ValueFromAmount(nBalance);
825 Value movecmd(const Array& params, bool fHelp)
827 if (fHelp || params.size() < 3 || params.size() > 5)
829 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
830 "Move from one account in your wallet to another.");
832 string strFrom = AccountFromValue(params[0]);
833 string strTo = AccountFromValue(params[1]);
834 int64 nAmount = AmountFromValue(params[2]);
835 if (params.size() > 3)
836 // unused parameter, used to be nMinDepth, keep type-checking it though
837 (void)params[3].get_int();
839 if (params.size() > 4)
840 strComment = params[4].get_str();
842 CWalletDB walletdb(pwalletMain->strWalletFile);
845 int64 nNow = GetAdjustedTime();
848 CAccountingEntry debit;
849 debit.strAccount = strFrom;
850 debit.nCreditDebit = -nAmount;
852 debit.strOtherAccount = strTo;
853 debit.strComment = strComment;
854 walletdb.WriteAccountingEntry(debit);
857 CAccountingEntry credit;
858 credit.strAccount = strTo;
859 credit.nCreditDebit = nAmount;
861 credit.strOtherAccount = strFrom;
862 credit.strComment = strComment;
863 walletdb.WriteAccountingEntry(credit);
865 walletdb.TxnCommit();
871 Value sendfrom(const Array& params, bool fHelp)
873 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
875 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
876 "<amount> is a real and is rounded to the nearest 0.00000001\n"
877 "requires wallet passphrase to be set with walletpassphrase first");
878 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
880 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
881 "<amount> is a real and is rounded to the nearest 0.00000001");
883 string strAccount = AccountFromValue(params[0]);
884 CBitcoinAddress address(params[1].get_str());
885 if (!address.IsValid())
886 throw JSONRPCError(-5, "Invalid bitcoin address");
887 int64 nAmount = AmountFromValue(params[2]);
889 if (params.size() > 3)
890 nMinDepth = params[3].get_int();
893 wtx.strFromAccount = strAccount;
894 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
895 wtx.mapValue["comment"] = params[4].get_str();
896 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
897 wtx.mapValue["to"] = params[5].get_str();
899 if (pwalletMain->IsLocked())
900 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
903 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
904 if (nAmount > nBalance)
905 throw JSONRPCError(-6, "Account has insufficient funds");
908 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
910 throw JSONRPCError(-4, strError);
912 return wtx.GetHash().GetHex();
916 Value sendmany(const Array& params, bool fHelp)
918 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
920 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
921 "amounts are double-precision floating point numbers\n"
922 "requires wallet passphrase to be set with walletpassphrase first");
923 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
925 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
926 "amounts are double-precision floating point numbers");
928 string strAccount = AccountFromValue(params[0]);
929 Object sendTo = params[1].get_obj();
931 if (params.size() > 2)
932 nMinDepth = params[2].get_int();
935 wtx.strFromAccount = strAccount;
936 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
937 wtx.mapValue["comment"] = params[3].get_str();
939 set<CBitcoinAddress> setAddress;
940 vector<pair<CScript, int64> > vecSend;
942 int64 totalAmount = 0;
943 BOOST_FOREACH(const Pair& s, sendTo)
945 CBitcoinAddress address(s.name_);
946 if (!address.IsValid())
947 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
949 if (setAddress.count(address))
950 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
951 setAddress.insert(address);
953 CScript scriptPubKey;
954 scriptPubKey.SetBitcoinAddress(address);
955 int64 nAmount = AmountFromValue(s.value_);
956 totalAmount += nAmount;
958 vecSend.push_back(make_pair(scriptPubKey, nAmount));
961 if (pwalletMain->IsLocked())
962 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
965 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
966 if (totalAmount > nBalance)
967 throw JSONRPCError(-6, "Account has insufficient funds");
970 CReserveKey keyChange(pwalletMain);
971 int64 nFeeRequired = 0;
972 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
975 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
976 throw JSONRPCError(-6, "Insufficient funds");
977 throw JSONRPCError(-4, "Transaction creation failed");
979 if (!pwalletMain->CommitTransaction(wtx, keyChange))
980 throw JSONRPCError(-4, "Transaction commit failed");
982 return wtx.GetHash().GetHex();
985 Value addmultisigaddress(const Array& params, bool fHelp)
987 if (fHelp || params.size() < 2 || params.size() > 3)
989 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
990 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
991 "each key is a bitcoin address or hex-encoded public key\n"
992 "If [account] is specified, assign address to [account].";
993 throw runtime_error(msg);
996 throw runtime_error("addmultisigaddress available only when running -testnet\n");
998 int nRequired = params[0].get_int();
999 const Array& keys = params[1].get_array();
1001 if (params.size() > 2)
1002 strAccount = AccountFromValue(params[2]);
1004 // Gather public keys
1005 if (nRequired < 1 || keys.size() < nRequired)
1006 throw runtime_error(
1007 strprintf("wrong number of keys"
1008 "(got %d, need at least %d)", keys.size(), nRequired));
1009 std::vector<CKey> pubkeys;
1010 pubkeys.resize(keys.size());
1011 for (unsigned int i = 0; i < keys.size(); i++)
1013 const std::string& ks = keys[i].get_str();
1015 // Case 1: bitcoin address and we have full public key:
1016 CBitcoinAddress address(ks);
1017 if (address.IsValid())
1019 if (address.IsScript())
1020 throw runtime_error(
1021 strprintf("%s is a pay-to-script address",ks.c_str()));
1022 std::vector<unsigned char> vchPubKey;
1023 if (!pwalletMain->GetPubKey(address, vchPubKey))
1024 throw runtime_error(
1025 strprintf("no full public key for address %s",ks.c_str()));
1026 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1027 throw runtime_error(" Invalid public key: "+ks);
1030 // Case 2: hex public key
1033 vector<unsigned char> vchPubKey = ParseHex(ks);
1034 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1035 throw runtime_error(" Invalid public key: "+ks);
1039 throw runtime_error(" Invalid public key: "+ks);
1043 // Construct using pay-to-script-hash:
1045 inner.SetMultisig(nRequired, pubkeys);
1047 uint160 scriptHash = Hash160(inner);
1048 CScript scriptPubKey;
1049 scriptPubKey.SetPayToScriptHash(inner);
1050 pwalletMain->AddCScript(inner);
1051 CBitcoinAddress address;
1052 address.SetScriptHash160(scriptHash);
1054 pwalletMain->SetAddressBookName(address, strAccount);
1055 return address.ToString();
1066 nConf = std::numeric_limits<int>::max();
1070 Value ListReceived(const Array& params, bool fByAccounts)
1072 // Minimum confirmations
1074 if (params.size() > 0)
1075 nMinDepth = params[0].get_int();
1077 // Whether to include empty accounts
1078 bool fIncludeEmpty = false;
1079 if (params.size() > 1)
1080 fIncludeEmpty = params[1].get_bool();
1083 map<CBitcoinAddress, tallyitem> mapTally;
1084 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1086 const CWalletTx& wtx = (*it).second;
1088 if (wtx.IsCoinBase() || !wtx.IsFinal())
1091 int nDepth = wtx.GetDepthInMainChain();
1092 if (nDepth < nMinDepth)
1095 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1097 CBitcoinAddress address;
1098 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1101 tallyitem& item = mapTally[address];
1102 item.nAmount += txout.nValue;
1103 item.nConf = min(item.nConf, nDepth);
1109 map<string, tallyitem> mapAccountTally;
1110 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1112 const CBitcoinAddress& address = item.first;
1113 const string& strAccount = item.second;
1114 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1115 if (it == mapTally.end() && !fIncludeEmpty)
1119 int nConf = std::numeric_limits<int>::max();
1120 if (it != mapTally.end())
1122 nAmount = (*it).second.nAmount;
1123 nConf = (*it).second.nConf;
1128 tallyitem& item = mapAccountTally[strAccount];
1129 item.nAmount += nAmount;
1130 item.nConf = min(item.nConf, nConf);
1135 obj.push_back(Pair("address", address.ToString()));
1136 obj.push_back(Pair("account", strAccount));
1137 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1138 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1145 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1147 int64 nAmount = (*it).second.nAmount;
1148 int nConf = (*it).second.nConf;
1150 obj.push_back(Pair("account", (*it).first));
1151 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1152 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1160 Value listreceivedbyaddress(const Array& params, bool fHelp)
1162 if (fHelp || params.size() > 2)
1163 throw runtime_error(
1164 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1165 "[minconf] is the minimum number of confirmations before payments are included.\n"
1166 "[includeempty] whether to include addresses that haven't received any payments.\n"
1167 "Returns an array of objects containing:\n"
1168 " \"address\" : receiving address\n"
1169 " \"account\" : the account of the receiving address\n"
1170 " \"amount\" : total amount received by the address\n"
1171 " \"confirmations\" : number of confirmations of the most recent transaction included");
1173 return ListReceived(params, false);
1176 Value listreceivedbyaccount(const Array& params, bool fHelp)
1178 if (fHelp || params.size() > 2)
1179 throw runtime_error(
1180 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1181 "[minconf] is the minimum number of confirmations before payments are included.\n"
1182 "[includeempty] whether to include accounts that haven't received any payments.\n"
1183 "Returns an array of objects containing:\n"
1184 " \"account\" : the account of the receiving addresses\n"
1185 " \"amount\" : total amount received by addresses with this account\n"
1186 " \"confirmations\" : number of confirmations of the most recent transaction included");
1188 return ListReceived(params, true);
1191 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1193 int64 nGeneratedImmature, nGeneratedMature, nFee;
1194 string strSentAccount;
1195 list<pair<CBitcoinAddress, int64> > listReceived;
1196 list<pair<CBitcoinAddress, int64> > listSent;
1198 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1200 bool fAllAccounts = (strAccount == string("*"));
1202 // Generated blocks assigned to account ""
1203 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1206 entry.push_back(Pair("account", string("")));
1207 if (nGeneratedImmature)
1209 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1210 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1214 entry.push_back(Pair("category", "generate"));
1215 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1218 WalletTxToJSON(wtx, entry);
1219 ret.push_back(entry);
1223 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1225 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1228 entry.push_back(Pair("account", strSentAccount));
1229 entry.push_back(Pair("address", s.first.ToString()));
1230 entry.push_back(Pair("category", "send"));
1231 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1232 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1234 WalletTxToJSON(wtx, entry);
1235 ret.push_back(entry);
1240 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1242 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1245 if (pwalletMain->mapAddressBook.count(r.first))
1246 account = pwalletMain->mapAddressBook[r.first];
1247 if (fAllAccounts || (account == strAccount))
1250 entry.push_back(Pair("account", account));
1251 entry.push_back(Pair("address", r.first.ToString()));
1252 entry.push_back(Pair("category", "receive"));
1253 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1255 WalletTxToJSON(wtx, entry);
1256 ret.push_back(entry);
1262 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1264 bool fAllAccounts = (strAccount == string("*"));
1266 if (fAllAccounts || acentry.strAccount == strAccount)
1269 entry.push_back(Pair("account", acentry.strAccount));
1270 entry.push_back(Pair("category", "move"));
1271 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1272 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1273 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1274 entry.push_back(Pair("comment", acentry.strComment));
1275 ret.push_back(entry);
1279 Value listtransactions(const Array& params, bool fHelp)
1281 if (fHelp || params.size() > 3)
1282 throw runtime_error(
1283 "listtransactions [account] [count=10] [from=0]\n"
1284 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1286 string strAccount = "*";
1287 if (params.size() > 0)
1288 strAccount = params[0].get_str();
1290 if (params.size() > 1)
1291 nCount = params[1].get_int();
1293 if (params.size() > 2)
1294 nFrom = params[2].get_int();
1297 throw JSONRPCError(-8, "Negative count");
1299 throw JSONRPCError(-8, "Negative from");
1302 CWalletDB walletdb(pwalletMain->strWalletFile);
1304 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1305 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1306 typedef multimap<int64, TxPair > TxItems;
1309 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1310 // would make this much faster for applications that do this a lot.
1311 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1313 CWalletTx* wtx = &((*it).second);
1314 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1316 list<CAccountingEntry> acentries;
1317 walletdb.ListAccountCreditDebit(strAccount, acentries);
1318 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1320 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1323 // iterate backwards until we have nCount items to return:
1324 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1326 CWalletTx *const pwtx = (*it).second.first;
1328 ListTransactions(*pwtx, strAccount, 0, true, ret);
1329 CAccountingEntry *const pacentry = (*it).second.second;
1331 AcentryToJSON(*pacentry, strAccount, ret);
1333 if (ret.size() >= (nCount+nFrom)) break;
1335 // ret is newest to oldest
1337 if (nFrom > ret.size()) nFrom = ret.size();
1338 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1339 Array::iterator first = ret.begin();
1340 std::advance(first, nFrom);
1341 Array::iterator last = ret.begin();
1342 std::advance(last, nFrom+nCount);
1344 if (last != ret.end()) ret.erase(last, ret.end());
1345 if (first != ret.begin()) ret.erase(ret.begin(), first);
1347 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1352 Value listaccounts(const Array& params, bool fHelp)
1354 if (fHelp || params.size() > 1)
1355 throw runtime_error(
1356 "listaccounts [minconf=1]\n"
1357 "Returns Object that has account names as keys, account balances as values.");
1360 if (params.size() > 0)
1361 nMinDepth = params[0].get_int();
1363 map<string, int64> mapAccountBalances;
1364 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1365 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1366 mapAccountBalances[entry.second] = 0;
1369 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1371 const CWalletTx& wtx = (*it).second;
1372 int64 nGeneratedImmature, nGeneratedMature, nFee;
1373 string strSentAccount;
1374 list<pair<CBitcoinAddress, int64> > listReceived;
1375 list<pair<CBitcoinAddress, int64> > listSent;
1376 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1377 mapAccountBalances[strSentAccount] -= nFee;
1378 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1379 mapAccountBalances[strSentAccount] -= s.second;
1380 if (wtx.GetDepthInMainChain() >= nMinDepth)
1382 mapAccountBalances[""] += nGeneratedMature;
1383 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1384 if (pwalletMain->mapAddressBook.count(r.first))
1385 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1387 mapAccountBalances[""] += r.second;
1391 list<CAccountingEntry> acentries;
1392 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1393 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1394 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1397 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1398 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1403 Value listsinceblock(const Array& params, bool fHelp)
1406 throw runtime_error(
1407 "listsinceblock [blockid] [target-confirmations]\n"
1408 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1410 CBlockIndex *pindex = NULL;
1411 int target_confirms = 1;
1413 if (params.size() > 0)
1415 uint256 blockId = 0;
1417 blockId.SetHex(params[0].get_str());
1418 pindex = CBlockLocator(blockId).GetBlockIndex();
1421 if (params.size() > 1)
1423 target_confirms = params[1].get_int();
1425 if (target_confirms < 1)
1426 throw JSONRPCError(-8, "Invalid parameter");
1429 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1433 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1435 CWalletTx tx = (*it).second;
1437 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1438 ListTransactions(tx, "*", 0, true, transactions);
1443 if (target_confirms == 1)
1446 lastblock = hashBestChain;
1450 int target_height = pindexBest->nHeight + 1 - target_confirms;
1453 for (block = pindexBest;
1454 block && block->nHeight > target_height;
1455 block = block->pprev) { }
1457 lastblock = block ? block->GetBlockHash() : 0;
1461 ret.push_back(Pair("transactions", transactions));
1462 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1467 Value gettransaction(const Array& params, bool fHelp)
1469 if (fHelp || params.size() != 1)
1470 throw runtime_error(
1471 "gettransaction <txid>\n"
1472 "Get detailed information about <txid>");
1475 hash.SetHex(params[0].get_str());
1479 if (!pwalletMain->mapWallet.count(hash))
1480 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1481 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1483 int64 nCredit = wtx.GetCredit();
1484 int64 nDebit = wtx.GetDebit();
1485 int64 nNet = nCredit - nDebit;
1486 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1488 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1490 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1492 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1495 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1496 entry.push_back(Pair("details", details));
1502 Value backupwallet(const Array& params, bool fHelp)
1504 if (fHelp || params.size() != 1)
1505 throw runtime_error(
1506 "backupwallet <destination>\n"
1507 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1509 string strDest = params[0].get_str();
1510 BackupWallet(*pwalletMain, strDest);
1516 Value keypoolrefill(const Array& params, bool fHelp)
1518 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1519 throw runtime_error(
1521 "Fills the keypool, requires wallet passphrase to be set.");
1522 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1523 throw runtime_error(
1525 "Fills the keypool.");
1527 if (pwalletMain->IsLocked())
1528 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1530 pwalletMain->TopUpKeyPool();
1532 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1533 throw JSONRPCError(-4, "Error refreshing keypool.");
1539 void ThreadTopUpKeyPool(void* parg)
1541 pwalletMain->TopUpKeyPool();
1544 void ThreadCleanWalletPassphrase(void* parg)
1546 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1548 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1550 if (nWalletUnlockTime == 0)
1552 nWalletUnlockTime = nMyWakeTime;
1556 if (nWalletUnlockTime==0)
1558 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1562 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1564 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1568 if (nWalletUnlockTime)
1570 nWalletUnlockTime = 0;
1571 pwalletMain->Lock();
1576 if (nWalletUnlockTime < nMyWakeTime)
1577 nWalletUnlockTime = nMyWakeTime;
1580 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1582 delete (int64*)parg;
1585 Value walletpassphrase(const Array& params, bool fHelp)
1587 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1588 throw runtime_error(
1589 "walletpassphrase <passphrase> <timeout>\n"
1590 "Stores the wallet decryption key in memory for <timeout> seconds.");
1593 if (!pwalletMain->IsCrypted())
1594 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1596 if (!pwalletMain->IsLocked())
1597 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1599 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1600 SecureString strWalletPass;
1601 strWalletPass.reserve(100);
1602 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1603 // Alternately, find a way to make params[0] mlock()'d to begin with.
1604 strWalletPass = params[0].get_str().c_str();
1606 if (strWalletPass.length() > 0)
1608 if (!pwalletMain->Unlock(strWalletPass))
1609 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1612 throw runtime_error(
1613 "walletpassphrase <passphrase> <timeout>\n"
1614 "Stores the wallet decryption key in memory for <timeout> seconds.");
1616 CreateThread(ThreadTopUpKeyPool, NULL);
1617 int64* pnSleepTime = new int64(params[1].get_int64());
1618 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1624 Value walletpassphrasechange(const Array& params, bool fHelp)
1626 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1627 throw runtime_error(
1628 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1629 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1632 if (!pwalletMain->IsCrypted())
1633 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1635 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1636 // Alternately, find a way to make params[0] mlock()'d to begin with.
1637 SecureString strOldWalletPass;
1638 strOldWalletPass.reserve(100);
1639 strOldWalletPass = params[0].get_str().c_str();
1641 SecureString strNewWalletPass;
1642 strNewWalletPass.reserve(100);
1643 strNewWalletPass = params[1].get_str().c_str();
1645 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1646 throw runtime_error(
1647 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1648 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1650 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1651 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1657 Value walletlock(const Array& params, bool fHelp)
1659 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1660 throw runtime_error(
1662 "Removes the wallet encryption key from memory, locking the wallet.\n"
1663 "After calling this method, you will need to call walletpassphrase again\n"
1664 "before being able to call any methods which require the wallet to be unlocked.");
1667 if (!pwalletMain->IsCrypted())
1668 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1670 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1672 pwalletMain->Lock();
1673 nWalletUnlockTime = 0;
1680 Value encryptwallet(const Array& params, bool fHelp)
1682 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1683 throw runtime_error(
1684 "encryptwallet <passphrase>\n"
1685 "Encrypts the wallet with <passphrase>.");
1688 if (pwalletMain->IsCrypted())
1689 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1692 // shutting down via RPC while the GUI is running does not work (yet):
1693 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1696 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1697 // Alternately, find a way to make params[0] mlock()'d to begin with.
1698 SecureString strWalletPass;
1699 strWalletPass.reserve(100);
1700 strWalletPass = params[0].get_str().c_str();
1702 if (strWalletPass.length() < 1)
1703 throw runtime_error(
1704 "encryptwallet <passphrase>\n"
1705 "Encrypts the wallet with <passphrase>.");
1707 if (!pwalletMain->EncryptWallet(strWalletPass))
1708 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1710 // BDB seems to have a bad habit of writing old data into
1711 // slack space in .dat files; that is bad if the old data is
1712 // unencrypted private keys. So:
1713 CreateThread(Shutdown, NULL);
1714 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1718 Value validateaddress(const Array& params, bool fHelp)
1720 if (fHelp || params.size() != 1)
1721 throw runtime_error(
1722 "validateaddress <bitcoinaddress>\n"
1723 "Return information about <bitcoinaddress>.");
1725 CBitcoinAddress address(params[0].get_str());
1726 bool isValid = address.IsValid();
1729 ret.push_back(Pair("isvalid", isValid));
1732 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1733 // version of the address:
1734 string currentAddress = address.ToString();
1735 ret.push_back(Pair("address", currentAddress));
1736 if (pwalletMain->HaveKey(address))
1738 ret.push_back(Pair("ismine", true));
1739 std::vector<unsigned char> vchPubKey;
1740 pwalletMain->GetPubKey(address, vchPubKey);
1741 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1743 key.SetPubKey(vchPubKey);
1744 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1746 else if (pwalletMain->HaveCScript(address.GetHash160()))
1748 ret.push_back(Pair("isscript", true));
1750 pwalletMain->GetCScript(address.GetHash160(), subscript);
1751 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1752 std::vector<CBitcoinAddress> addresses;
1753 txnouttype whichType;
1755 ExtractAddresses(subscript, whichType, addresses, nRequired);
1756 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1758 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1759 a.push_back(addr.ToString());
1760 ret.push_back(Pair("addresses", a));
1761 if (whichType == TX_MULTISIG)
1762 ret.push_back(Pair("sigsrequired", nRequired));
1765 ret.push_back(Pair("ismine", false));
1766 if (pwalletMain->mapAddressBook.count(address))
1767 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1772 Value getwork(const Array& params, bool fHelp)
1774 if (fHelp || params.size() > 1)
1775 throw runtime_error(
1777 "If [data] is not specified, returns formatted hash data to work on:\n"
1778 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1779 " \"data\" : block data\n"
1780 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1781 " \"target\" : little endian hash target\n"
1782 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1785 throw JSONRPCError(-9, "Bitcoin is not connected!");
1787 if (IsInitialBlockDownload())
1788 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1790 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1791 static mapNewBlock_t mapNewBlock;
1792 static vector<CBlock*> vNewBlock;
1793 static CReserveKey reservekey(pwalletMain);
1795 if (params.size() == 0)
1798 static unsigned int nTransactionsUpdatedLast;
1799 static CBlockIndex* pindexPrev;
1800 static int64 nStart;
1801 static CBlock* pblock;
1802 if (pindexPrev != pindexBest ||
1803 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1805 if (pindexPrev != pindexBest)
1807 // Deallocate old blocks since they're obsolete now
1808 mapNewBlock.clear();
1809 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1813 nTransactionsUpdatedLast = nTransactionsUpdated;
1814 pindexPrev = pindexBest;
1818 pblock = CreateNewBlock(reservekey);
1820 throw JSONRPCError(-7, "Out of memory");
1821 vNewBlock.push_back(pblock);
1825 pblock->UpdateTime(pindexPrev);
1828 // Update nExtraNonce
1829 static unsigned int nExtraNonce = 0;
1830 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1833 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1835 // Prebuild hash buffers
1839 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1841 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1844 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1845 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1846 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1847 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1853 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1854 if (vchData.size() != 128)
1855 throw JSONRPCError(-8, "Invalid parameter");
1856 CBlock* pdata = (CBlock*)&vchData[0];
1859 for (int i = 0; i < 128/4; i++)
1860 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1863 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1865 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1867 pblock->nTime = pdata->nTime;
1868 pblock->nNonce = pdata->nNonce;
1869 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1870 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1872 return CheckWork(pblock, *pwalletMain, reservekey);
1877 Value getmemorypool(const Array& params, bool fHelp)
1879 if (fHelp || params.size() > 1)
1880 throw runtime_error(
1881 "getmemorypool [data]\n"
1882 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1883 " \"version\" : block version\n"
1884 " \"previousblockhash\" : hash of current highest block\n"
1885 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1886 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1887 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1888 " \"time\" : timestamp appropriate for next block\n"
1889 " \"mintime\" : minimum timestamp appropriate for next block\n"
1890 " \"curtime\" : current timestamp\n"
1891 " \"bits\" : compressed target of next block\n"
1892 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1894 if (params.size() == 0)
1897 throw JSONRPCError(-9, "Bitcoin is not connected!");
1899 if (IsInitialBlockDownload())
1900 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1902 static CReserveKey reservekey(pwalletMain);
1905 static unsigned int nTransactionsUpdatedLast;
1906 static CBlockIndex* pindexPrev;
1907 static int64 nStart;
1908 static CBlock* pblock;
1909 if (pindexPrev != pindexBest ||
1910 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1912 nTransactionsUpdatedLast = nTransactionsUpdated;
1913 pindexPrev = pindexBest;
1919 pblock = CreateNewBlock(reservekey);
1921 throw JSONRPCError(-7, "Out of memory");
1925 pblock->UpdateTime(pindexPrev);
1929 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1936 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1940 result.push_back(Pair("version", pblock->nVersion));
1941 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1942 result.push_back(Pair("transactions", transactions));
1943 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1944 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1945 result.push_back(Pair("time", (int64_t)pblock->nTime));
1946 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1947 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1948 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1955 CDataStream ssBlock(ParseHex(params[0].get_str()));
1959 return ProcessBlock(NULL, &pblock);
1963 Value getblockhash(const Array& params, bool fHelp)
1965 if (fHelp || params.size() != 1)
1966 throw runtime_error(
1967 "getblockhash <index>\n"
1968 "Returns hash of block in best-block-chain at <index>.");
1970 int nHeight = params[0].get_int();
1971 if (nHeight < 0 || nHeight > nBestHeight)
1972 throw runtime_error("Block number out of range.");
1975 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1976 while (pblockindex->nHeight > nHeight)
1977 pblockindex = pblockindex->pprev;
1978 return pblockindex->phashBlock->GetHex();
1981 Value getblock(const Array& params, bool fHelp)
1983 if (fHelp || params.size() != 1)
1984 throw runtime_error(
1986 "Returns details of a block with given block-hash.");
1988 std::string strHash = params[0].get_str();
1989 uint256 hash(strHash);
1991 if (mapBlockIndex.count(hash) == 0)
1992 throw JSONRPCError(-5, "Block not found");
1995 CBlockIndex* pblockindex = mapBlockIndex[hash];
1996 block.ReadFromDisk(pblockindex, true);
1998 return blockToJSON(block, pblockindex);
2015 pair<string, rpcfn_type> pCallTable[] =
2017 make_pair("help", &help),
2018 make_pair("stop", &stop),
2019 make_pair("getblockcount", &getblockcount),
2020 make_pair("getblocknumber", &getblocknumber),
2021 make_pair("getconnectioncount", &getconnectioncount),
2022 make_pair("getdifficulty", &getdifficulty),
2023 make_pair("getgenerate", &getgenerate),
2024 make_pair("setgenerate", &setgenerate),
2025 make_pair("gethashespersec", &gethashespersec),
2026 make_pair("getinfo", &getinfo),
2027 make_pair("getmininginfo", &getmininginfo),
2028 make_pair("getnewaddress", &getnewaddress),
2029 make_pair("getaccountaddress", &getaccountaddress),
2030 make_pair("setaccount", &setaccount),
2031 make_pair("getaccount", &getaccount),
2032 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2033 make_pair("sendtoaddress", &sendtoaddress),
2034 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2035 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2036 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2037 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2038 make_pair("backupwallet", &backupwallet),
2039 make_pair("keypoolrefill", &keypoolrefill),
2040 make_pair("walletpassphrase", &walletpassphrase),
2041 make_pair("walletpassphrasechange", &walletpassphrasechange),
2042 make_pair("walletlock", &walletlock),
2043 make_pair("encryptwallet", &encryptwallet),
2044 make_pair("validateaddress", &validateaddress),
2045 make_pair("getbalance", &getbalance),
2046 make_pair("move", &movecmd),
2047 make_pair("sendfrom", &sendfrom),
2048 make_pair("sendmany", &sendmany),
2049 make_pair("addmultisigaddress", &addmultisigaddress),
2050 make_pair("getblock", &getblock),
2051 make_pair("getblockhash", &getblockhash),
2052 make_pair("gettransaction", &gettransaction),
2053 make_pair("listtransactions", &listtransactions),
2054 make_pair("signmessage", &signmessage),
2055 make_pair("verifymessage", &verifymessage),
2056 make_pair("getwork", &getwork),
2057 make_pair("listaccounts", &listaccounts),
2058 make_pair("settxfee", &settxfee),
2059 make_pair("getmemorypool", &getmemorypool),
2060 make_pair("listsinceblock", &listsinceblock),
2061 make_pair("dumpprivkey", &dumpprivkey),
2062 make_pair("importprivkey", &importprivkey)
2064 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2066 string pAllowInSafeMode[] =
2071 "getblocknumber", // deprecated
2072 "getconnectioncount",
2080 "getaccountaddress",
2082 "getaddressesbyaccount",
2091 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2099 // This ain't Apache. We're just using HTTP header for the length field
2100 // and to be compatible with other JSON-RPC implementations.
2103 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2106 s << "POST / HTTP/1.1\r\n"
2107 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2108 << "Host: 127.0.0.1\r\n"
2109 << "Content-Type: application/json\r\n"
2110 << "Content-Length: " << strMsg.size() << "\r\n"
2111 << "Connection: close\r\n"
2112 << "Accept: application/json\r\n";
2113 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2114 s << item.first << ": " << item.second << "\r\n";
2115 s << "\r\n" << strMsg;
2120 string rfc1123Time()
2125 struct tm* now_gmt = gmtime(&now);
2126 string locale(setlocale(LC_TIME, NULL));
2127 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2128 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2129 setlocale(LC_TIME, locale.c_str());
2130 return string(buffer);
2133 static string HTTPReply(int nStatus, const string& strMsg)
2136 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2138 "Server: bitcoin-json-rpc/%s\r\n"
2139 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2140 "Content-Type: text/html\r\n"
2141 "Content-Length: 296\r\n"
2143 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2144 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2147 "<TITLE>Error</TITLE>\r\n"
2148 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2150 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2151 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2152 const char *cStatus;
2153 if (nStatus == 200) cStatus = "OK";
2154 else if (nStatus == 400) cStatus = "Bad Request";
2155 else if (nStatus == 403) cStatus = "Forbidden";
2156 else if (nStatus == 404) cStatus = "Not Found";
2157 else if (nStatus == 500) cStatus = "Internal Server Error";
2160 "HTTP/1.1 %d %s\r\n"
2162 "Connection: close\r\n"
2163 "Content-Length: %d\r\n"
2164 "Content-Type: application/json\r\n"
2165 "Server: bitcoin-json-rpc/%s\r\n"
2170 rfc1123Time().c_str(),
2172 FormatFullVersion().c_str(),
2176 int ReadHTTPStatus(std::basic_istream<char>& stream)
2179 getline(stream, str);
2180 vector<string> vWords;
2181 boost::split(vWords, str, boost::is_any_of(" "));
2182 if (vWords.size() < 2)
2184 return atoi(vWords[1].c_str());
2187 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2193 std::getline(stream, str);
2194 if (str.empty() || str == "\r")
2196 string::size_type nColon = str.find(":");
2197 if (nColon != string::npos)
2199 string strHeader = str.substr(0, nColon);
2200 boost::trim(strHeader);
2201 boost::to_lower(strHeader);
2202 string strValue = str.substr(nColon+1);
2203 boost::trim(strValue);
2204 mapHeadersRet[strHeader] = strValue;
2205 if (strHeader == "content-length")
2206 nLen = atoi(strValue.c_str());
2212 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2214 mapHeadersRet.clear();
2218 int nStatus = ReadHTTPStatus(stream);
2221 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2222 if (nLen < 0 || nLen > MAX_SIZE)
2228 vector<char> vch(nLen);
2229 stream.read(&vch[0], nLen);
2230 strMessageRet = string(vch.begin(), vch.end());
2236 bool HTTPAuthorized(map<string, string>& mapHeaders)
2238 string strAuth = mapHeaders["authorization"];
2239 if (strAuth.substr(0,6) != "Basic ")
2241 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2242 string strUserPass = DecodeBase64(strUserPass64);
2243 return strUserPass == strRPCUserColonPass;
2247 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2248 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2249 // unspecified (HTTP errors and contents of 'error').
2251 // 1.0 spec: http://json-rpc.org/wiki/specification
2252 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2253 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2256 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2259 request.push_back(Pair("method", strMethod));
2260 request.push_back(Pair("params", params));
2261 request.push_back(Pair("id", id));
2262 return write_string(Value(request), false) + "\n";
2265 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2268 if (error.type() != null_type)
2269 reply.push_back(Pair("result", Value::null));
2271 reply.push_back(Pair("result", result));
2272 reply.push_back(Pair("error", error));
2273 reply.push_back(Pair("id", id));
2274 return write_string(Value(reply), false) + "\n";
2277 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2279 // Send error reply from json-rpc error object
2281 int code = find_value(objError, "code").get_int();
2282 if (code == -32600) nStatus = 400;
2283 else if (code == -32601) nStatus = 404;
2284 string strReply = JSONRPCReply(Value::null, objError, id);
2285 stream << HTTPReply(nStatus, strReply) << std::flush;
2288 bool ClientAllowed(const string& strAddress)
2290 if (strAddress == asio::ip::address_v4::loopback().to_string())
2292 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2293 BOOST_FOREACH(string strAllow, vAllow)
2294 if (WildcardMatch(strAddress, strAllow))
2301 // IOStream device that speaks SSL but can also speak non-SSL
2303 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2305 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2307 fUseSSL = fUseSSLIn;
2308 fNeedHandshake = fUseSSLIn;
2311 void handshake(ssl::stream_base::handshake_type role)
2313 if (!fNeedHandshake) return;
2314 fNeedHandshake = false;
2315 stream.handshake(role);
2317 std::streamsize read(char* s, std::streamsize n)
2319 handshake(ssl::stream_base::server); // HTTPS servers read first
2320 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2321 return stream.next_layer().read_some(asio::buffer(s, n));
2323 std::streamsize write(const char* s, std::streamsize n)
2325 handshake(ssl::stream_base::client); // HTTPS clients write first
2326 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2327 return asio::write(stream.next_layer(), asio::buffer(s, n));
2329 bool connect(const std::string& server, const std::string& port)
2331 ip::tcp::resolver resolver(stream.get_io_service());
2332 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2333 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2334 ip::tcp::resolver::iterator end;
2335 boost::system::error_code error = asio::error::host_not_found;
2336 while (error && endpoint_iterator != end)
2338 stream.lowest_layer().close();
2339 stream.lowest_layer().connect(*endpoint_iterator++, error);
2347 bool fNeedHandshake;
2353 void ThreadRPCServer(void* parg)
2355 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2358 vnThreadsRunning[THREAD_RPCSERVER]++;
2359 ThreadRPCServer2(parg);
2360 vnThreadsRunning[THREAD_RPCSERVER]--;
2362 catch (std::exception& e) {
2363 vnThreadsRunning[THREAD_RPCSERVER]--;
2364 PrintException(&e, "ThreadRPCServer()");
2366 vnThreadsRunning[THREAD_RPCSERVER]--;
2367 PrintException(NULL, "ThreadRPCServer()");
2369 printf("ThreadRPCServer exiting\n");
2373 extern bool HACK_SHUTDOWN;
2376 void ThreadRPCServer2(void* parg)
2378 printf("ThreadRPCServer started\n");
2380 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2381 if (mapArgs["-rpcpassword"] == "")
2383 unsigned char rand_pwd[32];
2384 RAND_bytes(rand_pwd, 32);
2385 string strWhatAmI = "To use bitcoind";
2386 if (mapArgs.count("-server"))
2387 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2388 else if (mapArgs.count("-daemon"))
2389 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2390 ThreadSafeMessageBox(strprintf(
2391 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2392 "It is recommended you use the following random password:\n"
2393 "rpcuser=bitcoinrpc\n"
2395 "(you do not need to remember this password)\n"
2396 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2398 GetConfigFile().c_str(),
2399 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2400 _("Error"), wxOK | wxMODAL);
2402 CreateThread(Shutdown, NULL);
2407 bool fUseSSL = GetBoolArg("-rpcssl");
2408 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2410 asio::io_service io_service;
2411 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2413 ip::tcp::acceptor acceptor(io_service, endpoint);
2415 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2417 ip::tcp::acceptor acceptor(io_service);
2420 acceptor.open(endpoint.protocol());
2421 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2422 acceptor.bind(endpoint);
2423 acceptor.listen(socket_base::max_connections);
2425 catch(system::system_error &e)
2427 HACK_SHUTDOWN = true;
2428 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2429 _("Error"), wxOK | wxMODAL);
2435 ssl::context context(io_service, ssl::context::sslv23);
2438 context.set_options(ssl::context::no_sslv2);
2439 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2440 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2441 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2442 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2443 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2444 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2445 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2446 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2448 string ciphers = GetArg("-rpcsslciphers",
2449 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2450 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2454 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2459 // Accept connection
2461 SSLStream sslStream(io_service, context);
2462 SSLIOStreamDevice d(sslStream, fUseSSL);
2463 iostreams::stream<SSLIOStreamDevice> stream(d);
2465 ip::tcp::iostream stream;
2468 ip::tcp::endpoint peer;
2469 vnThreadsRunning[THREAD_RPCSERVER]--;
2471 acceptor.accept(sslStream.lowest_layer(), peer);
2473 acceptor.accept(*stream.rdbuf(), peer);
2475 vnThreadsRunning[4]++;
2479 // Restrict callers by IP
2480 if (!ClientAllowed(peer.address().to_string()))
2482 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2484 stream << HTTPReply(403, "") << std::flush;
2488 map<string, string> mapHeaders;
2491 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2492 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2495 printf("ThreadRPCServer ReadHTTP timeout\n");
2499 // Check authorization
2500 if (mapHeaders.count("authorization") == 0)
2502 stream << HTTPReply(401, "") << std::flush;
2505 if (!HTTPAuthorized(mapHeaders))
2507 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2508 /* Deter brute-forcing short passwords.
2509 If this results in a DOS the user really
2510 shouldn't have their RPC port exposed.*/
2511 if (mapArgs["-rpcpassword"].size() < 20)
2514 stream << HTTPReply(401, "") << std::flush;
2518 Value id = Value::null;
2523 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2524 throw JSONRPCError(-32700, "Parse error");
2525 const Object& request = valRequest.get_obj();
2527 // Parse id now so errors from here on will have the id
2528 id = find_value(request, "id");
2531 Value valMethod = find_value(request, "method");
2532 if (valMethod.type() == null_type)
2533 throw JSONRPCError(-32600, "Missing method");
2534 if (valMethod.type() != str_type)
2535 throw JSONRPCError(-32600, "Method must be a string");
2536 string strMethod = valMethod.get_str();
2537 if (strMethod != "getwork" && strMethod != "getmemorypool")
2538 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2541 Value valParams = find_value(request, "params");
2543 if (valParams.type() == array_type)
2544 params = valParams.get_array();
2545 else if (valParams.type() == null_type)
2548 throw JSONRPCError(-32600, "Params must be an array");
2551 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2552 if (mi == mapCallTable.end())
2553 throw JSONRPCError(-32601, "Method not found");
2555 // Observe safe mode
2556 string strWarning = GetWarnings("rpc");
2557 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2558 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2564 CRITICAL_BLOCK(cs_main)
2565 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2566 result = (*(*mi).second)(params, false);
2569 string strReply = JSONRPCReply(result, Value::null, id);
2570 stream << HTTPReply(200, strReply) << std::flush;
2572 catch (std::exception& e)
2574 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2577 catch (Object& objError)
2579 ErrorReply(stream, objError, id);
2581 catch (std::exception& e)
2583 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2591 Object CallRPC(const string& strMethod, const Array& params)
2593 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2594 throw runtime_error(strprintf(
2595 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2596 "If the file does not exist, create it with owner-readable-only file permissions."),
2597 GetConfigFile().c_str()));
2599 // Connect to localhost
2600 bool fUseSSL = GetBoolArg("-rpcssl");
2602 asio::io_service io_service;
2603 ssl::context context(io_service, ssl::context::sslv23);
2604 context.set_options(ssl::context::no_sslv2);
2605 SSLStream sslStream(io_service, context);
2606 SSLIOStreamDevice d(sslStream, fUseSSL);
2607 iostreams::stream<SSLIOStreamDevice> stream(d);
2608 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2609 throw runtime_error("couldn't connect to server");
2612 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2614 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2616 throw runtime_error("couldn't connect to server");
2620 // HTTP basic authentication
2621 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2622 map<string, string> mapRequestHeaders;
2623 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2626 string strRequest = JSONRPCRequest(strMethod, params, 1);
2627 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2628 stream << strPost << std::flush;
2631 map<string, string> mapHeaders;
2633 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2635 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2636 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2637 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2638 else if (strReply.empty())
2639 throw runtime_error("no response from server");
2643 if (!read_string(strReply, valReply))
2644 throw runtime_error("couldn't parse reply from server");
2645 const Object& reply = valReply.get_obj();
2647 throw runtime_error("expected reply to have result, error and id properties");
2655 template<typename T>
2656 void ConvertTo(Value& value)
2658 if (value.type() == str_type)
2660 // reinterpret string as unquoted json value
2662 if (!read_string(value.get_str(), value2))
2663 throw runtime_error("type mismatch");
2664 value = value2.get_value<T>();
2668 value = value.get_value<T>();
2672 int CommandLineRPC(int argc, char *argv[])
2679 while (argc > 1 && IsSwitchChar(argv[1][0]))
2687 throw runtime_error("too few parameters");
2688 string strMethod = argv[1];
2690 // Parameters default to strings
2692 for (int i = 2; i < argc; i++)
2693 params.push_back(argv[i]);
2694 int n = params.size();
2697 // Special case non-string parameter types
2699 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2700 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2701 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2702 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2703 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2704 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2705 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2706 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2707 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2708 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2709 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2710 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2711 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2712 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2713 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2714 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2715 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2716 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2717 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2718 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2719 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2720 if (strMethod == "sendmany" && n > 1)
2722 string s = params[1].get_str();
2724 if (!read_string(s, v) || v.type() != obj_type)
2725 throw runtime_error("type mismatch");
2726 params[1] = v.get_obj();
2728 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2729 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2730 if (strMethod == "addmultisigaddress" && n > 1)
2732 string s = params[1].get_str();
2734 if (!read_string(s, v) || v.type() != array_type)
2735 throw runtime_error("type mismatch "+s);
2736 params[1] = v.get_array();
2740 Object reply = CallRPC(strMethod, params);
2743 const Value& result = find_value(reply, "result");
2744 const Value& error = find_value(reply, "error");
2746 if (error.type() != null_type)
2749 strPrint = "error: " + write_string(error, false);
2750 int code = find_value(error.get_obj(), "code").get_int();
2756 if (result.type() == null_type)
2758 else if (result.type() == str_type)
2759 strPrint = result.get_str();
2761 strPrint = write_string(result, true);
2764 catch (std::exception& e)
2766 strPrint = string("error: ") + e.what();
2771 PrintException(NULL, "CommandLineRPC()");
2776 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2785 int main(int argc, char *argv[])
2788 // Turn off microsoft heap dump noise
2789 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2790 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2792 setbuf(stdin, NULL);
2793 setbuf(stdout, NULL);
2794 setbuf(stderr, NULL);
2798 if (argc >= 2 && string(argv[1]) == "-server")
2800 printf("server ready\n");
2801 ThreadRPCServer(NULL);
2805 return CommandLineRPC(argc, argv);
2808 catch (std::exception& e) {
2809 PrintException(&e, "main()");
2811 PrintException(NULL, "main()");