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') != string::npos)
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
1006 throw runtime_error("a multisignature address must require at least one key to redeem");
1007 if (keys.size() < nRequired)
1008 throw runtime_error(
1009 strprintf("not enough keys supplied "
1010 "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1011 std::vector<CKey> pubkeys;
1012 pubkeys.resize(keys.size());
1013 for (unsigned int i = 0; i < keys.size(); i++)
1015 const std::string& ks = keys[i].get_str();
1017 // Case 1: bitcoin address and we have full public key:
1018 CBitcoinAddress address(ks);
1019 if (address.IsValid())
1021 if (address.IsScript())
1022 throw runtime_error(
1023 strprintf("%s is a pay-to-script address",ks.c_str()));
1024 std::vector<unsigned char> vchPubKey;
1025 if (!pwalletMain->GetPubKey(address, vchPubKey))
1026 throw runtime_error(
1027 strprintf("no full public key for address %s",ks.c_str()));
1028 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1029 throw runtime_error(" Invalid public key: "+ks);
1032 // Case 2: hex public key
1035 vector<unsigned char> vchPubKey = ParseHex(ks);
1036 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1037 throw runtime_error(" Invalid public key: "+ks);
1041 throw runtime_error(" Invalid public key: "+ks);
1045 // Construct using pay-to-script-hash:
1047 inner.SetMultisig(nRequired, pubkeys);
1049 uint160 scriptHash = Hash160(inner);
1050 CScript scriptPubKey;
1051 scriptPubKey.SetPayToScriptHash(inner);
1052 pwalletMain->AddCScript(inner);
1053 CBitcoinAddress address;
1054 address.SetScriptHash160(scriptHash);
1056 pwalletMain->SetAddressBookName(address, strAccount);
1057 return address.ToString();
1068 nConf = std::numeric_limits<int>::max();
1072 Value ListReceived(const Array& params, bool fByAccounts)
1074 // Minimum confirmations
1076 if (params.size() > 0)
1077 nMinDepth = params[0].get_int();
1079 // Whether to include empty accounts
1080 bool fIncludeEmpty = false;
1081 if (params.size() > 1)
1082 fIncludeEmpty = params[1].get_bool();
1085 map<CBitcoinAddress, tallyitem> mapTally;
1086 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1088 const CWalletTx& wtx = (*it).second;
1090 if (wtx.IsCoinBase() || !wtx.IsFinal())
1093 int nDepth = wtx.GetDepthInMainChain();
1094 if (nDepth < nMinDepth)
1097 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1099 CBitcoinAddress address;
1100 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1103 tallyitem& item = mapTally[address];
1104 item.nAmount += txout.nValue;
1105 item.nConf = min(item.nConf, nDepth);
1111 map<string, tallyitem> mapAccountTally;
1112 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1114 const CBitcoinAddress& address = item.first;
1115 const string& strAccount = item.second;
1116 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1117 if (it == mapTally.end() && !fIncludeEmpty)
1121 int nConf = std::numeric_limits<int>::max();
1122 if (it != mapTally.end())
1124 nAmount = (*it).second.nAmount;
1125 nConf = (*it).second.nConf;
1130 tallyitem& item = mapAccountTally[strAccount];
1131 item.nAmount += nAmount;
1132 item.nConf = min(item.nConf, nConf);
1137 obj.push_back(Pair("address", address.ToString()));
1138 obj.push_back(Pair("account", strAccount));
1139 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1140 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1147 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1149 int64 nAmount = (*it).second.nAmount;
1150 int nConf = (*it).second.nConf;
1152 obj.push_back(Pair("account", (*it).first));
1153 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1154 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1162 Value listreceivedbyaddress(const Array& params, bool fHelp)
1164 if (fHelp || params.size() > 2)
1165 throw runtime_error(
1166 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1167 "[minconf] is the minimum number of confirmations before payments are included.\n"
1168 "[includeempty] whether to include addresses that haven't received any payments.\n"
1169 "Returns an array of objects containing:\n"
1170 " \"address\" : receiving address\n"
1171 " \"account\" : the account of the receiving address\n"
1172 " \"amount\" : total amount received by the address\n"
1173 " \"confirmations\" : number of confirmations of the most recent transaction included");
1175 return ListReceived(params, false);
1178 Value listreceivedbyaccount(const Array& params, bool fHelp)
1180 if (fHelp || params.size() > 2)
1181 throw runtime_error(
1182 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1183 "[minconf] is the minimum number of confirmations before payments are included.\n"
1184 "[includeempty] whether to include accounts that haven't received any payments.\n"
1185 "Returns an array of objects containing:\n"
1186 " \"account\" : the account of the receiving addresses\n"
1187 " \"amount\" : total amount received by addresses with this account\n"
1188 " \"confirmations\" : number of confirmations of the most recent transaction included");
1190 return ListReceived(params, true);
1193 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1195 int64 nGeneratedImmature, nGeneratedMature, nFee;
1196 string strSentAccount;
1197 list<pair<CBitcoinAddress, int64> > listReceived;
1198 list<pair<CBitcoinAddress, int64> > listSent;
1200 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1202 bool fAllAccounts = (strAccount == string("*"));
1204 // Generated blocks assigned to account ""
1205 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1208 entry.push_back(Pair("account", string("")));
1209 if (nGeneratedImmature)
1211 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1212 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1216 entry.push_back(Pair("category", "generate"));
1217 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1220 WalletTxToJSON(wtx, entry);
1221 ret.push_back(entry);
1225 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1227 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1230 entry.push_back(Pair("account", strSentAccount));
1231 entry.push_back(Pair("address", s.first.ToString()));
1232 entry.push_back(Pair("category", "send"));
1233 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1234 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1236 WalletTxToJSON(wtx, entry);
1237 ret.push_back(entry);
1242 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1244 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1247 if (pwalletMain->mapAddressBook.count(r.first))
1248 account = pwalletMain->mapAddressBook[r.first];
1249 if (fAllAccounts || (account == strAccount))
1252 entry.push_back(Pair("account", account));
1253 entry.push_back(Pair("address", r.first.ToString()));
1254 entry.push_back(Pair("category", "receive"));
1255 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1257 WalletTxToJSON(wtx, entry);
1258 ret.push_back(entry);
1264 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1266 bool fAllAccounts = (strAccount == string("*"));
1268 if (fAllAccounts || acentry.strAccount == strAccount)
1271 entry.push_back(Pair("account", acentry.strAccount));
1272 entry.push_back(Pair("category", "move"));
1273 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1274 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1275 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1276 entry.push_back(Pair("comment", acentry.strComment));
1277 ret.push_back(entry);
1281 Value listtransactions(const Array& params, bool fHelp)
1283 if (fHelp || params.size() > 3)
1284 throw runtime_error(
1285 "listtransactions [account] [count=10] [from=0]\n"
1286 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1288 string strAccount = "*";
1289 if (params.size() > 0)
1290 strAccount = params[0].get_str();
1292 if (params.size() > 1)
1293 nCount = params[1].get_int();
1295 if (params.size() > 2)
1296 nFrom = params[2].get_int();
1299 throw JSONRPCError(-8, "Negative count");
1301 throw JSONRPCError(-8, "Negative from");
1304 CWalletDB walletdb(pwalletMain->strWalletFile);
1306 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1307 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1308 typedef multimap<int64, TxPair > TxItems;
1311 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1312 // would make this much faster for applications that do this a lot.
1313 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1315 CWalletTx* wtx = &((*it).second);
1316 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1318 list<CAccountingEntry> acentries;
1319 walletdb.ListAccountCreditDebit(strAccount, acentries);
1320 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1322 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1325 // iterate backwards until we have nCount items to return:
1326 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1328 CWalletTx *const pwtx = (*it).second.first;
1330 ListTransactions(*pwtx, strAccount, 0, true, ret);
1331 CAccountingEntry *const pacentry = (*it).second.second;
1333 AcentryToJSON(*pacentry, strAccount, ret);
1335 if (ret.size() >= (nCount+nFrom)) break;
1337 // ret is newest to oldest
1339 if (nFrom > ret.size()) nFrom = ret.size();
1340 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1341 Array::iterator first = ret.begin();
1342 std::advance(first, nFrom);
1343 Array::iterator last = ret.begin();
1344 std::advance(last, nFrom+nCount);
1346 if (last != ret.end()) ret.erase(last, ret.end());
1347 if (first != ret.begin()) ret.erase(ret.begin(), first);
1349 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1354 Value listaccounts(const Array& params, bool fHelp)
1356 if (fHelp || params.size() > 1)
1357 throw runtime_error(
1358 "listaccounts [minconf=1]\n"
1359 "Returns Object that has account names as keys, account balances as values.");
1362 if (params.size() > 0)
1363 nMinDepth = params[0].get_int();
1365 map<string, int64> mapAccountBalances;
1366 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1367 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1368 mapAccountBalances[entry.second] = 0;
1371 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1373 const CWalletTx& wtx = (*it).second;
1374 int64 nGeneratedImmature, nGeneratedMature, nFee;
1375 string strSentAccount;
1376 list<pair<CBitcoinAddress, int64> > listReceived;
1377 list<pair<CBitcoinAddress, int64> > listSent;
1378 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1379 mapAccountBalances[strSentAccount] -= nFee;
1380 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1381 mapAccountBalances[strSentAccount] -= s.second;
1382 if (wtx.GetDepthInMainChain() >= nMinDepth)
1384 mapAccountBalances[""] += nGeneratedMature;
1385 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1386 if (pwalletMain->mapAddressBook.count(r.first))
1387 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1389 mapAccountBalances[""] += r.second;
1393 list<CAccountingEntry> acentries;
1394 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1395 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1396 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1399 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1400 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1405 Value listsinceblock(const Array& params, bool fHelp)
1408 throw runtime_error(
1409 "listsinceblock [blockhash] [target-confirmations]\n"
1410 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1412 CBlockIndex *pindex = NULL;
1413 int target_confirms = 1;
1415 if (params.size() > 0)
1417 uint256 blockId = 0;
1419 blockId.SetHex(params[0].get_str());
1420 pindex = CBlockLocator(blockId).GetBlockIndex();
1423 if (params.size() > 1)
1425 target_confirms = params[1].get_int();
1427 if (target_confirms < 1)
1428 throw JSONRPCError(-8, "Invalid parameter");
1431 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1435 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1437 CWalletTx tx = (*it).second;
1439 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1440 ListTransactions(tx, "*", 0, true, transactions);
1445 if (target_confirms == 1)
1447 lastblock = hashBestChain;
1451 int target_height = pindexBest->nHeight + 1 - target_confirms;
1454 for (block = pindexBest;
1455 block && block->nHeight > target_height;
1456 block = block->pprev) { }
1458 lastblock = block ? block->GetBlockHash() : 0;
1462 ret.push_back(Pair("transactions", transactions));
1463 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1468 Value gettransaction(const Array& params, bool fHelp)
1470 if (fHelp || params.size() != 1)
1471 throw runtime_error(
1472 "gettransaction <txid>\n"
1473 "Get detailed information about <txid>");
1476 hash.SetHex(params[0].get_str());
1480 if (!pwalletMain->mapWallet.count(hash))
1481 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1482 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1484 int64 nCredit = wtx.GetCredit();
1485 int64 nDebit = wtx.GetDebit();
1486 int64 nNet = nCredit - nDebit;
1487 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1489 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1491 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1493 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1496 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1497 entry.push_back(Pair("details", details));
1503 Value backupwallet(const Array& params, bool fHelp)
1505 if (fHelp || params.size() != 1)
1506 throw runtime_error(
1507 "backupwallet <destination>\n"
1508 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1510 string strDest = params[0].get_str();
1511 BackupWallet(*pwalletMain, strDest);
1517 Value keypoolrefill(const Array& params, bool fHelp)
1519 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1520 throw runtime_error(
1522 "Fills the keypool, requires wallet passphrase to be set.");
1523 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1524 throw runtime_error(
1526 "Fills the keypool.");
1528 if (pwalletMain->IsLocked())
1529 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1531 pwalletMain->TopUpKeyPool();
1533 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1534 throw JSONRPCError(-4, "Error refreshing keypool.");
1540 void ThreadTopUpKeyPool(void* parg)
1542 pwalletMain->TopUpKeyPool();
1545 void ThreadCleanWalletPassphrase(void* parg)
1547 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1549 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1551 if (nWalletUnlockTime == 0)
1553 nWalletUnlockTime = nMyWakeTime;
1557 if (nWalletUnlockTime==0)
1559 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1563 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1565 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1569 if (nWalletUnlockTime)
1571 nWalletUnlockTime = 0;
1572 pwalletMain->Lock();
1577 if (nWalletUnlockTime < nMyWakeTime)
1578 nWalletUnlockTime = nMyWakeTime;
1581 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1583 delete (int64*)parg;
1586 Value walletpassphrase(const Array& params, bool fHelp)
1588 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1589 throw runtime_error(
1590 "walletpassphrase <passphrase> <timeout>\n"
1591 "Stores the wallet decryption key in memory for <timeout> seconds.");
1594 if (!pwalletMain->IsCrypted())
1595 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1597 if (!pwalletMain->IsLocked())
1598 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1600 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1601 SecureString strWalletPass;
1602 strWalletPass.reserve(100);
1603 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1604 // Alternately, find a way to make params[0] mlock()'d to begin with.
1605 strWalletPass = params[0].get_str().c_str();
1607 if (strWalletPass.length() > 0)
1609 if (!pwalletMain->Unlock(strWalletPass))
1610 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1613 throw runtime_error(
1614 "walletpassphrase <passphrase> <timeout>\n"
1615 "Stores the wallet decryption key in memory for <timeout> seconds.");
1617 CreateThread(ThreadTopUpKeyPool, NULL);
1618 int64* pnSleepTime = new int64(params[1].get_int64());
1619 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1625 Value walletpassphrasechange(const Array& params, bool fHelp)
1627 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1628 throw runtime_error(
1629 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1630 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1633 if (!pwalletMain->IsCrypted())
1634 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1636 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1637 // Alternately, find a way to make params[0] mlock()'d to begin with.
1638 SecureString strOldWalletPass;
1639 strOldWalletPass.reserve(100);
1640 strOldWalletPass = params[0].get_str().c_str();
1642 SecureString strNewWalletPass;
1643 strNewWalletPass.reserve(100);
1644 strNewWalletPass = params[1].get_str().c_str();
1646 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1647 throw runtime_error(
1648 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1649 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1651 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1652 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1658 Value walletlock(const Array& params, bool fHelp)
1660 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1661 throw runtime_error(
1663 "Removes the wallet encryption key from memory, locking the wallet.\n"
1664 "After calling this method, you will need to call walletpassphrase again\n"
1665 "before being able to call any methods which require the wallet to be unlocked.");
1668 if (!pwalletMain->IsCrypted())
1669 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1671 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1673 pwalletMain->Lock();
1674 nWalletUnlockTime = 0;
1681 Value encryptwallet(const Array& params, bool fHelp)
1683 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1684 throw runtime_error(
1685 "encryptwallet <passphrase>\n"
1686 "Encrypts the wallet with <passphrase>.");
1689 if (pwalletMain->IsCrypted())
1690 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1693 // shutting down via RPC while the GUI is running does not work (yet):
1694 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1697 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1698 // Alternately, find a way to make params[0] mlock()'d to begin with.
1699 SecureString strWalletPass;
1700 strWalletPass.reserve(100);
1701 strWalletPass = params[0].get_str().c_str();
1703 if (strWalletPass.length() < 1)
1704 throw runtime_error(
1705 "encryptwallet <passphrase>\n"
1706 "Encrypts the wallet with <passphrase>.");
1708 if (!pwalletMain->EncryptWallet(strWalletPass))
1709 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1711 // BDB seems to have a bad habit of writing old data into
1712 // slack space in .dat files; that is bad if the old data is
1713 // unencrypted private keys. So:
1714 CreateThread(Shutdown, NULL);
1715 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1719 Value validateaddress(const Array& params, bool fHelp)
1721 if (fHelp || params.size() != 1)
1722 throw runtime_error(
1723 "validateaddress <bitcoinaddress>\n"
1724 "Return information about <bitcoinaddress>.");
1726 CBitcoinAddress address(params[0].get_str());
1727 bool isValid = address.IsValid();
1730 ret.push_back(Pair("isvalid", isValid));
1733 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1734 // version of the address:
1735 string currentAddress = address.ToString();
1736 ret.push_back(Pair("address", currentAddress));
1737 if (pwalletMain->HaveKey(address))
1739 ret.push_back(Pair("ismine", true));
1740 std::vector<unsigned char> vchPubKey;
1741 pwalletMain->GetPubKey(address, vchPubKey);
1742 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1744 key.SetPubKey(vchPubKey);
1745 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1747 else if (pwalletMain->HaveCScript(address.GetHash160()))
1749 ret.push_back(Pair("isscript", true));
1751 pwalletMain->GetCScript(address.GetHash160(), subscript);
1752 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1753 std::vector<CBitcoinAddress> addresses;
1754 txnouttype whichType;
1756 ExtractAddresses(subscript, whichType, addresses, nRequired);
1757 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1759 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1760 a.push_back(addr.ToString());
1761 ret.push_back(Pair("addresses", a));
1762 if (whichType == TX_MULTISIG)
1763 ret.push_back(Pair("sigsrequired", nRequired));
1766 ret.push_back(Pair("ismine", false));
1767 if (pwalletMain->mapAddressBook.count(address))
1768 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1773 Value getwork(const Array& params, bool fHelp)
1775 if (fHelp || params.size() > 1)
1776 throw runtime_error(
1778 "If [data] is not specified, returns formatted hash data to work on:\n"
1779 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1780 " \"data\" : block data\n"
1781 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1782 " \"target\" : little endian hash target\n"
1783 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1786 throw JSONRPCError(-9, "Bitcoin is not connected!");
1788 if (IsInitialBlockDownload())
1789 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1791 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1792 static mapNewBlock_t mapNewBlock;
1793 static vector<CBlock*> vNewBlock;
1794 static CReserveKey reservekey(pwalletMain);
1796 if (params.size() == 0)
1799 static unsigned int nTransactionsUpdatedLast;
1800 static CBlockIndex* pindexPrev;
1801 static int64 nStart;
1802 static CBlock* pblock;
1803 if (pindexPrev != pindexBest ||
1804 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1806 if (pindexPrev != pindexBest)
1808 // Deallocate old blocks since they're obsolete now
1809 mapNewBlock.clear();
1810 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1814 nTransactionsUpdatedLast = nTransactionsUpdated;
1815 pindexPrev = pindexBest;
1819 pblock = CreateNewBlock(reservekey);
1821 throw JSONRPCError(-7, "Out of memory");
1822 vNewBlock.push_back(pblock);
1826 pblock->UpdateTime(pindexPrev);
1829 // Update nExtraNonce
1830 static unsigned int nExtraNonce = 0;
1831 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1834 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1836 // Prebuild hash buffers
1840 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1842 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1845 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1846 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1847 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1848 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1854 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1855 if (vchData.size() != 128)
1856 throw JSONRPCError(-8, "Invalid parameter");
1857 CBlock* pdata = (CBlock*)&vchData[0];
1860 for (int i = 0; i < 128/4; i++)
1861 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1864 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1866 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1868 pblock->nTime = pdata->nTime;
1869 pblock->nNonce = pdata->nNonce;
1870 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1871 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1873 return CheckWork(pblock, *pwalletMain, reservekey);
1878 Value getmemorypool(const Array& params, bool fHelp)
1880 if (fHelp || params.size() > 1)
1881 throw runtime_error(
1882 "getmemorypool [data]\n"
1883 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1884 " \"version\" : block version\n"
1885 " \"previousblockhash\" : hash of current highest block\n"
1886 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1887 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1888 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1889 " \"time\" : timestamp appropriate for next block\n"
1890 " \"mintime\" : minimum timestamp appropriate for next block\n"
1891 " \"curtime\" : current timestamp\n"
1892 " \"bits\" : compressed target of next block\n"
1893 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1895 if (params.size() == 0)
1898 throw JSONRPCError(-9, "Bitcoin is not connected!");
1900 if (IsInitialBlockDownload())
1901 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1903 static CReserveKey reservekey(pwalletMain);
1906 static unsigned int nTransactionsUpdatedLast;
1907 static CBlockIndex* pindexPrev;
1908 static int64 nStart;
1909 static CBlock* pblock;
1910 if (pindexPrev != pindexBest ||
1911 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1913 nTransactionsUpdatedLast = nTransactionsUpdated;
1914 pindexPrev = pindexBest;
1920 pblock = CreateNewBlock(reservekey);
1922 throw JSONRPCError(-7, "Out of memory");
1926 pblock->UpdateTime(pindexPrev);
1930 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1937 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1941 result.push_back(Pair("version", pblock->nVersion));
1942 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1943 result.push_back(Pair("transactions", transactions));
1944 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1945 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1946 result.push_back(Pair("time", (int64_t)pblock->nTime));
1947 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1948 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1949 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1956 CDataStream ssBlock(ParseHex(params[0].get_str()));
1960 return ProcessBlock(NULL, &pblock);
1964 Value getblockhash(const Array& params, bool fHelp)
1966 if (fHelp || params.size() != 1)
1967 throw runtime_error(
1968 "getblockhash <index>\n"
1969 "Returns hash of block in best-block-chain at <index>.");
1971 int nHeight = params[0].get_int();
1972 if (nHeight < 0 || nHeight > nBestHeight)
1973 throw runtime_error("Block number out of range.");
1976 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1977 while (pblockindex->nHeight > nHeight)
1978 pblockindex = pblockindex->pprev;
1979 return pblockindex->phashBlock->GetHex();
1982 Value getblock(const Array& params, bool fHelp)
1984 if (fHelp || params.size() != 1)
1985 throw runtime_error(
1987 "Returns details of a block with given block-hash.");
1989 std::string strHash = params[0].get_str();
1990 uint256 hash(strHash);
1992 if (mapBlockIndex.count(hash) == 0)
1993 throw JSONRPCError(-5, "Block not found");
1996 CBlockIndex* pblockindex = mapBlockIndex[hash];
1997 block.ReadFromDisk(pblockindex, true);
1999 return blockToJSON(block, pblockindex);
2016 pair<string, rpcfn_type> pCallTable[] =
2018 make_pair("help", &help),
2019 make_pair("stop", &stop),
2020 make_pair("getblockcount", &getblockcount),
2021 make_pair("getblocknumber", &getblocknumber),
2022 make_pair("getconnectioncount", &getconnectioncount),
2023 make_pair("getdifficulty", &getdifficulty),
2024 make_pair("getgenerate", &getgenerate),
2025 make_pair("setgenerate", &setgenerate),
2026 make_pair("gethashespersec", &gethashespersec),
2027 make_pair("getinfo", &getinfo),
2028 make_pair("getmininginfo", &getmininginfo),
2029 make_pair("getnewaddress", &getnewaddress),
2030 make_pair("getaccountaddress", &getaccountaddress),
2031 make_pair("setaccount", &setaccount),
2032 make_pair("getaccount", &getaccount),
2033 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2034 make_pair("sendtoaddress", &sendtoaddress),
2035 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2036 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2037 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2038 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2039 make_pair("backupwallet", &backupwallet),
2040 make_pair("keypoolrefill", &keypoolrefill),
2041 make_pair("walletpassphrase", &walletpassphrase),
2042 make_pair("walletpassphrasechange", &walletpassphrasechange),
2043 make_pair("walletlock", &walletlock),
2044 make_pair("encryptwallet", &encryptwallet),
2045 make_pair("validateaddress", &validateaddress),
2046 make_pair("getbalance", &getbalance),
2047 make_pair("move", &movecmd),
2048 make_pair("sendfrom", &sendfrom),
2049 make_pair("sendmany", &sendmany),
2050 make_pair("addmultisigaddress", &addmultisigaddress),
2051 make_pair("getblock", &getblock),
2052 make_pair("getblockhash", &getblockhash),
2053 make_pair("gettransaction", &gettransaction),
2054 make_pair("listtransactions", &listtransactions),
2055 make_pair("signmessage", &signmessage),
2056 make_pair("verifymessage", &verifymessage),
2057 make_pair("getwork", &getwork),
2058 make_pair("listaccounts", &listaccounts),
2059 make_pair("settxfee", &settxfee),
2060 make_pair("getmemorypool", &getmemorypool),
2061 make_pair("listsinceblock", &listsinceblock),
2062 make_pair("dumpprivkey", &dumpprivkey),
2063 make_pair("importprivkey", &importprivkey)
2065 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2067 string pAllowInSafeMode[] =
2072 "getblocknumber", // deprecated
2073 "getconnectioncount",
2081 "getaccountaddress",
2083 "getaddressesbyaccount",
2092 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2100 // This ain't Apache. We're just using HTTP header for the length field
2101 // and to be compatible with other JSON-RPC implementations.
2104 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2107 s << "POST / HTTP/1.1\r\n"
2108 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2109 << "Host: 127.0.0.1\r\n"
2110 << "Content-Type: application/json\r\n"
2111 << "Content-Length: " << strMsg.size() << "\r\n"
2112 << "Connection: close\r\n"
2113 << "Accept: application/json\r\n";
2114 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2115 s << item.first << ": " << item.second << "\r\n";
2116 s << "\r\n" << strMsg;
2121 string rfc1123Time()
2126 struct tm* now_gmt = gmtime(&now);
2127 string locale(setlocale(LC_TIME, NULL));
2128 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2129 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2130 setlocale(LC_TIME, locale.c_str());
2131 return string(buffer);
2134 static string HTTPReply(int nStatus, const string& strMsg)
2137 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2139 "Server: bitcoin-json-rpc/%s\r\n"
2140 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2141 "Content-Type: text/html\r\n"
2142 "Content-Length: 296\r\n"
2144 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2145 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2148 "<TITLE>Error</TITLE>\r\n"
2149 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2151 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2152 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2153 const char *cStatus;
2154 if (nStatus == 200) cStatus = "OK";
2155 else if (nStatus == 400) cStatus = "Bad Request";
2156 else if (nStatus == 403) cStatus = "Forbidden";
2157 else if (nStatus == 404) cStatus = "Not Found";
2158 else if (nStatus == 500) cStatus = "Internal Server Error";
2161 "HTTP/1.1 %d %s\r\n"
2163 "Connection: close\r\n"
2164 "Content-Length: %d\r\n"
2165 "Content-Type: application/json\r\n"
2166 "Server: bitcoin-json-rpc/%s\r\n"
2171 rfc1123Time().c_str(),
2173 FormatFullVersion().c_str(),
2177 int ReadHTTPStatus(std::basic_istream<char>& stream)
2180 getline(stream, str);
2181 vector<string> vWords;
2182 boost::split(vWords, str, boost::is_any_of(" "));
2183 if (vWords.size() < 2)
2185 return atoi(vWords[1].c_str());
2188 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2194 std::getline(stream, str);
2195 if (str.empty() || str == "\r")
2197 string::size_type nColon = str.find(":");
2198 if (nColon != string::npos)
2200 string strHeader = str.substr(0, nColon);
2201 boost::trim(strHeader);
2202 boost::to_lower(strHeader);
2203 string strValue = str.substr(nColon+1);
2204 boost::trim(strValue);
2205 mapHeadersRet[strHeader] = strValue;
2206 if (strHeader == "content-length")
2207 nLen = atoi(strValue.c_str());
2213 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2215 mapHeadersRet.clear();
2219 int nStatus = ReadHTTPStatus(stream);
2222 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2223 if (nLen < 0 || nLen > MAX_SIZE)
2229 vector<char> vch(nLen);
2230 stream.read(&vch[0], nLen);
2231 strMessageRet = string(vch.begin(), vch.end());
2237 bool HTTPAuthorized(map<string, string>& mapHeaders)
2239 string strAuth = mapHeaders["authorization"];
2240 if (strAuth.substr(0,6) != "Basic ")
2242 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2243 string strUserPass = DecodeBase64(strUserPass64);
2244 return strUserPass == strRPCUserColonPass;
2248 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2249 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2250 // unspecified (HTTP errors and contents of 'error').
2252 // 1.0 spec: http://json-rpc.org/wiki/specification
2253 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2254 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2257 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2260 request.push_back(Pair("method", strMethod));
2261 request.push_back(Pair("params", params));
2262 request.push_back(Pair("id", id));
2263 return write_string(Value(request), false) + "\n";
2266 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2269 if (error.type() != null_type)
2270 reply.push_back(Pair("result", Value::null));
2272 reply.push_back(Pair("result", result));
2273 reply.push_back(Pair("error", error));
2274 reply.push_back(Pair("id", id));
2275 return write_string(Value(reply), false) + "\n";
2278 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2280 // Send error reply from json-rpc error object
2282 int code = find_value(objError, "code").get_int();
2283 if (code == -32600) nStatus = 400;
2284 else if (code == -32601) nStatus = 404;
2285 string strReply = JSONRPCReply(Value::null, objError, id);
2286 stream << HTTPReply(nStatus, strReply) << std::flush;
2289 bool ClientAllowed(const string& strAddress)
2291 if (strAddress == asio::ip::address_v4::loopback().to_string())
2293 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2294 BOOST_FOREACH(string strAllow, vAllow)
2295 if (WildcardMatch(strAddress, strAllow))
2302 // IOStream device that speaks SSL but can also speak non-SSL
2304 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2306 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2308 fUseSSL = fUseSSLIn;
2309 fNeedHandshake = fUseSSLIn;
2312 void handshake(ssl::stream_base::handshake_type role)
2314 if (!fNeedHandshake) return;
2315 fNeedHandshake = false;
2316 stream.handshake(role);
2318 std::streamsize read(char* s, std::streamsize n)
2320 handshake(ssl::stream_base::server); // HTTPS servers read first
2321 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2322 return stream.next_layer().read_some(asio::buffer(s, n));
2324 std::streamsize write(const char* s, std::streamsize n)
2326 handshake(ssl::stream_base::client); // HTTPS clients write first
2327 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2328 return asio::write(stream.next_layer(), asio::buffer(s, n));
2330 bool connect(const std::string& server, const std::string& port)
2332 ip::tcp::resolver resolver(stream.get_io_service());
2333 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2334 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2335 ip::tcp::resolver::iterator end;
2336 boost::system::error_code error = asio::error::host_not_found;
2337 while (error && endpoint_iterator != end)
2339 stream.lowest_layer().close();
2340 stream.lowest_layer().connect(*endpoint_iterator++, error);
2348 bool fNeedHandshake;
2354 void ThreadRPCServer(void* parg)
2356 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2359 vnThreadsRunning[THREAD_RPCSERVER]++;
2360 ThreadRPCServer2(parg);
2361 vnThreadsRunning[THREAD_RPCSERVER]--;
2363 catch (std::exception& e) {
2364 vnThreadsRunning[THREAD_RPCSERVER]--;
2365 PrintException(&e, "ThreadRPCServer()");
2367 vnThreadsRunning[THREAD_RPCSERVER]--;
2368 PrintException(NULL, "ThreadRPCServer()");
2370 printf("ThreadRPCServer exiting\n");
2374 extern bool HACK_SHUTDOWN;
2377 void ThreadRPCServer2(void* parg)
2379 printf("ThreadRPCServer started\n");
2381 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2382 if (mapArgs["-rpcpassword"] == "")
2384 unsigned char rand_pwd[32];
2385 RAND_bytes(rand_pwd, 32);
2386 string strWhatAmI = "To use bitcoind";
2387 if (mapArgs.count("-server"))
2388 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2389 else if (mapArgs.count("-daemon"))
2390 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2391 ThreadSafeMessageBox(strprintf(
2392 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2393 "It is recommended you use the following random password:\n"
2394 "rpcuser=bitcoinrpc\n"
2396 "(you do not need to remember this password)\n"
2397 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2399 GetConfigFile().c_str(),
2400 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2401 _("Error"), wxOK | wxMODAL);
2403 CreateThread(Shutdown, NULL);
2408 bool fUseSSL = GetBoolArg("-rpcssl");
2409 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2411 asio::io_service io_service;
2412 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));
2418 ip::tcp::acceptor acceptor(io_service);
2421 acceptor.open(endpoint.protocol());
2422 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2423 acceptor.bind(endpoint);
2424 acceptor.listen(socket_base::max_connections);
2426 catch(boost::system::system_error &e)
2428 HACK_SHUTDOWN = true;
2429 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2430 _("Error"), wxOK | wxMODAL);
2436 ssl::context context(io_service, ssl::context::sslv23);
2439 context.set_options(ssl::context::no_sslv2);
2440 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2441 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2442 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2443 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2444 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2445 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2446 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2447 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2449 string ciphers = GetArg("-rpcsslciphers",
2450 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2451 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2455 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2460 // Accept connection
2462 SSLStream sslStream(io_service, context);
2463 SSLIOStreamDevice d(sslStream, fUseSSL);
2464 iostreams::stream<SSLIOStreamDevice> stream(d);
2466 ip::tcp::iostream stream;
2469 ip::tcp::endpoint peer;
2470 vnThreadsRunning[THREAD_RPCSERVER]--;
2472 acceptor.accept(sslStream.lowest_layer(), peer);
2474 acceptor.accept(*stream.rdbuf(), peer);
2476 vnThreadsRunning[4]++;
2480 // Restrict callers by IP
2481 if (!ClientAllowed(peer.address().to_string()))
2483 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2485 stream << HTTPReply(403, "") << std::flush;
2489 map<string, string> mapHeaders;
2492 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2493 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2496 printf("ThreadRPCServer ReadHTTP timeout\n");
2500 // Check authorization
2501 if (mapHeaders.count("authorization") == 0)
2503 stream << HTTPReply(401, "") << std::flush;
2506 if (!HTTPAuthorized(mapHeaders))
2508 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2509 /* Deter brute-forcing short passwords.
2510 If this results in a DOS the user really
2511 shouldn't have their RPC port exposed.*/
2512 if (mapArgs["-rpcpassword"].size() < 20)
2515 stream << HTTPReply(401, "") << std::flush;
2519 Value id = Value::null;
2524 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2525 throw JSONRPCError(-32700, "Parse error");
2526 const Object& request = valRequest.get_obj();
2528 // Parse id now so errors from here on will have the id
2529 id = find_value(request, "id");
2532 Value valMethod = find_value(request, "method");
2533 if (valMethod.type() == null_type)
2534 throw JSONRPCError(-32600, "Missing method");
2535 if (valMethod.type() != str_type)
2536 throw JSONRPCError(-32600, "Method must be a string");
2537 string strMethod = valMethod.get_str();
2538 if (strMethod != "getwork" && strMethod != "getmemorypool")
2539 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2542 Value valParams = find_value(request, "params");
2544 if (valParams.type() == array_type)
2545 params = valParams.get_array();
2546 else if (valParams.type() == null_type)
2549 throw JSONRPCError(-32600, "Params must be an array");
2552 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2553 if (mi == mapCallTable.end())
2554 throw JSONRPCError(-32601, "Method not found");
2556 // Observe safe mode
2557 string strWarning = GetWarnings("rpc");
2558 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2559 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2565 CRITICAL_BLOCK(cs_main)
2566 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2567 result = (*(*mi).second)(params, false);
2570 string strReply = JSONRPCReply(result, Value::null, id);
2571 stream << HTTPReply(200, strReply) << std::flush;
2573 catch (std::exception& e)
2575 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2578 catch (Object& objError)
2580 ErrorReply(stream, objError, id);
2582 catch (std::exception& e)
2584 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2592 Object CallRPC(const string& strMethod, const Array& params)
2594 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2595 throw runtime_error(strprintf(
2596 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2597 "If the file does not exist, create it with owner-readable-only file permissions."),
2598 GetConfigFile().c_str()));
2600 // Connect to localhost
2601 bool fUseSSL = GetBoolArg("-rpcssl");
2603 asio::io_service io_service;
2604 ssl::context context(io_service, ssl::context::sslv23);
2605 context.set_options(ssl::context::no_sslv2);
2606 SSLStream sslStream(io_service, context);
2607 SSLIOStreamDevice d(sslStream, fUseSSL);
2608 iostreams::stream<SSLIOStreamDevice> stream(d);
2609 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2610 throw runtime_error("couldn't connect to server");
2613 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2615 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2617 throw runtime_error("couldn't connect to server");
2621 // HTTP basic authentication
2622 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2623 map<string, string> mapRequestHeaders;
2624 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2627 string strRequest = JSONRPCRequest(strMethod, params, 1);
2628 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2629 stream << strPost << std::flush;
2632 map<string, string> mapHeaders;
2634 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2636 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2637 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2638 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2639 else if (strReply.empty())
2640 throw runtime_error("no response from server");
2644 if (!read_string(strReply, valReply))
2645 throw runtime_error("couldn't parse reply from server");
2646 const Object& reply = valReply.get_obj();
2648 throw runtime_error("expected reply to have result, error and id properties");
2656 template<typename T>
2657 void ConvertTo(Value& value)
2659 if (value.type() == str_type)
2661 // reinterpret string as unquoted json value
2663 if (!read_string(value.get_str(), value2))
2664 throw runtime_error("type mismatch");
2665 value = value2.get_value<T>();
2669 value = value.get_value<T>();
2673 int CommandLineRPC(int argc, char *argv[])
2680 while (argc > 1 && IsSwitchChar(argv[1][0]))
2688 throw runtime_error("too few parameters");
2689 string strMethod = argv[1];
2691 // Parameters default to strings
2693 for (int i = 2; i < argc; i++)
2694 params.push_back(argv[i]);
2695 int n = params.size();
2698 // Special case non-string parameter types
2700 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2701 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2702 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2703 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2704 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2705 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2706 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2707 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2708 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2709 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2710 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2711 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2712 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2713 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2714 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2715 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2716 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2717 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2718 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2719 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2720 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2721 if (strMethod == "sendmany" && n > 1)
2723 string s = params[1].get_str();
2725 if (!read_string(s, v) || v.type() != obj_type)
2726 throw runtime_error("type mismatch");
2727 params[1] = v.get_obj();
2729 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2730 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2731 if (strMethod == "addmultisigaddress" && n > 1)
2733 string s = params[1].get_str();
2735 if (!read_string(s, v) || v.type() != array_type)
2736 throw runtime_error("type mismatch "+s);
2737 params[1] = v.get_array();
2741 Object reply = CallRPC(strMethod, params);
2744 const Value& result = find_value(reply, "result");
2745 const Value& error = find_value(reply, "error");
2747 if (error.type() != null_type)
2750 strPrint = "error: " + write_string(error, false);
2751 int code = find_value(error.get_obj(), "code").get_int();
2757 if (result.type() == null_type)
2759 else if (result.type() == str_type)
2760 strPrint = result.get_str();
2762 strPrint = write_string(result, true);
2765 catch (std::exception& e)
2767 strPrint = string("error: ") + e.what();
2772 PrintException(NULL, "CommandLineRPC()");
2777 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2786 int main(int argc, char *argv[])
2789 // Turn off microsoft heap dump noise
2790 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2791 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2793 setbuf(stdin, NULL);
2794 setbuf(stdout, NULL);
2795 setbuf(stderr, NULL);
2799 if (argc >= 2 && string(argv[1]) == "-server")
2801 printf("server ready\n");
2802 ThreadRPCServer(NULL);
2806 return CommandLineRPC(argc, argv);
2809 catch (std::exception& e) {
2810 PrintException(&e, "main()");
2812 PrintException(NULL, "main()");