1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 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));
58 void PrintConsole(const std::string &format, ...)
61 int limit = sizeof(buffer);
63 va_start(arg_ptr, format);
64 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
66 if (ret < 0 || ret >= limit)
72 fprintf(stdout, "%s", buffer);
75 double GetDifficulty(const CBlockIndex* blockindex = NULL)
77 // Floating point number that is a multiple of the minimum difficulty,
78 // minimum difficulty = 1.0.
79 if (blockindex == NULL)
81 if (pindexBest == NULL)
84 blockindex = pindexBest;
87 int nShift = (blockindex->nBits >> 24) & 0xff;
90 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
107 int64 AmountFromValue(const Value& value)
109 double dAmount = value.get_real();
110 if (dAmount <= 0.0 || dAmount > 21000000.0)
111 throw JSONRPCError(-3, "Invalid amount");
112 int64 nAmount = roundint64(dAmount * COIN);
113 if (!MoneyRange(nAmount))
114 throw JSONRPCError(-3, "Invalid amount");
118 Value ValueFromAmount(int64 amount)
120 return (double)amount / (double)COIN;
123 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
125 int confirms = wtx.GetDepthInMainChain();
126 entry.push_back(Pair("confirmations", confirms));
129 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
130 entry.push_back(Pair("blockindex", wtx.nIndex));
132 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
133 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
134 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
135 entry.push_back(Pair(item.first, item.second));
138 string AccountFromValue(const Value& value)
140 string strAccount = value.get_str();
141 if (strAccount == "*")
142 throw JSONRPCError(-11, "Invalid account name");
146 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
149 result.push_back(Pair("hash", block.GetHash().GetHex()));
150 result.push_back(Pair("blockcount", blockindex->nHeight));
151 result.push_back(Pair("version", block.nVersion));
152 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
153 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
154 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
155 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
157 BOOST_FOREACH (const CTransaction&tx, block.vtx)
158 txhashes.push_back(tx.GetHash().GetHex());
159 result.push_back(Pair("tx", txhashes));
161 if (blockindex->pprev)
162 result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex()));
163 if (blockindex->pnext)
164 result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex()));
171 /// Note: This interface may still be subject to change.
175 Value help(const Array& params, bool fHelp)
177 if (fHelp || params.size() > 1)
180 "List commands, or get help for a command.");
183 if (params.size() > 0)
184 strCommand = params[0].get_str();
187 set<rpcfn_type> setDone;
188 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
190 string strMethod = (*mi).first;
191 // We already filter duplicates, but these deprecated screw up the sort order
192 if (strMethod == "getamountreceived" ||
193 strMethod == "getallreceived" ||
194 strMethod == "getblocknumber" || // deprecated
195 (strMethod.find("label") != string::npos))
197 if (strCommand != "" && strMethod != strCommand)
202 rpcfn_type pfn = (*mi).second;
203 if (setDone.insert(pfn).second)
204 (*pfn)(params, true);
206 catch (std::exception& e)
208 // Help text is returned in an exception
209 string strHelp = string(e.what());
210 if (strCommand == "")
211 if (strHelp.find('\n') != -1)
212 strHelp = strHelp.substr(0, strHelp.find('\n'));
213 strRet += strHelp + "\n";
217 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
218 strRet = strRet.substr(0,strRet.size()-1);
223 Value stop(const Array& params, bool fHelp)
225 if (fHelp || params.size() != 0)
228 "Stop bitcoin server.");
230 // Shutdown will take long enough that the response should get back
231 CreateThread(Shutdown, NULL);
232 return "bitcoin server stopping";
234 throw runtime_error("NYI: cannot shut down GUI with RPC command");
239 Value getblockcount(const Array& params, bool fHelp)
241 if (fHelp || params.size() != 0)
244 "Returns the number of blocks in the longest block chain.");
251 Value getblocknumber(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Deprecated. Use getblockcount.");
262 Value getconnectioncount(const Array& params, bool fHelp)
264 if (fHelp || params.size() != 0)
266 "getconnectioncount\n"
267 "Returns the number of connections to other nodes.");
269 return (int)vNodes.size();
273 Value getdifficulty(const Array& params, bool fHelp)
275 if (fHelp || params.size() != 0)
278 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
280 return GetDifficulty();
284 Value getgenerate(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns true or false.");
291 return (bool)fGenerateBitcoins;
295 Value setgenerate(const Array& params, bool fHelp)
297 if (fHelp || params.size() < 1 || params.size() > 2)
299 "setgenerate <generate> [genproclimit]\n"
300 "<generate> is true or false to turn generation on or off.\n"
301 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
303 bool fGenerate = true;
304 if (params.size() > 0)
305 fGenerate = params[0].get_bool();
307 if (params.size() > 1)
309 int nGenProcLimit = params[1].get_int();
310 fLimitProcessors = (nGenProcLimit != -1);
311 WriteSetting("fLimitProcessors", fLimitProcessors);
312 if (nGenProcLimit != -1)
313 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
314 if (nGenProcLimit == 0)
318 GenerateBitcoins(fGenerate, pwalletMain);
323 Value gethashespersec(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 0)
328 "Returns a recent hashes per second performance measurement while generating.");
330 if (GetTimeMillis() - nHPSTimerStart > 8000)
331 return (boost::int64_t)0;
332 return (boost::int64_t)dHashesPerSec;
336 Value getinfo(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 0)
341 "Returns an object containing various state info.");
344 obj.push_back(Pair("version", (int)CLIENT_VERSION));
345 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
346 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
347 obj.push_back(Pair("blocks", (int)nBestHeight));
348 obj.push_back(Pair("connections", (int)vNodes.size()));
349 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
350 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
351 obj.push_back(Pair("testnet", fTestNet));
352 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
353 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
354 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
355 if (pwalletMain->IsCrypted())
356 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
357 obj.push_back(Pair("errors", GetWarnings("statusbar")));
362 Value getmininginfo(const Array& params, bool fHelp)
364 if (fHelp || params.size() != 0)
367 "Returns an object containing mining-related information.");
370 obj.push_back(Pair("blocks", (int)nBestHeight));
371 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
372 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
373 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
374 obj.push_back(Pair("errors", GetWarnings("statusbar")));
375 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
376 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
377 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
378 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
379 obj.push_back(Pair("testnet", fTestNet));
384 Value getnewaddress(const Array& params, bool fHelp)
386 if (fHelp || params.size() > 1)
388 "getnewaddress [account]\n"
389 "Returns a new bitcoin address for receiving payments. "
390 "If [account] is specified (recommended), it is added to the address book "
391 "so payments received with the address will be credited to [account].");
393 // Parse the account first so we don't generate a key if there's an error
395 if (params.size() > 0)
396 strAccount = AccountFromValue(params[0]);
398 if (!pwalletMain->IsLocked())
399 pwalletMain->TopUpKeyPool();
401 // Generate a new key that is added to wallet
402 std::vector<unsigned char> newKey;
403 if (!pwalletMain->GetKeyFromPool(newKey, false))
404 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
405 CBitcoinAddress address(newKey);
407 pwalletMain->SetAddressBookName(address, strAccount);
409 return address.ToString();
413 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
415 CWalletDB walletdb(pwalletMain->strWalletFile);
418 walletdb.ReadAccount(strAccount, account);
420 bool bKeyUsed = false;
422 // Check if the current key has been used
423 if (!account.vchPubKey.empty())
425 CScript scriptPubKey;
426 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
427 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
428 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
431 const CWalletTx& wtx = (*it).second;
432 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
433 if (txout.scriptPubKey == scriptPubKey)
438 // Generate a new key
439 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
441 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
442 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
444 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
445 walletdb.WriteAccount(strAccount, account);
448 return CBitcoinAddress(account.vchPubKey);
451 Value getaccountaddress(const Array& params, bool fHelp)
453 if (fHelp || params.size() != 1)
455 "getaccountaddress <account>\n"
456 "Returns the current bitcoin address for receiving payments to this account.");
458 // Parse the account first so we don't generate a key if there's an error
459 string strAccount = AccountFromValue(params[0]);
463 ret = GetAccountAddress(strAccount).ToString();
470 Value setaccount(const Array& params, bool fHelp)
472 if (fHelp || params.size() < 1 || params.size() > 2)
474 "setaccount <bitcoinaddress> <account>\n"
475 "Sets the account associated with the given address.");
477 CBitcoinAddress address(params[0].get_str());
478 if (!address.IsValid())
479 throw JSONRPCError(-5, "Invalid bitcoin address");
483 if (params.size() > 1)
484 strAccount = AccountFromValue(params[1]);
486 // Detect when changing the account of an address that is the 'unused current key' of another account:
487 if (pwalletMain->mapAddressBook.count(address))
489 string strOldAccount = pwalletMain->mapAddressBook[address];
490 if (address == GetAccountAddress(strOldAccount))
491 GetAccountAddress(strOldAccount, true);
494 pwalletMain->SetAddressBookName(address, strAccount);
500 Value getaccount(const Array& params, bool fHelp)
502 if (fHelp || params.size() != 1)
504 "getaccount <bitcoinaddress>\n"
505 "Returns the account associated with the given address.");
507 CBitcoinAddress address(params[0].get_str());
508 if (!address.IsValid())
509 throw JSONRPCError(-5, "Invalid bitcoin address");
512 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
513 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
514 strAccount = (*mi).second;
519 Value getaddressesbyaccount(const Array& params, bool fHelp)
521 if (fHelp || params.size() != 1)
523 "getaddressesbyaccount <account>\n"
524 "Returns the list of addresses for the given account.");
526 string strAccount = AccountFromValue(params[0]);
528 // Find all addresses that have the given account
530 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
532 const CBitcoinAddress& address = item.first;
533 const string& strName = item.second;
534 if (strName == strAccount)
535 ret.push_back(address.ToString());
540 Value settxfee(const Array& params, bool fHelp)
542 if (fHelp || params.size() < 1 || params.size() > 1)
544 "settxfee <amount>\n"
545 "<amount> is a real and is rounded to the nearest 0.00000001");
549 if (params[0].get_real() != 0.0)
550 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
552 nTransactionFee = nAmount;
556 Value sendtoaddress(const Array& params, bool fHelp)
558 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
560 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
561 "<amount> is a real and is rounded to the nearest 0.00000001\n"
562 "requires wallet passphrase to be set with walletpassphrase first");
563 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
565 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
566 "<amount> is a real and is rounded to the nearest 0.00000001");
568 CBitcoinAddress address(params[0].get_str());
569 if (!address.IsValid())
570 throw JSONRPCError(-5, "Invalid bitcoin address");
573 int64 nAmount = AmountFromValue(params[1]);
577 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
578 wtx.mapValue["comment"] = params[2].get_str();
579 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
580 wtx.mapValue["to"] = params[3].get_str();
582 if (pwalletMain->IsLocked())
583 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
585 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
587 throw JSONRPCError(-4, strError);
589 return wtx.GetHash().GetHex();
592 static const string strMessageMagic = "Bitcoin Signed Message:\n";
594 Value signmessage(const Array& params, bool fHelp)
596 if (fHelp || params.size() != 2)
598 "signmessage <bitcoinaddress> <message>\n"
599 "Sign a message with the private key of an address");
601 if (pwalletMain->IsLocked())
602 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
604 string strAddress = params[0].get_str();
605 string strMessage = params[1].get_str();
607 CBitcoinAddress addr(strAddress);
609 throw JSONRPCError(-3, "Invalid address");
612 if (!pwalletMain->GetKey(addr, key))
613 throw JSONRPCError(-4, "Private key not available");
615 CDataStream ss(SER_GETHASH);
616 ss << strMessageMagic;
619 vector<unsigned char> vchSig;
620 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
621 throw JSONRPCError(-5, "Sign failed");
623 return EncodeBase64(&vchSig[0], vchSig.size());
626 Value verifymessage(const Array& params, bool fHelp)
628 if (fHelp || params.size() != 3)
630 "verifymessage <bitcoinaddress> <signature> <message>\n"
631 "Verify a signed message");
633 string strAddress = params[0].get_str();
634 string strSign = params[1].get_str();
635 string strMessage = params[2].get_str();
637 CBitcoinAddress addr(strAddress);
639 throw JSONRPCError(-3, "Invalid address");
641 bool fInvalid = false;
642 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
645 throw JSONRPCError(-5, "Malformed base64 encoding");
647 CDataStream ss(SER_GETHASH);
648 ss << strMessageMagic;
652 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
655 return (CBitcoinAddress(key.GetPubKey()) == addr);
659 Value getreceivedbyaddress(const Array& params, bool fHelp)
661 if (fHelp || params.size() < 1 || params.size() > 2)
663 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
664 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
667 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
668 CScript scriptPubKey;
669 if (!address.IsValid())
670 throw JSONRPCError(-5, "Invalid bitcoin address");
671 scriptPubKey.SetBitcoinAddress(address);
672 if (!IsMine(*pwalletMain,scriptPubKey))
675 // Minimum confirmations
677 if (params.size() > 1)
678 nMinDepth = params[1].get_int();
682 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
684 const CWalletTx& wtx = (*it).second;
685 if (wtx.IsCoinBase() || !wtx.IsFinal())
688 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
689 if (txout.scriptPubKey == scriptPubKey)
690 if (wtx.GetDepthInMainChain() >= nMinDepth)
691 nAmount += txout.nValue;
694 return ValueFromAmount(nAmount);
698 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
700 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
702 const CBitcoinAddress& address = item.first;
703 const string& strName = item.second;
704 if (strName == strAccount)
705 setAddress.insert(address);
710 Value getreceivedbyaccount(const Array& params, bool fHelp)
712 if (fHelp || params.size() < 1 || params.size() > 2)
714 "getreceivedbyaccount <account> [minconf=1]\n"
715 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
717 // Minimum confirmations
719 if (params.size() > 1)
720 nMinDepth = params[1].get_int();
722 // Get the set of pub keys assigned to account
723 string strAccount = AccountFromValue(params[0]);
724 set<CBitcoinAddress> setAddress;
725 GetAccountAddresses(strAccount, setAddress);
729 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
731 const CWalletTx& wtx = (*it).second;
732 if (wtx.IsCoinBase() || !wtx.IsFinal())
735 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
737 CBitcoinAddress address;
738 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
739 if (wtx.GetDepthInMainChain() >= nMinDepth)
740 nAmount += txout.nValue;
744 return (double)nAmount / (double)COIN;
748 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
752 // Tally wallet transactions
753 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
755 const CWalletTx& wtx = (*it).second;
759 int64 nGenerated, nReceived, nSent, nFee;
760 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
762 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
763 nBalance += nReceived;
764 nBalance += nGenerated - nSent - nFee;
767 // Tally internal accounting entries
768 nBalance += walletdb.GetAccountCreditDebit(strAccount);
773 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
775 CWalletDB walletdb(pwalletMain->strWalletFile);
776 return GetAccountBalance(walletdb, strAccount, nMinDepth);
780 Value getbalance(const Array& params, bool fHelp)
782 if (fHelp || params.size() > 2)
784 "getbalance [account] [minconf=1]\n"
785 "If [account] is not specified, returns the server's total available balance.\n"
786 "If [account] is specified, returns the balance in the account.");
788 if (params.size() == 0)
789 return ValueFromAmount(pwalletMain->GetBalance());
792 if (params.size() > 1)
793 nMinDepth = params[1].get_int();
795 if (params[0].get_str() == "*") {
796 // Calculate total balance a different way from GetBalance()
797 // (GetBalance() sums up all unspent TxOuts)
798 // getbalance and getbalance '*' should always return the same number.
800 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
802 const CWalletTx& wtx = (*it).second;
806 int64 allGeneratedImmature, allGeneratedMature, allFee;
807 allGeneratedImmature = allGeneratedMature = allFee = 0;
808 string strSentAccount;
809 list<pair<CBitcoinAddress, int64> > listReceived;
810 list<pair<CBitcoinAddress, int64> > listSent;
811 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
812 if (wtx.GetDepthInMainChain() >= nMinDepth)
813 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
814 nBalance += r.second;
815 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
816 nBalance -= r.second;
818 nBalance += allGeneratedMature;
820 return ValueFromAmount(nBalance);
823 string strAccount = AccountFromValue(params[0]);
825 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
827 return ValueFromAmount(nBalance);
831 Value movecmd(const Array& params, bool fHelp)
833 if (fHelp || params.size() < 3 || params.size() > 5)
835 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
836 "Move from one account in your wallet to another.");
838 string strFrom = AccountFromValue(params[0]);
839 string strTo = AccountFromValue(params[1]);
840 int64 nAmount = AmountFromValue(params[2]);
841 if (params.size() > 3)
842 // unused parameter, used to be nMinDepth, keep type-checking it though
843 (void)params[3].get_int();
845 if (params.size() > 4)
846 strComment = params[4].get_str();
848 CWalletDB walletdb(pwalletMain->strWalletFile);
851 int64 nNow = GetAdjustedTime();
854 CAccountingEntry debit;
855 debit.strAccount = strFrom;
856 debit.nCreditDebit = -nAmount;
858 debit.strOtherAccount = strTo;
859 debit.strComment = strComment;
860 walletdb.WriteAccountingEntry(debit);
863 CAccountingEntry credit;
864 credit.strAccount = strTo;
865 credit.nCreditDebit = nAmount;
867 credit.strOtherAccount = strFrom;
868 credit.strComment = strComment;
869 walletdb.WriteAccountingEntry(credit);
871 walletdb.TxnCommit();
877 Value sendfrom(const Array& params, bool fHelp)
879 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
881 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
882 "<amount> is a real and is rounded to the nearest 0.00000001\n"
883 "requires wallet passphrase to be set with walletpassphrase first");
884 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
886 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
887 "<amount> is a real and is rounded to the nearest 0.00000001");
889 string strAccount = AccountFromValue(params[0]);
890 CBitcoinAddress address(params[1].get_str());
891 if (!address.IsValid())
892 throw JSONRPCError(-5, "Invalid bitcoin address");
893 int64 nAmount = AmountFromValue(params[2]);
895 if (params.size() > 3)
896 nMinDepth = params[3].get_int();
899 wtx.strFromAccount = strAccount;
900 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
901 wtx.mapValue["comment"] = params[4].get_str();
902 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
903 wtx.mapValue["to"] = params[5].get_str();
905 if (pwalletMain->IsLocked())
906 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
909 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
910 if (nAmount > nBalance)
911 throw JSONRPCError(-6, "Account has insufficient funds");
914 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
916 throw JSONRPCError(-4, strError);
918 return wtx.GetHash().GetHex();
922 Value sendmany(const Array& params, bool fHelp)
924 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
926 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
927 "amounts are double-precision floating point numbers\n"
928 "requires wallet passphrase to be set with walletpassphrase first");
929 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
931 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
932 "amounts are double-precision floating point numbers");
934 string strAccount = AccountFromValue(params[0]);
935 Object sendTo = params[1].get_obj();
937 if (params.size() > 2)
938 nMinDepth = params[2].get_int();
941 wtx.strFromAccount = strAccount;
942 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
943 wtx.mapValue["comment"] = params[3].get_str();
945 set<CBitcoinAddress> setAddress;
946 vector<pair<CScript, int64> > vecSend;
948 int64 totalAmount = 0;
949 BOOST_FOREACH(const Pair& s, sendTo)
951 CBitcoinAddress address(s.name_);
952 if (!address.IsValid())
953 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
955 if (setAddress.count(address))
956 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
957 setAddress.insert(address);
959 CScript scriptPubKey;
960 scriptPubKey.SetBitcoinAddress(address);
961 int64 nAmount = AmountFromValue(s.value_);
962 totalAmount += nAmount;
964 vecSend.push_back(make_pair(scriptPubKey, nAmount));
967 if (pwalletMain->IsLocked())
968 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
971 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
972 if (totalAmount > nBalance)
973 throw JSONRPCError(-6, "Account has insufficient funds");
976 CReserveKey keyChange(pwalletMain);
977 int64 nFeeRequired = 0;
978 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
981 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
982 throw JSONRPCError(-6, "Insufficient funds");
983 throw JSONRPCError(-4, "Transaction creation failed");
985 if (!pwalletMain->CommitTransaction(wtx, keyChange))
986 throw JSONRPCError(-4, "Transaction commit failed");
988 return wtx.GetHash().GetHex();
991 Value addmultisigaddress(const Array& params, bool fHelp)
993 if (fHelp || params.size() < 2 || params.size() > 3)
995 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
996 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
997 "each key is a bitcoin address, hex or base58 public key\n"
998 "If [account] is specified, assign address to [account].";
999 throw runtime_error(msg);
1002 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1004 int nRequired = params[0].get_int();
1005 const Array& keys = params[1].get_array();
1007 if (params.size() > 2)
1008 strAccount = AccountFromValue(params[2]);
1010 // Gather public keys
1011 if (keys.size() < nRequired)
1012 throw runtime_error(
1013 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
1014 std::vector<CKey> pubkeys;
1015 pubkeys.resize(keys.size());
1016 for (int i = 0; i < keys.size(); i++)
1018 const std::string& ks = keys[i].get_str();
1019 if (ks.size() == 130) // hex public key
1020 pubkeys[i].SetPubKey(ParseHex(ks));
1021 else if (ks.size() > 34) // base58-encoded
1023 std::vector<unsigned char> vchPubKey;
1024 if (DecodeBase58(ks, vchPubKey))
1025 pubkeys[i].SetPubKey(vchPubKey);
1027 throw runtime_error("Error base58 decoding key: "+ks);
1029 else // bitcoin address for key in this wallet
1031 CBitcoinAddress address(ks);
1032 if (!pwalletMain->GetKey(address, pubkeys[i]))
1033 throw runtime_error(
1034 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
1038 // Construct using OP_EVAL
1040 inner.SetMultisig(nRequired, pubkeys);
1042 uint160 scriptHash = Hash160(inner);
1043 CScript scriptPubKey;
1044 scriptPubKey.SetEval(inner);
1045 pwalletMain->AddCScript(scriptHash, inner);
1046 CBitcoinAddress address;
1047 address.SetScriptHash160(scriptHash);
1049 pwalletMain->SetAddressBookName(address, strAccount);
1050 return address.ToString();
1061 nConf = std::numeric_limits<int>::max();
1065 Value ListReceived(const Array& params, bool fByAccounts)
1067 // Minimum confirmations
1069 if (params.size() > 0)
1070 nMinDepth = params[0].get_int();
1072 // Whether to include empty accounts
1073 bool fIncludeEmpty = false;
1074 if (params.size() > 1)
1075 fIncludeEmpty = params[1].get_bool();
1078 map<CBitcoinAddress, tallyitem> mapTally;
1079 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1081 const CWalletTx& wtx = (*it).second;
1083 if (wtx.IsCoinBase() || !wtx.IsFinal())
1086 int nDepth = wtx.GetDepthInMainChain();
1087 if (nDepth < nMinDepth)
1090 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1092 CBitcoinAddress address;
1093 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1096 tallyitem& item = mapTally[address];
1097 item.nAmount += txout.nValue;
1098 item.nConf = min(item.nConf, nDepth);
1104 map<string, tallyitem> mapAccountTally;
1105 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1107 const CBitcoinAddress& address = item.first;
1108 const string& strAccount = item.second;
1109 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1110 if (it == mapTally.end() && !fIncludeEmpty)
1114 int nConf = std::numeric_limits<int>::max();
1115 if (it != mapTally.end())
1117 nAmount = (*it).second.nAmount;
1118 nConf = (*it).second.nConf;
1123 tallyitem& item = mapAccountTally[strAccount];
1124 item.nAmount += nAmount;
1125 item.nConf = min(item.nConf, nConf);
1130 obj.push_back(Pair("address", address.ToString()));
1131 obj.push_back(Pair("account", strAccount));
1132 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1133 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1140 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1142 int64 nAmount = (*it).second.nAmount;
1143 int nConf = (*it).second.nConf;
1145 obj.push_back(Pair("account", (*it).first));
1146 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1147 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1155 Value listreceivedbyaddress(const Array& params, bool fHelp)
1157 if (fHelp || params.size() > 2)
1158 throw runtime_error(
1159 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1160 "[minconf] is the minimum number of confirmations before payments are included.\n"
1161 "[includeempty] whether to include addresses that haven't received any payments.\n"
1162 "Returns an array of objects containing:\n"
1163 " \"address\" : receiving address\n"
1164 " \"account\" : the account of the receiving address\n"
1165 " \"amount\" : total amount received by the address\n"
1166 " \"confirmations\" : number of confirmations of the most recent transaction included");
1168 return ListReceived(params, false);
1171 Value listreceivedbyaccount(const Array& params, bool fHelp)
1173 if (fHelp || params.size() > 2)
1174 throw runtime_error(
1175 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1176 "[minconf] is the minimum number of confirmations before payments are included.\n"
1177 "[includeempty] whether to include accounts that haven't received any payments.\n"
1178 "Returns an array of objects containing:\n"
1179 " \"account\" : the account of the receiving addresses\n"
1180 " \"amount\" : total amount received by addresses with this account\n"
1181 " \"confirmations\" : number of confirmations of the most recent transaction included");
1183 return ListReceived(params, true);
1186 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1188 int64 nGeneratedImmature, nGeneratedMature, nFee;
1189 string strSentAccount;
1190 list<pair<CBitcoinAddress, int64> > listReceived;
1191 list<pair<CBitcoinAddress, int64> > listSent;
1193 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1195 bool fAllAccounts = (strAccount == string("*"));
1197 // Generated blocks assigned to account ""
1198 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1201 entry.push_back(Pair("account", string("")));
1202 if (nGeneratedImmature)
1204 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1205 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1209 entry.push_back(Pair("category", "generate"));
1210 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1213 WalletTxToJSON(wtx, entry);
1214 ret.push_back(entry);
1218 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1220 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1223 entry.push_back(Pair("account", strSentAccount));
1224 entry.push_back(Pair("address", s.first.ToString()));
1225 entry.push_back(Pair("category", "send"));
1226 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1227 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1229 WalletTxToJSON(wtx, entry);
1230 ret.push_back(entry);
1235 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1236 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1239 if (pwalletMain->mapAddressBook.count(r.first))
1240 account = pwalletMain->mapAddressBook[r.first];
1241 if (fAllAccounts || (account == strAccount))
1244 entry.push_back(Pair("account", account));
1245 entry.push_back(Pair("address", r.first.ToString()));
1246 entry.push_back(Pair("category", "receive"));
1247 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1249 WalletTxToJSON(wtx, entry);
1250 ret.push_back(entry);
1255 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1257 bool fAllAccounts = (strAccount == string("*"));
1259 if (fAllAccounts || acentry.strAccount == strAccount)
1262 entry.push_back(Pair("account", acentry.strAccount));
1263 entry.push_back(Pair("category", "move"));
1264 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1265 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1266 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1267 entry.push_back(Pair("comment", acentry.strComment));
1268 ret.push_back(entry);
1272 Value listtransactions(const Array& params, bool fHelp)
1274 if (fHelp || params.size() > 3)
1275 throw runtime_error(
1276 "listtransactions [account] [count=10] [from=0]\n"
1277 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1279 string strAccount = "*";
1280 if (params.size() > 0)
1281 strAccount = params[0].get_str();
1283 if (params.size() > 1)
1284 nCount = params[1].get_int();
1286 if (params.size() > 2)
1287 nFrom = params[2].get_int();
1290 CWalletDB walletdb(pwalletMain->strWalletFile);
1292 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1293 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1294 typedef multimap<int64, TxPair > TxItems;
1297 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1299 CWalletTx* wtx = &((*it).second);
1300 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1302 list<CAccountingEntry> acentries;
1303 walletdb.ListAccountCreditDebit(strAccount, acentries);
1304 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1306 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1309 // Now: iterate backwards until we have nCount items to return:
1310 TxItems::reverse_iterator it = txByTime.rbegin();
1311 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1312 for (; it != txByTime.rend(); ++it)
1314 CWalletTx *const pwtx = (*it).second.first;
1316 ListTransactions(*pwtx, strAccount, 0, true, ret);
1317 CAccountingEntry *const pacentry = (*it).second.second;
1319 AcentryToJSON(*pacentry, strAccount, ret);
1321 if (ret.size() >= nCount) break;
1323 // ret is now newest to oldest
1325 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1326 if (ret.size() > nCount)
1328 Array::iterator last = ret.begin();
1329 std::advance(last, nCount);
1330 ret.erase(last, ret.end());
1332 std::reverse(ret.begin(), ret.end()); // oldest to newest
1337 Value listaccounts(const Array& params, bool fHelp)
1339 if (fHelp || params.size() > 1)
1340 throw runtime_error(
1341 "listaccounts [minconf=1]\n"
1342 "Returns Object that has account names as keys, account balances as values.");
1345 if (params.size() > 0)
1346 nMinDepth = params[0].get_int();
1348 map<string, int64> mapAccountBalances;
1349 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1350 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1351 mapAccountBalances[entry.second] = 0;
1354 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1356 const CWalletTx& wtx = (*it).second;
1357 int64 nGeneratedImmature, nGeneratedMature, nFee;
1358 string strSentAccount;
1359 list<pair<CBitcoinAddress, int64> > listReceived;
1360 list<pair<CBitcoinAddress, int64> > listSent;
1361 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1362 mapAccountBalances[strSentAccount] -= nFee;
1363 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1364 mapAccountBalances[strSentAccount] -= s.second;
1365 if (wtx.GetDepthInMainChain() >= nMinDepth)
1367 mapAccountBalances[""] += nGeneratedMature;
1368 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1369 if (pwalletMain->mapAddressBook.count(r.first))
1370 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1372 mapAccountBalances[""] += r.second;
1376 list<CAccountingEntry> acentries;
1377 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1378 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1379 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1382 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1383 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1388 Value listsinceblock(const Array& params, bool fHelp)
1391 throw runtime_error(
1392 "listsinceblock [blockid] [target-confirmations]\n"
1393 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1395 CBlockIndex *pindex = NULL;
1396 int target_confirms = 1;
1398 if (params.size() > 0)
1400 uint256 blockId = 0;
1402 blockId.SetHex(params[0].get_str());
1403 pindex = CBlockLocator(blockId).GetBlockIndex();
1406 if (params.size() > 1)
1408 target_confirms = params[1].get_int();
1410 if (target_confirms < 1)
1411 throw JSONRPCError(-8, "Invalid parameter");
1414 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1418 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1420 CWalletTx tx = (*it).second;
1422 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1423 ListTransactions(tx, "*", 0, true, transactions);
1428 if (target_confirms == 1)
1431 lastblock = hashBestChain;
1435 int target_height = pindexBest->nHeight + 1 - target_confirms;
1438 for (block = pindexBest;
1439 block && block->nHeight > target_height;
1440 block = block->pprev) { }
1442 lastblock = block ? block->GetBlockHash() : 0;
1446 ret.push_back(Pair("transactions", transactions));
1447 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1452 Value gettransaction(const Array& params, bool fHelp)
1454 if (fHelp || params.size() != 1)
1455 throw runtime_error(
1456 "gettransaction <txid>\n"
1457 "Get detailed information about <txid>");
1460 hash.SetHex(params[0].get_str());
1464 if (!pwalletMain->mapWallet.count(hash))
1465 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1466 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1468 int64 nCredit = wtx.GetCredit();
1469 int64 nDebit = wtx.GetDebit();
1470 int64 nNet = nCredit - nDebit;
1471 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1473 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1475 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1477 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1480 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1481 entry.push_back(Pair("details", details));
1487 Value backupwallet(const Array& params, bool fHelp)
1489 if (fHelp || params.size() != 1)
1490 throw runtime_error(
1491 "backupwallet <destination>\n"
1492 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1494 string strDest = params[0].get_str();
1495 BackupWallet(*pwalletMain, strDest);
1501 Value keypoolrefill(const Array& params, bool fHelp)
1503 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1504 throw runtime_error(
1506 "Fills the keypool, requires wallet passphrase to be set.");
1507 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1508 throw runtime_error(
1510 "Fills the keypool.");
1512 if (pwalletMain->IsLocked())
1513 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1515 pwalletMain->TopUpKeyPool();
1517 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1518 throw JSONRPCError(-4, "Error refreshing keypool.");
1524 void ThreadTopUpKeyPool(void* parg)
1526 pwalletMain->TopUpKeyPool();
1529 void ThreadCleanWalletPassphrase(void* parg)
1531 int64 nMyWakeTime = GetTime() + *((int*)parg);
1533 if (nWalletUnlockTime == 0)
1535 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1537 nWalletUnlockTime = nMyWakeTime;
1540 while (GetTime() < nWalletUnlockTime)
1541 Sleep(GetTime() - nWalletUnlockTime);
1543 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1545 nWalletUnlockTime = 0;
1550 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1552 if (nWalletUnlockTime < nMyWakeTime)
1553 nWalletUnlockTime = nMyWakeTime;
1559 pwalletMain->Lock();
1564 Value walletpassphrase(const Array& params, bool fHelp)
1566 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1567 throw runtime_error(
1568 "walletpassphrase <passphrase> <timeout>\n"
1569 "Stores the wallet decryption key in memory for <timeout> seconds.");
1572 if (!pwalletMain->IsCrypted())
1573 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1575 if (!pwalletMain->IsLocked())
1576 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1578 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1579 SecureString strWalletPass;
1580 strWalletPass.reserve(100);
1581 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1582 // Alternately, find a way to make params[0] mlock()'d to begin with.
1583 strWalletPass = params[0].get_str().c_str();
1585 if (strWalletPass.length() > 0)
1587 if (!pwalletMain->Unlock(strWalletPass))
1588 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1591 throw runtime_error(
1592 "walletpassphrase <passphrase> <timeout>\n"
1593 "Stores the wallet decryption key in memory for <timeout> seconds.");
1595 CreateThread(ThreadTopUpKeyPool, NULL);
1596 int* pnSleepTime = new int(params[1].get_int());
1597 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1603 Value walletpassphrasechange(const Array& params, bool fHelp)
1605 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1606 throw runtime_error(
1607 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1608 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1611 if (!pwalletMain->IsCrypted())
1612 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1614 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1615 // Alternately, find a way to make params[0] mlock()'d to begin with.
1616 SecureString strOldWalletPass;
1617 strOldWalletPass.reserve(100);
1618 strOldWalletPass = params[0].get_str().c_str();
1620 SecureString strNewWalletPass;
1621 strNewWalletPass.reserve(100);
1622 strNewWalletPass = params[1].get_str().c_str();
1624 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1625 throw runtime_error(
1626 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1627 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1629 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1630 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1636 Value walletlock(const Array& params, bool fHelp)
1638 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1639 throw runtime_error(
1641 "Removes the wallet encryption key from memory, locking the wallet.\n"
1642 "After calling this method, you will need to call walletpassphrase again\n"
1643 "before being able to call any methods which require the wallet to be unlocked.");
1646 if (!pwalletMain->IsCrypted())
1647 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1649 pwalletMain->Lock();
1650 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1652 nWalletUnlockTime = 0;
1659 Value encryptwallet(const Array& params, bool fHelp)
1661 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1662 throw runtime_error(
1663 "encryptwallet <passphrase>\n"
1664 "Encrypts the wallet with <passphrase>.");
1667 if (pwalletMain->IsCrypted())
1668 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1671 // shutting down via RPC while the GUI is running does not work (yet):
1672 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1675 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1676 // Alternately, find a way to make params[0] mlock()'d to begin with.
1677 SecureString strWalletPass;
1678 strWalletPass.reserve(100);
1679 strWalletPass = params[0].get_str().c_str();
1681 if (strWalletPass.length() < 1)
1682 throw runtime_error(
1683 "encryptwallet <passphrase>\n"
1684 "Encrypts the wallet with <passphrase>.");
1686 if (!pwalletMain->EncryptWallet(strWalletPass))
1687 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1689 // BDB seems to have a bad habit of writing old data into
1690 // slack space in .dat files; that is bad if the old data is
1691 // unencrypted private keys. So:
1692 CreateThread(Shutdown, NULL);
1693 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1697 Value validateaddress(const Array& params, bool fHelp)
1699 if (fHelp || params.size() != 1)
1700 throw runtime_error(
1701 "validateaddress <bitcoinaddress>\n"
1702 "Return information about <bitcoinaddress>.");
1704 CBitcoinAddress address(params[0].get_str());
1705 bool isValid = address.IsValid();
1708 ret.push_back(Pair("isvalid", isValid));
1711 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1712 // version of the address:
1713 string currentAddress = address.ToString();
1714 ret.push_back(Pair("address", currentAddress));
1715 if (pwalletMain->HaveKey(address))
1717 ret.push_back(Pair("ismine", true));
1718 std::vector<unsigned char> vchPubKey;
1719 pwalletMain->GetPubKey(address, vchPubKey);
1720 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1721 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1722 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1724 key.SetPubKey(vchPubKey);
1725 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1727 else if (pwalletMain->HaveCScript(address.GetHash160()))
1729 ret.push_back(Pair("isscript", true));
1731 pwalletMain->GetCScript(address.GetHash160(), subscript);
1732 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1733 std::vector<CBitcoinAddress> addresses;
1734 txnouttype whichType;
1736 ExtractAddresses(subscript, whichType, addresses, nRequired);
1737 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1739 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1740 a.push_back(addr.ToString());
1741 ret.push_back(Pair("addresses", a));
1742 if (whichType == TX_MULTISIG)
1743 ret.push_back(Pair("sigsrequired", nRequired));
1746 ret.push_back(Pair("ismine", false));
1747 if (pwalletMain->mapAddressBook.count(address))
1748 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1753 Value getwork(const Array& params, bool fHelp)
1755 if (fHelp || params.size() > 1)
1756 throw runtime_error(
1758 "If [data] is not specified, returns formatted hash data to work on:\n"
1759 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1760 " \"data\" : block data\n"
1761 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1762 " \"target\" : little endian hash target\n"
1763 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1766 throw JSONRPCError(-9, "Bitcoin is not connected!");
1768 if (IsInitialBlockDownload())
1769 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1771 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1772 static mapNewBlock_t mapNewBlock;
1773 static vector<CBlock*> vNewBlock;
1774 static CReserveKey reservekey(pwalletMain);
1776 if (params.size() == 0)
1779 static unsigned int nTransactionsUpdatedLast;
1780 static CBlockIndex* pindexPrev;
1781 static int64 nStart;
1782 static CBlock* pblock;
1783 if (pindexPrev != pindexBest ||
1784 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1786 if (pindexPrev != pindexBest)
1788 // Deallocate old blocks since they're obsolete now
1789 mapNewBlock.clear();
1790 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1794 nTransactionsUpdatedLast = nTransactionsUpdated;
1795 pindexPrev = pindexBest;
1799 pblock = CreateNewBlock(reservekey);
1801 throw JSONRPCError(-7, "Out of memory");
1802 vNewBlock.push_back(pblock);
1806 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1809 // Update nExtraNonce
1810 static unsigned int nExtraNonce = 0;
1811 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1814 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1816 // Prebuild hash buffers
1820 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1822 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1825 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1826 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1827 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1828 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1834 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1835 if (vchData.size() != 128)
1836 throw JSONRPCError(-8, "Invalid parameter");
1837 CBlock* pdata = (CBlock*)&vchData[0];
1840 for (int i = 0; i < 128/4; i++)
1841 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1844 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1846 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1848 pblock->nTime = pdata->nTime;
1849 pblock->nNonce = pdata->nNonce;
1850 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1851 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1853 return CheckWork(pblock, *pwalletMain, reservekey);
1858 Value getmemorypool(const Array& params, bool fHelp)
1860 if (fHelp || params.size() > 1)
1861 throw runtime_error(
1862 "getmemorypool [data]\n"
1863 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1864 " \"version\" : block version\n"
1865 " \"previousblockhash\" : hash of current highest block\n"
1866 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1867 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1868 " \"time\" : timestamp appropriate for next block\n"
1869 " \"bits\" : compressed target of next block\n"
1870 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1872 if (params.size() == 0)
1875 throw JSONRPCError(-9, "Bitcoin is not connected!");
1877 if (IsInitialBlockDownload())
1878 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1880 static CReserveKey reservekey(pwalletMain);
1883 static unsigned int nTransactionsUpdatedLast;
1884 static CBlockIndex* pindexPrev;
1885 static int64 nStart;
1886 static CBlock* pblock;
1887 if (pindexPrev != pindexBest ||
1888 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1890 nTransactionsUpdatedLast = nTransactionsUpdated;
1891 pindexPrev = pindexBest;
1897 pblock = CreateNewBlock(reservekey);
1899 throw JSONRPCError(-7, "Out of memory");
1903 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1907 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1914 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1918 result.push_back(Pair("version", pblock->nVersion));
1919 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1920 result.push_back(Pair("transactions", transactions));
1921 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1922 result.push_back(Pair("time", (int64_t)pblock->nTime));
1928 uBits.nBits = htonl((int32_t)pblock->nBits);
1929 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1936 CDataStream ssBlock(ParseHex(params[0].get_str()));
1940 return ProcessBlock(NULL, &pblock);
1944 Value getblockhash(const Array& params, bool fHelp)
1946 if (fHelp || params.size() != 1)
1947 throw runtime_error(
1948 "getblockhash <index>\n"
1949 "Returns hash of block in best-block-chain at <index>.");
1951 int nHeight = params[0].get_int();
1952 if (nHeight < 0 || nHeight > nBestHeight)
1953 throw runtime_error("Block number out of range.");
1956 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1957 while (pblockindex->nHeight > nHeight)
1958 pblockindex = pblockindex->pprev;
1959 return pblockindex->phashBlock->GetHex();
1962 Value getblock(const Array& params, bool fHelp)
1964 if (fHelp || params.size() != 1)
1965 throw runtime_error(
1967 "Returns details of a block with given block-hash.");
1969 std::string strHash = params[0].get_str();
1970 uint256 hash(strHash);
1972 if (mapBlockIndex.count(hash) == 0)
1973 throw JSONRPCError(-5, "Block not found");
1976 CBlockIndex* pblockindex = mapBlockIndex[hash];
1977 block.ReadFromDisk(pblockindex, true);
1979 return blockToJSON(block, pblockindex);
1996 pair<string, rpcfn_type> pCallTable[] =
1998 make_pair("help", &help),
1999 make_pair("stop", &stop),
2000 make_pair("getblockcount", &getblockcount),
2001 make_pair("getblocknumber", &getblocknumber),
2002 make_pair("getconnectioncount", &getconnectioncount),
2003 make_pair("getdifficulty", &getdifficulty),
2004 make_pair("getgenerate", &getgenerate),
2005 make_pair("setgenerate", &setgenerate),
2006 make_pair("gethashespersec", &gethashespersec),
2007 make_pair("getinfo", &getinfo),
2008 make_pair("getmininginfo", &getmininginfo),
2009 make_pair("getnewaddress", &getnewaddress),
2010 make_pair("getaccountaddress", &getaccountaddress),
2011 make_pair("setaccount", &setaccount),
2012 make_pair("getaccount", &getaccount),
2013 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2014 make_pair("sendtoaddress", &sendtoaddress),
2015 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2016 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2017 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2018 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2019 make_pair("backupwallet", &backupwallet),
2020 make_pair("keypoolrefill", &keypoolrefill),
2021 make_pair("walletpassphrase", &walletpassphrase),
2022 make_pair("walletpassphrasechange", &walletpassphrasechange),
2023 make_pair("walletlock", &walletlock),
2024 make_pair("encryptwallet", &encryptwallet),
2025 make_pair("validateaddress", &validateaddress),
2026 make_pair("getbalance", &getbalance),
2027 make_pair("move", &movecmd),
2028 make_pair("sendfrom", &sendfrom),
2029 make_pair("sendmany", &sendmany),
2030 make_pair("addmultisigaddress", &addmultisigaddress),
2031 make_pair("getblock", &getblock),
2032 make_pair("getblockhash", &getblockhash),
2033 make_pair("gettransaction", &gettransaction),
2034 make_pair("listtransactions", &listtransactions),
2035 make_pair("signmessage", &signmessage),
2036 make_pair("verifymessage", &verifymessage),
2037 make_pair("getwork", &getwork),
2038 make_pair("listaccounts", &listaccounts),
2039 make_pair("settxfee", &settxfee),
2040 make_pair("getmemorypool", &getmemorypool),
2041 make_pair("listsinceblock", &listsinceblock),
2042 make_pair("dumpprivkey", &dumpprivkey),
2043 make_pair("importprivkey", &importprivkey)
2045 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2047 string pAllowInSafeMode[] =
2052 "getblocknumber", // deprecated
2053 "getconnectioncount",
2061 "getaccountaddress",
2063 "getaddressesbyaccount",
2072 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2080 // This ain't Apache. We're just using HTTP header for the length field
2081 // and to be compatible with other JSON-RPC implementations.
2084 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2087 s << "POST / HTTP/1.1\r\n"
2088 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2089 << "Host: 127.0.0.1\r\n"
2090 << "Content-Type: application/json\r\n"
2091 << "Content-Length: " << strMsg.size() << "\r\n"
2092 << "Connection: close\r\n"
2093 << "Accept: application/json\r\n";
2094 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2095 s << item.first << ": " << item.second << "\r\n";
2096 s << "\r\n" << strMsg;
2101 string rfc1123Time()
2106 struct tm* now_gmt = gmtime(&now);
2107 string locale(setlocale(LC_TIME, NULL));
2108 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2109 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2110 setlocale(LC_TIME, locale.c_str());
2111 return string(buffer);
2114 static string HTTPReply(int nStatus, const string& strMsg)
2117 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2119 "Server: bitcoin-json-rpc/%s\r\n"
2120 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2121 "Content-Type: text/html\r\n"
2122 "Content-Length: 296\r\n"
2124 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2125 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2128 "<TITLE>Error</TITLE>\r\n"
2129 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2131 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2132 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2133 const char *cStatus;
2134 if (nStatus == 200) cStatus = "OK";
2135 else if (nStatus == 400) cStatus = "Bad Request";
2136 else if (nStatus == 403) cStatus = "Forbidden";
2137 else if (nStatus == 404) cStatus = "Not Found";
2138 else if (nStatus == 500) cStatus = "Internal Server Error";
2141 "HTTP/1.1 %d %s\r\n"
2143 "Connection: close\r\n"
2144 "Content-Length: %d\r\n"
2145 "Content-Type: application/json\r\n"
2146 "Server: bitcoin-json-rpc/%s\r\n"
2151 rfc1123Time().c_str(),
2153 FormatFullVersion().c_str(),
2157 int ReadHTTPStatus(std::basic_istream<char>& stream)
2160 getline(stream, str);
2161 vector<string> vWords;
2162 boost::split(vWords, str, boost::is_any_of(" "));
2163 if (vWords.size() < 2)
2165 return atoi(vWords[1].c_str());
2168 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2174 std::getline(stream, str);
2175 if (str.empty() || str == "\r")
2177 string::size_type nColon = str.find(":");
2178 if (nColon != string::npos)
2180 string strHeader = str.substr(0, nColon);
2181 boost::trim(strHeader);
2182 boost::to_lower(strHeader);
2183 string strValue = str.substr(nColon+1);
2184 boost::trim(strValue);
2185 mapHeadersRet[strHeader] = strValue;
2186 if (strHeader == "content-length")
2187 nLen = atoi(strValue.c_str());
2193 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2195 mapHeadersRet.clear();
2199 int nStatus = ReadHTTPStatus(stream);
2202 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2203 if (nLen < 0 || nLen > MAX_SIZE)
2209 vector<char> vch(nLen);
2210 stream.read(&vch[0], nLen);
2211 strMessageRet = string(vch.begin(), vch.end());
2217 bool HTTPAuthorized(map<string, string>& mapHeaders)
2219 string strAuth = mapHeaders["authorization"];
2220 if (strAuth.substr(0,6) != "Basic ")
2222 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2223 string strUserPass = DecodeBase64(strUserPass64);
2224 return strUserPass == strRPCUserColonPass;
2228 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2229 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2230 // unspecified (HTTP errors and contents of 'error').
2232 // 1.0 spec: http://json-rpc.org/wiki/specification
2233 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2234 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2237 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2240 request.push_back(Pair("method", strMethod));
2241 request.push_back(Pair("params", params));
2242 request.push_back(Pair("id", id));
2243 return write_string(Value(request), false) + "\n";
2246 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2249 if (error.type() != null_type)
2250 reply.push_back(Pair("result", Value::null));
2252 reply.push_back(Pair("result", result));
2253 reply.push_back(Pair("error", error));
2254 reply.push_back(Pair("id", id));
2255 return write_string(Value(reply), false) + "\n";
2258 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2260 // Send error reply from json-rpc error object
2262 int code = find_value(objError, "code").get_int();
2263 if (code == -32600) nStatus = 400;
2264 else if (code == -32601) nStatus = 404;
2265 string strReply = JSONRPCReply(Value::null, objError, id);
2266 stream << HTTPReply(nStatus, strReply) << std::flush;
2269 bool ClientAllowed(const string& strAddress)
2271 if (strAddress == asio::ip::address_v4::loopback().to_string())
2273 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2274 BOOST_FOREACH(string strAllow, vAllow)
2275 if (WildcardMatch(strAddress, strAllow))
2282 // IOStream device that speaks SSL but can also speak non-SSL
2284 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2286 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2288 fUseSSL = fUseSSLIn;
2289 fNeedHandshake = fUseSSLIn;
2292 void handshake(ssl::stream_base::handshake_type role)
2294 if (!fNeedHandshake) return;
2295 fNeedHandshake = false;
2296 stream.handshake(role);
2298 std::streamsize read(char* s, std::streamsize n)
2300 handshake(ssl::stream_base::server); // HTTPS servers read first
2301 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2302 return stream.next_layer().read_some(asio::buffer(s, n));
2304 std::streamsize write(const char* s, std::streamsize n)
2306 handshake(ssl::stream_base::client); // HTTPS clients write first
2307 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2308 return asio::write(stream.next_layer(), asio::buffer(s, n));
2310 bool connect(const std::string& server, const std::string& port)
2312 ip::tcp::resolver resolver(stream.get_io_service());
2313 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2314 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2315 ip::tcp::resolver::iterator end;
2316 boost::system::error_code error = asio::error::host_not_found;
2317 while (error && endpoint_iterator != end)
2319 stream.lowest_layer().close();
2320 stream.lowest_layer().connect(*endpoint_iterator++, error);
2328 bool fNeedHandshake;
2334 void ThreadRPCServer(void* parg)
2336 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2339 vnThreadsRunning[4]++;
2340 ThreadRPCServer2(parg);
2341 vnThreadsRunning[4]--;
2343 catch (std::exception& e) {
2344 vnThreadsRunning[4]--;
2345 PrintException(&e, "ThreadRPCServer()");
2347 vnThreadsRunning[4]--;
2348 PrintException(NULL, "ThreadRPCServer()");
2350 printf("ThreadRPCServer exiting\n");
2353 void ThreadRPCServer2(void* parg)
2355 printf("ThreadRPCServer started\n");
2357 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2358 if (strRPCUserColonPass == ":")
2360 string strWhatAmI = "To use bitcoind";
2361 if (mapArgs.count("-server"))
2362 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2363 else if (mapArgs.count("-daemon"))
2364 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2366 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2367 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2369 GetConfigFile().c_str());
2371 CreateThread(Shutdown, NULL);
2376 bool fUseSSL = GetBoolArg("-rpcssl");
2377 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2379 asio::io_service io_service;
2380 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2381 ip::tcp::acceptor acceptor(io_service, endpoint);
2383 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2386 ssl::context context(io_service, ssl::context::sslv23);
2389 context.set_options(ssl::context::no_sslv2);
2390 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2391 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2392 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2393 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2394 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2395 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2396 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2397 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2399 string ciphers = GetArg("-rpcsslciphers",
2400 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2401 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2405 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2410 // Accept connection
2412 SSLStream sslStream(io_service, context);
2413 SSLIOStreamDevice d(sslStream, fUseSSL);
2414 iostreams::stream<SSLIOStreamDevice> stream(d);
2416 ip::tcp::iostream stream;
2419 ip::tcp::endpoint peer;
2420 vnThreadsRunning[4]--;
2422 acceptor.accept(sslStream.lowest_layer(), peer);
2424 acceptor.accept(*stream.rdbuf(), peer);
2426 vnThreadsRunning[4]++;
2430 // Restrict callers by IP
2431 if (!ClientAllowed(peer.address().to_string()))
2433 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2435 stream << HTTPReply(403, "") << std::flush;
2439 map<string, string> mapHeaders;
2442 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2443 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2446 printf("ThreadRPCServer ReadHTTP timeout\n");
2450 // Check authorization
2451 if (mapHeaders.count("authorization") == 0)
2453 stream << HTTPReply(401, "") << std::flush;
2456 if (!HTTPAuthorized(mapHeaders))
2458 // Deter brute-forcing short passwords
2459 if (mapArgs["-rpcpassword"].size() < 15)
2462 stream << HTTPReply(401, "") << std::flush;
2463 printf("ThreadRPCServer incorrect password attempt\n");
2467 Value id = Value::null;
2472 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2473 throw JSONRPCError(-32700, "Parse error");
2474 const Object& request = valRequest.get_obj();
2476 // Parse id now so errors from here on will have the id
2477 id = find_value(request, "id");
2480 Value valMethod = find_value(request, "method");
2481 if (valMethod.type() == null_type)
2482 throw JSONRPCError(-32600, "Missing method");
2483 if (valMethod.type() != str_type)
2484 throw JSONRPCError(-32600, "Method must be a string");
2485 string strMethod = valMethod.get_str();
2486 if (strMethod != "getwork" && strMethod != "getmemorypool")
2487 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2490 Value valParams = find_value(request, "params");
2492 if (valParams.type() == array_type)
2493 params = valParams.get_array();
2494 else if (valParams.type() == null_type)
2497 throw JSONRPCError(-32600, "Params must be an array");
2500 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2501 if (mi == mapCallTable.end())
2502 throw JSONRPCError(-32601, "Method not found");
2504 // Observe safe mode
2505 string strWarning = GetWarnings("rpc");
2506 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2507 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2513 CRITICAL_BLOCK(cs_main)
2514 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2515 result = (*(*mi).second)(params, false);
2518 string strReply = JSONRPCReply(result, Value::null, id);
2519 stream << HTTPReply(200, strReply) << std::flush;
2521 catch (std::exception& e)
2523 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2526 catch (Object& objError)
2528 ErrorReply(stream, objError, id);
2530 catch (std::exception& e)
2532 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2540 Object CallRPC(const string& strMethod, const Array& params)
2542 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2543 throw runtime_error(strprintf(
2544 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2545 "If the file does not exist, create it with owner-readable-only file permissions."),
2546 GetConfigFile().c_str()));
2548 // Connect to localhost
2549 bool fUseSSL = GetBoolArg("-rpcssl");
2551 asio::io_service io_service;
2552 ssl::context context(io_service, ssl::context::sslv23);
2553 context.set_options(ssl::context::no_sslv2);
2554 SSLStream sslStream(io_service, context);
2555 SSLIOStreamDevice d(sslStream, fUseSSL);
2556 iostreams::stream<SSLIOStreamDevice> stream(d);
2557 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2558 throw runtime_error("couldn't connect to server");
2561 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2563 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2565 throw runtime_error("couldn't connect to server");
2569 // HTTP basic authentication
2570 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2571 map<string, string> mapRequestHeaders;
2572 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2575 string strRequest = JSONRPCRequest(strMethod, params, 1);
2576 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2577 stream << strPost << std::flush;
2580 map<string, string> mapHeaders;
2582 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2584 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2585 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2586 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2587 else if (strReply.empty())
2588 throw runtime_error("no response from server");
2592 if (!read_string(strReply, valReply))
2593 throw runtime_error("couldn't parse reply from server");
2594 const Object& reply = valReply.get_obj();
2596 throw runtime_error("expected reply to have result, error and id properties");
2604 template<typename T>
2605 void ConvertTo(Value& value)
2607 if (value.type() == str_type)
2609 // reinterpret string as unquoted json value
2611 if (!read_string(value.get_str(), value2))
2612 throw runtime_error("type mismatch");
2613 value = value2.get_value<T>();
2617 value = value.get_value<T>();
2621 int CommandLineRPC(int argc, char *argv[])
2628 while (argc > 1 && IsSwitchChar(argv[1][0]))
2636 throw runtime_error("too few parameters");
2637 string strMethod = argv[1];
2639 // Parameters default to strings
2641 for (int i = 2; i < argc; i++)
2642 params.push_back(argv[i]);
2643 int n = params.size();
2646 // Special case non-string parameter types
2648 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2649 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2650 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2651 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2652 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2654 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2655 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2656 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2657 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2658 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2661 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2662 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2663 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2664 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2666 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2669 if (strMethod == "sendmany" && n > 1)
2671 string s = params[1].get_str();
2673 if (!read_string(s, v) || v.type() != obj_type)
2674 throw runtime_error("type mismatch");
2675 params[1] = v.get_obj();
2677 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2678 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679 if (strMethod == "addmultisigaddress" && n > 1)
2681 string s = params[1].get_str();
2683 if (!read_string(s, v) || v.type() != array_type)
2684 throw runtime_error("addmultisigaddress: type mismatch "+s);
2685 params[1] = v.get_array();
2689 Object reply = CallRPC(strMethod, params);
2692 const Value& result = find_value(reply, "result");
2693 const Value& error = find_value(reply, "error");
2695 if (error.type() != null_type)
2698 strPrint = "error: " + write_string(error, false);
2699 int code = find_value(error.get_obj(), "code").get_int();
2705 if (result.type() == null_type)
2707 else if (result.type() == str_type)
2708 strPrint = result.get_str();
2710 strPrint = write_string(result, true);
2713 catch (std::exception& e)
2715 strPrint = string("error: ") + e.what();
2720 PrintException(NULL, "CommandLineRPC()");
2725 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2734 int main(int argc, char *argv[])
2737 // Turn off microsoft heap dump noise
2738 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2739 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2741 setbuf(stdin, NULL);
2742 setbuf(stdout, NULL);
2743 setbuf(stderr, NULL);
2747 if (argc >= 2 && string(argv[1]) == "-server")
2749 printf("server ready\n");
2750 ThreadRPCServer(NULL);
2754 return CommandLineRPC(argc, argv);
2757 catch (std::exception& e) {
2758 PrintException(&e, "main()");
2760 PrintException(NULL, "main()");