1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
57 double GetDifficulty(const CBlockIndex* blockindex = NULL)
59 // Floating point number that is a multiple of the minimum difficulty,
60 // minimum difficulty = 1.0.
61 if (blockindex == NULL)
63 if (pindexBest == NULL)
66 blockindex = pindexBest;
69 int nShift = (blockindex->nBits >> 24) & 0xff;
72 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
89 int64 AmountFromValue(const Value& value)
91 double dAmount = value.get_real();
92 if (dAmount <= 0.0 || dAmount > 21000000.0)
93 throw JSONRPCError(-3, "Invalid amount");
94 int64 nAmount = roundint64(dAmount * COIN);
95 if (!MoneyRange(nAmount))
96 throw JSONRPCError(-3, "Invalid amount");
100 Value ValueFromAmount(int64 amount)
102 return (double)amount / (double)COIN;
106 HexBits(unsigned int nBits)
112 uBits.nBits = htonl((int32_t)nBits);
113 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
116 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
118 int confirms = wtx.GetDepthInMainChain();
119 entry.push_back(Pair("confirmations", confirms));
122 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
123 entry.push_back(Pair("blockindex", wtx.nIndex));
125 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
126 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
127 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
128 entry.push_back(Pair(item.first, item.second));
131 string AccountFromValue(const Value& value)
133 string strAccount = value.get_str();
134 if (strAccount == "*")
135 throw JSONRPCError(-11, "Invalid account name");
139 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
142 result.push_back(Pair("hash", block.GetHash().GetHex()));
143 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
144 result.push_back(Pair("height", blockindex->nHeight));
145 result.push_back(Pair("version", block.nVersion));
146 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
147 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
148 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
149 result.push_back(Pair("bits", HexBits(block.nBits)));
150 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
152 BOOST_FOREACH (const CTransaction&tx, block.vtx)
153 txhashes.push_back(tx.GetHash().GetHex());
154 result.push_back(Pair("tx", txhashes));
156 if (blockindex->pprev)
157 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
158 if (blockindex->pnext)
159 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
166 /// Note: This interface may still be subject to change.
170 Value help(const Array& params, bool fHelp)
172 if (fHelp || params.size() > 1)
175 "List commands, or get help for a command.");
178 if (params.size() > 0)
179 strCommand = params[0].get_str();
182 set<rpcfn_type> setDone;
183 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
185 string strMethod = (*mi).first;
186 // We already filter duplicates, but these deprecated screw up the sort order
187 if (strMethod == "getamountreceived" ||
188 strMethod == "getallreceived" ||
189 strMethod == "getblocknumber" || // deprecated
190 (strMethod.find("label") != string::npos))
192 if (strCommand != "" && strMethod != strCommand)
197 rpcfn_type pfn = (*mi).second;
198 if (setDone.insert(pfn).second)
199 (*pfn)(params, true);
201 catch (std::exception& e)
203 // Help text is returned in an exception
204 string strHelp = string(e.what());
205 if (strCommand == "")
206 if (strHelp.find('\n') != -1)
207 strHelp = strHelp.substr(0, strHelp.find('\n'));
208 strRet += strHelp + "\n";
212 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
213 strRet = strRet.substr(0,strRet.size()-1);
218 Value stop(const Array& params, bool fHelp)
220 if (fHelp || params.size() != 0)
223 "Stop bitcoin server.");
225 // Shutdown will take long enough that the response should get back
226 CreateThread(Shutdown, NULL);
227 return "bitcoin server stopping";
229 throw runtime_error("NYI: cannot shut down GUI with RPC command");
234 Value getblockcount(const Array& params, bool fHelp)
236 if (fHelp || params.size() != 0)
239 "Returns the number of blocks in the longest block chain.");
246 Value getblocknumber(const Array& params, bool fHelp)
248 if (fHelp || params.size() != 0)
251 "Deprecated. Use getblockcount.");
257 Value getconnectioncount(const Array& params, bool fHelp)
259 if (fHelp || params.size() != 0)
261 "getconnectioncount\n"
262 "Returns the number of connections to other nodes.");
264 return (int)vNodes.size();
268 Value getdifficulty(const Array& params, bool fHelp)
270 if (fHelp || params.size() != 0)
273 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
275 return GetDifficulty();
279 Value getgenerate(const Array& params, bool fHelp)
281 if (fHelp || params.size() != 0)
284 "Returns true or false.");
286 return GetBoolArg("-gen");
290 Value setgenerate(const Array& params, bool fHelp)
292 if (fHelp || params.size() < 1 || params.size() > 2)
294 "setgenerate <generate> [genproclimit]\n"
295 "<generate> is true or false to turn generation on or off.\n"
296 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
298 bool fGenerate = true;
299 if (params.size() > 0)
300 fGenerate = params[0].get_bool();
302 if (params.size() > 1)
304 int nGenProcLimit = params[1].get_int();
305 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
306 if (nGenProcLimit == 0)
309 mapArgs["-gen"] = (fGenerate ? "1" : "0");
311 GenerateBitcoins(fGenerate, pwalletMain);
316 Value gethashespersec(const Array& params, bool fHelp)
318 if (fHelp || params.size() != 0)
321 "Returns a recent hashes per second performance measurement while generating.");
323 if (GetTimeMillis() - nHPSTimerStart > 8000)
324 return (boost::int64_t)0;
325 return (boost::int64_t)dHashesPerSec;
329 Value getinfo(const Array& params, bool fHelp)
331 if (fHelp || params.size() != 0)
334 "Returns an object containing various state info.");
337 obj.push_back(Pair("version", (int)CLIENT_VERSION));
338 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
339 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
340 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
341 obj.push_back(Pair("blocks", (int)nBestHeight));
342 obj.push_back(Pair("connections", (int)vNodes.size()));
343 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
344 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
345 obj.push_back(Pair("testnet", fTestNet));
346 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
347 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
348 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
349 if (pwalletMain->IsCrypted())
350 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
351 obj.push_back(Pair("errors", GetWarnings("statusbar")));
356 Value getmininginfo(const Array& params, bool fHelp)
358 if (fHelp || params.size() != 0)
361 "Returns an object containing mining-related information.");
364 obj.push_back(Pair("blocks", (int)nBestHeight));
365 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
366 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
367 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
368 obj.push_back(Pair("errors", GetWarnings("statusbar")));
369 obj.push_back(Pair("generate", GetBoolArg("-gen")));
370 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
371 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
372 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
373 obj.push_back(Pair("testnet", fTestNet));
378 Value getnewaddress(const Array& params, bool fHelp)
380 if (fHelp || params.size() > 1)
382 "getnewaddress [account]\n"
383 "Returns a new bitcoin address for receiving payments. "
384 "If [account] is specified (recommended), it is added to the address book "
385 "so payments received with the address will be credited to [account].");
387 // Parse the account first so we don't generate a key if there's an error
389 if (params.size() > 0)
390 strAccount = AccountFromValue(params[0]);
392 if (!pwalletMain->IsLocked())
393 pwalletMain->TopUpKeyPool();
395 // Generate a new key that is added to wallet
396 std::vector<unsigned char> newKey;
397 if (!pwalletMain->GetKeyFromPool(newKey, false))
398 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
399 CBitcoinAddress address(newKey);
401 pwalletMain->SetAddressBookName(address, strAccount);
403 return address.ToString();
407 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
409 CWalletDB walletdb(pwalletMain->strWalletFile);
412 walletdb.ReadAccount(strAccount, account);
414 bool bKeyUsed = false;
416 // Check if the current key has been used
417 if (!account.vchPubKey.empty())
419 CScript scriptPubKey;
420 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
421 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
422 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
425 const CWalletTx& wtx = (*it).second;
426 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
427 if (txout.scriptPubKey == scriptPubKey)
432 // Generate a new key
433 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
435 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
436 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
438 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
439 walletdb.WriteAccount(strAccount, account);
442 return CBitcoinAddress(account.vchPubKey);
445 Value getaccountaddress(const Array& params, bool fHelp)
447 if (fHelp || params.size() != 1)
449 "getaccountaddress <account>\n"
450 "Returns the current bitcoin address for receiving payments to this account.");
452 // Parse the account first so we don't generate a key if there's an error
453 string strAccount = AccountFromValue(params[0]);
457 ret = GetAccountAddress(strAccount).ToString();
464 Value setaccount(const Array& params, bool fHelp)
466 if (fHelp || params.size() < 1 || params.size() > 2)
468 "setaccount <bitcoinaddress> <account>\n"
469 "Sets the account associated with the given address.");
471 CBitcoinAddress address(params[0].get_str());
472 if (!address.IsValid())
473 throw JSONRPCError(-5, "Invalid bitcoin address");
477 if (params.size() > 1)
478 strAccount = AccountFromValue(params[1]);
480 // Detect when changing the account of an address that is the 'unused current key' of another account:
481 if (pwalletMain->mapAddressBook.count(address))
483 string strOldAccount = pwalletMain->mapAddressBook[address];
484 if (address == GetAccountAddress(strOldAccount))
485 GetAccountAddress(strOldAccount, true);
488 pwalletMain->SetAddressBookName(address, strAccount);
494 Value getaccount(const Array& params, bool fHelp)
496 if (fHelp || params.size() != 1)
498 "getaccount <bitcoinaddress>\n"
499 "Returns the account associated with the given address.");
501 CBitcoinAddress address(params[0].get_str());
502 if (!address.IsValid())
503 throw JSONRPCError(-5, "Invalid bitcoin address");
506 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
507 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
508 strAccount = (*mi).second;
513 Value getaddressesbyaccount(const Array& params, bool fHelp)
515 if (fHelp || params.size() != 1)
517 "getaddressesbyaccount <account>\n"
518 "Returns the list of addresses for the given account.");
520 string strAccount = AccountFromValue(params[0]);
522 // Find all addresses that have the given account
524 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
526 const CBitcoinAddress& address = item.first;
527 const string& strName = item.second;
528 if (strName == strAccount)
529 ret.push_back(address.ToString());
534 Value settxfee(const Array& params, bool fHelp)
536 if (fHelp || params.size() < 1 || params.size() > 1)
538 "settxfee <amount>\n"
539 "<amount> is a real and is rounded to the nearest 0.00000001");
543 if (params[0].get_real() != 0.0)
544 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
546 nTransactionFee = nAmount;
550 Value sendtoaddress(const Array& params, bool fHelp)
552 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
554 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
555 "<amount> is a real and is rounded to the nearest 0.00000001\n"
556 "requires wallet passphrase to be set with walletpassphrase first");
557 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
559 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
560 "<amount> is a real and is rounded to the nearest 0.00000001");
562 CBitcoinAddress address(params[0].get_str());
563 if (!address.IsValid())
564 throw JSONRPCError(-5, "Invalid bitcoin address");
567 int64 nAmount = AmountFromValue(params[1]);
571 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
572 wtx.mapValue["comment"] = params[2].get_str();
573 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
574 wtx.mapValue["to"] = params[3].get_str();
576 if (pwalletMain->IsLocked())
577 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
579 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
581 throw JSONRPCError(-4, strError);
583 return wtx.GetHash().GetHex();
586 Value signmessage(const Array& params, bool fHelp)
588 if (fHelp || params.size() != 2)
590 "signmessage <bitcoinaddress> <message>\n"
591 "Sign a message with the private key of an address");
593 if (pwalletMain->IsLocked())
594 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
596 string strAddress = params[0].get_str();
597 string strMessage = params[1].get_str();
599 CBitcoinAddress addr(strAddress);
601 throw JSONRPCError(-3, "Invalid address");
604 if (!pwalletMain->GetKey(addr, key))
605 throw JSONRPCError(-4, "Private key not available");
607 CDataStream ss(SER_GETHASH);
608 ss << strMessageMagic;
611 vector<unsigned char> vchSig;
612 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
613 throw JSONRPCError(-5, "Sign failed");
615 return EncodeBase64(&vchSig[0], vchSig.size());
618 Value verifymessage(const Array& params, bool fHelp)
620 if (fHelp || params.size() != 3)
622 "verifymessage <bitcoinaddress> <signature> <message>\n"
623 "Verify a signed message");
625 string strAddress = params[0].get_str();
626 string strSign = params[1].get_str();
627 string strMessage = params[2].get_str();
629 CBitcoinAddress addr(strAddress);
631 throw JSONRPCError(-3, "Invalid address");
633 bool fInvalid = false;
634 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
637 throw JSONRPCError(-5, "Malformed base64 encoding");
639 CDataStream ss(SER_GETHASH);
640 ss << strMessageMagic;
644 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
647 return (CBitcoinAddress(key.GetPubKey()) == addr);
651 Value getreceivedbyaddress(const Array& params, bool fHelp)
653 if (fHelp || params.size() < 1 || params.size() > 2)
655 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
656 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
659 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
660 CScript scriptPubKey;
661 if (!address.IsValid())
662 throw JSONRPCError(-5, "Invalid bitcoin address");
663 scriptPubKey.SetBitcoinAddress(address);
664 if (!IsMine(*pwalletMain,scriptPubKey))
667 // Minimum confirmations
669 if (params.size() > 1)
670 nMinDepth = params[1].get_int();
674 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
676 const CWalletTx& wtx = (*it).second;
677 if (wtx.IsCoinBase() || !wtx.IsFinal())
680 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
681 if (txout.scriptPubKey == scriptPubKey)
682 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 nAmount += txout.nValue;
686 return ValueFromAmount(nAmount);
690 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
692 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
694 const CBitcoinAddress& address = item.first;
695 const string& strName = item.second;
696 if (strName == strAccount)
697 setAddress.insert(address);
702 Value getreceivedbyaccount(const Array& params, bool fHelp)
704 if (fHelp || params.size() < 1 || params.size() > 2)
706 "getreceivedbyaccount <account> [minconf=1]\n"
707 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
709 // Minimum confirmations
711 if (params.size() > 1)
712 nMinDepth = params[1].get_int();
714 // Get the set of pub keys assigned to account
715 string strAccount = AccountFromValue(params[0]);
716 set<CBitcoinAddress> setAddress;
717 GetAccountAddresses(strAccount, setAddress);
721 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
723 const CWalletTx& wtx = (*it).second;
724 if (wtx.IsCoinBase() || !wtx.IsFinal())
727 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
729 CBitcoinAddress address;
730 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
731 if (wtx.GetDepthInMainChain() >= nMinDepth)
732 nAmount += txout.nValue;
736 return (double)nAmount / (double)COIN;
740 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
744 // Tally wallet transactions
745 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
747 const CWalletTx& wtx = (*it).second;
751 int64 nGenerated, nReceived, nSent, nFee;
752 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
754 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
755 nBalance += nReceived;
756 nBalance += nGenerated - nSent - nFee;
759 // Tally internal accounting entries
760 nBalance += walletdb.GetAccountCreditDebit(strAccount);
765 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
767 CWalletDB walletdb(pwalletMain->strWalletFile);
768 return GetAccountBalance(walletdb, strAccount, nMinDepth);
772 Value getbalance(const Array& params, bool fHelp)
774 if (fHelp || params.size() > 2)
776 "getbalance [account] [minconf=1]\n"
777 "If [account] is not specified, returns the server's total available balance.\n"
778 "If [account] is specified, returns the balance in the account.");
780 if (params.size() == 0)
781 return ValueFromAmount(pwalletMain->GetBalance());
784 if (params.size() > 1)
785 nMinDepth = params[1].get_int();
787 if (params[0].get_str() == "*") {
788 // Calculate total balance a different way from GetBalance()
789 // (GetBalance() sums up all unspent TxOuts)
790 // getbalance and getbalance '*' should always return the same number.
792 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
794 const CWalletTx& wtx = (*it).second;
798 int64 allGeneratedImmature, allGeneratedMature, allFee;
799 allGeneratedImmature = allGeneratedMature = allFee = 0;
800 string strSentAccount;
801 list<pair<CBitcoinAddress, int64> > listReceived;
802 list<pair<CBitcoinAddress, int64> > listSent;
803 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
804 if (wtx.GetDepthInMainChain() >= nMinDepth)
806 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
807 nBalance += r.second;
809 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
810 nBalance -= r.second;
812 nBalance += allGeneratedMature;
814 return ValueFromAmount(nBalance);
817 string strAccount = AccountFromValue(params[0]);
819 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
821 return ValueFromAmount(nBalance);
825 Value movecmd(const Array& params, bool fHelp)
827 if (fHelp || params.size() < 3 || params.size() > 5)
829 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
830 "Move from one account in your wallet to another.");
832 string strFrom = AccountFromValue(params[0]);
833 string strTo = AccountFromValue(params[1]);
834 int64 nAmount = AmountFromValue(params[2]);
835 if (params.size() > 3)
836 // unused parameter, used to be nMinDepth, keep type-checking it though
837 (void)params[3].get_int();
839 if (params.size() > 4)
840 strComment = params[4].get_str();
842 CWalletDB walletdb(pwalletMain->strWalletFile);
845 int64 nNow = GetAdjustedTime();
848 CAccountingEntry debit;
849 debit.strAccount = strFrom;
850 debit.nCreditDebit = -nAmount;
852 debit.strOtherAccount = strTo;
853 debit.strComment = strComment;
854 walletdb.WriteAccountingEntry(debit);
857 CAccountingEntry credit;
858 credit.strAccount = strTo;
859 credit.nCreditDebit = nAmount;
861 credit.strOtherAccount = strFrom;
862 credit.strComment = strComment;
863 walletdb.WriteAccountingEntry(credit);
865 walletdb.TxnCommit();
871 Value sendfrom(const Array& params, bool fHelp)
873 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
875 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
876 "<amount> is a real and is rounded to the nearest 0.00000001\n"
877 "requires wallet passphrase to be set with walletpassphrase first");
878 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
880 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
881 "<amount> is a real and is rounded to the nearest 0.00000001");
883 string strAccount = AccountFromValue(params[0]);
884 CBitcoinAddress address(params[1].get_str());
885 if (!address.IsValid())
886 throw JSONRPCError(-5, "Invalid bitcoin address");
887 int64 nAmount = AmountFromValue(params[2]);
889 if (params.size() > 3)
890 nMinDepth = params[3].get_int();
893 wtx.strFromAccount = strAccount;
894 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
895 wtx.mapValue["comment"] = params[4].get_str();
896 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
897 wtx.mapValue["to"] = params[5].get_str();
899 if (pwalletMain->IsLocked())
900 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
903 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
904 if (nAmount > nBalance)
905 throw JSONRPCError(-6, "Account has insufficient funds");
908 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
910 throw JSONRPCError(-4, strError);
912 return wtx.GetHash().GetHex();
916 Value sendmany(const Array& params, bool fHelp)
918 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
920 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
921 "amounts are double-precision floating point numbers\n"
922 "requires wallet passphrase to be set with walletpassphrase first");
923 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
925 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
926 "amounts are double-precision floating point numbers");
928 string strAccount = AccountFromValue(params[0]);
929 Object sendTo = params[1].get_obj();
931 if (params.size() > 2)
932 nMinDepth = params[2].get_int();
935 wtx.strFromAccount = strAccount;
936 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
937 wtx.mapValue["comment"] = params[3].get_str();
939 set<CBitcoinAddress> setAddress;
940 vector<pair<CScript, int64> > vecSend;
942 int64 totalAmount = 0;
943 BOOST_FOREACH(const Pair& s, sendTo)
945 CBitcoinAddress address(s.name_);
946 if (!address.IsValid())
947 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
949 if (setAddress.count(address))
950 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
951 setAddress.insert(address);
953 CScript scriptPubKey;
954 scriptPubKey.SetBitcoinAddress(address);
955 int64 nAmount = AmountFromValue(s.value_);
956 totalAmount += nAmount;
958 vecSend.push_back(make_pair(scriptPubKey, nAmount));
961 if (pwalletMain->IsLocked())
962 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
965 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
966 if (totalAmount > nBalance)
967 throw JSONRPCError(-6, "Account has insufficient funds");
970 CReserveKey keyChange(pwalletMain);
971 int64 nFeeRequired = 0;
972 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
975 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
976 throw JSONRPCError(-6, "Insufficient funds");
977 throw JSONRPCError(-4, "Transaction creation failed");
979 if (!pwalletMain->CommitTransaction(wtx, keyChange))
980 throw JSONRPCError(-4, "Transaction commit failed");
982 return wtx.GetHash().GetHex();
985 Value addmultisigaddress(const Array& params, bool fHelp)
987 if (fHelp || params.size() < 2 || params.size() > 3)
989 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
990 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
991 "each key is a bitcoin address or hex-encoded public key\n"
992 "If [account] is specified, assign address to [account].";
993 throw runtime_error(msg);
996 throw runtime_error("addmultisigaddress available only when running -testnet\n");
998 int nRequired = params[0].get_int();
999 const Array& keys = params[1].get_array();
1001 if (params.size() > 2)
1002 strAccount = AccountFromValue(params[2]);
1004 // Gather public keys
1005 if (nRequired < 1 || keys.size() < nRequired)
1006 throw runtime_error(
1007 strprintf("wrong number of keys"
1008 "(got %d, need at least %d)", keys.size(), nRequired));
1009 std::vector<CKey> pubkeys;
1010 pubkeys.resize(keys.size());
1011 for (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 CWalletDB walletdb(pwalletMain->strWalletFile);
1299 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1300 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1301 typedef multimap<int64, TxPair > TxItems;
1304 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1306 CWalletTx* wtx = &((*it).second);
1307 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1309 list<CAccountingEntry> acentries;
1310 walletdb.ListAccountCreditDebit(strAccount, acentries);
1311 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1313 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1316 // Now: iterate backwards until we have nCount items to return:
1317 TxItems::reverse_iterator it = txByTime.rbegin();
1318 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1319 for (; it != txByTime.rend(); ++it)
1321 CWalletTx *const pwtx = (*it).second.first;
1323 ListTransactions(*pwtx, strAccount, 0, true, ret);
1324 CAccountingEntry *const pacentry = (*it).second.second;
1326 AcentryToJSON(*pacentry, strAccount, ret);
1328 if (ret.size() >= nCount) break;
1330 // ret is now newest to oldest
1332 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1333 if (ret.size() > nCount)
1335 Array::iterator last = ret.begin();
1336 std::advance(last, nCount);
1337 ret.erase(last, ret.end());
1339 std::reverse(ret.begin(), ret.end()); // oldest to newest
1344 Value listaccounts(const Array& params, bool fHelp)
1346 if (fHelp || params.size() > 1)
1347 throw runtime_error(
1348 "listaccounts [minconf=1]\n"
1349 "Returns Object that has account names as keys, account balances as values.");
1352 if (params.size() > 0)
1353 nMinDepth = params[0].get_int();
1355 map<string, int64> mapAccountBalances;
1356 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1357 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1358 mapAccountBalances[entry.second] = 0;
1361 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1363 const CWalletTx& wtx = (*it).second;
1364 int64 nGeneratedImmature, nGeneratedMature, nFee;
1365 string strSentAccount;
1366 list<pair<CBitcoinAddress, int64> > listReceived;
1367 list<pair<CBitcoinAddress, int64> > listSent;
1368 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1369 mapAccountBalances[strSentAccount] -= nFee;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1371 mapAccountBalances[strSentAccount] -= s.second;
1372 if (wtx.GetDepthInMainChain() >= nMinDepth)
1374 mapAccountBalances[""] += nGeneratedMature;
1375 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1376 if (pwalletMain->mapAddressBook.count(r.first))
1377 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1379 mapAccountBalances[""] += r.second;
1383 list<CAccountingEntry> acentries;
1384 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1385 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1386 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1389 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1390 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1395 Value listsinceblock(const Array& params, bool fHelp)
1398 throw runtime_error(
1399 "listsinceblock [blockid] [target-confirmations]\n"
1400 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1402 CBlockIndex *pindex = NULL;
1403 int target_confirms = 1;
1405 if (params.size() > 0)
1407 uint256 blockId = 0;
1409 blockId.SetHex(params[0].get_str());
1410 pindex = CBlockLocator(blockId).GetBlockIndex();
1413 if (params.size() > 1)
1415 target_confirms = params[1].get_int();
1417 if (target_confirms < 1)
1418 throw JSONRPCError(-8, "Invalid parameter");
1421 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1425 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1427 CWalletTx tx = (*it).second;
1429 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1430 ListTransactions(tx, "*", 0, true, transactions);
1435 if (target_confirms == 1)
1438 lastblock = hashBestChain;
1442 int target_height = pindexBest->nHeight + 1 - target_confirms;
1445 for (block = pindexBest;
1446 block && block->nHeight > target_height;
1447 block = block->pprev) { }
1449 lastblock = block ? block->GetBlockHash() : 0;
1453 ret.push_back(Pair("transactions", transactions));
1454 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1459 Value gettransaction(const Array& params, bool fHelp)
1461 if (fHelp || params.size() != 1)
1462 throw runtime_error(
1463 "gettransaction <txid>\n"
1464 "Get detailed information about <txid>");
1467 hash.SetHex(params[0].get_str());
1471 if (!pwalletMain->mapWallet.count(hash))
1472 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1473 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1475 int64 nCredit = wtx.GetCredit();
1476 int64 nDebit = wtx.GetDebit();
1477 int64 nNet = nCredit - nDebit;
1478 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1480 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1482 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1484 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1487 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1488 entry.push_back(Pair("details", details));
1494 Value backupwallet(const Array& params, bool fHelp)
1496 if (fHelp || params.size() != 1)
1497 throw runtime_error(
1498 "backupwallet <destination>\n"
1499 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1501 string strDest = params[0].get_str();
1502 BackupWallet(*pwalletMain, strDest);
1508 Value keypoolrefill(const Array& params, bool fHelp)
1510 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511 throw runtime_error(
1513 "Fills the keypool, requires wallet passphrase to be set.");
1514 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1515 throw runtime_error(
1517 "Fills the keypool.");
1519 if (pwalletMain->IsLocked())
1520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1522 pwalletMain->TopUpKeyPool();
1524 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1525 throw JSONRPCError(-4, "Error refreshing keypool.");
1531 void ThreadTopUpKeyPool(void* parg)
1533 pwalletMain->TopUpKeyPool();
1536 void ThreadCleanWalletPassphrase(void* parg)
1538 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1540 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1542 if (nWalletUnlockTime == 0)
1544 nWalletUnlockTime = nMyWakeTime;
1548 if (nWalletUnlockTime==0)
1550 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1554 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1560 if (nWalletUnlockTime)
1562 nWalletUnlockTime = 0;
1563 pwalletMain->Lock();
1568 if (nWalletUnlockTime < nMyWakeTime)
1569 nWalletUnlockTime = nMyWakeTime;
1572 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1574 delete (int64*)parg;
1577 Value walletpassphrase(const Array& params, bool fHelp)
1579 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1580 throw runtime_error(
1581 "walletpassphrase <passphrase> <timeout>\n"
1582 "Stores the wallet decryption key in memory for <timeout> seconds.");
1585 if (!pwalletMain->IsCrypted())
1586 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1588 if (!pwalletMain->IsLocked())
1589 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1591 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1592 SecureString strWalletPass;
1593 strWalletPass.reserve(100);
1594 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1595 // Alternately, find a way to make params[0] mlock()'d to begin with.
1596 strWalletPass = params[0].get_str().c_str();
1598 if (strWalletPass.length() > 0)
1600 if (!pwalletMain->Unlock(strWalletPass))
1601 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1604 throw runtime_error(
1605 "walletpassphrase <passphrase> <timeout>\n"
1606 "Stores the wallet decryption key in memory for <timeout> seconds.");
1608 CreateThread(ThreadTopUpKeyPool, NULL);
1609 int64* pnSleepTime = new int64(params[1].get_int64());
1610 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1616 Value walletpassphrasechange(const Array& params, bool fHelp)
1618 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1619 throw runtime_error(
1620 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1621 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1624 if (!pwalletMain->IsCrypted())
1625 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1627 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1628 // Alternately, find a way to make params[0] mlock()'d to begin with.
1629 SecureString strOldWalletPass;
1630 strOldWalletPass.reserve(100);
1631 strOldWalletPass = params[0].get_str().c_str();
1633 SecureString strNewWalletPass;
1634 strNewWalletPass.reserve(100);
1635 strNewWalletPass = params[1].get_str().c_str();
1637 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1638 throw runtime_error(
1639 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1640 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1642 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1643 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1649 Value walletlock(const Array& params, bool fHelp)
1651 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1652 throw runtime_error(
1654 "Removes the wallet encryption key from memory, locking the wallet.\n"
1655 "After calling this method, you will need to call walletpassphrase again\n"
1656 "before being able to call any methods which require the wallet to be unlocked.");
1659 if (!pwalletMain->IsCrypted())
1660 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1662 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1664 pwalletMain->Lock();
1665 nWalletUnlockTime = 0;
1672 Value encryptwallet(const Array& params, bool fHelp)
1674 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1675 throw runtime_error(
1676 "encryptwallet <passphrase>\n"
1677 "Encrypts the wallet with <passphrase>.");
1680 if (pwalletMain->IsCrypted())
1681 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1684 // shutting down via RPC while the GUI is running does not work (yet):
1685 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1688 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1689 // Alternately, find a way to make params[0] mlock()'d to begin with.
1690 SecureString strWalletPass;
1691 strWalletPass.reserve(100);
1692 strWalletPass = params[0].get_str().c_str();
1694 if (strWalletPass.length() < 1)
1695 throw runtime_error(
1696 "encryptwallet <passphrase>\n"
1697 "Encrypts the wallet with <passphrase>.");
1699 if (!pwalletMain->EncryptWallet(strWalletPass))
1700 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1702 // BDB seems to have a bad habit of writing old data into
1703 // slack space in .dat files; that is bad if the old data is
1704 // unencrypted private keys. So:
1705 CreateThread(Shutdown, NULL);
1706 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1710 Value validateaddress(const Array& params, bool fHelp)
1712 if (fHelp || params.size() != 1)
1713 throw runtime_error(
1714 "validateaddress <bitcoinaddress>\n"
1715 "Return information about <bitcoinaddress>.");
1717 CBitcoinAddress address(params[0].get_str());
1718 bool isValid = address.IsValid();
1721 ret.push_back(Pair("isvalid", isValid));
1724 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1725 // version of the address:
1726 string currentAddress = address.ToString();
1727 ret.push_back(Pair("address", currentAddress));
1728 if (pwalletMain->HaveKey(address))
1730 ret.push_back(Pair("ismine", true));
1731 std::vector<unsigned char> vchPubKey;
1732 pwalletMain->GetPubKey(address, vchPubKey);
1733 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1735 key.SetPubKey(vchPubKey);
1736 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1738 else if (pwalletMain->HaveCScript(address.GetHash160()))
1740 ret.push_back(Pair("isscript", true));
1742 pwalletMain->GetCScript(address.GetHash160(), subscript);
1743 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1744 std::vector<CBitcoinAddress> addresses;
1745 txnouttype whichType;
1747 ExtractAddresses(subscript, whichType, addresses, nRequired);
1748 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1750 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1751 a.push_back(addr.ToString());
1752 ret.push_back(Pair("addresses", a));
1753 if (whichType == TX_MULTISIG)
1754 ret.push_back(Pair("sigsrequired", nRequired));
1757 ret.push_back(Pair("ismine", false));
1758 if (pwalletMain->mapAddressBook.count(address))
1759 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1764 Value getwork(const Array& params, bool fHelp)
1766 if (fHelp || params.size() > 1)
1767 throw runtime_error(
1769 "If [data] is not specified, returns formatted hash data to work on:\n"
1770 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1771 " \"data\" : block data\n"
1772 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1773 " \"target\" : little endian hash target\n"
1774 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1777 throw JSONRPCError(-9, "Bitcoin is not connected!");
1779 if (IsInitialBlockDownload())
1780 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1782 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1783 static mapNewBlock_t mapNewBlock;
1784 static vector<CBlock*> vNewBlock;
1785 static CReserveKey reservekey(pwalletMain);
1787 if (params.size() == 0)
1790 static unsigned int nTransactionsUpdatedLast;
1791 static CBlockIndex* pindexPrev;
1792 static int64 nStart;
1793 static CBlock* pblock;
1794 if (pindexPrev != pindexBest ||
1795 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1797 if (pindexPrev != pindexBest)
1799 // Deallocate old blocks since they're obsolete now
1800 mapNewBlock.clear();
1801 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1805 nTransactionsUpdatedLast = nTransactionsUpdated;
1806 pindexPrev = pindexBest;
1810 pblock = CreateNewBlock(reservekey);
1812 throw JSONRPCError(-7, "Out of memory");
1813 vNewBlock.push_back(pblock);
1817 pblock->UpdateTime(pindexPrev);
1820 // Update nExtraNonce
1821 static unsigned int nExtraNonce = 0;
1822 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1825 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1827 // Prebuild hash buffers
1831 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1833 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1836 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1837 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1838 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1839 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1845 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1846 if (vchData.size() != 128)
1847 throw JSONRPCError(-8, "Invalid parameter");
1848 CBlock* pdata = (CBlock*)&vchData[0];
1851 for (int i = 0; i < 128/4; i++)
1852 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1855 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1857 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1859 pblock->nTime = pdata->nTime;
1860 pblock->nNonce = pdata->nNonce;
1861 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1862 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1864 return CheckWork(pblock, *pwalletMain, reservekey);
1869 Value getmemorypool(const Array& params, bool fHelp)
1871 if (fHelp || params.size() > 1)
1872 throw runtime_error(
1873 "getmemorypool [data]\n"
1874 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1875 " \"version\" : block version\n"
1876 " \"previousblockhash\" : hash of current highest block\n"
1877 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1878 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1879 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1880 " \"time\" : timestamp appropriate for next block\n"
1881 " \"mintime\" : minimum timestamp appropriate for next block\n"
1882 " \"curtime\" : current timestamp\n"
1883 " \"bits\" : compressed target of next block\n"
1884 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1886 if (params.size() == 0)
1889 throw JSONRPCError(-9, "Bitcoin is not connected!");
1891 if (IsInitialBlockDownload())
1892 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1894 static CReserveKey reservekey(pwalletMain);
1897 static unsigned int nTransactionsUpdatedLast;
1898 static CBlockIndex* pindexPrev;
1899 static int64 nStart;
1900 static CBlock* pblock;
1901 if (pindexPrev != pindexBest ||
1902 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1904 nTransactionsUpdatedLast = nTransactionsUpdated;
1905 pindexPrev = pindexBest;
1911 pblock = CreateNewBlock(reservekey);
1913 throw JSONRPCError(-7, "Out of memory");
1917 pblock->UpdateTime(pindexPrev);
1921 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1928 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1932 result.push_back(Pair("version", pblock->nVersion));
1933 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1934 result.push_back(Pair("transactions", transactions));
1935 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1936 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1937 result.push_back(Pair("time", (int64_t)pblock->nTime));
1938 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1939 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1940 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1947 CDataStream ssBlock(ParseHex(params[0].get_str()));
1951 return ProcessBlock(NULL, &pblock);
1955 Value getblockhash(const Array& params, bool fHelp)
1957 if (fHelp || params.size() != 1)
1958 throw runtime_error(
1959 "getblockhash <index>\n"
1960 "Returns hash of block in best-block-chain at <index>.");
1962 int nHeight = params[0].get_int();
1963 if (nHeight < 0 || nHeight > nBestHeight)
1964 throw runtime_error("Block number out of range.");
1967 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1968 while (pblockindex->nHeight > nHeight)
1969 pblockindex = pblockindex->pprev;
1970 return pblockindex->phashBlock->GetHex();
1973 Value getblock(const Array& params, bool fHelp)
1975 if (fHelp || params.size() != 1)
1976 throw runtime_error(
1978 "Returns details of a block with given block-hash.");
1980 std::string strHash = params[0].get_str();
1981 uint256 hash(strHash);
1983 if (mapBlockIndex.count(hash) == 0)
1984 throw JSONRPCError(-5, "Block not found");
1987 CBlockIndex* pblockindex = mapBlockIndex[hash];
1988 block.ReadFromDisk(pblockindex, true);
1990 return blockToJSON(block, pblockindex);
2007 pair<string, rpcfn_type> pCallTable[] =
2009 make_pair("help", &help),
2010 make_pair("stop", &stop),
2011 make_pair("getblockcount", &getblockcount),
2012 make_pair("getblocknumber", &getblocknumber),
2013 make_pair("getconnectioncount", &getconnectioncount),
2014 make_pair("getdifficulty", &getdifficulty),
2015 make_pair("getgenerate", &getgenerate),
2016 make_pair("setgenerate", &setgenerate),
2017 make_pair("gethashespersec", &gethashespersec),
2018 make_pair("getinfo", &getinfo),
2019 make_pair("getmininginfo", &getmininginfo),
2020 make_pair("getnewaddress", &getnewaddress),
2021 make_pair("getaccountaddress", &getaccountaddress),
2022 make_pair("setaccount", &setaccount),
2023 make_pair("getaccount", &getaccount),
2024 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2025 make_pair("sendtoaddress", &sendtoaddress),
2026 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2027 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2028 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2029 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2030 make_pair("backupwallet", &backupwallet),
2031 make_pair("keypoolrefill", &keypoolrefill),
2032 make_pair("walletpassphrase", &walletpassphrase),
2033 make_pair("walletpassphrasechange", &walletpassphrasechange),
2034 make_pair("walletlock", &walletlock),
2035 make_pair("encryptwallet", &encryptwallet),
2036 make_pair("validateaddress", &validateaddress),
2037 make_pair("getbalance", &getbalance),
2038 make_pair("move", &movecmd),
2039 make_pair("sendfrom", &sendfrom),
2040 make_pair("sendmany", &sendmany),
2041 make_pair("addmultisigaddress", &addmultisigaddress),
2042 make_pair("getblock", &getblock),
2043 make_pair("getblockhash", &getblockhash),
2044 make_pair("gettransaction", &gettransaction),
2045 make_pair("listtransactions", &listtransactions),
2046 make_pair("signmessage", &signmessage),
2047 make_pair("verifymessage", &verifymessage),
2048 make_pair("getwork", &getwork),
2049 make_pair("listaccounts", &listaccounts),
2050 make_pair("settxfee", &settxfee),
2051 make_pair("getmemorypool", &getmemorypool),
2052 make_pair("listsinceblock", &listsinceblock),
2053 make_pair("dumpprivkey", &dumpprivkey),
2054 make_pair("importprivkey", &importprivkey)
2056 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2058 string pAllowInSafeMode[] =
2063 "getblocknumber", // deprecated
2064 "getconnectioncount",
2072 "getaccountaddress",
2074 "getaddressesbyaccount",
2083 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2091 // This ain't Apache. We're just using HTTP header for the length field
2092 // and to be compatible with other JSON-RPC implementations.
2095 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2098 s << "POST / HTTP/1.1\r\n"
2099 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2100 << "Host: 127.0.0.1\r\n"
2101 << "Content-Type: application/json\r\n"
2102 << "Content-Length: " << strMsg.size() << "\r\n"
2103 << "Connection: close\r\n"
2104 << "Accept: application/json\r\n";
2105 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2106 s << item.first << ": " << item.second << "\r\n";
2107 s << "\r\n" << strMsg;
2112 string rfc1123Time()
2117 struct tm* now_gmt = gmtime(&now);
2118 string locale(setlocale(LC_TIME, NULL));
2119 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2120 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2121 setlocale(LC_TIME, locale.c_str());
2122 return string(buffer);
2125 static string HTTPReply(int nStatus, const string& strMsg)
2128 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2130 "Server: bitcoin-json-rpc/%s\r\n"
2131 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2132 "Content-Type: text/html\r\n"
2133 "Content-Length: 296\r\n"
2135 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2136 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2139 "<TITLE>Error</TITLE>\r\n"
2140 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2142 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2143 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2144 const char *cStatus;
2145 if (nStatus == 200) cStatus = "OK";
2146 else if (nStatus == 400) cStatus = "Bad Request";
2147 else if (nStatus == 403) cStatus = "Forbidden";
2148 else if (nStatus == 404) cStatus = "Not Found";
2149 else if (nStatus == 500) cStatus = "Internal Server Error";
2152 "HTTP/1.1 %d %s\r\n"
2154 "Connection: close\r\n"
2155 "Content-Length: %d\r\n"
2156 "Content-Type: application/json\r\n"
2157 "Server: bitcoin-json-rpc/%s\r\n"
2162 rfc1123Time().c_str(),
2164 FormatFullVersion().c_str(),
2168 int ReadHTTPStatus(std::basic_istream<char>& stream)
2171 getline(stream, str);
2172 vector<string> vWords;
2173 boost::split(vWords, str, boost::is_any_of(" "));
2174 if (vWords.size() < 2)
2176 return atoi(vWords[1].c_str());
2179 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2185 std::getline(stream, str);
2186 if (str.empty() || str == "\r")
2188 string::size_type nColon = str.find(":");
2189 if (nColon != string::npos)
2191 string strHeader = str.substr(0, nColon);
2192 boost::trim(strHeader);
2193 boost::to_lower(strHeader);
2194 string strValue = str.substr(nColon+1);
2195 boost::trim(strValue);
2196 mapHeadersRet[strHeader] = strValue;
2197 if (strHeader == "content-length")
2198 nLen = atoi(strValue.c_str());
2204 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2206 mapHeadersRet.clear();
2210 int nStatus = ReadHTTPStatus(stream);
2213 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2214 if (nLen < 0 || nLen > MAX_SIZE)
2220 vector<char> vch(nLen);
2221 stream.read(&vch[0], nLen);
2222 strMessageRet = string(vch.begin(), vch.end());
2228 bool HTTPAuthorized(map<string, string>& mapHeaders)
2230 string strAuth = mapHeaders["authorization"];
2231 if (strAuth.substr(0,6) != "Basic ")
2233 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2234 string strUserPass = DecodeBase64(strUserPass64);
2235 return strUserPass == strRPCUserColonPass;
2239 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2240 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2241 // unspecified (HTTP errors and contents of 'error').
2243 // 1.0 spec: http://json-rpc.org/wiki/specification
2244 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2245 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2248 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2251 request.push_back(Pair("method", strMethod));
2252 request.push_back(Pair("params", params));
2253 request.push_back(Pair("id", id));
2254 return write_string(Value(request), false) + "\n";
2257 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2260 if (error.type() != null_type)
2261 reply.push_back(Pair("result", Value::null));
2263 reply.push_back(Pair("result", result));
2264 reply.push_back(Pair("error", error));
2265 reply.push_back(Pair("id", id));
2266 return write_string(Value(reply), false) + "\n";
2269 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2271 // Send error reply from json-rpc error object
2273 int code = find_value(objError, "code").get_int();
2274 if (code == -32600) nStatus = 400;
2275 else if (code == -32601) nStatus = 404;
2276 string strReply = JSONRPCReply(Value::null, objError, id);
2277 stream << HTTPReply(nStatus, strReply) << std::flush;
2280 bool ClientAllowed(const string& strAddress)
2282 if (strAddress == asio::ip::address_v4::loopback().to_string())
2284 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2285 BOOST_FOREACH(string strAllow, vAllow)
2286 if (WildcardMatch(strAddress, strAllow))
2293 // IOStream device that speaks SSL but can also speak non-SSL
2295 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2297 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2299 fUseSSL = fUseSSLIn;
2300 fNeedHandshake = fUseSSLIn;
2303 void handshake(ssl::stream_base::handshake_type role)
2305 if (!fNeedHandshake) return;
2306 fNeedHandshake = false;
2307 stream.handshake(role);
2309 std::streamsize read(char* s, std::streamsize n)
2311 handshake(ssl::stream_base::server); // HTTPS servers read first
2312 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2313 return stream.next_layer().read_some(asio::buffer(s, n));
2315 std::streamsize write(const char* s, std::streamsize n)
2317 handshake(ssl::stream_base::client); // HTTPS clients write first
2318 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2319 return asio::write(stream.next_layer(), asio::buffer(s, n));
2321 bool connect(const std::string& server, const std::string& port)
2323 ip::tcp::resolver resolver(stream.get_io_service());
2324 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2325 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2326 ip::tcp::resolver::iterator end;
2327 boost::system::error_code error = asio::error::host_not_found;
2328 while (error && endpoint_iterator != end)
2330 stream.lowest_layer().close();
2331 stream.lowest_layer().connect(*endpoint_iterator++, error);
2339 bool fNeedHandshake;
2345 void ThreadRPCServer(void* parg)
2347 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2350 vnThreadsRunning[THREAD_RPCSERVER]++;
2351 ThreadRPCServer2(parg);
2352 vnThreadsRunning[THREAD_RPCSERVER]--;
2354 catch (std::exception& e) {
2355 vnThreadsRunning[THREAD_RPCSERVER]--;
2356 PrintException(&e, "ThreadRPCServer()");
2358 vnThreadsRunning[THREAD_RPCSERVER]--;
2359 PrintException(NULL, "ThreadRPCServer()");
2361 printf("ThreadRPCServer exiting\n");
2364 void ThreadRPCServer2(void* parg)
2366 printf("ThreadRPCServer started\n");
2368 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2369 if (mapArgs["-rpcpassword"] == "")
2371 unsigned char rand_pwd[32];
2372 RAND_bytes(rand_pwd, 32);
2373 string strWhatAmI = "To use bitcoind";
2374 if (mapArgs.count("-server"))
2375 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2376 else if (mapArgs.count("-daemon"))
2377 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2378 ThreadSafeMessageBox(strprintf(
2379 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2380 "It is recommended you use the following random password:\n"
2381 "rpcuser=bitcoinrpc\n"
2383 "(you do not need to remember this password)\n"
2384 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2386 GetConfigFile().c_str(),
2387 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2388 _("Error"), wxOK | wxMODAL);
2390 CreateThread(Shutdown, NULL);
2395 bool fUseSSL = GetBoolArg("-rpcssl");
2396 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2398 asio::io_service io_service;
2399 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2400 ip::tcp::acceptor acceptor(io_service, endpoint);
2402 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2405 ssl::context context(io_service, ssl::context::sslv23);
2408 context.set_options(ssl::context::no_sslv2);
2409 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2410 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2411 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2412 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2413 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2414 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2415 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2416 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2418 string ciphers = GetArg("-rpcsslciphers",
2419 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2420 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2424 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2429 // Accept connection
2431 SSLStream sslStream(io_service, context);
2432 SSLIOStreamDevice d(sslStream, fUseSSL);
2433 iostreams::stream<SSLIOStreamDevice> stream(d);
2435 ip::tcp::iostream stream;
2438 ip::tcp::endpoint peer;
2439 vnThreadsRunning[THREAD_RPCSERVER]--;
2441 acceptor.accept(sslStream.lowest_layer(), peer);
2443 acceptor.accept(*stream.rdbuf(), peer);
2445 vnThreadsRunning[4]++;
2449 // Restrict callers by IP
2450 if (!ClientAllowed(peer.address().to_string()))
2452 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2454 stream << HTTPReply(403, "") << std::flush;
2458 map<string, string> mapHeaders;
2461 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2462 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2465 printf("ThreadRPCServer ReadHTTP timeout\n");
2469 // Check authorization
2470 if (mapHeaders.count("authorization") == 0)
2472 stream << HTTPReply(401, "") << std::flush;
2475 if (!HTTPAuthorized(mapHeaders))
2477 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2478 /* Deter brute-forcing short passwords.
2479 If this results in a DOS the user really
2480 shouldn't have their RPC port exposed.*/
2481 if (mapArgs["-rpcpassword"].size() < 20)
2484 stream << HTTPReply(401, "") << std::flush;
2488 Value id = Value::null;
2493 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2494 throw JSONRPCError(-32700, "Parse error");
2495 const Object& request = valRequest.get_obj();
2497 // Parse id now so errors from here on will have the id
2498 id = find_value(request, "id");
2501 Value valMethod = find_value(request, "method");
2502 if (valMethod.type() == null_type)
2503 throw JSONRPCError(-32600, "Missing method");
2504 if (valMethod.type() != str_type)
2505 throw JSONRPCError(-32600, "Method must be a string");
2506 string strMethod = valMethod.get_str();
2507 if (strMethod != "getwork" && strMethod != "getmemorypool")
2508 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2511 Value valParams = find_value(request, "params");
2513 if (valParams.type() == array_type)
2514 params = valParams.get_array();
2515 else if (valParams.type() == null_type)
2518 throw JSONRPCError(-32600, "Params must be an array");
2521 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2522 if (mi == mapCallTable.end())
2523 throw JSONRPCError(-32601, "Method not found");
2525 // Observe safe mode
2526 string strWarning = GetWarnings("rpc");
2527 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2528 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2534 CRITICAL_BLOCK(cs_main)
2535 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2536 result = (*(*mi).second)(params, false);
2539 string strReply = JSONRPCReply(result, Value::null, id);
2540 stream << HTTPReply(200, strReply) << std::flush;
2542 catch (std::exception& e)
2544 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2547 catch (Object& objError)
2549 ErrorReply(stream, objError, id);
2551 catch (std::exception& e)
2553 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2561 Object CallRPC(const string& strMethod, const Array& params)
2563 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2564 throw runtime_error(strprintf(
2565 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2566 "If the file does not exist, create it with owner-readable-only file permissions."),
2567 GetConfigFile().c_str()));
2569 // Connect to localhost
2570 bool fUseSSL = GetBoolArg("-rpcssl");
2572 asio::io_service io_service;
2573 ssl::context context(io_service, ssl::context::sslv23);
2574 context.set_options(ssl::context::no_sslv2);
2575 SSLStream sslStream(io_service, context);
2576 SSLIOStreamDevice d(sslStream, fUseSSL);
2577 iostreams::stream<SSLIOStreamDevice> stream(d);
2578 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2579 throw runtime_error("couldn't connect to server");
2582 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2584 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2586 throw runtime_error("couldn't connect to server");
2590 // HTTP basic authentication
2591 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2592 map<string, string> mapRequestHeaders;
2593 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2596 string strRequest = JSONRPCRequest(strMethod, params, 1);
2597 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2598 stream << strPost << std::flush;
2601 map<string, string> mapHeaders;
2603 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2605 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2606 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2607 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2608 else if (strReply.empty())
2609 throw runtime_error("no response from server");
2613 if (!read_string(strReply, valReply))
2614 throw runtime_error("couldn't parse reply from server");
2615 const Object& reply = valReply.get_obj();
2617 throw runtime_error("expected reply to have result, error and id properties");
2625 template<typename T>
2626 void ConvertTo(Value& value)
2628 if (value.type() == str_type)
2630 // reinterpret string as unquoted json value
2632 if (!read_string(value.get_str(), value2))
2633 throw runtime_error("type mismatch");
2634 value = value2.get_value<T>();
2638 value = value.get_value<T>();
2642 int CommandLineRPC(int argc, char *argv[])
2649 while (argc > 1 && IsSwitchChar(argv[1][0]))
2657 throw runtime_error("too few parameters");
2658 string strMethod = argv[1];
2660 // Parameters default to strings
2662 for (int i = 2; i < argc; i++)
2663 params.push_back(argv[i]);
2664 int n = params.size();
2667 // Special case non-string parameter types
2669 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2670 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2672 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2673 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2676 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2677 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2678 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2679 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2680 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2681 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2682 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2683 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2684 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2685 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2686 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2687 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2688 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2689 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2690 if (strMethod == "sendmany" && n > 1)
2692 string s = params[1].get_str();
2694 if (!read_string(s, v) || v.type() != obj_type)
2695 throw runtime_error("type mismatch");
2696 params[1] = v.get_obj();
2698 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2699 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2700 if (strMethod == "addmultisigaddress" && n > 1)
2702 string s = params[1].get_str();
2704 if (!read_string(s, v) || v.type() != array_type)
2705 throw runtime_error("type mismatch "+s);
2706 params[1] = v.get_array();
2710 Object reply = CallRPC(strMethod, params);
2713 const Value& result = find_value(reply, "result");
2714 const Value& error = find_value(reply, "error");
2716 if (error.type() != null_type)
2719 strPrint = "error: " + write_string(error, false);
2720 int code = find_value(error.get_obj(), "code").get_int();
2726 if (result.type() == null_type)
2728 else if (result.type() == str_type)
2729 strPrint = result.get_str();
2731 strPrint = write_string(result, true);
2734 catch (std::exception& e)
2736 strPrint = string("error: ") + e.what();
2741 PrintException(NULL, "CommandLineRPC()");
2746 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2755 int main(int argc, char *argv[])
2758 // Turn off microsoft heap dump noise
2759 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2760 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2762 setbuf(stdin, NULL);
2763 setbuf(stdout, NULL);
2764 setbuf(stderr, NULL);
2768 if (argc >= 2 && string(argv[1]) == "-server")
2770 printf("server ready\n");
2771 ThreadRPCServer(NULL);
2775 return CommandLineRPC(argc, argv);
2778 catch (std::exception& e) {
2779 PrintException(&e, "main()");
2781 PrintException(NULL, "main()");