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);
843 if (!walletdb.TxnBegin())
844 throw JSONRPCError(-20, "database error");
846 int64 nNow = GetAdjustedTime();
849 CAccountingEntry debit;
850 debit.strAccount = strFrom;
851 debit.nCreditDebit = -nAmount;
853 debit.strOtherAccount = strTo;
854 debit.strComment = strComment;
855 walletdb.WriteAccountingEntry(debit);
858 CAccountingEntry credit;
859 credit.strAccount = strTo;
860 credit.nCreditDebit = nAmount;
862 credit.strOtherAccount = strFrom;
863 credit.strComment = strComment;
864 walletdb.WriteAccountingEntry(credit);
866 if (!walletdb.TxnCommit())
867 throw JSONRPCError(-20, "database error");
873 Value sendfrom(const Array& params, bool fHelp)
875 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
877 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
878 "<amount> is a real and is rounded to the nearest 0.00000001\n"
879 "requires wallet passphrase to be set with walletpassphrase first");
880 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
882 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
883 "<amount> is a real and is rounded to the nearest 0.00000001");
885 string strAccount = AccountFromValue(params[0]);
886 CBitcoinAddress address(params[1].get_str());
887 if (!address.IsValid())
888 throw JSONRPCError(-5, "Invalid bitcoin address");
889 int64 nAmount = AmountFromValue(params[2]);
891 if (params.size() > 3)
892 nMinDepth = params[3].get_int();
895 wtx.strFromAccount = strAccount;
896 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
897 wtx.mapValue["comment"] = params[4].get_str();
898 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
899 wtx.mapValue["to"] = params[5].get_str();
901 if (pwalletMain->IsLocked())
902 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
905 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
906 if (nAmount > nBalance)
907 throw JSONRPCError(-6, "Account has insufficient funds");
910 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
912 throw JSONRPCError(-4, strError);
914 return wtx.GetHash().GetHex();
918 Value sendmany(const Array& params, bool fHelp)
920 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
922 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
923 "amounts are double-precision floating point numbers\n"
924 "requires wallet passphrase to be set with walletpassphrase first");
925 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
927 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
928 "amounts are double-precision floating point numbers");
930 string strAccount = AccountFromValue(params[0]);
931 Object sendTo = params[1].get_obj();
933 if (params.size() > 2)
934 nMinDepth = params[2].get_int();
937 wtx.strFromAccount = strAccount;
938 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
939 wtx.mapValue["comment"] = params[3].get_str();
941 set<CBitcoinAddress> setAddress;
942 vector<pair<CScript, int64> > vecSend;
944 int64 totalAmount = 0;
945 BOOST_FOREACH(const Pair& s, sendTo)
947 CBitcoinAddress address(s.name_);
948 if (!address.IsValid())
949 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
951 if (setAddress.count(address))
952 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
953 setAddress.insert(address);
955 CScript scriptPubKey;
956 scriptPubKey.SetBitcoinAddress(address);
957 int64 nAmount = AmountFromValue(s.value_);
958 totalAmount += nAmount;
960 vecSend.push_back(make_pair(scriptPubKey, nAmount));
963 if (pwalletMain->IsLocked())
964 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
967 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
968 if (totalAmount > nBalance)
969 throw JSONRPCError(-6, "Account has insufficient funds");
972 CReserveKey keyChange(pwalletMain);
973 int64 nFeeRequired = 0;
974 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
977 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
978 throw JSONRPCError(-6, "Insufficient funds");
979 throw JSONRPCError(-4, "Transaction creation failed");
981 if (!pwalletMain->CommitTransaction(wtx, keyChange))
982 throw JSONRPCError(-4, "Transaction commit failed");
984 return wtx.GetHash().GetHex();
987 Value addmultisigaddress(const Array& params, bool fHelp)
989 if (fHelp || params.size() < 2 || params.size() > 3)
991 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
992 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
993 "each key is a bitcoin address or hex-encoded public key\n"
994 "If [account] is specified, assign address to [account].";
995 throw runtime_error(msg);
998 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1000 int nRequired = params[0].get_int();
1001 const Array& keys = params[1].get_array();
1003 if (params.size() > 2)
1004 strAccount = AccountFromValue(params[2]);
1006 // Gather public keys
1008 throw runtime_error("a multisignature address must require at least one key to redeem");
1009 if (keys.size() < nRequired)
1010 throw runtime_error(
1011 strprintf("not enough keys supplied "
1012 "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1013 std::vector<CKey> pubkeys;
1014 pubkeys.resize(keys.size());
1015 for (unsigned int i = 0; i < keys.size(); i++)
1017 const std::string& ks = keys[i].get_str();
1019 // Case 1: bitcoin address and we have full public key:
1020 CBitcoinAddress address(ks);
1021 if (address.IsValid())
1023 if (address.IsScript())
1024 throw runtime_error(
1025 strprintf("%s is a pay-to-script address",ks.c_str()));
1026 std::vector<unsigned char> vchPubKey;
1027 if (!pwalletMain->GetPubKey(address, vchPubKey))
1028 throw runtime_error(
1029 strprintf("no full public key for address %s",ks.c_str()));
1030 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1031 throw runtime_error(" Invalid public key: "+ks);
1034 // Case 2: hex public key
1037 vector<unsigned char> vchPubKey = ParseHex(ks);
1038 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1039 throw runtime_error(" Invalid public key: "+ks);
1043 throw runtime_error(" Invalid public key: "+ks);
1047 // Construct using pay-to-script-hash:
1049 inner.SetMultisig(nRequired, pubkeys);
1051 uint160 scriptHash = Hash160(inner);
1052 CScript scriptPubKey;
1053 scriptPubKey.SetPayToScriptHash(inner);
1054 pwalletMain->AddCScript(inner);
1055 CBitcoinAddress address;
1056 address.SetScriptHash160(scriptHash);
1058 pwalletMain->SetAddressBookName(address, strAccount);
1059 return address.ToString();
1070 nConf = std::numeric_limits<int>::max();
1074 Value ListReceived(const Array& params, bool fByAccounts)
1076 // Minimum confirmations
1078 if (params.size() > 0)
1079 nMinDepth = params[0].get_int();
1081 // Whether to include empty accounts
1082 bool fIncludeEmpty = false;
1083 if (params.size() > 1)
1084 fIncludeEmpty = params[1].get_bool();
1087 map<CBitcoinAddress, tallyitem> mapTally;
1088 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1090 const CWalletTx& wtx = (*it).second;
1092 if (wtx.IsCoinBase() || !wtx.IsFinal())
1095 int nDepth = wtx.GetDepthInMainChain();
1096 if (nDepth < nMinDepth)
1099 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1101 CBitcoinAddress address;
1102 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1105 tallyitem& item = mapTally[address];
1106 item.nAmount += txout.nValue;
1107 item.nConf = min(item.nConf, nDepth);
1113 map<string, tallyitem> mapAccountTally;
1114 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1116 const CBitcoinAddress& address = item.first;
1117 const string& strAccount = item.second;
1118 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1119 if (it == mapTally.end() && !fIncludeEmpty)
1123 int nConf = std::numeric_limits<int>::max();
1124 if (it != mapTally.end())
1126 nAmount = (*it).second.nAmount;
1127 nConf = (*it).second.nConf;
1132 tallyitem& item = mapAccountTally[strAccount];
1133 item.nAmount += nAmount;
1134 item.nConf = min(item.nConf, nConf);
1139 obj.push_back(Pair("address", address.ToString()));
1140 obj.push_back(Pair("account", strAccount));
1141 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1142 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1149 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1151 int64 nAmount = (*it).second.nAmount;
1152 int nConf = (*it).second.nConf;
1154 obj.push_back(Pair("account", (*it).first));
1155 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1156 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1164 Value listreceivedbyaddress(const Array& params, bool fHelp)
1166 if (fHelp || params.size() > 2)
1167 throw runtime_error(
1168 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1169 "[minconf] is the minimum number of confirmations before payments are included.\n"
1170 "[includeempty] whether to include addresses that haven't received any payments.\n"
1171 "Returns an array of objects containing:\n"
1172 " \"address\" : receiving address\n"
1173 " \"account\" : the account of the receiving address\n"
1174 " \"amount\" : total amount received by the address\n"
1175 " \"confirmations\" : number of confirmations of the most recent transaction included");
1177 return ListReceived(params, false);
1180 Value listreceivedbyaccount(const Array& params, bool fHelp)
1182 if (fHelp || params.size() > 2)
1183 throw runtime_error(
1184 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1185 "[minconf] is the minimum number of confirmations before payments are included.\n"
1186 "[includeempty] whether to include accounts that haven't received any payments.\n"
1187 "Returns an array of objects containing:\n"
1188 " \"account\" : the account of the receiving addresses\n"
1189 " \"amount\" : total amount received by addresses with this account\n"
1190 " \"confirmations\" : number of confirmations of the most recent transaction included");
1192 return ListReceived(params, true);
1195 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1197 int64 nGeneratedImmature, nGeneratedMature, nFee;
1198 string strSentAccount;
1199 list<pair<CBitcoinAddress, int64> > listReceived;
1200 list<pair<CBitcoinAddress, int64> > listSent;
1202 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1204 bool fAllAccounts = (strAccount == string("*"));
1206 // Generated blocks assigned to account ""
1207 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1210 entry.push_back(Pair("account", string("")));
1211 if (nGeneratedImmature)
1213 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1214 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1218 entry.push_back(Pair("category", "generate"));
1219 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1222 WalletTxToJSON(wtx, entry);
1223 ret.push_back(entry);
1227 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1229 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1232 entry.push_back(Pair("account", strSentAccount));
1233 entry.push_back(Pair("address", s.first.ToString()));
1234 entry.push_back(Pair("category", "send"));
1235 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1236 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1238 WalletTxToJSON(wtx, entry);
1239 ret.push_back(entry);
1244 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1246 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1249 if (pwalletMain->mapAddressBook.count(r.first))
1250 account = pwalletMain->mapAddressBook[r.first];
1251 if (fAllAccounts || (account == strAccount))
1254 entry.push_back(Pair("account", account));
1255 entry.push_back(Pair("address", r.first.ToString()));
1256 entry.push_back(Pair("category", "receive"));
1257 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1259 WalletTxToJSON(wtx, entry);
1260 ret.push_back(entry);
1266 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1268 bool fAllAccounts = (strAccount == string("*"));
1270 if (fAllAccounts || acentry.strAccount == strAccount)
1273 entry.push_back(Pair("account", acentry.strAccount));
1274 entry.push_back(Pair("category", "move"));
1275 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1276 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1277 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1278 entry.push_back(Pair("comment", acentry.strComment));
1279 ret.push_back(entry);
1283 Value listtransactions(const Array& params, bool fHelp)
1285 if (fHelp || params.size() > 3)
1286 throw runtime_error(
1287 "listtransactions [account] [count=10] [from=0]\n"
1288 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1290 string strAccount = "*";
1291 if (params.size() > 0)
1292 strAccount = params[0].get_str();
1294 if (params.size() > 1)
1295 nCount = params[1].get_int();
1297 if (params.size() > 2)
1298 nFrom = params[2].get_int();
1301 throw JSONRPCError(-8, "Negative count");
1303 throw JSONRPCError(-8, "Negative from");
1306 CWalletDB walletdb(pwalletMain->strWalletFile);
1308 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1309 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1310 typedef multimap<int64, TxPair > TxItems;
1313 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1314 // would make this much faster for applications that do this a lot.
1315 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1317 CWalletTx* wtx = &((*it).second);
1318 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1320 list<CAccountingEntry> acentries;
1321 walletdb.ListAccountCreditDebit(strAccount, acentries);
1322 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1324 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1327 // iterate backwards until we have nCount items to return:
1328 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1330 CWalletTx *const pwtx = (*it).second.first;
1332 ListTransactions(*pwtx, strAccount, 0, true, ret);
1333 CAccountingEntry *const pacentry = (*it).second.second;
1335 AcentryToJSON(*pacentry, strAccount, ret);
1337 if (ret.size() >= (nCount+nFrom)) break;
1339 // ret is newest to oldest
1341 if (nFrom > ret.size()) nFrom = ret.size();
1342 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1343 Array::iterator first = ret.begin();
1344 std::advance(first, nFrom);
1345 Array::iterator last = ret.begin();
1346 std::advance(last, nFrom+nCount);
1348 if (last != ret.end()) ret.erase(last, ret.end());
1349 if (first != ret.begin()) ret.erase(ret.begin(), first);
1351 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1356 Value listaccounts(const Array& params, bool fHelp)
1358 if (fHelp || params.size() > 1)
1359 throw runtime_error(
1360 "listaccounts [minconf=1]\n"
1361 "Returns Object that has account names as keys, account balances as values.");
1364 if (params.size() > 0)
1365 nMinDepth = params[0].get_int();
1367 map<string, int64> mapAccountBalances;
1368 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1369 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1370 mapAccountBalances[entry.second] = 0;
1373 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1375 const CWalletTx& wtx = (*it).second;
1376 int64 nGeneratedImmature, nGeneratedMature, nFee;
1377 string strSentAccount;
1378 list<pair<CBitcoinAddress, int64> > listReceived;
1379 list<pair<CBitcoinAddress, int64> > listSent;
1380 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1381 mapAccountBalances[strSentAccount] -= nFee;
1382 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1383 mapAccountBalances[strSentAccount] -= s.second;
1384 if (wtx.GetDepthInMainChain() >= nMinDepth)
1386 mapAccountBalances[""] += nGeneratedMature;
1387 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1388 if (pwalletMain->mapAddressBook.count(r.first))
1389 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1391 mapAccountBalances[""] += r.second;
1395 list<CAccountingEntry> acentries;
1396 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1397 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1398 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1401 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1402 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1407 Value listsinceblock(const Array& params, bool fHelp)
1410 throw runtime_error(
1411 "listsinceblock [blockhash] [target-confirmations]\n"
1412 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1414 CBlockIndex *pindex = NULL;
1415 int target_confirms = 1;
1417 if (params.size() > 0)
1419 uint256 blockId = 0;
1421 blockId.SetHex(params[0].get_str());
1422 pindex = CBlockLocator(blockId).GetBlockIndex();
1425 if (params.size() > 1)
1427 target_confirms = params[1].get_int();
1429 if (target_confirms < 1)
1430 throw JSONRPCError(-8, "Invalid parameter");
1433 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1437 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1439 CWalletTx tx = (*it).second;
1441 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1442 ListTransactions(tx, "*", 0, true, transactions);
1447 if (target_confirms == 1)
1449 lastblock = hashBestChain;
1453 int target_height = pindexBest->nHeight + 1 - target_confirms;
1456 for (block = pindexBest;
1457 block && block->nHeight > target_height;
1458 block = block->pprev) { }
1460 lastblock = block ? block->GetBlockHash() : 0;
1464 ret.push_back(Pair("transactions", transactions));
1465 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1470 Value gettransaction(const Array& params, bool fHelp)
1472 if (fHelp || params.size() != 1)
1473 throw runtime_error(
1474 "gettransaction <txid>\n"
1475 "Get detailed information about <txid>");
1478 hash.SetHex(params[0].get_str());
1482 if (!pwalletMain->mapWallet.count(hash))
1483 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1484 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1486 int64 nCredit = wtx.GetCredit();
1487 int64 nDebit = wtx.GetDebit();
1488 int64 nNet = nCredit - nDebit;
1489 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1491 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1493 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1495 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1498 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1499 entry.push_back(Pair("details", details));
1505 Value backupwallet(const Array& params, bool fHelp)
1507 if (fHelp || params.size() != 1)
1508 throw runtime_error(
1509 "backupwallet <destination>\n"
1510 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1512 string strDest = params[0].get_str();
1513 BackupWallet(*pwalletMain, strDest);
1519 Value keypoolrefill(const Array& params, bool fHelp)
1521 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1522 throw runtime_error(
1524 "Fills the keypool, requires wallet passphrase to be set.");
1525 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1526 throw runtime_error(
1528 "Fills the keypool.");
1530 if (pwalletMain->IsLocked())
1531 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1533 pwalletMain->TopUpKeyPool();
1535 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1536 throw JSONRPCError(-4, "Error refreshing keypool.");
1542 void ThreadTopUpKeyPool(void* parg)
1544 pwalletMain->TopUpKeyPool();
1547 void ThreadCleanWalletPassphrase(void* parg)
1549 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1551 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1553 if (nWalletUnlockTime == 0)
1555 nWalletUnlockTime = nMyWakeTime;
1559 if (nWalletUnlockTime==0)
1561 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1565 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1567 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1571 if (nWalletUnlockTime)
1573 nWalletUnlockTime = 0;
1574 pwalletMain->Lock();
1579 if (nWalletUnlockTime < nMyWakeTime)
1580 nWalletUnlockTime = nMyWakeTime;
1583 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1585 delete (int64*)parg;
1588 Value walletpassphrase(const Array& params, bool fHelp)
1590 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1591 throw runtime_error(
1592 "walletpassphrase <passphrase> <timeout>\n"
1593 "Stores the wallet decryption key in memory for <timeout> seconds.");
1596 if (!pwalletMain->IsCrypted())
1597 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1599 if (!pwalletMain->IsLocked())
1600 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1602 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1603 SecureString strWalletPass;
1604 strWalletPass.reserve(100);
1605 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1606 // Alternately, find a way to make params[0] mlock()'d to begin with.
1607 strWalletPass = params[0].get_str().c_str();
1609 if (strWalletPass.length() > 0)
1611 if (!pwalletMain->Unlock(strWalletPass))
1612 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1615 throw runtime_error(
1616 "walletpassphrase <passphrase> <timeout>\n"
1617 "Stores the wallet decryption key in memory for <timeout> seconds.");
1619 CreateThread(ThreadTopUpKeyPool, NULL);
1620 int64* pnSleepTime = new int64(params[1].get_int64());
1621 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1627 Value walletpassphrasechange(const Array& params, bool fHelp)
1629 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1630 throw runtime_error(
1631 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1632 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1635 if (!pwalletMain->IsCrypted())
1636 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1638 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1639 // Alternately, find a way to make params[0] mlock()'d to begin with.
1640 SecureString strOldWalletPass;
1641 strOldWalletPass.reserve(100);
1642 strOldWalletPass = params[0].get_str().c_str();
1644 SecureString strNewWalletPass;
1645 strNewWalletPass.reserve(100);
1646 strNewWalletPass = params[1].get_str().c_str();
1648 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1649 throw runtime_error(
1650 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1651 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1653 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1654 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1660 Value walletlock(const Array& params, bool fHelp)
1662 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1663 throw runtime_error(
1665 "Removes the wallet encryption key from memory, locking the wallet.\n"
1666 "After calling this method, you will need to call walletpassphrase again\n"
1667 "before being able to call any methods which require the wallet to be unlocked.");
1670 if (!pwalletMain->IsCrypted())
1671 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1673 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1675 pwalletMain->Lock();
1676 nWalletUnlockTime = 0;
1683 Value encryptwallet(const Array& params, bool fHelp)
1685 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1686 throw runtime_error(
1687 "encryptwallet <passphrase>\n"
1688 "Encrypts the wallet with <passphrase>.");
1691 if (pwalletMain->IsCrypted())
1692 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1695 // shutting down via RPC while the GUI is running does not work (yet):
1696 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1699 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1700 // Alternately, find a way to make params[0] mlock()'d to begin with.
1701 SecureString strWalletPass;
1702 strWalletPass.reserve(100);
1703 strWalletPass = params[0].get_str().c_str();
1705 if (strWalletPass.length() < 1)
1706 throw runtime_error(
1707 "encryptwallet <passphrase>\n"
1708 "Encrypts the wallet with <passphrase>.");
1710 if (!pwalletMain->EncryptWallet(strWalletPass))
1711 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1713 // BDB seems to have a bad habit of writing old data into
1714 // slack space in .dat files; that is bad if the old data is
1715 // unencrypted private keys. So:
1716 CreateThread(Shutdown, NULL);
1717 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1721 Value validateaddress(const Array& params, bool fHelp)
1723 if (fHelp || params.size() != 1)
1724 throw runtime_error(
1725 "validateaddress <bitcoinaddress>\n"
1726 "Return information about <bitcoinaddress>.");
1728 CBitcoinAddress address(params[0].get_str());
1729 bool isValid = address.IsValid();
1732 ret.push_back(Pair("isvalid", isValid));
1735 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1736 // version of the address:
1737 string currentAddress = address.ToString();
1738 ret.push_back(Pair("address", currentAddress));
1739 if (pwalletMain->HaveKey(address))
1741 ret.push_back(Pair("ismine", true));
1742 std::vector<unsigned char> vchPubKey;
1743 pwalletMain->GetPubKey(address, vchPubKey);
1744 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1746 key.SetPubKey(vchPubKey);
1747 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1749 else if (pwalletMain->HaveCScript(address.GetHash160()))
1751 ret.push_back(Pair("isscript", true));
1753 pwalletMain->GetCScript(address.GetHash160(), subscript);
1754 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1755 std::vector<CBitcoinAddress> addresses;
1756 txnouttype whichType;
1758 ExtractAddresses(subscript, whichType, addresses, nRequired);
1759 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1761 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1762 a.push_back(addr.ToString());
1763 ret.push_back(Pair("addresses", a));
1764 if (whichType == TX_MULTISIG)
1765 ret.push_back(Pair("sigsrequired", nRequired));
1768 ret.push_back(Pair("ismine", false));
1769 if (pwalletMain->mapAddressBook.count(address))
1770 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1775 Value getwork(const Array& params, bool fHelp)
1777 if (fHelp || params.size() > 1)
1778 throw runtime_error(
1780 "If [data] is not specified, returns formatted hash data to work on:\n"
1781 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1782 " \"data\" : block data\n"
1783 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1784 " \"target\" : little endian hash target\n"
1785 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1788 throw JSONRPCError(-9, "Bitcoin is not connected!");
1790 if (IsInitialBlockDownload())
1791 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1793 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1794 static mapNewBlock_t mapNewBlock;
1795 static vector<CBlock*> vNewBlock;
1796 static CReserveKey reservekey(pwalletMain);
1798 if (params.size() == 0)
1801 static unsigned int nTransactionsUpdatedLast;
1802 static CBlockIndex* pindexPrev;
1803 static int64 nStart;
1804 static CBlock* pblock;
1805 if (pindexPrev != pindexBest ||
1806 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1808 if (pindexPrev != pindexBest)
1810 // Deallocate old blocks since they're obsolete now
1811 mapNewBlock.clear();
1812 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1816 nTransactionsUpdatedLast = nTransactionsUpdated;
1817 pindexPrev = pindexBest;
1821 pblock = CreateNewBlock(reservekey);
1823 throw JSONRPCError(-7, "Out of memory");
1824 vNewBlock.push_back(pblock);
1828 pblock->UpdateTime(pindexPrev);
1831 // Update nExtraNonce
1832 static unsigned int nExtraNonce = 0;
1833 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1836 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1838 // Prebuild hash buffers
1842 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1844 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1847 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1848 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1849 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1850 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1856 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1857 if (vchData.size() != 128)
1858 throw JSONRPCError(-8, "Invalid parameter");
1859 CBlock* pdata = (CBlock*)&vchData[0];
1862 for (int i = 0; i < 128/4; i++)
1863 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1866 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1868 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1870 pblock->nTime = pdata->nTime;
1871 pblock->nNonce = pdata->nNonce;
1872 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1873 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1875 return CheckWork(pblock, *pwalletMain, reservekey);
1880 Value getmemorypool(const Array& params, bool fHelp)
1882 if (fHelp || params.size() > 1)
1883 throw runtime_error(
1884 "getmemorypool [data]\n"
1885 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1886 " \"version\" : block version\n"
1887 " \"previousblockhash\" : hash of current highest block\n"
1888 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1889 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1890 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1891 " \"time\" : timestamp appropriate for next block\n"
1892 " \"mintime\" : minimum timestamp appropriate for next block\n"
1893 " \"curtime\" : current timestamp\n"
1894 " \"bits\" : compressed target of next block\n"
1895 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1897 if (params.size() == 0)
1900 throw JSONRPCError(-9, "Bitcoin is not connected!");
1902 if (IsInitialBlockDownload())
1903 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1905 static CReserveKey reservekey(pwalletMain);
1908 static unsigned int nTransactionsUpdatedLast;
1909 static CBlockIndex* pindexPrev;
1910 static int64 nStart;
1911 static CBlock* pblock;
1912 if (pindexPrev != pindexBest ||
1913 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1915 nTransactionsUpdatedLast = nTransactionsUpdated;
1916 pindexPrev = pindexBest;
1922 pblock = CreateNewBlock(reservekey);
1924 throw JSONRPCError(-7, "Out of memory");
1928 pblock->UpdateTime(pindexPrev);
1932 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1939 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1943 result.push_back(Pair("version", pblock->nVersion));
1944 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1945 result.push_back(Pair("transactions", transactions));
1946 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1947 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1948 result.push_back(Pair("time", (int64_t)pblock->nTime));
1949 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1950 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1951 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1958 CDataStream ssBlock(ParseHex(params[0].get_str()));
1962 return ProcessBlock(NULL, &pblock);
1966 Value getblockhash(const Array& params, bool fHelp)
1968 if (fHelp || params.size() != 1)
1969 throw runtime_error(
1970 "getblockhash <index>\n"
1971 "Returns hash of block in best-block-chain at <index>.");
1973 int nHeight = params[0].get_int();
1974 if (nHeight < 0 || nHeight > nBestHeight)
1975 throw runtime_error("Block number out of range.");
1978 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1979 while (pblockindex->nHeight > nHeight)
1980 pblockindex = pblockindex->pprev;
1981 return pblockindex->phashBlock->GetHex();
1984 Value getblock(const Array& params, bool fHelp)
1986 if (fHelp || params.size() != 1)
1987 throw runtime_error(
1989 "Returns details of a block with given block-hash.");
1991 std::string strHash = params[0].get_str();
1992 uint256 hash(strHash);
1994 if (mapBlockIndex.count(hash) == 0)
1995 throw JSONRPCError(-5, "Block not found");
1998 CBlockIndex* pblockindex = mapBlockIndex[hash];
1999 block.ReadFromDisk(pblockindex, true);
2001 return blockToJSON(block, pblockindex);
2018 pair<string, rpcfn_type> pCallTable[] =
2020 make_pair("help", &help),
2021 make_pair("stop", &stop),
2022 make_pair("getblockcount", &getblockcount),
2023 make_pair("getblocknumber", &getblocknumber),
2024 make_pair("getconnectioncount", &getconnectioncount),
2025 make_pair("getdifficulty", &getdifficulty),
2026 make_pair("getgenerate", &getgenerate),
2027 make_pair("setgenerate", &setgenerate),
2028 make_pair("gethashespersec", &gethashespersec),
2029 make_pair("getinfo", &getinfo),
2030 make_pair("getmininginfo", &getmininginfo),
2031 make_pair("getnewaddress", &getnewaddress),
2032 make_pair("getaccountaddress", &getaccountaddress),
2033 make_pair("setaccount", &setaccount),
2034 make_pair("getaccount", &getaccount),
2035 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2036 make_pair("sendtoaddress", &sendtoaddress),
2037 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2038 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2039 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2040 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2041 make_pair("backupwallet", &backupwallet),
2042 make_pair("keypoolrefill", &keypoolrefill),
2043 make_pair("walletpassphrase", &walletpassphrase),
2044 make_pair("walletpassphrasechange", &walletpassphrasechange),
2045 make_pair("walletlock", &walletlock),
2046 make_pair("encryptwallet", &encryptwallet),
2047 make_pair("validateaddress", &validateaddress),
2048 make_pair("getbalance", &getbalance),
2049 make_pair("move", &movecmd),
2050 make_pair("sendfrom", &sendfrom),
2051 make_pair("sendmany", &sendmany),
2052 make_pair("addmultisigaddress", &addmultisigaddress),
2053 make_pair("getblock", &getblock),
2054 make_pair("getblockhash", &getblockhash),
2055 make_pair("gettransaction", &gettransaction),
2056 make_pair("listtransactions", &listtransactions),
2057 make_pair("signmessage", &signmessage),
2058 make_pair("verifymessage", &verifymessage),
2059 make_pair("getwork", &getwork),
2060 make_pair("listaccounts", &listaccounts),
2061 make_pair("settxfee", &settxfee),
2062 make_pair("getmemorypool", &getmemorypool),
2063 make_pair("listsinceblock", &listsinceblock),
2064 make_pair("dumpprivkey", &dumpprivkey),
2065 make_pair("importprivkey", &importprivkey)
2067 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2069 string pAllowInSafeMode[] =
2074 "getblocknumber", // deprecated
2075 "getconnectioncount",
2083 "getaccountaddress",
2085 "getaddressesbyaccount",
2094 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2102 // This ain't Apache. We're just using HTTP header for the length field
2103 // and to be compatible with other JSON-RPC implementations.
2106 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2109 s << "POST / HTTP/1.1\r\n"
2110 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2111 << "Host: 127.0.0.1\r\n"
2112 << "Content-Type: application/json\r\n"
2113 << "Content-Length: " << strMsg.size() << "\r\n"
2114 << "Connection: close\r\n"
2115 << "Accept: application/json\r\n";
2116 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2117 s << item.first << ": " << item.second << "\r\n";
2118 s << "\r\n" << strMsg;
2123 string rfc1123Time()
2128 struct tm* now_gmt = gmtime(&now);
2129 string locale(setlocale(LC_TIME, NULL));
2130 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2131 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2132 setlocale(LC_TIME, locale.c_str());
2133 return string(buffer);
2136 static string HTTPReply(int nStatus, const string& strMsg)
2139 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2141 "Server: bitcoin-json-rpc/%s\r\n"
2142 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2143 "Content-Type: text/html\r\n"
2144 "Content-Length: 296\r\n"
2146 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2147 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2150 "<TITLE>Error</TITLE>\r\n"
2151 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2153 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2154 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2155 const char *cStatus;
2156 if (nStatus == 200) cStatus = "OK";
2157 else if (nStatus == 400) cStatus = "Bad Request";
2158 else if (nStatus == 403) cStatus = "Forbidden";
2159 else if (nStatus == 404) cStatus = "Not Found";
2160 else if (nStatus == 500) cStatus = "Internal Server Error";
2163 "HTTP/1.1 %d %s\r\n"
2165 "Connection: close\r\n"
2166 "Content-Length: %d\r\n"
2167 "Content-Type: application/json\r\n"
2168 "Server: bitcoin-json-rpc/%s\r\n"
2173 rfc1123Time().c_str(),
2175 FormatFullVersion().c_str(),
2179 int ReadHTTPStatus(std::basic_istream<char>& stream)
2182 getline(stream, str);
2183 vector<string> vWords;
2184 boost::split(vWords, str, boost::is_any_of(" "));
2185 if (vWords.size() < 2)
2187 return atoi(vWords[1].c_str());
2190 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2196 std::getline(stream, str);
2197 if (str.empty() || str == "\r")
2199 string::size_type nColon = str.find(":");
2200 if (nColon != string::npos)
2202 string strHeader = str.substr(0, nColon);
2203 boost::trim(strHeader);
2204 boost::to_lower(strHeader);
2205 string strValue = str.substr(nColon+1);
2206 boost::trim(strValue);
2207 mapHeadersRet[strHeader] = strValue;
2208 if (strHeader == "content-length")
2209 nLen = atoi(strValue.c_str());
2215 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2217 mapHeadersRet.clear();
2221 int nStatus = ReadHTTPStatus(stream);
2224 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2225 if (nLen < 0 || nLen > MAX_SIZE)
2231 vector<char> vch(nLen);
2232 stream.read(&vch[0], nLen);
2233 strMessageRet = string(vch.begin(), vch.end());
2239 bool HTTPAuthorized(map<string, string>& mapHeaders)
2241 string strAuth = mapHeaders["authorization"];
2242 if (strAuth.substr(0,6) != "Basic ")
2244 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2245 string strUserPass = DecodeBase64(strUserPass64);
2246 return strUserPass == strRPCUserColonPass;
2250 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2251 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2252 // unspecified (HTTP errors and contents of 'error').
2254 // 1.0 spec: http://json-rpc.org/wiki/specification
2255 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2256 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2259 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2262 request.push_back(Pair("method", strMethod));
2263 request.push_back(Pair("params", params));
2264 request.push_back(Pair("id", id));
2265 return write_string(Value(request), false) + "\n";
2268 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2271 if (error.type() != null_type)
2272 reply.push_back(Pair("result", Value::null));
2274 reply.push_back(Pair("result", result));
2275 reply.push_back(Pair("error", error));
2276 reply.push_back(Pair("id", id));
2277 return write_string(Value(reply), false) + "\n";
2280 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2282 // Send error reply from json-rpc error object
2284 int code = find_value(objError, "code").get_int();
2285 if (code == -32600) nStatus = 400;
2286 else if (code == -32601) nStatus = 404;
2287 string strReply = JSONRPCReply(Value::null, objError, id);
2288 stream << HTTPReply(nStatus, strReply) << std::flush;
2291 bool ClientAllowed(const string& strAddress)
2293 if (strAddress == asio::ip::address_v4::loopback().to_string())
2295 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2296 BOOST_FOREACH(string strAllow, vAllow)
2297 if (WildcardMatch(strAddress, strAllow))
2304 // IOStream device that speaks SSL but can also speak non-SSL
2306 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2308 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2310 fUseSSL = fUseSSLIn;
2311 fNeedHandshake = fUseSSLIn;
2314 void handshake(ssl::stream_base::handshake_type role)
2316 if (!fNeedHandshake) return;
2317 fNeedHandshake = false;
2318 stream.handshake(role);
2320 std::streamsize read(char* s, std::streamsize n)
2322 handshake(ssl::stream_base::server); // HTTPS servers read first
2323 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2324 return stream.next_layer().read_some(asio::buffer(s, n));
2326 std::streamsize write(const char* s, std::streamsize n)
2328 handshake(ssl::stream_base::client); // HTTPS clients write first
2329 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2330 return asio::write(stream.next_layer(), asio::buffer(s, n));
2332 bool connect(const std::string& server, const std::string& port)
2334 ip::tcp::resolver resolver(stream.get_io_service());
2335 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2336 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2337 ip::tcp::resolver::iterator end;
2338 boost::system::error_code error = asio::error::host_not_found;
2339 while (error && endpoint_iterator != end)
2341 stream.lowest_layer().close();
2342 stream.lowest_layer().connect(*endpoint_iterator++, error);
2350 bool fNeedHandshake;
2356 void ThreadRPCServer(void* parg)
2358 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2361 vnThreadsRunning[THREAD_RPCSERVER]++;
2362 ThreadRPCServer2(parg);
2363 vnThreadsRunning[THREAD_RPCSERVER]--;
2365 catch (std::exception& e) {
2366 vnThreadsRunning[THREAD_RPCSERVER]--;
2367 PrintException(&e, "ThreadRPCServer()");
2369 vnThreadsRunning[THREAD_RPCSERVER]--;
2370 PrintException(NULL, "ThreadRPCServer()");
2372 printf("ThreadRPCServer exiting\n");
2376 extern bool HACK_SHUTDOWN;
2379 void ThreadRPCServer2(void* parg)
2381 printf("ThreadRPCServer started\n");
2383 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2384 if (mapArgs["-rpcpassword"] == "")
2386 unsigned char rand_pwd[32];
2387 RAND_bytes(rand_pwd, 32);
2388 string strWhatAmI = "To use bitcoind";
2389 if (mapArgs.count("-server"))
2390 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2391 else if (mapArgs.count("-daemon"))
2392 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2393 ThreadSafeMessageBox(strprintf(
2394 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2395 "It is recommended you use the following random password:\n"
2396 "rpcuser=bitcoinrpc\n"
2398 "(you do not need to remember this password)\n"
2399 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2401 GetConfigFile().c_str(),
2402 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2403 _("Error"), wxOK | wxMODAL);
2405 CreateThread(Shutdown, NULL);
2410 bool fUseSSL = GetBoolArg("-rpcssl");
2411 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2413 asio::io_service io_service;
2414 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2416 ip::tcp::acceptor acceptor(io_service, endpoint);
2418 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2420 ip::tcp::acceptor acceptor(io_service);
2423 acceptor.open(endpoint.protocol());
2424 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2425 acceptor.bind(endpoint);
2426 acceptor.listen(socket_base::max_connections);
2428 catch(boost::system::system_error &e)
2430 HACK_SHUTDOWN = true;
2431 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2432 _("Error"), wxOK | wxMODAL);
2438 ssl::context context(io_service, ssl::context::sslv23);
2441 context.set_options(ssl::context::no_sslv2);
2442 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2443 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2444 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2445 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2446 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2447 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2448 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2449 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2451 string ciphers = GetArg("-rpcsslciphers",
2452 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2453 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2457 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2462 // Accept connection
2464 SSLStream sslStream(io_service, context);
2465 SSLIOStreamDevice d(sslStream, fUseSSL);
2466 iostreams::stream<SSLIOStreamDevice> stream(d);
2468 ip::tcp::iostream stream;
2471 ip::tcp::endpoint peer;
2472 vnThreadsRunning[THREAD_RPCSERVER]--;
2474 acceptor.accept(sslStream.lowest_layer(), peer);
2476 acceptor.accept(*stream.rdbuf(), peer);
2478 vnThreadsRunning[4]++;
2482 // Restrict callers by IP
2483 if (!ClientAllowed(peer.address().to_string()))
2485 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2487 stream << HTTPReply(403, "") << std::flush;
2491 map<string, string> mapHeaders;
2494 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2495 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2498 printf("ThreadRPCServer ReadHTTP timeout\n");
2502 // Check authorization
2503 if (mapHeaders.count("authorization") == 0)
2505 stream << HTTPReply(401, "") << std::flush;
2508 if (!HTTPAuthorized(mapHeaders))
2510 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2511 /* Deter brute-forcing short passwords.
2512 If this results in a DOS the user really
2513 shouldn't have their RPC port exposed.*/
2514 if (mapArgs["-rpcpassword"].size() < 20)
2517 stream << HTTPReply(401, "") << std::flush;
2521 Value id = Value::null;
2526 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2527 throw JSONRPCError(-32700, "Parse error");
2528 const Object& request = valRequest.get_obj();
2530 // Parse id now so errors from here on will have the id
2531 id = find_value(request, "id");
2534 Value valMethod = find_value(request, "method");
2535 if (valMethod.type() == null_type)
2536 throw JSONRPCError(-32600, "Missing method");
2537 if (valMethod.type() != str_type)
2538 throw JSONRPCError(-32600, "Method must be a string");
2539 string strMethod = valMethod.get_str();
2540 if (strMethod != "getwork" && strMethod != "getmemorypool")
2541 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2544 Value valParams = find_value(request, "params");
2546 if (valParams.type() == array_type)
2547 params = valParams.get_array();
2548 else if (valParams.type() == null_type)
2551 throw JSONRPCError(-32600, "Params must be an array");
2554 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2555 if (mi == mapCallTable.end())
2556 throw JSONRPCError(-32601, "Method not found");
2558 // Observe safe mode
2559 string strWarning = GetWarnings("rpc");
2560 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2561 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2567 CRITICAL_BLOCK(cs_main)
2568 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2569 result = (*(*mi).second)(params, false);
2572 string strReply = JSONRPCReply(result, Value::null, id);
2573 stream << HTTPReply(200, strReply) << std::flush;
2575 catch (std::exception& e)
2577 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2580 catch (Object& objError)
2582 ErrorReply(stream, objError, id);
2584 catch (std::exception& e)
2586 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2594 Object CallRPC(const string& strMethod, const Array& params)
2596 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2597 throw runtime_error(strprintf(
2598 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2599 "If the file does not exist, create it with owner-readable-only file permissions."),
2600 GetConfigFile().c_str()));
2602 // Connect to localhost
2603 bool fUseSSL = GetBoolArg("-rpcssl");
2605 asio::io_service io_service;
2606 ssl::context context(io_service, ssl::context::sslv23);
2607 context.set_options(ssl::context::no_sslv2);
2608 SSLStream sslStream(io_service, context);
2609 SSLIOStreamDevice d(sslStream, fUseSSL);
2610 iostreams::stream<SSLIOStreamDevice> stream(d);
2611 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2612 throw runtime_error("couldn't connect to server");
2615 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2617 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2619 throw runtime_error("couldn't connect to server");
2623 // HTTP basic authentication
2624 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2625 map<string, string> mapRequestHeaders;
2626 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2629 string strRequest = JSONRPCRequest(strMethod, params, 1);
2630 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2631 stream << strPost << std::flush;
2634 map<string, string> mapHeaders;
2636 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2638 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2639 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2640 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2641 else if (strReply.empty())
2642 throw runtime_error("no response from server");
2646 if (!read_string(strReply, valReply))
2647 throw runtime_error("couldn't parse reply from server");
2648 const Object& reply = valReply.get_obj();
2650 throw runtime_error("expected reply to have result, error and id properties");
2658 template<typename T>
2659 void ConvertTo(Value& value)
2661 if (value.type() == str_type)
2663 // reinterpret string as unquoted json value
2665 if (!read_string(value.get_str(), value2))
2666 throw runtime_error("type mismatch");
2667 value = value2.get_value<T>();
2671 value = value.get_value<T>();
2675 int CommandLineRPC(int argc, char *argv[])
2682 while (argc > 1 && IsSwitchChar(argv[1][0]))
2690 throw runtime_error("too few parameters");
2691 string strMethod = argv[1];
2693 // Parameters default to strings
2695 for (int i = 2; i < argc; i++)
2696 params.push_back(argv[i]);
2697 int n = params.size();
2700 // Special case non-string parameter types
2702 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2703 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2704 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2705 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2706 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2707 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2708 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2709 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2710 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2711 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2712 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2713 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2714 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2715 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2716 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2717 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2718 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2719 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2720 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2721 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2722 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2723 if (strMethod == "sendmany" && n > 1)
2725 string s = params[1].get_str();
2727 if (!read_string(s, v) || v.type() != obj_type)
2728 throw runtime_error("type mismatch");
2729 params[1] = v.get_obj();
2731 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2732 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2733 if (strMethod == "addmultisigaddress" && n > 1)
2735 string s = params[1].get_str();
2737 if (!read_string(s, v) || v.type() != array_type)
2738 throw runtime_error("type mismatch "+s);
2739 params[1] = v.get_array();
2743 Object reply = CallRPC(strMethod, params);
2746 const Value& result = find_value(reply, "result");
2747 const Value& error = find_value(reply, "error");
2749 if (error.type() != null_type)
2752 strPrint = "error: " + write_string(error, false);
2753 int code = find_value(error.get_obj(), "code").get_int();
2759 if (result.type() == null_type)
2761 else if (result.type() == str_type)
2762 strPrint = result.get_str();
2764 strPrint = write_string(result, true);
2767 catch (std::exception& e)
2769 strPrint = string("error: ") + e.what();
2774 PrintException(NULL, "CommandLineRPC()");
2779 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2788 int main(int argc, char *argv[])
2791 // Turn off microsoft heap dump noise
2792 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2793 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2795 setbuf(stdin, NULL);
2796 setbuf(stdout, NULL);
2797 setbuf(stderr, NULL);
2801 if (argc >= 2 && string(argv[1]) == "-server")
2803 printf("server ready\n");
2804 ThreadRPCServer(NULL);
2808 return CommandLineRPC(argc, argv);
2811 catch (std::exception& e) {
2812 PrintException(&e, "main()");
2814 PrintException(NULL, "main()");