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
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 [blockhash] [target-confirmations]\n"
1408 "Get all transactions in blocks since block [blockhash], 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)
1445 lastblock = hashBestChain;
1449 int target_height = pindexBest->nHeight + 1 - target_confirms;
1452 for (block = pindexBest;
1453 block && block->nHeight > target_height;
1454 block = block->pprev) { }
1456 lastblock = block ? block->GetBlockHash() : 0;
1460 ret.push_back(Pair("transactions", transactions));
1461 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1466 Value gettransaction(const Array& params, bool fHelp)
1468 if (fHelp || params.size() != 1)
1469 throw runtime_error(
1470 "gettransaction <txid>\n"
1471 "Get detailed information about <txid>");
1474 hash.SetHex(params[0].get_str());
1478 if (!pwalletMain->mapWallet.count(hash))
1479 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1480 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1482 int64 nCredit = wtx.GetCredit();
1483 int64 nDebit = wtx.GetDebit();
1484 int64 nNet = nCredit - nDebit;
1485 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1487 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1489 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1491 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1494 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1495 entry.push_back(Pair("details", details));
1501 Value backupwallet(const Array& params, bool fHelp)
1503 if (fHelp || params.size() != 1)
1504 throw runtime_error(
1505 "backupwallet <destination>\n"
1506 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1508 string strDest = params[0].get_str();
1509 BackupWallet(*pwalletMain, strDest);
1515 Value keypoolrefill(const Array& params, bool fHelp)
1517 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1518 throw runtime_error(
1520 "Fills the keypool, requires wallet passphrase to be set.");
1521 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1522 throw runtime_error(
1524 "Fills the keypool.");
1526 if (pwalletMain->IsLocked())
1527 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1529 pwalletMain->TopUpKeyPool();
1531 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1532 throw JSONRPCError(-4, "Error refreshing keypool.");
1538 void ThreadTopUpKeyPool(void* parg)
1540 pwalletMain->TopUpKeyPool();
1543 void ThreadCleanWalletPassphrase(void* parg)
1545 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1547 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1549 if (nWalletUnlockTime == 0)
1551 nWalletUnlockTime = nMyWakeTime;
1555 if (nWalletUnlockTime==0)
1557 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1561 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1563 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1567 if (nWalletUnlockTime)
1569 nWalletUnlockTime = 0;
1570 pwalletMain->Lock();
1575 if (nWalletUnlockTime < nMyWakeTime)
1576 nWalletUnlockTime = nMyWakeTime;
1579 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1581 delete (int64*)parg;
1584 Value walletpassphrase(const Array& params, bool fHelp)
1586 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1587 throw runtime_error(
1588 "walletpassphrase <passphrase> <timeout>\n"
1589 "Stores the wallet decryption key in memory for <timeout> seconds.");
1592 if (!pwalletMain->IsCrypted())
1593 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1595 if (!pwalletMain->IsLocked())
1596 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1598 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1599 SecureString strWalletPass;
1600 strWalletPass.reserve(100);
1601 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1602 // Alternately, find a way to make params[0] mlock()'d to begin with.
1603 strWalletPass = params[0].get_str().c_str();
1605 if (strWalletPass.length() > 0)
1607 if (!pwalletMain->Unlock(strWalletPass))
1608 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1611 throw runtime_error(
1612 "walletpassphrase <passphrase> <timeout>\n"
1613 "Stores the wallet decryption key in memory for <timeout> seconds.");
1615 CreateThread(ThreadTopUpKeyPool, NULL);
1616 int64* pnSleepTime = new int64(params[1].get_int64());
1617 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1623 Value walletpassphrasechange(const Array& params, bool fHelp)
1625 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1626 throw runtime_error(
1627 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1628 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1631 if (!pwalletMain->IsCrypted())
1632 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1634 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1635 // Alternately, find a way to make params[0] mlock()'d to begin with.
1636 SecureString strOldWalletPass;
1637 strOldWalletPass.reserve(100);
1638 strOldWalletPass = params[0].get_str().c_str();
1640 SecureString strNewWalletPass;
1641 strNewWalletPass.reserve(100);
1642 strNewWalletPass = params[1].get_str().c_str();
1644 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1645 throw runtime_error(
1646 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1647 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1649 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1650 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1656 Value walletlock(const Array& params, bool fHelp)
1658 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1659 throw runtime_error(
1661 "Removes the wallet encryption key from memory, locking the wallet.\n"
1662 "After calling this method, you will need to call walletpassphrase again\n"
1663 "before being able to call any methods which require the wallet to be unlocked.");
1666 if (!pwalletMain->IsCrypted())
1667 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1669 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1671 pwalletMain->Lock();
1672 nWalletUnlockTime = 0;
1679 Value encryptwallet(const Array& params, bool fHelp)
1681 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1682 throw runtime_error(
1683 "encryptwallet <passphrase>\n"
1684 "Encrypts the wallet with <passphrase>.");
1687 if (pwalletMain->IsCrypted())
1688 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1691 // shutting down via RPC while the GUI is running does not work (yet):
1692 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1695 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1696 // Alternately, find a way to make params[0] mlock()'d to begin with.
1697 SecureString strWalletPass;
1698 strWalletPass.reserve(100);
1699 strWalletPass = params[0].get_str().c_str();
1701 if (strWalletPass.length() < 1)
1702 throw runtime_error(
1703 "encryptwallet <passphrase>\n"
1704 "Encrypts the wallet with <passphrase>.");
1706 if (!pwalletMain->EncryptWallet(strWalletPass))
1707 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1709 // BDB seems to have a bad habit of writing old data into
1710 // slack space in .dat files; that is bad if the old data is
1711 // unencrypted private keys. So:
1712 CreateThread(Shutdown, NULL);
1713 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1717 Value validateaddress(const Array& params, bool fHelp)
1719 if (fHelp || params.size() != 1)
1720 throw runtime_error(
1721 "validateaddress <bitcoinaddress>\n"
1722 "Return information about <bitcoinaddress>.");
1724 CBitcoinAddress address(params[0].get_str());
1725 bool isValid = address.IsValid();
1728 ret.push_back(Pair("isvalid", isValid));
1731 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1732 // version of the address:
1733 string currentAddress = address.ToString();
1734 ret.push_back(Pair("address", currentAddress));
1735 if (pwalletMain->HaveKey(address))
1737 ret.push_back(Pair("ismine", true));
1738 std::vector<unsigned char> vchPubKey;
1739 pwalletMain->GetPubKey(address, vchPubKey);
1740 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1742 key.SetPubKey(vchPubKey);
1743 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1745 else if (pwalletMain->HaveCScript(address.GetHash160()))
1747 ret.push_back(Pair("isscript", true));
1749 pwalletMain->GetCScript(address.GetHash160(), subscript);
1750 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1751 std::vector<CBitcoinAddress> addresses;
1752 txnouttype whichType;
1754 ExtractAddresses(subscript, whichType, addresses, nRequired);
1755 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1757 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1758 a.push_back(addr.ToString());
1759 ret.push_back(Pair("addresses", a));
1760 if (whichType == TX_MULTISIG)
1761 ret.push_back(Pair("sigsrequired", nRequired));
1764 ret.push_back(Pair("ismine", false));
1765 if (pwalletMain->mapAddressBook.count(address))
1766 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1771 Value getwork(const Array& params, bool fHelp)
1773 if (fHelp || params.size() > 1)
1774 throw runtime_error(
1776 "If [data] is not specified, returns formatted hash data to work on:\n"
1777 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1778 " \"data\" : block data\n"
1779 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1780 " \"target\" : little endian hash target\n"
1781 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1784 throw JSONRPCError(-9, "Bitcoin is not connected!");
1786 if (IsInitialBlockDownload())
1787 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1789 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1790 static mapNewBlock_t mapNewBlock;
1791 static vector<CBlock*> vNewBlock;
1792 static CReserveKey reservekey(pwalletMain);
1794 if (params.size() == 0)
1797 static unsigned int nTransactionsUpdatedLast;
1798 static CBlockIndex* pindexPrev;
1799 static int64 nStart;
1800 static CBlock* pblock;
1801 if (pindexPrev != pindexBest ||
1802 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1804 if (pindexPrev != pindexBest)
1806 // Deallocate old blocks since they're obsolete now
1807 mapNewBlock.clear();
1808 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1812 nTransactionsUpdatedLast = nTransactionsUpdated;
1813 pindexPrev = pindexBest;
1817 pblock = CreateNewBlock(reservekey);
1819 throw JSONRPCError(-7, "Out of memory");
1820 vNewBlock.push_back(pblock);
1824 pblock->UpdateTime(pindexPrev);
1827 // Update nExtraNonce
1828 static unsigned int nExtraNonce = 0;
1829 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1832 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1834 // Prebuild hash buffers
1838 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1840 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1843 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1844 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1845 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1846 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1852 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1853 if (vchData.size() != 128)
1854 throw JSONRPCError(-8, "Invalid parameter");
1855 CBlock* pdata = (CBlock*)&vchData[0];
1858 for (int i = 0; i < 128/4; i++)
1859 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1862 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1864 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1866 pblock->nTime = pdata->nTime;
1867 pblock->nNonce = pdata->nNonce;
1868 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1869 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1871 return CheckWork(pblock, *pwalletMain, reservekey);
1876 Value getmemorypool(const Array& params, bool fHelp)
1878 if (fHelp || params.size() > 1)
1879 throw runtime_error(
1880 "getmemorypool [data]\n"
1881 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1882 " \"version\" : block version\n"
1883 " \"previousblockhash\" : hash of current highest block\n"
1884 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1885 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1886 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1887 " \"time\" : timestamp appropriate for next block\n"
1888 " \"mintime\" : minimum timestamp appropriate for next block\n"
1889 " \"curtime\" : current timestamp\n"
1890 " \"bits\" : compressed target of next block\n"
1891 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1893 if (params.size() == 0)
1896 throw JSONRPCError(-9, "Bitcoin is not connected!");
1898 if (IsInitialBlockDownload())
1899 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1901 static CReserveKey reservekey(pwalletMain);
1904 static unsigned int nTransactionsUpdatedLast;
1905 static CBlockIndex* pindexPrev;
1906 static int64 nStart;
1907 static CBlock* pblock;
1908 if (pindexPrev != pindexBest ||
1909 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1911 nTransactionsUpdatedLast = nTransactionsUpdated;
1912 pindexPrev = pindexBest;
1918 pblock = CreateNewBlock(reservekey);
1920 throw JSONRPCError(-7, "Out of memory");
1924 pblock->UpdateTime(pindexPrev);
1928 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1935 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1939 result.push_back(Pair("version", pblock->nVersion));
1940 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1941 result.push_back(Pair("transactions", transactions));
1942 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1943 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1944 result.push_back(Pair("time", (int64_t)pblock->nTime));
1945 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1946 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1947 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1954 CDataStream ssBlock(ParseHex(params[0].get_str()));
1958 return ProcessBlock(NULL, &pblock);
1962 Value getblockhash(const Array& params, bool fHelp)
1964 if (fHelp || params.size() != 1)
1965 throw runtime_error(
1966 "getblockhash <index>\n"
1967 "Returns hash of block in best-block-chain at <index>.");
1969 int nHeight = params[0].get_int();
1970 if (nHeight < 0 || nHeight > nBestHeight)
1971 throw runtime_error("Block number out of range.");
1974 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1975 while (pblockindex->nHeight > nHeight)
1976 pblockindex = pblockindex->pprev;
1977 return pblockindex->phashBlock->GetHex();
1980 Value getblock(const Array& params, bool fHelp)
1982 if (fHelp || params.size() != 1)
1983 throw runtime_error(
1985 "Returns details of a block with given block-hash.");
1987 std::string strHash = params[0].get_str();
1988 uint256 hash(strHash);
1990 if (mapBlockIndex.count(hash) == 0)
1991 throw JSONRPCError(-5, "Block not found");
1994 CBlockIndex* pblockindex = mapBlockIndex[hash];
1995 block.ReadFromDisk(pblockindex, true);
1997 return blockToJSON(block, pblockindex);
2014 pair<string, rpcfn_type> pCallTable[] =
2016 make_pair("help", &help),
2017 make_pair("stop", &stop),
2018 make_pair("getblockcount", &getblockcount),
2019 make_pair("getblocknumber", &getblocknumber),
2020 make_pair("getconnectioncount", &getconnectioncount),
2021 make_pair("getdifficulty", &getdifficulty),
2022 make_pair("getgenerate", &getgenerate),
2023 make_pair("setgenerate", &setgenerate),
2024 make_pair("gethashespersec", &gethashespersec),
2025 make_pair("getinfo", &getinfo),
2026 make_pair("getmininginfo", &getmininginfo),
2027 make_pair("getnewaddress", &getnewaddress),
2028 make_pair("getaccountaddress", &getaccountaddress),
2029 make_pair("setaccount", &setaccount),
2030 make_pair("getaccount", &getaccount),
2031 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2032 make_pair("sendtoaddress", &sendtoaddress),
2033 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2034 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2035 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2036 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2037 make_pair("backupwallet", &backupwallet),
2038 make_pair("keypoolrefill", &keypoolrefill),
2039 make_pair("walletpassphrase", &walletpassphrase),
2040 make_pair("walletpassphrasechange", &walletpassphrasechange),
2041 make_pair("walletlock", &walletlock),
2042 make_pair("encryptwallet", &encryptwallet),
2043 make_pair("validateaddress", &validateaddress),
2044 make_pair("getbalance", &getbalance),
2045 make_pair("move", &movecmd),
2046 make_pair("sendfrom", &sendfrom),
2047 make_pair("sendmany", &sendmany),
2048 make_pair("addmultisigaddress", &addmultisigaddress),
2049 make_pair("getblock", &getblock),
2050 make_pair("getblockhash", &getblockhash),
2051 make_pair("gettransaction", &gettransaction),
2052 make_pair("listtransactions", &listtransactions),
2053 make_pair("signmessage", &signmessage),
2054 make_pair("verifymessage", &verifymessage),
2055 make_pair("getwork", &getwork),
2056 make_pair("listaccounts", &listaccounts),
2057 make_pair("settxfee", &settxfee),
2058 make_pair("getmemorypool", &getmemorypool),
2059 make_pair("listsinceblock", &listsinceblock),
2060 make_pair("dumpprivkey", &dumpprivkey),
2061 make_pair("importprivkey", &importprivkey)
2063 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2065 string pAllowInSafeMode[] =
2070 "getblocknumber", // deprecated
2071 "getconnectioncount",
2079 "getaccountaddress",
2081 "getaddressesbyaccount",
2090 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2098 // This ain't Apache. We're just using HTTP header for the length field
2099 // and to be compatible with other JSON-RPC implementations.
2102 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2105 s << "POST / HTTP/1.1\r\n"
2106 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2107 << "Host: 127.0.0.1\r\n"
2108 << "Content-Type: application/json\r\n"
2109 << "Content-Length: " << strMsg.size() << "\r\n"
2110 << "Connection: close\r\n"
2111 << "Accept: application/json\r\n";
2112 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2113 s << item.first << ": " << item.second << "\r\n";
2114 s << "\r\n" << strMsg;
2119 string rfc1123Time()
2124 struct tm* now_gmt = gmtime(&now);
2125 string locale(setlocale(LC_TIME, NULL));
2126 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2127 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2128 setlocale(LC_TIME, locale.c_str());
2129 return string(buffer);
2132 static string HTTPReply(int nStatus, const string& strMsg)
2135 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2137 "Server: bitcoin-json-rpc/%s\r\n"
2138 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2139 "Content-Type: text/html\r\n"
2140 "Content-Length: 296\r\n"
2142 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2143 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2146 "<TITLE>Error</TITLE>\r\n"
2147 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2149 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2150 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2151 const char *cStatus;
2152 if (nStatus == 200) cStatus = "OK";
2153 else if (nStatus == 400) cStatus = "Bad Request";
2154 else if (nStatus == 403) cStatus = "Forbidden";
2155 else if (nStatus == 404) cStatus = "Not Found";
2156 else if (nStatus == 500) cStatus = "Internal Server Error";
2159 "HTTP/1.1 %d %s\r\n"
2161 "Connection: close\r\n"
2162 "Content-Length: %d\r\n"
2163 "Content-Type: application/json\r\n"
2164 "Server: bitcoin-json-rpc/%s\r\n"
2169 rfc1123Time().c_str(),
2171 FormatFullVersion().c_str(),
2175 int ReadHTTPStatus(std::basic_istream<char>& stream)
2178 getline(stream, str);
2179 vector<string> vWords;
2180 boost::split(vWords, str, boost::is_any_of(" "));
2181 if (vWords.size() < 2)
2183 return atoi(vWords[1].c_str());
2186 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2192 std::getline(stream, str);
2193 if (str.empty() || str == "\r")
2195 string::size_type nColon = str.find(":");
2196 if (nColon != string::npos)
2198 string strHeader = str.substr(0, nColon);
2199 boost::trim(strHeader);
2200 boost::to_lower(strHeader);
2201 string strValue = str.substr(nColon+1);
2202 boost::trim(strValue);
2203 mapHeadersRet[strHeader] = strValue;
2204 if (strHeader == "content-length")
2205 nLen = atoi(strValue.c_str());
2211 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2213 mapHeadersRet.clear();
2217 int nStatus = ReadHTTPStatus(stream);
2220 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2221 if (nLen < 0 || nLen > MAX_SIZE)
2227 vector<char> vch(nLen);
2228 stream.read(&vch[0], nLen);
2229 strMessageRet = string(vch.begin(), vch.end());
2235 bool HTTPAuthorized(map<string, string>& mapHeaders)
2237 string strAuth = mapHeaders["authorization"];
2238 if (strAuth.substr(0,6) != "Basic ")
2240 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2241 string strUserPass = DecodeBase64(strUserPass64);
2242 return strUserPass == strRPCUserColonPass;
2246 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2247 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2248 // unspecified (HTTP errors and contents of 'error').
2250 // 1.0 spec: http://json-rpc.org/wiki/specification
2251 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2252 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2255 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2258 request.push_back(Pair("method", strMethod));
2259 request.push_back(Pair("params", params));
2260 request.push_back(Pair("id", id));
2261 return write_string(Value(request), false) + "\n";
2264 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2267 if (error.type() != null_type)
2268 reply.push_back(Pair("result", Value::null));
2270 reply.push_back(Pair("result", result));
2271 reply.push_back(Pair("error", error));
2272 reply.push_back(Pair("id", id));
2273 return write_string(Value(reply), false) + "\n";
2276 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2278 // Send error reply from json-rpc error object
2280 int code = find_value(objError, "code").get_int();
2281 if (code == -32600) nStatus = 400;
2282 else if (code == -32601) nStatus = 404;
2283 string strReply = JSONRPCReply(Value::null, objError, id);
2284 stream << HTTPReply(nStatus, strReply) << std::flush;
2287 bool ClientAllowed(const string& strAddress)
2289 if (strAddress == asio::ip::address_v4::loopback().to_string())
2291 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2292 BOOST_FOREACH(string strAllow, vAllow)
2293 if (WildcardMatch(strAddress, strAllow))
2300 // IOStream device that speaks SSL but can also speak non-SSL
2302 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2304 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2306 fUseSSL = fUseSSLIn;
2307 fNeedHandshake = fUseSSLIn;
2310 void handshake(ssl::stream_base::handshake_type role)
2312 if (!fNeedHandshake) return;
2313 fNeedHandshake = false;
2314 stream.handshake(role);
2316 std::streamsize read(char* s, std::streamsize n)
2318 handshake(ssl::stream_base::server); // HTTPS servers read first
2319 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2320 return stream.next_layer().read_some(asio::buffer(s, n));
2322 std::streamsize write(const char* s, std::streamsize n)
2324 handshake(ssl::stream_base::client); // HTTPS clients write first
2325 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2326 return asio::write(stream.next_layer(), asio::buffer(s, n));
2328 bool connect(const std::string& server, const std::string& port)
2330 ip::tcp::resolver resolver(stream.get_io_service());
2331 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2332 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2333 ip::tcp::resolver::iterator end;
2334 boost::system::error_code error = asio::error::host_not_found;
2335 while (error && endpoint_iterator != end)
2337 stream.lowest_layer().close();
2338 stream.lowest_layer().connect(*endpoint_iterator++, error);
2346 bool fNeedHandshake;
2352 void ThreadRPCServer(void* parg)
2354 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2357 vnThreadsRunning[THREAD_RPCSERVER]++;
2358 ThreadRPCServer2(parg);
2359 vnThreadsRunning[THREAD_RPCSERVER]--;
2361 catch (std::exception& e) {
2362 vnThreadsRunning[THREAD_RPCSERVER]--;
2363 PrintException(&e, "ThreadRPCServer()");
2365 vnThreadsRunning[THREAD_RPCSERVER]--;
2366 PrintException(NULL, "ThreadRPCServer()");
2368 printf("ThreadRPCServer exiting\n");
2372 extern bool HACK_SHUTDOWN;
2375 void ThreadRPCServer2(void* parg)
2377 printf("ThreadRPCServer started\n");
2379 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2380 if (mapArgs["-rpcpassword"] == "")
2382 unsigned char rand_pwd[32];
2383 RAND_bytes(rand_pwd, 32);
2384 string strWhatAmI = "To use bitcoind";
2385 if (mapArgs.count("-server"))
2386 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2387 else if (mapArgs.count("-daemon"))
2388 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2389 ThreadSafeMessageBox(strprintf(
2390 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2391 "It is recommended you use the following random password:\n"
2392 "rpcuser=bitcoinrpc\n"
2394 "(you do not need to remember this password)\n"
2395 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2397 GetConfigFile().c_str(),
2398 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2399 _("Error"), wxOK | wxMODAL);
2401 CreateThread(Shutdown, NULL);
2406 bool fUseSSL = GetBoolArg("-rpcssl");
2407 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2409 asio::io_service io_service;
2410 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2412 ip::tcp::acceptor acceptor(io_service, endpoint);
2414 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2416 ip::tcp::acceptor acceptor(io_service);
2419 acceptor.open(endpoint.protocol());
2420 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2421 acceptor.bind(endpoint);
2422 acceptor.listen(socket_base::max_connections);
2424 catch(system::system_error &e)
2426 HACK_SHUTDOWN = true;
2427 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2428 _("Error"), wxOK | wxMODAL);
2434 ssl::context context(io_service, ssl::context::sslv23);
2437 context.set_options(ssl::context::no_sslv2);
2438 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2439 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2440 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2441 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2442 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2443 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2444 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2445 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2447 string ciphers = GetArg("-rpcsslciphers",
2448 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2449 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2453 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2458 // Accept connection
2460 SSLStream sslStream(io_service, context);
2461 SSLIOStreamDevice d(sslStream, fUseSSL);
2462 iostreams::stream<SSLIOStreamDevice> stream(d);
2464 ip::tcp::iostream stream;
2467 ip::tcp::endpoint peer;
2468 vnThreadsRunning[THREAD_RPCSERVER]--;
2470 acceptor.accept(sslStream.lowest_layer(), peer);
2472 acceptor.accept(*stream.rdbuf(), peer);
2474 vnThreadsRunning[4]++;
2478 // Restrict callers by IP
2479 if (!ClientAllowed(peer.address().to_string()))
2481 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2483 stream << HTTPReply(403, "") << std::flush;
2487 map<string, string> mapHeaders;
2490 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2491 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2494 printf("ThreadRPCServer ReadHTTP timeout\n");
2498 // Check authorization
2499 if (mapHeaders.count("authorization") == 0)
2501 stream << HTTPReply(401, "") << std::flush;
2504 if (!HTTPAuthorized(mapHeaders))
2506 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2507 /* Deter brute-forcing short passwords.
2508 If this results in a DOS the user really
2509 shouldn't have their RPC port exposed.*/
2510 if (mapArgs["-rpcpassword"].size() < 20)
2513 stream << HTTPReply(401, "") << std::flush;
2517 Value id = Value::null;
2522 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2523 throw JSONRPCError(-32700, "Parse error");
2524 const Object& request = valRequest.get_obj();
2526 // Parse id now so errors from here on will have the id
2527 id = find_value(request, "id");
2530 Value valMethod = find_value(request, "method");
2531 if (valMethod.type() == null_type)
2532 throw JSONRPCError(-32600, "Missing method");
2533 if (valMethod.type() != str_type)
2534 throw JSONRPCError(-32600, "Method must be a string");
2535 string strMethod = valMethod.get_str();
2536 if (strMethod != "getwork" && strMethod != "getmemorypool")
2537 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2540 Value valParams = find_value(request, "params");
2542 if (valParams.type() == array_type)
2543 params = valParams.get_array();
2544 else if (valParams.type() == null_type)
2547 throw JSONRPCError(-32600, "Params must be an array");
2550 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2551 if (mi == mapCallTable.end())
2552 throw JSONRPCError(-32601, "Method not found");
2554 // Observe safe mode
2555 string strWarning = GetWarnings("rpc");
2556 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2557 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2563 CRITICAL_BLOCK(cs_main)
2564 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2565 result = (*(*mi).second)(params, false);
2568 string strReply = JSONRPCReply(result, Value::null, id);
2569 stream << HTTPReply(200, strReply) << std::flush;
2571 catch (std::exception& e)
2573 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2576 catch (Object& objError)
2578 ErrorReply(stream, objError, id);
2580 catch (std::exception& e)
2582 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2590 Object CallRPC(const string& strMethod, const Array& params)
2592 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2593 throw runtime_error(strprintf(
2594 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2595 "If the file does not exist, create it with owner-readable-only file permissions."),
2596 GetConfigFile().c_str()));
2598 // Connect to localhost
2599 bool fUseSSL = GetBoolArg("-rpcssl");
2601 asio::io_service io_service;
2602 ssl::context context(io_service, ssl::context::sslv23);
2603 context.set_options(ssl::context::no_sslv2);
2604 SSLStream sslStream(io_service, context);
2605 SSLIOStreamDevice d(sslStream, fUseSSL);
2606 iostreams::stream<SSLIOStreamDevice> stream(d);
2607 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2608 throw runtime_error("couldn't connect to server");
2611 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2613 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2615 throw runtime_error("couldn't connect to server");
2619 // HTTP basic authentication
2620 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2621 map<string, string> mapRequestHeaders;
2622 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2625 string strRequest = JSONRPCRequest(strMethod, params, 1);
2626 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2627 stream << strPost << std::flush;
2630 map<string, string> mapHeaders;
2632 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2634 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2635 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2636 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2637 else if (strReply.empty())
2638 throw runtime_error("no response from server");
2642 if (!read_string(strReply, valReply))
2643 throw runtime_error("couldn't parse reply from server");
2644 const Object& reply = valReply.get_obj();
2646 throw runtime_error("expected reply to have result, error and id properties");
2654 template<typename T>
2655 void ConvertTo(Value& value)
2657 if (value.type() == str_type)
2659 // reinterpret string as unquoted json value
2661 if (!read_string(value.get_str(), value2))
2662 throw runtime_error("type mismatch");
2663 value = value2.get_value<T>();
2667 value = value.get_value<T>();
2671 int CommandLineRPC(int argc, char *argv[])
2678 while (argc > 1 && IsSwitchChar(argv[1][0]))
2686 throw runtime_error("too few parameters");
2687 string strMethod = argv[1];
2689 // Parameters default to strings
2691 for (int i = 2; i < argc; i++)
2692 params.push_back(argv[i]);
2693 int n = params.size();
2696 // Special case non-string parameter types
2698 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2699 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2700 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2701 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2702 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2703 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2704 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2705 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2706 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2707 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2708 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2709 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2710 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2711 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2712 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2713 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2714 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2715 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2716 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2717 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2718 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2719 if (strMethod == "sendmany" && n > 1)
2721 string s = params[1].get_str();
2723 if (!read_string(s, v) || v.type() != obj_type)
2724 throw runtime_error("type mismatch");
2725 params[1] = v.get_obj();
2727 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2728 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2729 if (strMethod == "addmultisigaddress" && n > 1)
2731 string s = params[1].get_str();
2733 if (!read_string(s, v) || v.type() != array_type)
2734 throw runtime_error("type mismatch "+s);
2735 params[1] = v.get_array();
2739 Object reply = CallRPC(strMethod, params);
2742 const Value& result = find_value(reply, "result");
2743 const Value& error = find_value(reply, "error");
2745 if (error.type() != null_type)
2748 strPrint = "error: " + write_string(error, false);
2749 int code = find_value(error.get_obj(), "code").get_int();
2755 if (result.type() == null_type)
2757 else if (result.type() == str_type)
2758 strPrint = result.get_str();
2760 strPrint = write_string(result, true);
2763 catch (std::exception& e)
2765 strPrint = string("error: ") + e.what();
2770 PrintException(NULL, "CommandLineRPC()");
2775 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2784 int main(int argc, char *argv[])
2787 // Turn off microsoft heap dump noise
2788 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2789 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2791 setbuf(stdin, NULL);
2792 setbuf(stdout, NULL);
2793 setbuf(stderr, NULL);
2797 if (argc >= 2 && string(argv[1]) == "-server")
2799 printf("server ready\n");
2800 ThreadRPCServer(NULL);
2804 return CommandLineRPC(argc, argv);
2807 catch (std::exception& e) {
2808 PrintException(&e, "main()");
2810 PrintException(NULL, "main()");