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)
805 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
806 nBalance += r.second;
807 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
808 nBalance -= r.second;
810 nBalance += allGeneratedMature;
812 return ValueFromAmount(nBalance);
815 string strAccount = AccountFromValue(params[0]);
817 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
819 return ValueFromAmount(nBalance);
823 Value movecmd(const Array& params, bool fHelp)
825 if (fHelp || params.size() < 3 || params.size() > 5)
827 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
828 "Move from one account in your wallet to another.");
830 string strFrom = AccountFromValue(params[0]);
831 string strTo = AccountFromValue(params[1]);
832 int64 nAmount = AmountFromValue(params[2]);
833 if (params.size() > 3)
834 // unused parameter, used to be nMinDepth, keep type-checking it though
835 (void)params[3].get_int();
837 if (params.size() > 4)
838 strComment = params[4].get_str();
840 CWalletDB walletdb(pwalletMain->strWalletFile);
843 int64 nNow = GetAdjustedTime();
846 CAccountingEntry debit;
847 debit.strAccount = strFrom;
848 debit.nCreditDebit = -nAmount;
850 debit.strOtherAccount = strTo;
851 debit.strComment = strComment;
852 walletdb.WriteAccountingEntry(debit);
855 CAccountingEntry credit;
856 credit.strAccount = strTo;
857 credit.nCreditDebit = nAmount;
859 credit.strOtherAccount = strFrom;
860 credit.strComment = strComment;
861 walletdb.WriteAccountingEntry(credit);
863 walletdb.TxnCommit();
869 Value sendfrom(const Array& params, bool fHelp)
871 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
873 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
874 "<amount> is a real and is rounded to the nearest 0.00000001\n"
875 "requires wallet passphrase to be set with walletpassphrase first");
876 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
878 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
879 "<amount> is a real and is rounded to the nearest 0.00000001");
881 string strAccount = AccountFromValue(params[0]);
882 CBitcoinAddress address(params[1].get_str());
883 if (!address.IsValid())
884 throw JSONRPCError(-5, "Invalid bitcoin address");
885 int64 nAmount = AmountFromValue(params[2]);
887 if (params.size() > 3)
888 nMinDepth = params[3].get_int();
891 wtx.strFromAccount = strAccount;
892 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
893 wtx.mapValue["comment"] = params[4].get_str();
894 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
895 wtx.mapValue["to"] = params[5].get_str();
897 if (pwalletMain->IsLocked())
898 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
901 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
902 if (nAmount > nBalance)
903 throw JSONRPCError(-6, "Account has insufficient funds");
906 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
908 throw JSONRPCError(-4, strError);
910 return wtx.GetHash().GetHex();
914 Value sendmany(const Array& params, bool fHelp)
916 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
918 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
919 "amounts are double-precision floating point numbers\n"
920 "requires wallet passphrase to be set with walletpassphrase first");
921 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
923 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
924 "amounts are double-precision floating point numbers");
926 string strAccount = AccountFromValue(params[0]);
927 Object sendTo = params[1].get_obj();
929 if (params.size() > 2)
930 nMinDepth = params[2].get_int();
933 wtx.strFromAccount = strAccount;
934 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
935 wtx.mapValue["comment"] = params[3].get_str();
937 set<CBitcoinAddress> setAddress;
938 vector<pair<CScript, int64> > vecSend;
940 int64 totalAmount = 0;
941 BOOST_FOREACH(const Pair& s, sendTo)
943 CBitcoinAddress address(s.name_);
944 if (!address.IsValid())
945 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
947 if (setAddress.count(address))
948 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
949 setAddress.insert(address);
951 CScript scriptPubKey;
952 scriptPubKey.SetBitcoinAddress(address);
953 int64 nAmount = AmountFromValue(s.value_);
954 totalAmount += nAmount;
956 vecSend.push_back(make_pair(scriptPubKey, nAmount));
959 if (pwalletMain->IsLocked())
960 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
963 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
964 if (totalAmount > nBalance)
965 throw JSONRPCError(-6, "Account has insufficient funds");
968 CReserveKey keyChange(pwalletMain);
969 int64 nFeeRequired = 0;
970 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
973 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
974 throw JSONRPCError(-6, "Insufficient funds");
975 throw JSONRPCError(-4, "Transaction creation failed");
977 if (!pwalletMain->CommitTransaction(wtx, keyChange))
978 throw JSONRPCError(-4, "Transaction commit failed");
980 return wtx.GetHash().GetHex();
983 Value addmultisigaddress(const Array& params, bool fHelp)
985 if (fHelp || params.size() < 2 || params.size() > 3)
987 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
988 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
989 "each key is a bitcoin address or hex-encoded public key\n"
990 "If [account] is specified, assign address to [account].";
991 throw runtime_error(msg);
994 throw runtime_error("addmultisigaddress available only when running -testnet\n");
996 int nRequired = params[0].get_int();
997 const Array& keys = params[1].get_array();
999 if (params.size() > 2)
1000 strAccount = AccountFromValue(params[2]);
1002 // Gather public keys
1003 if (nRequired < 1 || keys.size() < nRequired)
1004 throw runtime_error(
1005 strprintf("wrong number of keys"
1006 "(got %d, need at least %d)", keys.size(), nRequired));
1007 std::vector<CKey> pubkeys;
1008 pubkeys.resize(keys.size());
1009 for (int i = 0; i < keys.size(); i++)
1011 const std::string& ks = keys[i].get_str();
1013 // Case 1: bitcoin address and we have full public key:
1014 CBitcoinAddress address(ks);
1015 if (address.IsValid())
1017 if (address.IsScript())
1018 throw runtime_error(
1019 strprintf("%s is a pay-to-script address",ks.c_str()));
1020 std::vector<unsigned char> vchPubKey;
1021 if (!pwalletMain->GetPubKey(address, vchPubKey))
1022 throw runtime_error(
1023 strprintf("no full public key for address %s",ks.c_str()));
1024 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1025 throw runtime_error(" Invalid public key: "+ks);
1028 // Case 2: hex public key
1031 vector<unsigned char> vchPubKey = ParseHex(ks);
1032 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1033 throw runtime_error(" Invalid public key: "+ks);
1037 throw runtime_error(" Invalid public key: "+ks);
1041 // Construct using pay-to-script-hash:
1043 inner.SetMultisig(nRequired, pubkeys);
1045 uint160 scriptHash = Hash160(inner);
1046 CScript scriptPubKey;
1047 scriptPubKey.SetPayToScriptHash(inner);
1048 pwalletMain->AddCScript(inner);
1049 CBitcoinAddress address;
1050 address.SetScriptHash160(scriptHash);
1052 pwalletMain->SetAddressBookName(address, strAccount);
1053 return address.ToString();
1064 nConf = std::numeric_limits<int>::max();
1068 Value ListReceived(const Array& params, bool fByAccounts)
1070 // Minimum confirmations
1072 if (params.size() > 0)
1073 nMinDepth = params[0].get_int();
1075 // Whether to include empty accounts
1076 bool fIncludeEmpty = false;
1077 if (params.size() > 1)
1078 fIncludeEmpty = params[1].get_bool();
1081 map<CBitcoinAddress, tallyitem> mapTally;
1082 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1084 const CWalletTx& wtx = (*it).second;
1086 if (wtx.IsCoinBase() || !wtx.IsFinal())
1089 int nDepth = wtx.GetDepthInMainChain();
1090 if (nDepth < nMinDepth)
1093 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1095 CBitcoinAddress address;
1096 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1099 tallyitem& item = mapTally[address];
1100 item.nAmount += txout.nValue;
1101 item.nConf = min(item.nConf, nDepth);
1107 map<string, tallyitem> mapAccountTally;
1108 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1110 const CBitcoinAddress& address = item.first;
1111 const string& strAccount = item.second;
1112 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1113 if (it == mapTally.end() && !fIncludeEmpty)
1117 int nConf = std::numeric_limits<int>::max();
1118 if (it != mapTally.end())
1120 nAmount = (*it).second.nAmount;
1121 nConf = (*it).second.nConf;
1126 tallyitem& item = mapAccountTally[strAccount];
1127 item.nAmount += nAmount;
1128 item.nConf = min(item.nConf, nConf);
1133 obj.push_back(Pair("address", address.ToString()));
1134 obj.push_back(Pair("account", strAccount));
1135 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1136 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1143 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1145 int64 nAmount = (*it).second.nAmount;
1146 int nConf = (*it).second.nConf;
1148 obj.push_back(Pair("account", (*it).first));
1149 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1150 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1158 Value listreceivedbyaddress(const Array& params, bool fHelp)
1160 if (fHelp || params.size() > 2)
1161 throw runtime_error(
1162 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1163 "[minconf] is the minimum number of confirmations before payments are included.\n"
1164 "[includeempty] whether to include addresses that haven't received any payments.\n"
1165 "Returns an array of objects containing:\n"
1166 " \"address\" : receiving address\n"
1167 " \"account\" : the account of the receiving address\n"
1168 " \"amount\" : total amount received by the address\n"
1169 " \"confirmations\" : number of confirmations of the most recent transaction included");
1171 return ListReceived(params, false);
1174 Value listreceivedbyaccount(const Array& params, bool fHelp)
1176 if (fHelp || params.size() > 2)
1177 throw runtime_error(
1178 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1179 "[minconf] is the minimum number of confirmations before payments are included.\n"
1180 "[includeempty] whether to include accounts that haven't received any payments.\n"
1181 "Returns an array of objects containing:\n"
1182 " \"account\" : the account of the receiving addresses\n"
1183 " \"amount\" : total amount received by addresses with this account\n"
1184 " \"confirmations\" : number of confirmations of the most recent transaction included");
1186 return ListReceived(params, true);
1189 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1191 int64 nGeneratedImmature, nGeneratedMature, nFee;
1192 string strSentAccount;
1193 list<pair<CBitcoinAddress, int64> > listReceived;
1194 list<pair<CBitcoinAddress, int64> > listSent;
1196 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1198 bool fAllAccounts = (strAccount == string("*"));
1200 // Generated blocks assigned to account ""
1201 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1204 entry.push_back(Pair("account", string("")));
1205 if (nGeneratedImmature)
1207 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1208 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1212 entry.push_back(Pair("category", "generate"));
1213 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1216 WalletTxToJSON(wtx, entry);
1217 ret.push_back(entry);
1221 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1223 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1226 entry.push_back(Pair("account", strSentAccount));
1227 entry.push_back(Pair("address", s.first.ToString()));
1228 entry.push_back(Pair("category", "send"));
1229 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1230 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1232 WalletTxToJSON(wtx, entry);
1233 ret.push_back(entry);
1238 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1239 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1242 if (pwalletMain->mapAddressBook.count(r.first))
1243 account = pwalletMain->mapAddressBook[r.first];
1244 if (fAllAccounts || (account == strAccount))
1247 entry.push_back(Pair("account", account));
1248 entry.push_back(Pair("address", r.first.ToString()));
1249 entry.push_back(Pair("category", "receive"));
1250 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1252 WalletTxToJSON(wtx, entry);
1253 ret.push_back(entry);
1258 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1260 bool fAllAccounts = (strAccount == string("*"));
1262 if (fAllAccounts || acentry.strAccount == strAccount)
1265 entry.push_back(Pair("account", acentry.strAccount));
1266 entry.push_back(Pair("category", "move"));
1267 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1268 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1269 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1270 entry.push_back(Pair("comment", acentry.strComment));
1271 ret.push_back(entry);
1275 Value listtransactions(const Array& params, bool fHelp)
1277 if (fHelp || params.size() > 3)
1278 throw runtime_error(
1279 "listtransactions [account] [count=10] [from=0]\n"
1280 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1282 string strAccount = "*";
1283 if (params.size() > 0)
1284 strAccount = params[0].get_str();
1286 if (params.size() > 1)
1287 nCount = params[1].get_int();
1289 if (params.size() > 2)
1290 nFrom = params[2].get_int();
1293 CWalletDB walletdb(pwalletMain->strWalletFile);
1295 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1296 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1297 typedef multimap<int64, TxPair > TxItems;
1300 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1302 CWalletTx* wtx = &((*it).second);
1303 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1305 list<CAccountingEntry> acentries;
1306 walletdb.ListAccountCreditDebit(strAccount, acentries);
1307 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1309 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1312 // Now: iterate backwards until we have nCount items to return:
1313 TxItems::reverse_iterator it = txByTime.rbegin();
1314 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1315 for (; it != txByTime.rend(); ++it)
1317 CWalletTx *const pwtx = (*it).second.first;
1319 ListTransactions(*pwtx, strAccount, 0, true, ret);
1320 CAccountingEntry *const pacentry = (*it).second.second;
1322 AcentryToJSON(*pacentry, strAccount, ret);
1324 if (ret.size() >= nCount) break;
1326 // ret is now newest to oldest
1328 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1329 if (ret.size() > nCount)
1331 Array::iterator last = ret.begin();
1332 std::advance(last, nCount);
1333 ret.erase(last, ret.end());
1335 std::reverse(ret.begin(), ret.end()); // oldest to newest
1340 Value listaccounts(const Array& params, bool fHelp)
1342 if (fHelp || params.size() > 1)
1343 throw runtime_error(
1344 "listaccounts [minconf=1]\n"
1345 "Returns Object that has account names as keys, account balances as values.");
1348 if (params.size() > 0)
1349 nMinDepth = params[0].get_int();
1351 map<string, int64> mapAccountBalances;
1352 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1353 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1354 mapAccountBalances[entry.second] = 0;
1357 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1359 const CWalletTx& wtx = (*it).second;
1360 int64 nGeneratedImmature, nGeneratedMature, nFee;
1361 string strSentAccount;
1362 list<pair<CBitcoinAddress, int64> > listReceived;
1363 list<pair<CBitcoinAddress, int64> > listSent;
1364 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1365 mapAccountBalances[strSentAccount] -= nFee;
1366 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1367 mapAccountBalances[strSentAccount] -= s.second;
1368 if (wtx.GetDepthInMainChain() >= nMinDepth)
1370 mapAccountBalances[""] += nGeneratedMature;
1371 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1372 if (pwalletMain->mapAddressBook.count(r.first))
1373 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1375 mapAccountBalances[""] += r.second;
1379 list<CAccountingEntry> acentries;
1380 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1381 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1382 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1385 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1386 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1391 Value listsinceblock(const Array& params, bool fHelp)
1394 throw runtime_error(
1395 "listsinceblock [blockid] [target-confirmations]\n"
1396 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1398 CBlockIndex *pindex = NULL;
1399 int target_confirms = 1;
1401 if (params.size() > 0)
1403 uint256 blockId = 0;
1405 blockId.SetHex(params[0].get_str());
1406 pindex = CBlockLocator(blockId).GetBlockIndex();
1409 if (params.size() > 1)
1411 target_confirms = params[1].get_int();
1413 if (target_confirms < 1)
1414 throw JSONRPCError(-8, "Invalid parameter");
1417 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1421 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1423 CWalletTx tx = (*it).second;
1425 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1426 ListTransactions(tx, "*", 0, true, transactions);
1431 if (target_confirms == 1)
1434 lastblock = hashBestChain;
1438 int target_height = pindexBest->nHeight + 1 - target_confirms;
1441 for (block = pindexBest;
1442 block && block->nHeight > target_height;
1443 block = block->pprev) { }
1445 lastblock = block ? block->GetBlockHash() : 0;
1449 ret.push_back(Pair("transactions", transactions));
1450 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1455 Value gettransaction(const Array& params, bool fHelp)
1457 if (fHelp || params.size() != 1)
1458 throw runtime_error(
1459 "gettransaction <txid>\n"
1460 "Get detailed information about <txid>");
1463 hash.SetHex(params[0].get_str());
1467 if (!pwalletMain->mapWallet.count(hash))
1468 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1469 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1471 int64 nCredit = wtx.GetCredit();
1472 int64 nDebit = wtx.GetDebit();
1473 int64 nNet = nCredit - nDebit;
1474 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1476 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1478 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1480 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1483 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1484 entry.push_back(Pair("details", details));
1490 Value backupwallet(const Array& params, bool fHelp)
1492 if (fHelp || params.size() != 1)
1493 throw runtime_error(
1494 "backupwallet <destination>\n"
1495 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1497 string strDest = params[0].get_str();
1498 BackupWallet(*pwalletMain, strDest);
1504 Value keypoolrefill(const Array& params, bool fHelp)
1506 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1507 throw runtime_error(
1509 "Fills the keypool, requires wallet passphrase to be set.");
1510 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511 throw runtime_error(
1513 "Fills the keypool.");
1515 if (pwalletMain->IsLocked())
1516 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1518 pwalletMain->TopUpKeyPool();
1520 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1521 throw JSONRPCError(-4, "Error refreshing keypool.");
1527 void ThreadTopUpKeyPool(void* parg)
1529 pwalletMain->TopUpKeyPool();
1532 void ThreadCleanWalletPassphrase(void* parg)
1534 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1536 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1538 if (nWalletUnlockTime == 0)
1540 nWalletUnlockTime = nMyWakeTime;
1544 if (nWalletUnlockTime==0)
1546 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1550 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1552 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 if (nWalletUnlockTime)
1558 nWalletUnlockTime = 0;
1559 pwalletMain->Lock();
1564 if (nWalletUnlockTime < nMyWakeTime)
1565 nWalletUnlockTime = nMyWakeTime;
1568 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1570 delete (int64*)parg;
1573 Value walletpassphrase(const Array& params, bool fHelp)
1575 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1576 throw runtime_error(
1577 "walletpassphrase <passphrase> <timeout>\n"
1578 "Stores the wallet decryption key in memory for <timeout> seconds.");
1581 if (!pwalletMain->IsCrypted())
1582 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1584 if (!pwalletMain->IsLocked())
1585 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1587 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1588 SecureString strWalletPass;
1589 strWalletPass.reserve(100);
1590 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1591 // Alternately, find a way to make params[0] mlock()'d to begin with.
1592 strWalletPass = params[0].get_str().c_str();
1594 if (strWalletPass.length() > 0)
1596 if (!pwalletMain->Unlock(strWalletPass))
1597 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1600 throw runtime_error(
1601 "walletpassphrase <passphrase> <timeout>\n"
1602 "Stores the wallet decryption key in memory for <timeout> seconds.");
1604 CreateThread(ThreadTopUpKeyPool, NULL);
1605 int64* pnSleepTime = new int64(params[1].get_int64());
1606 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1612 Value walletpassphrasechange(const Array& params, bool fHelp)
1614 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1615 throw runtime_error(
1616 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1617 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1620 if (!pwalletMain->IsCrypted())
1621 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1623 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1624 // Alternately, find a way to make params[0] mlock()'d to begin with.
1625 SecureString strOldWalletPass;
1626 strOldWalletPass.reserve(100);
1627 strOldWalletPass = params[0].get_str().c_str();
1629 SecureString strNewWalletPass;
1630 strNewWalletPass.reserve(100);
1631 strNewWalletPass = params[1].get_str().c_str();
1633 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1634 throw runtime_error(
1635 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1636 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1638 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1639 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1645 Value walletlock(const Array& params, bool fHelp)
1647 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1648 throw runtime_error(
1650 "Removes the wallet encryption key from memory, locking the wallet.\n"
1651 "After calling this method, you will need to call walletpassphrase again\n"
1652 "before being able to call any methods which require the wallet to be unlocked.");
1655 if (!pwalletMain->IsCrypted())
1656 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1658 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1660 pwalletMain->Lock();
1661 nWalletUnlockTime = 0;
1668 Value encryptwallet(const Array& params, bool fHelp)
1670 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1671 throw runtime_error(
1672 "encryptwallet <passphrase>\n"
1673 "Encrypts the wallet with <passphrase>.");
1676 if (pwalletMain->IsCrypted())
1677 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1680 // shutting down via RPC while the GUI is running does not work (yet):
1681 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1684 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1685 // Alternately, find a way to make params[0] mlock()'d to begin with.
1686 SecureString strWalletPass;
1687 strWalletPass.reserve(100);
1688 strWalletPass = params[0].get_str().c_str();
1690 if (strWalletPass.length() < 1)
1691 throw runtime_error(
1692 "encryptwallet <passphrase>\n"
1693 "Encrypts the wallet with <passphrase>.");
1695 if (!pwalletMain->EncryptWallet(strWalletPass))
1696 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1698 // BDB seems to have a bad habit of writing old data into
1699 // slack space in .dat files; that is bad if the old data is
1700 // unencrypted private keys. So:
1701 CreateThread(Shutdown, NULL);
1702 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1706 Value validateaddress(const Array& params, bool fHelp)
1708 if (fHelp || params.size() != 1)
1709 throw runtime_error(
1710 "validateaddress <bitcoinaddress>\n"
1711 "Return information about <bitcoinaddress>.");
1713 CBitcoinAddress address(params[0].get_str());
1714 bool isValid = address.IsValid();
1717 ret.push_back(Pair("isvalid", isValid));
1720 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1721 // version of the address:
1722 string currentAddress = address.ToString();
1723 ret.push_back(Pair("address", currentAddress));
1724 if (pwalletMain->HaveKey(address))
1726 ret.push_back(Pair("ismine", true));
1727 std::vector<unsigned char> vchPubKey;
1728 pwalletMain->GetPubKey(address, vchPubKey);
1729 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1731 key.SetPubKey(vchPubKey);
1732 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1734 else if (pwalletMain->HaveCScript(address.GetHash160()))
1736 ret.push_back(Pair("isscript", true));
1738 pwalletMain->GetCScript(address.GetHash160(), subscript);
1739 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1740 std::vector<CBitcoinAddress> addresses;
1741 txnouttype whichType;
1743 ExtractAddresses(subscript, whichType, addresses, nRequired);
1744 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1746 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1747 a.push_back(addr.ToString());
1748 ret.push_back(Pair("addresses", a));
1749 if (whichType == TX_MULTISIG)
1750 ret.push_back(Pair("sigsrequired", nRequired));
1753 ret.push_back(Pair("ismine", false));
1754 if (pwalletMain->mapAddressBook.count(address))
1755 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1760 Value getwork(const Array& params, bool fHelp)
1762 if (fHelp || params.size() > 1)
1763 throw runtime_error(
1765 "If [data] is not specified, returns formatted hash data to work on:\n"
1766 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1767 " \"data\" : block data\n"
1768 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1769 " \"target\" : little endian hash target\n"
1770 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1773 throw JSONRPCError(-9, "Bitcoin is not connected!");
1775 if (IsInitialBlockDownload())
1776 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1778 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1779 static mapNewBlock_t mapNewBlock;
1780 static vector<CBlock*> vNewBlock;
1781 static CReserveKey reservekey(pwalletMain);
1783 if (params.size() == 0)
1786 static unsigned int nTransactionsUpdatedLast;
1787 static CBlockIndex* pindexPrev;
1788 static int64 nStart;
1789 static CBlock* pblock;
1790 if (pindexPrev != pindexBest ||
1791 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1793 if (pindexPrev != pindexBest)
1795 // Deallocate old blocks since they're obsolete now
1796 mapNewBlock.clear();
1797 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1801 nTransactionsUpdatedLast = nTransactionsUpdated;
1802 pindexPrev = pindexBest;
1806 pblock = CreateNewBlock(reservekey);
1808 throw JSONRPCError(-7, "Out of memory");
1809 vNewBlock.push_back(pblock);
1813 pblock->UpdateTime(pindexPrev);
1816 // Update nExtraNonce
1817 static unsigned int nExtraNonce = 0;
1818 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1821 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1823 // Prebuild hash buffers
1827 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1829 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1832 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1833 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1834 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1835 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1841 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1842 if (vchData.size() != 128)
1843 throw JSONRPCError(-8, "Invalid parameter");
1844 CBlock* pdata = (CBlock*)&vchData[0];
1847 for (int i = 0; i < 128/4; i++)
1848 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1851 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1853 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1855 pblock->nTime = pdata->nTime;
1856 pblock->nNonce = pdata->nNonce;
1857 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1858 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1860 return CheckWork(pblock, *pwalletMain, reservekey);
1865 Value getmemorypool(const Array& params, bool fHelp)
1867 if (fHelp || params.size() > 1)
1868 throw runtime_error(
1869 "getmemorypool [data]\n"
1870 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1871 " \"version\" : block version\n"
1872 " \"previousblockhash\" : hash of current highest block\n"
1873 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1874 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1875 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1876 " \"time\" : timestamp appropriate for next block\n"
1877 " \"mintime\" : minimum timestamp appropriate for next block\n"
1878 " \"curtime\" : current timestamp\n"
1879 " \"bits\" : compressed target of next block\n"
1880 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1882 if (params.size() == 0)
1885 throw JSONRPCError(-9, "Bitcoin is not connected!");
1887 if (IsInitialBlockDownload())
1888 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1890 static CReserveKey reservekey(pwalletMain);
1893 static unsigned int nTransactionsUpdatedLast;
1894 static CBlockIndex* pindexPrev;
1895 static int64 nStart;
1896 static CBlock* pblock;
1897 if (pindexPrev != pindexBest ||
1898 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1900 nTransactionsUpdatedLast = nTransactionsUpdated;
1901 pindexPrev = pindexBest;
1907 pblock = CreateNewBlock(reservekey);
1909 throw JSONRPCError(-7, "Out of memory");
1913 pblock->UpdateTime(pindexPrev);
1917 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1924 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1928 result.push_back(Pair("version", pblock->nVersion));
1929 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1930 result.push_back(Pair("transactions", transactions));
1931 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1932 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1933 result.push_back(Pair("time", (int64_t)pblock->nTime));
1934 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1935 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1936 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1943 CDataStream ssBlock(ParseHex(params[0].get_str()));
1947 return ProcessBlock(NULL, &pblock);
1951 Value getblockhash(const Array& params, bool fHelp)
1953 if (fHelp || params.size() != 1)
1954 throw runtime_error(
1955 "getblockhash <index>\n"
1956 "Returns hash of block in best-block-chain at <index>.");
1958 int nHeight = params[0].get_int();
1959 if (nHeight < 0 || nHeight > nBestHeight)
1960 throw runtime_error("Block number out of range.");
1963 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1964 while (pblockindex->nHeight > nHeight)
1965 pblockindex = pblockindex->pprev;
1966 return pblockindex->phashBlock->GetHex();
1969 Value getblock(const Array& params, bool fHelp)
1971 if (fHelp || params.size() != 1)
1972 throw runtime_error(
1974 "Returns details of a block with given block-hash.");
1976 std::string strHash = params[0].get_str();
1977 uint256 hash(strHash);
1979 if (mapBlockIndex.count(hash) == 0)
1980 throw JSONRPCError(-5, "Block not found");
1983 CBlockIndex* pblockindex = mapBlockIndex[hash];
1984 block.ReadFromDisk(pblockindex, true);
1986 return blockToJSON(block, pblockindex);
2003 pair<string, rpcfn_type> pCallTable[] =
2005 make_pair("help", &help),
2006 make_pair("stop", &stop),
2007 make_pair("getblockcount", &getblockcount),
2008 make_pair("getblocknumber", &getblocknumber),
2009 make_pair("getconnectioncount", &getconnectioncount),
2010 make_pair("getdifficulty", &getdifficulty),
2011 make_pair("getgenerate", &getgenerate),
2012 make_pair("setgenerate", &setgenerate),
2013 make_pair("gethashespersec", &gethashespersec),
2014 make_pair("getinfo", &getinfo),
2015 make_pair("getmininginfo", &getmininginfo),
2016 make_pair("getnewaddress", &getnewaddress),
2017 make_pair("getaccountaddress", &getaccountaddress),
2018 make_pair("setaccount", &setaccount),
2019 make_pair("getaccount", &getaccount),
2020 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2021 make_pair("sendtoaddress", &sendtoaddress),
2022 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2023 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2024 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2025 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2026 make_pair("backupwallet", &backupwallet),
2027 make_pair("keypoolrefill", &keypoolrefill),
2028 make_pair("walletpassphrase", &walletpassphrase),
2029 make_pair("walletpassphrasechange", &walletpassphrasechange),
2030 make_pair("walletlock", &walletlock),
2031 make_pair("encryptwallet", &encryptwallet),
2032 make_pair("validateaddress", &validateaddress),
2033 make_pair("getbalance", &getbalance),
2034 make_pair("move", &movecmd),
2035 make_pair("sendfrom", &sendfrom),
2036 make_pair("sendmany", &sendmany),
2037 make_pair("addmultisigaddress", &addmultisigaddress),
2038 make_pair("getblock", &getblock),
2039 make_pair("getblockhash", &getblockhash),
2040 make_pair("gettransaction", &gettransaction),
2041 make_pair("listtransactions", &listtransactions),
2042 make_pair("signmessage", &signmessage),
2043 make_pair("verifymessage", &verifymessage),
2044 make_pair("getwork", &getwork),
2045 make_pair("listaccounts", &listaccounts),
2046 make_pair("settxfee", &settxfee),
2047 make_pair("getmemorypool", &getmemorypool),
2048 make_pair("listsinceblock", &listsinceblock),
2049 make_pair("dumpprivkey", &dumpprivkey),
2050 make_pair("importprivkey", &importprivkey)
2052 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2054 string pAllowInSafeMode[] =
2059 "getblocknumber", // deprecated
2060 "getconnectioncount",
2068 "getaccountaddress",
2070 "getaddressesbyaccount",
2079 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2087 // This ain't Apache. We're just using HTTP header for the length field
2088 // and to be compatible with other JSON-RPC implementations.
2091 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2094 s << "POST / HTTP/1.1\r\n"
2095 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2096 << "Host: 127.0.0.1\r\n"
2097 << "Content-Type: application/json\r\n"
2098 << "Content-Length: " << strMsg.size() << "\r\n"
2099 << "Connection: close\r\n"
2100 << "Accept: application/json\r\n";
2101 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2102 s << item.first << ": " << item.second << "\r\n";
2103 s << "\r\n" << strMsg;
2108 string rfc1123Time()
2113 struct tm* now_gmt = gmtime(&now);
2114 string locale(setlocale(LC_TIME, NULL));
2115 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2116 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2117 setlocale(LC_TIME, locale.c_str());
2118 return string(buffer);
2121 static string HTTPReply(int nStatus, const string& strMsg)
2124 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2126 "Server: bitcoin-json-rpc/%s\r\n"
2127 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2128 "Content-Type: text/html\r\n"
2129 "Content-Length: 296\r\n"
2131 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2132 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2135 "<TITLE>Error</TITLE>\r\n"
2136 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2138 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2139 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2140 const char *cStatus;
2141 if (nStatus == 200) cStatus = "OK";
2142 else if (nStatus == 400) cStatus = "Bad Request";
2143 else if (nStatus == 403) cStatus = "Forbidden";
2144 else if (nStatus == 404) cStatus = "Not Found";
2145 else if (nStatus == 500) cStatus = "Internal Server Error";
2148 "HTTP/1.1 %d %s\r\n"
2150 "Connection: close\r\n"
2151 "Content-Length: %d\r\n"
2152 "Content-Type: application/json\r\n"
2153 "Server: bitcoin-json-rpc/%s\r\n"
2158 rfc1123Time().c_str(),
2160 FormatFullVersion().c_str(),
2164 int ReadHTTPStatus(std::basic_istream<char>& stream)
2167 getline(stream, str);
2168 vector<string> vWords;
2169 boost::split(vWords, str, boost::is_any_of(" "));
2170 if (vWords.size() < 2)
2172 return atoi(vWords[1].c_str());
2175 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2181 std::getline(stream, str);
2182 if (str.empty() || str == "\r")
2184 string::size_type nColon = str.find(":");
2185 if (nColon != string::npos)
2187 string strHeader = str.substr(0, nColon);
2188 boost::trim(strHeader);
2189 boost::to_lower(strHeader);
2190 string strValue = str.substr(nColon+1);
2191 boost::trim(strValue);
2192 mapHeadersRet[strHeader] = strValue;
2193 if (strHeader == "content-length")
2194 nLen = atoi(strValue.c_str());
2200 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2202 mapHeadersRet.clear();
2206 int nStatus = ReadHTTPStatus(stream);
2209 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2210 if (nLen < 0 || nLen > MAX_SIZE)
2216 vector<char> vch(nLen);
2217 stream.read(&vch[0], nLen);
2218 strMessageRet = string(vch.begin(), vch.end());
2224 bool HTTPAuthorized(map<string, string>& mapHeaders)
2226 string strAuth = mapHeaders["authorization"];
2227 if (strAuth.substr(0,6) != "Basic ")
2229 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2230 string strUserPass = DecodeBase64(strUserPass64);
2231 return strUserPass == strRPCUserColonPass;
2235 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2236 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2237 // unspecified (HTTP errors and contents of 'error').
2239 // 1.0 spec: http://json-rpc.org/wiki/specification
2240 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2241 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2244 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2247 request.push_back(Pair("method", strMethod));
2248 request.push_back(Pair("params", params));
2249 request.push_back(Pair("id", id));
2250 return write_string(Value(request), false) + "\n";
2253 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2256 if (error.type() != null_type)
2257 reply.push_back(Pair("result", Value::null));
2259 reply.push_back(Pair("result", result));
2260 reply.push_back(Pair("error", error));
2261 reply.push_back(Pair("id", id));
2262 return write_string(Value(reply), false) + "\n";
2265 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2267 // Send error reply from json-rpc error object
2269 int code = find_value(objError, "code").get_int();
2270 if (code == -32600) nStatus = 400;
2271 else if (code == -32601) nStatus = 404;
2272 string strReply = JSONRPCReply(Value::null, objError, id);
2273 stream << HTTPReply(nStatus, strReply) << std::flush;
2276 bool ClientAllowed(const string& strAddress)
2278 if (strAddress == asio::ip::address_v4::loopback().to_string())
2280 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2281 BOOST_FOREACH(string strAllow, vAllow)
2282 if (WildcardMatch(strAddress, strAllow))
2289 // IOStream device that speaks SSL but can also speak non-SSL
2291 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2293 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2295 fUseSSL = fUseSSLIn;
2296 fNeedHandshake = fUseSSLIn;
2299 void handshake(ssl::stream_base::handshake_type role)
2301 if (!fNeedHandshake) return;
2302 fNeedHandshake = false;
2303 stream.handshake(role);
2305 std::streamsize read(char* s, std::streamsize n)
2307 handshake(ssl::stream_base::server); // HTTPS servers read first
2308 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2309 return stream.next_layer().read_some(asio::buffer(s, n));
2311 std::streamsize write(const char* s, std::streamsize n)
2313 handshake(ssl::stream_base::client); // HTTPS clients write first
2314 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2315 return asio::write(stream.next_layer(), asio::buffer(s, n));
2317 bool connect(const std::string& server, const std::string& port)
2319 ip::tcp::resolver resolver(stream.get_io_service());
2320 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2321 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2322 ip::tcp::resolver::iterator end;
2323 boost::system::error_code error = asio::error::host_not_found;
2324 while (error && endpoint_iterator != end)
2326 stream.lowest_layer().close();
2327 stream.lowest_layer().connect(*endpoint_iterator++, error);
2335 bool fNeedHandshake;
2341 void ThreadRPCServer(void* parg)
2343 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2346 vnThreadsRunning[THREAD_RPCSERVER]++;
2347 ThreadRPCServer2(parg);
2348 vnThreadsRunning[THREAD_RPCSERVER]--;
2350 catch (std::exception& e) {
2351 vnThreadsRunning[THREAD_RPCSERVER]--;
2352 PrintException(&e, "ThreadRPCServer()");
2354 vnThreadsRunning[THREAD_RPCSERVER]--;
2355 PrintException(NULL, "ThreadRPCServer()");
2357 printf("ThreadRPCServer exiting\n");
2360 void ThreadRPCServer2(void* parg)
2362 printf("ThreadRPCServer started\n");
2364 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2365 if (mapArgs["-rpcpassword"] == "")
2367 unsigned char rand_pwd[32];
2368 RAND_bytes(rand_pwd, 32);
2369 string strWhatAmI = "To use bitcoind";
2370 if (mapArgs.count("-server"))
2371 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2372 else if (mapArgs.count("-daemon"))
2373 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2374 ThreadSafeMessageBox(strprintf(
2375 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2376 "It is recommended you use the following random password:\n"
2377 "rpcuser=bitcoinrpc\n"
2379 "(you do not need to remember this password)\n"
2380 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2382 GetConfigFile().c_str(),
2383 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2384 _("Error"), wxOK | wxMODAL);
2386 CreateThread(Shutdown, NULL);
2391 bool fUseSSL = GetBoolArg("-rpcssl");
2392 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2394 asio::io_service io_service;
2395 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2396 ip::tcp::acceptor acceptor(io_service, endpoint);
2398 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2401 ssl::context context(io_service, ssl::context::sslv23);
2404 context.set_options(ssl::context::no_sslv2);
2405 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2406 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2407 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2408 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2409 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2410 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2411 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2412 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2414 string ciphers = GetArg("-rpcsslciphers",
2415 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2416 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2420 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2425 // Accept connection
2427 SSLStream sslStream(io_service, context);
2428 SSLIOStreamDevice d(sslStream, fUseSSL);
2429 iostreams::stream<SSLIOStreamDevice> stream(d);
2431 ip::tcp::iostream stream;
2434 ip::tcp::endpoint peer;
2435 vnThreadsRunning[THREAD_RPCSERVER]--;
2437 acceptor.accept(sslStream.lowest_layer(), peer);
2439 acceptor.accept(*stream.rdbuf(), peer);
2441 vnThreadsRunning[4]++;
2445 // Restrict callers by IP
2446 if (!ClientAllowed(peer.address().to_string()))
2448 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2450 stream << HTTPReply(403, "") << std::flush;
2454 map<string, string> mapHeaders;
2457 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2458 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2461 printf("ThreadRPCServer ReadHTTP timeout\n");
2465 // Check authorization
2466 if (mapHeaders.count("authorization") == 0)
2468 stream << HTTPReply(401, "") << std::flush;
2471 if (!HTTPAuthorized(mapHeaders))
2473 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2474 /* Deter brute-forcing short passwords.
2475 If this results in a DOS the user really
2476 shouldn't have their RPC port exposed.*/
2477 if (mapArgs["-rpcpassword"].size() < 20)
2480 stream << HTTPReply(401, "") << std::flush;
2484 Value id = Value::null;
2489 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2490 throw JSONRPCError(-32700, "Parse error");
2491 const Object& request = valRequest.get_obj();
2493 // Parse id now so errors from here on will have the id
2494 id = find_value(request, "id");
2497 Value valMethod = find_value(request, "method");
2498 if (valMethod.type() == null_type)
2499 throw JSONRPCError(-32600, "Missing method");
2500 if (valMethod.type() != str_type)
2501 throw JSONRPCError(-32600, "Method must be a string");
2502 string strMethod = valMethod.get_str();
2503 if (strMethod != "getwork" && strMethod != "getmemorypool")
2504 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2507 Value valParams = find_value(request, "params");
2509 if (valParams.type() == array_type)
2510 params = valParams.get_array();
2511 else if (valParams.type() == null_type)
2514 throw JSONRPCError(-32600, "Params must be an array");
2517 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2518 if (mi == mapCallTable.end())
2519 throw JSONRPCError(-32601, "Method not found");
2521 // Observe safe mode
2522 string strWarning = GetWarnings("rpc");
2523 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2524 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2530 CRITICAL_BLOCK(cs_main)
2531 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2532 result = (*(*mi).second)(params, false);
2535 string strReply = JSONRPCReply(result, Value::null, id);
2536 stream << HTTPReply(200, strReply) << std::flush;
2538 catch (std::exception& e)
2540 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2543 catch (Object& objError)
2545 ErrorReply(stream, objError, id);
2547 catch (std::exception& e)
2549 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2557 Object CallRPC(const string& strMethod, const Array& params)
2559 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2560 throw runtime_error(strprintf(
2561 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2562 "If the file does not exist, create it with owner-readable-only file permissions."),
2563 GetConfigFile().c_str()));
2565 // Connect to localhost
2566 bool fUseSSL = GetBoolArg("-rpcssl");
2568 asio::io_service io_service;
2569 ssl::context context(io_service, ssl::context::sslv23);
2570 context.set_options(ssl::context::no_sslv2);
2571 SSLStream sslStream(io_service, context);
2572 SSLIOStreamDevice d(sslStream, fUseSSL);
2573 iostreams::stream<SSLIOStreamDevice> stream(d);
2574 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2575 throw runtime_error("couldn't connect to server");
2578 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2580 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2582 throw runtime_error("couldn't connect to server");
2586 // HTTP basic authentication
2587 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2588 map<string, string> mapRequestHeaders;
2589 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2592 string strRequest = JSONRPCRequest(strMethod, params, 1);
2593 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2594 stream << strPost << std::flush;
2597 map<string, string> mapHeaders;
2599 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2601 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2602 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2603 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2604 else if (strReply.empty())
2605 throw runtime_error("no response from server");
2609 if (!read_string(strReply, valReply))
2610 throw runtime_error("couldn't parse reply from server");
2611 const Object& reply = valReply.get_obj();
2613 throw runtime_error("expected reply to have result, error and id properties");
2621 template<typename T>
2622 void ConvertTo(Value& value)
2624 if (value.type() == str_type)
2626 // reinterpret string as unquoted json value
2628 if (!read_string(value.get_str(), value2))
2629 throw runtime_error("type mismatch");
2630 value = value2.get_value<T>();
2634 value = value.get_value<T>();
2638 int CommandLineRPC(int argc, char *argv[])
2645 while (argc > 1 && IsSwitchChar(argv[1][0]))
2653 throw runtime_error("too few parameters");
2654 string strMethod = argv[1];
2656 // Parameters default to strings
2658 for (int i = 2; i < argc; i++)
2659 params.push_back(argv[i]);
2660 int n = params.size();
2663 // Special case non-string parameter types
2665 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2666 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2667 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2668 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2669 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2670 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2672 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2673 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2674 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2675 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2676 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2677 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2678 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2679 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2680 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2681 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2682 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2683 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2684 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2685 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2686 if (strMethod == "sendmany" && n > 1)
2688 string s = params[1].get_str();
2690 if (!read_string(s, v) || v.type() != obj_type)
2691 throw runtime_error("type mismatch");
2692 params[1] = v.get_obj();
2694 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2695 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2696 if (strMethod == "addmultisigaddress" && n > 1)
2698 string s = params[1].get_str();
2700 if (!read_string(s, v) || v.type() != array_type)
2701 throw runtime_error("type mismatch "+s);
2702 params[1] = v.get_array();
2706 Object reply = CallRPC(strMethod, params);
2709 const Value& result = find_value(reply, "result");
2710 const Value& error = find_value(reply, "error");
2712 if (error.type() != null_type)
2715 strPrint = "error: " + write_string(error, false);
2716 int code = find_value(error.get_obj(), "code").get_int();
2722 if (result.type() == null_type)
2724 else if (result.type() == str_type)
2725 strPrint = result.get_str();
2727 strPrint = write_string(result, true);
2730 catch (std::exception& e)
2732 strPrint = string("error: ") + e.what();
2737 PrintException(NULL, "CommandLineRPC()");
2742 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2751 int main(int argc, char *argv[])
2754 // Turn off microsoft heap dump noise
2755 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2756 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2758 setbuf(stdin, NULL);
2759 setbuf(stdout, NULL);
2760 setbuf(stderr, NULL);
2764 if (argc >= 2 && string(argv[1]) == "-server")
2766 printf("server ready\n");
2767 ThreadRPCServer(NULL);
2771 return CommandLineRPC(argc, argv);
2774 catch (std::exception& e) {
2775 PrintException(&e, "main()");
2777 PrintException(NULL, "main()");