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/iostreams/concepts.hpp>
13 #include <boost/iostreams/stream.hpp>
14 #include <boost/algorithm/string.hpp>
16 #include <boost/asio/ssl.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/filesystem/fstream.hpp>
19 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #include "json/json_spirit_reader_template.h"
22 #include "json/json_spirit_writer_template.h"
23 #include "json/json_spirit_utils.h"
24 #define printf OutputDebugStringF
25 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
26 // precompiled in headers.h. The problem might be when the pch file goes over
27 // a certain size around 145MB. If we need access to json_spirit outside this
28 // file, we could use the compiled json_spirit option.
31 using namespace boost;
32 using namespace boost::asio;
33 using namespace json_spirit;
35 void ThreadRPCServer2(void* parg);
36 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
37 extern map<string, rpcfn_type> mapCallTable;
39 static int64 nWalletUnlockTime;
40 static CCriticalSection cs_nWalletUnlockTime;
43 Object JSONRPCError(int code, const string& message)
46 error.push_back(Pair("code", code));
47 error.push_back(Pair("message", message));
52 void PrintConsole(const std::string &format, ...)
55 int limit = sizeof(buffer);
57 va_start(arg_ptr, format);
58 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
60 if (ret < 0 || ret >= limit)
66 fprintf(stdout, "%s", buffer);
70 int64 AmountFromValue(const Value& value)
72 double dAmount = value.get_real();
73 if (dAmount <= 0.0 || dAmount > 21000000.0)
74 throw JSONRPCError(-3, "Invalid amount");
75 int64 nAmount = roundint64(dAmount * COIN);
76 if (!MoneyRange(nAmount))
77 throw JSONRPCError(-3, "Invalid amount");
81 Value ValueFromAmount(int64 amount)
83 return (double)amount / (double)COIN;
86 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
88 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
89 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
90 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
91 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
92 entry.push_back(Pair(item.first, item.second));
95 string AccountFromValue(const Value& value)
97 string strAccount = value.get_str();
98 if (strAccount == "*")
99 throw JSONRPCError(-11, "Invalid account name");
106 /// Note: This interface may still be subject to change.
110 Value help(const Array& params, bool fHelp)
112 if (fHelp || params.size() > 1)
115 "List commands, or get help for a command.");
118 if (params.size() > 0)
119 strCommand = params[0].get_str();
122 set<rpcfn_type> setDone;
123 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
125 string strMethod = (*mi).first;
126 // We already filter duplicates, but these deprecated screw up the sort order
127 if (strMethod == "getamountreceived" ||
128 strMethod == "getallreceived" ||
129 (strMethod.find("label") != string::npos))
131 if (strCommand != "" && strMethod != strCommand)
136 rpcfn_type pfn = (*mi).second;
137 if (setDone.insert(pfn).second)
138 (*pfn)(params, true);
140 catch (std::exception& e)
142 // Help text is returned in an exception
143 string strHelp = string(e.what());
144 if (strCommand == "")
145 if (strHelp.find('\n') != -1)
146 strHelp = strHelp.substr(0, strHelp.find('\n'));
147 strRet += strHelp + "\n";
151 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
152 strRet = strRet.substr(0,strRet.size()-1);
157 Value stop(const Array& params, bool fHelp)
159 if (fHelp || params.size() != 0)
162 "Stop bitcoin server.");
164 // Shutdown will take long enough that the response should get back
165 CreateThread(Shutdown, NULL);
166 return "bitcoin server stopping";
170 Value getblockcount(const Array& params, bool fHelp)
172 if (fHelp || params.size() != 0)
175 "Returns the number of blocks in the longest block chain.");
181 Value getblocknumber(const Array& params, bool fHelp)
183 if (fHelp || params.size() != 0)
186 "Returns the block number of the latest block in the longest block chain.");
192 Value getconnectioncount(const Array& params, bool fHelp)
194 if (fHelp || params.size() != 0)
196 "getconnectioncount\n"
197 "Returns the number of connections to other nodes.");
199 return (int)vNodes.size();
203 double GetDifficulty()
205 // Floating point number that is a multiple of the minimum difficulty,
206 // minimum difficulty = 1.0.
208 if (pindexBest == NULL)
210 int nShift = (pindexBest->nBits >> 24) & 0xff;
213 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
229 Value getdifficulty(const Array& params, bool fHelp)
231 if (fHelp || params.size() != 0)
234 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
236 return GetDifficulty();
240 Value getgenerate(const Array& params, bool fHelp)
242 if (fHelp || params.size() != 0)
245 "Returns true or false.");
247 return (bool)fGenerateBitcoins;
251 Value setgenerate(const Array& params, bool fHelp)
253 if (fHelp || params.size() < 1 || params.size() > 2)
255 "setgenerate <generate> [genproclimit]\n"
256 "<generate> is true or false to turn generation on or off.\n"
257 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
259 bool fGenerate = true;
260 if (params.size() > 0)
261 fGenerate = params[0].get_bool();
263 if (params.size() > 1)
265 int nGenProcLimit = params[1].get_int();
266 fLimitProcessors = (nGenProcLimit != -1);
267 WriteSetting("fLimitProcessors", fLimitProcessors);
268 if (nGenProcLimit != -1)
269 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
270 if (nGenProcLimit == 0)
274 GenerateBitcoins(fGenerate, pwalletMain);
279 Value gethashespersec(const Array& params, bool fHelp)
281 if (fHelp || params.size() != 0)
284 "Returns a recent hashes per second performance measurement while generating.");
286 if (GetTimeMillis() - nHPSTimerStart > 8000)
287 return (boost::int64_t)0;
288 return (boost::int64_t)dHashesPerSec;
292 Value getinfo(const Array& params, bool fHelp)
294 if (fHelp || params.size() != 0)
297 "Returns an object containing various state info.");
300 obj.push_back(Pair("version", (int)VERSION));
301 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
302 obj.push_back(Pair("blocks", (int)nBestHeight));
303 obj.push_back(Pair("connections", (int)vNodes.size()));
304 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
305 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
306 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
307 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
308 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
309 obj.push_back(Pair("testnet", fTestNet));
310 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
311 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
312 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
313 if (pwalletMain->IsCrypted())
314 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
315 obj.push_back(Pair("errors", GetWarnings("statusbar")));
320 Value getnewaddress(const Array& params, bool fHelp)
322 if (fHelp || params.size() > 1)
324 "getnewaddress [account]\n"
325 "Returns a new bitcoin address for receiving payments. "
326 "If [account] is specified (recommended), it is added to the address book "
327 "so payments received with the address will be credited to [account].");
329 // Parse the account first so we don't generate a key if there's an error
331 if (params.size() > 0)
332 strAccount = AccountFromValue(params[0]);
334 if (!pwalletMain->IsLocked())
335 pwalletMain->TopUpKeyPool();
337 // Generate a new key that is added to wallet
338 std::vector<unsigned char> newKey;
339 if (!pwalletMain->GetKeyFromPool(newKey, false))
340 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
341 CBitcoinAddress address(newKey);
343 pwalletMain->SetAddressBookName(address, strAccount);
345 return address.ToString();
349 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
351 CWalletDB walletdb(pwalletMain->strWalletFile);
354 walletdb.ReadAccount(strAccount, account);
356 bool bKeyUsed = false;
358 // Check if the current key has been used
359 if (!account.vchPubKey.empty())
361 CScript scriptPubKey;
362 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
363 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
364 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
367 const CWalletTx& wtx = (*it).second;
368 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
369 if (txout.scriptPubKey == scriptPubKey)
374 // Generate a new key
375 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
377 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
378 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
380 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
381 walletdb.WriteAccount(strAccount, account);
384 return CBitcoinAddress(account.vchPubKey);
387 Value getaccountaddress(const Array& params, bool fHelp)
389 if (fHelp || params.size() != 1)
391 "getaccountaddress <account>\n"
392 "Returns the current bitcoin address for receiving payments to this account.");
394 // Parse the account first so we don't generate a key if there's an error
395 string strAccount = AccountFromValue(params[0]);
399 ret = GetAccountAddress(strAccount).ToString();
406 Value setaccount(const Array& params, bool fHelp)
408 if (fHelp || params.size() < 1 || params.size() > 2)
410 "setaccount <bitcoinaddress> <account>\n"
411 "Sets the account associated with the given address.");
413 CBitcoinAddress address(params[0].get_str());
414 if (!address.IsValid())
415 throw JSONRPCError(-5, "Invalid bitcoin address");
419 if (params.size() > 1)
420 strAccount = AccountFromValue(params[1]);
422 // Detect when changing the account of an address that is the 'unused current key' of another account:
423 if (pwalletMain->mapAddressBook.count(address))
425 string strOldAccount = pwalletMain->mapAddressBook[address];
426 if (address == GetAccountAddress(strOldAccount))
427 GetAccountAddress(strOldAccount, true);
430 pwalletMain->SetAddressBookName(address, strAccount);
436 Value getaccount(const Array& params, bool fHelp)
438 if (fHelp || params.size() != 1)
440 "getaccount <bitcoinaddress>\n"
441 "Returns the account associated with the given address.");
443 CBitcoinAddress address(params[0].get_str());
444 if (!address.IsValid())
445 throw JSONRPCError(-5, "Invalid bitcoin address");
448 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
449 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
450 strAccount = (*mi).second;
455 Value getaddressesbyaccount(const Array& params, bool fHelp)
457 if (fHelp || params.size() != 1)
459 "getaddressesbyaccount <account>\n"
460 "Returns the list of addresses for the given account.");
462 string strAccount = AccountFromValue(params[0]);
464 // Find all addresses that have the given account
466 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
468 const CBitcoinAddress& address = item.first;
469 const string& strName = item.second;
470 if (strName == strAccount)
471 ret.push_back(address.ToString());
476 Value settxfee(const Array& params, bool fHelp)
478 if (fHelp || params.size() < 1 || params.size() > 1)
480 "settxfee <amount>\n"
481 "<amount> is a real and is rounded to the nearest 0.00000001");
485 if (params[0].get_real() != 0.0)
486 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
488 nTransactionFee = nAmount;
492 Value sendtoaddress(const Array& params, bool fHelp)
494 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
496 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
497 "<amount> is a real and is rounded to the nearest 0.00000001\n"
498 "requires wallet passphrase to be set with walletpassphrase first");
499 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
501 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
502 "<amount> is a real and is rounded to the nearest 0.00000001");
504 CBitcoinAddress address(params[0].get_str());
505 if (!address.IsValid())
506 throw JSONRPCError(-5, "Invalid bitcoin address");
509 int64 nAmount = AmountFromValue(params[1]);
513 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
514 wtx.mapValue["comment"] = params[2].get_str();
515 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
516 wtx.mapValue["to"] = params[3].get_str();
518 if (pwalletMain->IsLocked())
519 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
521 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
523 throw JSONRPCError(-4, strError);
525 return wtx.GetHash().GetHex();
528 static const string strMessageMagic = "Bitcoin Signed Message:\n";
530 Value signmessage(const Array& params, bool fHelp)
532 if (fHelp || params.size() != 2)
534 "signmessage <bitcoinaddress> <message>\n"
535 "Sign a message with the private key of an address");
537 if (pwalletMain->IsLocked())
538 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
540 string strAddress = params[0].get_str();
541 string strMessage = params[1].get_str();
543 CBitcoinAddress addr(strAddress);
545 throw JSONRPCError(-3, "Invalid address");
548 if (!pwalletMain->GetKey(addr, key))
549 throw JSONRPCError(-4, "Private key not available");
551 CDataStream ss(SER_GETHASH);
552 ss << strMessageMagic;
555 vector<unsigned char> vchSig;
556 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
557 throw JSONRPCError(-5, "Sign failed");
559 return EncodeBase64(&vchSig[0], vchSig.size());
562 Value verifymessage(const Array& params, bool fHelp)
564 if (fHelp || params.size() != 3)
566 "verifymessage <bitcoinaddress> <signature> <message>\n"
567 "Verify a signed message");
569 string strAddress = params[0].get_str();
570 string strSign = params[1].get_str();
571 string strMessage = params[2].get_str();
573 CBitcoinAddress addr(strAddress);
575 throw JSONRPCError(-3, "Invalid address");
577 bool fInvalid = false;
578 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
581 throw JSONRPCError(-5, "Malformed base64 encoding");
583 CDataStream ss(SER_GETHASH);
584 ss << strMessageMagic;
588 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
591 return (key.GetAddress() == addr);
595 Value getreceivedbyaddress(const Array& params, bool fHelp)
597 if (fHelp || params.size() < 1 || params.size() > 2)
599 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
600 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
603 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
604 CScript scriptPubKey;
605 if (!address.IsValid())
606 throw JSONRPCError(-5, "Invalid bitcoin address");
607 scriptPubKey.SetBitcoinAddress(address);
608 if (!IsMine(*pwalletMain,scriptPubKey))
611 // Minimum confirmations
613 if (params.size() > 1)
614 nMinDepth = params[1].get_int();
618 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
620 const CWalletTx& wtx = (*it).second;
621 if (wtx.IsCoinBase() || !wtx.IsFinal())
624 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
625 if (txout.scriptPubKey == scriptPubKey)
626 if (wtx.GetDepthInMainChain() >= nMinDepth)
627 nAmount += txout.nValue;
630 return ValueFromAmount(nAmount);
634 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
636 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
638 const CBitcoinAddress& address = item.first;
639 const string& strName = item.second;
640 if (strName == strAccount)
641 setAddress.insert(address);
646 Value getreceivedbyaccount(const Array& params, bool fHelp)
648 if (fHelp || params.size() < 1 || params.size() > 2)
650 "getreceivedbyaccount <account> [minconf=1]\n"
651 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
653 // Minimum confirmations
655 if (params.size() > 1)
656 nMinDepth = params[1].get_int();
658 // Get the set of pub keys that have the label
659 string strAccount = AccountFromValue(params[0]);
660 set<CBitcoinAddress> setAddress;
661 GetAccountAddresses(strAccount, setAddress);
665 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
667 const CWalletTx& wtx = (*it).second;
668 if (wtx.IsCoinBase() || !wtx.IsFinal())
671 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
673 CBitcoinAddress address;
674 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
675 if (wtx.GetDepthInMainChain() >= nMinDepth)
676 nAmount += txout.nValue;
680 return (double)nAmount / (double)COIN;
684 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
688 // Tally wallet transactions
689 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
691 const CWalletTx& wtx = (*it).second;
695 int64 nGenerated, nReceived, nSent, nFee;
696 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
698 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
699 nBalance += nReceived;
700 nBalance += nGenerated - nSent - nFee;
703 // Tally internal accounting entries
704 nBalance += walletdb.GetAccountCreditDebit(strAccount);
709 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
711 CWalletDB walletdb(pwalletMain->strWalletFile);
712 return GetAccountBalance(walletdb, strAccount, nMinDepth);
716 Value getbalance(const Array& params, bool fHelp)
718 if (fHelp || params.size() > 2)
720 "getbalance [account] [minconf=1]\n"
721 "If [account] is not specified, returns the server's total available balance.\n"
722 "If [account] is specified, returns the balance in the account.");
724 if (params.size() == 0)
725 return ValueFromAmount(pwalletMain->GetBalance());
728 if (params.size() > 1)
729 nMinDepth = params[1].get_int();
731 if (params[0].get_str() == "*") {
732 // Calculate total balance a different way from GetBalance()
733 // (GetBalance() sums up all unspent TxOuts)
734 // getbalance and getbalance '*' should always return the same number.
736 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
738 const CWalletTx& wtx = (*it).second;
742 int64 allGeneratedImmature, allGeneratedMature, allFee;
743 allGeneratedImmature = allGeneratedMature = allFee = 0;
744 string strSentAccount;
745 list<pair<CBitcoinAddress, int64> > listReceived;
746 list<pair<CBitcoinAddress, int64> > listSent;
747 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
748 if (wtx.GetDepthInMainChain() >= nMinDepth)
749 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
750 nBalance += r.second;
751 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
752 nBalance -= r.second;
754 nBalance += allGeneratedMature;
756 return ValueFromAmount(nBalance);
759 string strAccount = AccountFromValue(params[0]);
761 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
763 return ValueFromAmount(nBalance);
767 Value movecmd(const Array& params, bool fHelp)
769 if (fHelp || params.size() < 3 || params.size() > 5)
771 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
772 "Move from one account in your wallet to another.");
774 string strFrom = AccountFromValue(params[0]);
775 string strTo = AccountFromValue(params[1]);
776 int64 nAmount = AmountFromValue(params[2]);
777 if (params.size() > 3)
778 // unused parameter, used to be nMinDepth, keep type-checking it though
779 (void)params[3].get_int();
781 if (params.size() > 4)
782 strComment = params[4].get_str();
784 CWalletDB walletdb(pwalletMain->strWalletFile);
787 int64 nNow = GetAdjustedTime();
790 CAccountingEntry debit;
791 debit.strAccount = strFrom;
792 debit.nCreditDebit = -nAmount;
794 debit.strOtherAccount = strTo;
795 debit.strComment = strComment;
796 walletdb.WriteAccountingEntry(debit);
799 CAccountingEntry credit;
800 credit.strAccount = strTo;
801 credit.nCreditDebit = nAmount;
803 credit.strOtherAccount = strFrom;
804 credit.strComment = strComment;
805 walletdb.WriteAccountingEntry(credit);
807 walletdb.TxnCommit();
813 Value sendfrom(const Array& params, bool fHelp)
815 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
817 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
818 "<amount> is a real and is rounded to the nearest 0.00000001\n"
819 "requires wallet passphrase to be set with walletpassphrase first");
820 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
822 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
823 "<amount> is a real and is rounded to the nearest 0.00000001");
825 string strAccount = AccountFromValue(params[0]);
826 CBitcoinAddress address(params[1].get_str());
827 if (!address.IsValid())
828 throw JSONRPCError(-5, "Invalid bitcoin address");
829 int64 nAmount = AmountFromValue(params[2]);
831 if (params.size() > 3)
832 nMinDepth = params[3].get_int();
835 wtx.strFromAccount = strAccount;
836 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
837 wtx.mapValue["comment"] = params[4].get_str();
838 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
839 wtx.mapValue["to"] = params[5].get_str();
841 if (pwalletMain->IsLocked())
842 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
845 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
846 if (nAmount > nBalance)
847 throw JSONRPCError(-6, "Account has insufficient funds");
850 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
852 throw JSONRPCError(-4, strError);
854 return wtx.GetHash().GetHex();
858 Value sendmany(const Array& params, bool fHelp)
860 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
862 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
863 "amounts are double-precision floating point numbers\n"
864 "requires wallet passphrase to be set with walletpassphrase first");
865 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
867 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
868 "amounts are double-precision floating point numbers");
870 string strAccount = AccountFromValue(params[0]);
871 Object sendTo = params[1].get_obj();
873 if (params.size() > 2)
874 nMinDepth = params[2].get_int();
877 wtx.strFromAccount = strAccount;
878 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
879 wtx.mapValue["comment"] = params[3].get_str();
881 set<CBitcoinAddress> setAddress;
882 vector<pair<CScript, int64> > vecSend;
884 int64 totalAmount = 0;
885 BOOST_FOREACH(const Pair& s, sendTo)
887 CBitcoinAddress address(s.name_);
888 if (!address.IsValid())
889 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
891 if (setAddress.count(address))
892 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
893 setAddress.insert(address);
895 CScript scriptPubKey;
896 scriptPubKey.SetBitcoinAddress(address);
897 int64 nAmount = AmountFromValue(s.value_);
898 totalAmount += nAmount;
900 vecSend.push_back(make_pair(scriptPubKey, nAmount));
903 if (pwalletMain->IsLocked())
904 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
907 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
908 if (totalAmount > nBalance)
909 throw JSONRPCError(-6, "Account has insufficient funds");
912 CReserveKey keyChange(pwalletMain);
913 int64 nFeeRequired = 0;
914 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
917 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
918 throw JSONRPCError(-6, "Insufficient funds");
919 throw JSONRPCError(-4, "Transaction creation failed");
921 if (!pwalletMain->CommitTransaction(wtx, keyChange))
922 throw JSONRPCError(-4, "Transaction commit failed");
924 return wtx.GetHash().GetHex();
939 Value ListReceived(const Array& params, bool fByAccounts)
941 // Minimum confirmations
943 if (params.size() > 0)
944 nMinDepth = params[0].get_int();
946 // Whether to include empty accounts
947 bool fIncludeEmpty = false;
948 if (params.size() > 1)
949 fIncludeEmpty = params[1].get_bool();
952 map<CBitcoinAddress, tallyitem> mapTally;
953 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
955 const CWalletTx& wtx = (*it).second;
956 if (wtx.IsCoinBase() || !wtx.IsFinal())
959 int nDepth = wtx.GetDepthInMainChain();
960 if (nDepth < nMinDepth)
963 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
965 CBitcoinAddress address;
966 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
969 tallyitem& item = mapTally[address];
970 item.nAmount += txout.nValue;
971 item.nConf = min(item.nConf, nDepth);
977 map<string, tallyitem> mapAccountTally;
978 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
980 const CBitcoinAddress& address = item.first;
981 const string& strAccount = item.second;
982 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
983 if (it == mapTally.end() && !fIncludeEmpty)
988 if (it != mapTally.end())
990 nAmount = (*it).second.nAmount;
991 nConf = (*it).second.nConf;
996 tallyitem& item = mapAccountTally[strAccount];
997 item.nAmount += nAmount;
998 item.nConf = min(item.nConf, nConf);
1003 obj.push_back(Pair("address", address.ToString()));
1004 obj.push_back(Pair("account", strAccount));
1005 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1006 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1013 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1015 int64 nAmount = (*it).second.nAmount;
1016 int nConf = (*it).second.nConf;
1018 obj.push_back(Pair("account", (*it).first));
1019 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1020 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1028 Value listreceivedbyaddress(const Array& params, bool fHelp)
1030 if (fHelp || params.size() > 2)
1031 throw runtime_error(
1032 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1033 "[minconf] is the minimum number of confirmations before payments are included.\n"
1034 "[includeempty] whether to include addresses that haven't received any payments.\n"
1035 "Returns an array of objects containing:\n"
1036 " \"address\" : receiving address\n"
1037 " \"account\" : the account of the receiving address\n"
1038 " \"amount\" : total amount received by the address\n"
1039 " \"confirmations\" : number of confirmations of the most recent transaction included");
1041 return ListReceived(params, false);
1044 Value listreceivedbyaccount(const Array& params, bool fHelp)
1046 if (fHelp || params.size() > 2)
1047 throw runtime_error(
1048 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1049 "[minconf] is the minimum number of confirmations before payments are included.\n"
1050 "[includeempty] whether to include accounts that haven't received any payments.\n"
1051 "Returns an array of objects containing:\n"
1052 " \"account\" : the account of the receiving addresses\n"
1053 " \"amount\" : total amount received by addresses with this account\n"
1054 " \"confirmations\" : number of confirmations of the most recent transaction included");
1056 return ListReceived(params, true);
1059 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1061 int64 nGeneratedImmature, nGeneratedMature, nFee;
1062 string strSentAccount;
1063 list<pair<CBitcoinAddress, int64> > listReceived;
1064 list<pair<CBitcoinAddress, int64> > listSent;
1065 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1067 bool fAllAccounts = (strAccount == string("*"));
1069 // Generated blocks assigned to account ""
1070 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1073 entry.push_back(Pair("account", string("")));
1074 if (nGeneratedImmature)
1076 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1077 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1081 entry.push_back(Pair("category", "generate"));
1082 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1085 WalletTxToJSON(wtx, entry);
1086 ret.push_back(entry);
1090 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1092 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1095 entry.push_back(Pair("account", strSentAccount));
1096 entry.push_back(Pair("address", s.first.ToString()));
1097 entry.push_back(Pair("category", "send"));
1098 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1099 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1101 WalletTxToJSON(wtx, entry);
1102 ret.push_back(entry);
1107 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1108 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1111 if (pwalletMain->mapAddressBook.count(r.first))
1112 account = pwalletMain->mapAddressBook[r.first];
1113 if (fAllAccounts || (account == strAccount))
1116 entry.push_back(Pair("account", account));
1117 entry.push_back(Pair("address", r.first.ToString()));
1118 entry.push_back(Pair("category", "receive"));
1119 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1121 WalletTxToJSON(wtx, entry);
1122 ret.push_back(entry);
1127 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1129 bool fAllAccounts = (strAccount == string("*"));
1131 if (fAllAccounts || acentry.strAccount == strAccount)
1134 entry.push_back(Pair("account", acentry.strAccount));
1135 entry.push_back(Pair("category", "move"));
1136 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1137 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1138 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1139 entry.push_back(Pair("comment", acentry.strComment));
1140 ret.push_back(entry);
1144 Value listtransactions(const Array& params, bool fHelp)
1146 if (fHelp || params.size() > 3)
1147 throw runtime_error(
1148 "listtransactions [account] [count=10] [from=0]\n"
1149 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1151 string strAccount = "*";
1152 if (params.size() > 0)
1153 strAccount = params[0].get_str();
1155 if (params.size() > 1)
1156 nCount = params[1].get_int();
1158 if (params.size() > 2)
1159 nFrom = params[2].get_int();
1162 CWalletDB walletdb(pwalletMain->strWalletFile);
1164 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1165 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1166 typedef multimap<int64, TxPair > TxItems;
1169 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1171 CWalletTx* wtx = &((*it).second);
1172 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1174 list<CAccountingEntry> acentries;
1175 walletdb.ListAccountCreditDebit(strAccount, acentries);
1176 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1178 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1181 // Now: iterate backwards until we have nCount items to return:
1182 TxItems::reverse_iterator it = txByTime.rbegin();
1183 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1184 for (; it != txByTime.rend(); ++it)
1186 CWalletTx *const pwtx = (*it).second.first;
1188 ListTransactions(*pwtx, strAccount, 0, true, ret);
1189 CAccountingEntry *const pacentry = (*it).second.second;
1191 AcentryToJSON(*pacentry, strAccount, ret);
1193 if (ret.size() >= nCount) break;
1195 // ret is now newest to oldest
1197 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1198 if (ret.size() > nCount)
1200 Array::iterator last = ret.begin();
1201 std::advance(last, nCount);
1202 ret.erase(last, ret.end());
1204 std::reverse(ret.begin(), ret.end()); // oldest to newest
1209 Value listaccounts(const Array& params, bool fHelp)
1211 if (fHelp || params.size() > 1)
1212 throw runtime_error(
1213 "listaccounts [minconf=1]\n"
1214 "Returns Object that has account names as keys, account balances as values.");
1217 if (params.size() > 0)
1218 nMinDepth = params[0].get_int();
1220 map<string, int64> mapAccountBalances;
1221 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1222 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1223 mapAccountBalances[entry.second] = 0;
1226 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1228 const CWalletTx& wtx = (*it).second;
1229 int64 nGeneratedImmature, nGeneratedMature, nFee;
1230 string strSentAccount;
1231 list<pair<CBitcoinAddress, int64> > listReceived;
1232 list<pair<CBitcoinAddress, int64> > listSent;
1233 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1234 mapAccountBalances[strSentAccount] -= nFee;
1235 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1236 mapAccountBalances[strSentAccount] -= s.second;
1237 if (wtx.GetDepthInMainChain() >= nMinDepth)
1239 mapAccountBalances[""] += nGeneratedMature;
1240 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1241 if (pwalletMain->mapAddressBook.count(r.first))
1242 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1244 mapAccountBalances[""] += r.second;
1248 list<CAccountingEntry> acentries;
1249 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1250 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1251 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1254 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1255 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1260 Value gettransaction(const Array& params, bool fHelp)
1262 if (fHelp || params.size() != 1)
1263 throw runtime_error(
1264 "gettransaction <txid>\n"
1265 "Get detailed information about <txid>");
1268 hash.SetHex(params[0].get_str());
1272 if (!pwalletMain->mapWallet.count(hash))
1273 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1274 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1276 int64 nCredit = wtx.GetCredit();
1277 int64 nDebit = wtx.GetDebit();
1278 int64 nNet = nCredit - nDebit;
1279 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1281 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1283 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1285 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1288 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1289 entry.push_back(Pair("details", details));
1295 Value backupwallet(const Array& params, bool fHelp)
1297 if (fHelp || params.size() != 1)
1298 throw runtime_error(
1299 "backupwallet <destination>\n"
1300 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1302 string strDest = params[0].get_str();
1303 BackupWallet(*pwalletMain, strDest);
1309 Value keypoolrefill(const Array& params, bool fHelp)
1311 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1312 throw runtime_error(
1314 "Fills the keypool, requires wallet passphrase to be set.");
1315 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1316 throw runtime_error(
1318 "Fills the keypool.");
1320 if (pwalletMain->IsLocked())
1321 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1323 pwalletMain->TopUpKeyPool();
1325 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1326 throw JSONRPCError(-4, "Error refreshing keypool.");
1332 void ThreadTopUpKeyPool(void* parg)
1334 pwalletMain->TopUpKeyPool();
1337 void ThreadCleanWalletPassphrase(void* parg)
1339 int64 nMyWakeTime = GetTime() + *((int*)parg);
1341 if (nWalletUnlockTime == 0)
1343 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1345 nWalletUnlockTime = nMyWakeTime;
1348 while (GetTime() < nWalletUnlockTime)
1349 Sleep(GetTime() - nWalletUnlockTime);
1351 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1353 nWalletUnlockTime = 0;
1358 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1360 if (nWalletUnlockTime < nMyWakeTime)
1361 nWalletUnlockTime = nMyWakeTime;
1367 pwalletMain->Lock();
1372 Value walletpassphrase(const Array& params, bool fHelp)
1374 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1375 throw runtime_error(
1376 "walletpassphrase <passphrase> <timeout>\n"
1377 "Stores the wallet decryption key in memory for <timeout> seconds.");
1380 if (!pwalletMain->IsCrypted())
1381 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1383 if (!pwalletMain->IsLocked())
1384 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1386 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1387 string strWalletPass;
1388 strWalletPass.reserve(100);
1389 mlock(&strWalletPass[0], strWalletPass.capacity());
1390 strWalletPass = params[0].get_str();
1392 if (strWalletPass.length() > 0)
1394 if (!pwalletMain->Unlock(strWalletPass))
1396 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1397 munlock(&strWalletPass[0], strWalletPass.capacity());
1398 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1400 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1401 munlock(&strWalletPass[0], strWalletPass.capacity());
1404 throw runtime_error(
1405 "walletpassphrase <passphrase> <timeout>\n"
1406 "Stores the wallet decryption key in memory for <timeout> seconds.");
1408 CreateThread(ThreadTopUpKeyPool, NULL);
1409 int* pnSleepTime = new int(params[1].get_int());
1410 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1416 Value walletpassphrasechange(const Array& params, bool fHelp)
1418 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1419 throw runtime_error(
1420 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1421 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1424 if (!pwalletMain->IsCrypted())
1425 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1427 string strOldWalletPass;
1428 strOldWalletPass.reserve(100);
1429 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1430 strOldWalletPass = params[0].get_str();
1432 string strNewWalletPass;
1433 strNewWalletPass.reserve(100);
1434 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1435 strNewWalletPass = params[1].get_str();
1437 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1438 throw runtime_error(
1439 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1440 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1442 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1444 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1445 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1446 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1447 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1448 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1450 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1451 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1452 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1453 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1459 Value walletlock(const Array& params, bool fHelp)
1461 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1462 throw runtime_error(
1464 "Removes the wallet encryption key from memory, locking the wallet.\n"
1465 "After calling this method, you will need to call walletpassphrase again\n"
1466 "before being able to call any methods which require the wallet to be unlocked.");
1469 if (!pwalletMain->IsCrypted())
1470 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1472 pwalletMain->Lock();
1473 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1475 nWalletUnlockTime = 0;
1482 Value encryptwallet(const Array& params, bool fHelp)
1484 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1485 throw runtime_error(
1486 "encryptwallet <passphrase>\n"
1487 "Encrypts the wallet with <passphrase>.");
1490 if (pwalletMain->IsCrypted())
1491 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1493 string strWalletPass;
1494 strWalletPass.reserve(100);
1495 mlock(&strWalletPass[0], strWalletPass.capacity());
1496 strWalletPass = params[0].get_str();
1498 if (strWalletPass.length() < 1)
1499 throw runtime_error(
1500 "encryptwallet <passphrase>\n"
1501 "Encrypts the wallet with <passphrase>.");
1503 if (!pwalletMain->EncryptWallet(strWalletPass))
1505 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1506 munlock(&strWalletPass[0], strWalletPass.capacity());
1507 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1509 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1510 munlock(&strWalletPass[0], strWalletPass.capacity());
1516 Value validateaddress(const Array& params, bool fHelp)
1518 if (fHelp || params.size() != 1)
1519 throw runtime_error(
1520 "validateaddress <bitcoinaddress>\n"
1521 "Return information about <bitcoinaddress>.");
1523 CBitcoinAddress address(params[0].get_str());
1524 bool isValid = address.IsValid();
1527 ret.push_back(Pair("isvalid", isValid));
1530 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1531 // version of the address:
1532 string currentAddress = address.ToString();
1533 ret.push_back(Pair("address", currentAddress));
1534 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1535 if (pwalletMain->mapAddressBook.count(address))
1536 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1542 Value getwork(const Array& params, bool fHelp)
1544 if (fHelp || params.size() > 1)
1545 throw runtime_error(
1547 "If [data] is not specified, returns formatted hash data to work on:\n"
1548 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1549 " \"data\" : block data\n"
1550 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1551 " \"target\" : little endian hash target\n"
1552 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1555 throw JSONRPCError(-9, "Bitcoin is not connected!");
1557 if (IsInitialBlockDownload())
1558 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1560 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1561 static mapNewBlock_t mapNewBlock;
1562 static vector<CBlock*> vNewBlock;
1563 static CReserveKey reservekey(pwalletMain);
1565 if (params.size() == 0)
1568 static unsigned int nTransactionsUpdatedLast;
1569 static CBlockIndex* pindexPrev;
1570 static int64 nStart;
1571 static CBlock* pblock;
1572 if (pindexPrev != pindexBest ||
1573 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1575 if (pindexPrev != pindexBest)
1577 // Deallocate old blocks since they're obsolete now
1578 mapNewBlock.clear();
1579 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1583 nTransactionsUpdatedLast = nTransactionsUpdated;
1584 pindexPrev = pindexBest;
1588 pblock = CreateNewBlock(reservekey);
1590 throw JSONRPCError(-7, "Out of memory");
1591 vNewBlock.push_back(pblock);
1595 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1598 // Update nExtraNonce
1599 static unsigned int nExtraNonce = 0;
1600 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1603 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1605 // Prebuild hash buffers
1609 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1611 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1614 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1615 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1616 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1617 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1623 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1624 if (vchData.size() != 128)
1625 throw JSONRPCError(-8, "Invalid parameter");
1626 CBlock* pdata = (CBlock*)&vchData[0];
1629 for (int i = 0; i < 128/4; i++)
1630 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1633 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1635 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1637 pblock->nTime = pdata->nTime;
1638 pblock->nNonce = pdata->nNonce;
1639 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1640 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1642 return CheckWork(pblock, *pwalletMain, reservekey);
1647 Value getmemorypool(const Array& params, bool fHelp)
1649 if (fHelp || params.size() > 1)
1650 throw runtime_error(
1651 "getmemorypool [data]\n"
1652 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1653 " \"version\" : block version\n"
1654 " \"previousblockhash\" : hash of current highest block\n"
1655 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1656 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1657 " \"time\" : timestamp appropriate for next block\n"
1658 " \"bits\" : compressed target of next block\n"
1659 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1661 if (params.size() == 0)
1664 throw JSONRPCError(-9, "Bitcoin is not connected!");
1666 if (IsInitialBlockDownload())
1667 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1669 static CReserveKey reservekey(pwalletMain);
1672 static unsigned int nTransactionsUpdatedLast;
1673 static CBlockIndex* pindexPrev;
1674 static int64 nStart;
1675 static CBlock* pblock;
1676 if (pindexPrev != pindexBest ||
1677 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1679 nTransactionsUpdatedLast = nTransactionsUpdated;
1680 pindexPrev = pindexBest;
1686 pblock = CreateNewBlock(reservekey);
1688 throw JSONRPCError(-7, "Out of memory");
1692 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1696 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1703 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1707 result.push_back(Pair("version", pblock->nVersion));
1708 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1709 result.push_back(Pair("transactions", transactions));
1710 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1711 result.push_back(Pair("time", (int64_t)pblock->nTime));
1712 result.push_back(Pair("bits", (int64_t)pblock->nBits));
1718 CDataStream ssBlock(ParseHex(params[0].get_str()));
1722 return ProcessBlock(NULL, &pblock);
1740 pair<string, rpcfn_type> pCallTable[] =
1742 make_pair("help", &help),
1743 make_pair("stop", &stop),
1744 make_pair("getblockcount", &getblockcount),
1745 make_pair("getblocknumber", &getblocknumber),
1746 make_pair("getconnectioncount", &getconnectioncount),
1747 make_pair("getdifficulty", &getdifficulty),
1748 make_pair("getgenerate", &getgenerate),
1749 make_pair("setgenerate", &setgenerate),
1750 make_pair("gethashespersec", &gethashespersec),
1751 make_pair("getinfo", &getinfo),
1752 make_pair("getnewaddress", &getnewaddress),
1753 make_pair("getaccountaddress", &getaccountaddress),
1754 make_pair("setaccount", &setaccount),
1755 make_pair("getaccount", &getaccount),
1756 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1757 make_pair("sendtoaddress", &sendtoaddress),
1758 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1759 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1760 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1761 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1762 make_pair("backupwallet", &backupwallet),
1763 make_pair("keypoolrefill", &keypoolrefill),
1764 make_pair("walletpassphrase", &walletpassphrase),
1765 make_pair("walletpassphrasechange", &walletpassphrasechange),
1766 make_pair("walletlock", &walletlock),
1767 make_pair("encryptwallet", &encryptwallet),
1768 make_pair("validateaddress", &validateaddress),
1769 make_pair("getbalance", &getbalance),
1770 make_pair("move", &movecmd),
1771 make_pair("sendfrom", &sendfrom),
1772 make_pair("sendmany", &sendmany),
1773 make_pair("gettransaction", &gettransaction),
1774 make_pair("listtransactions", &listtransactions),
1775 make_pair("signmessage", &signmessage),
1776 make_pair("verifymessage", &verifymessage),
1777 make_pair("getwork", &getwork),
1778 make_pair("listaccounts", &listaccounts),
1779 make_pair("settxfee", &settxfee),
1780 make_pair("getmemorypool", &getmemorypool),
1782 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1784 string pAllowInSafeMode[] =
1790 "getconnectioncount",
1797 "getaccountaddress",
1799 "getaddressesbyaccount",
1808 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1816 // This ain't Apache. We're just using HTTP header for the length field
1817 // and to be compatible with other JSON-RPC implementations.
1820 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1823 s << "POST / HTTP/1.1\r\n"
1824 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1825 << "Host: 127.0.0.1\r\n"
1826 << "Content-Type: application/json\r\n"
1827 << "Content-Length: " << strMsg.size() << "\r\n"
1828 << "Connection: close\r\n"
1829 << "Accept: application/json\r\n";
1830 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1831 s << item.first << ": " << item.second << "\r\n";
1832 s << "\r\n" << strMsg;
1837 string rfc1123Time()
1842 struct tm* now_gmt = gmtime(&now);
1843 string locale(setlocale(LC_TIME, NULL));
1844 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1845 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1846 setlocale(LC_TIME, locale.c_str());
1847 return string(buffer);
1850 static string HTTPReply(int nStatus, const string& strMsg)
1853 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1855 "Server: bitcoin-json-rpc/%s\r\n"
1856 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1857 "Content-Type: text/html\r\n"
1858 "Content-Length: 296\r\n"
1860 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1861 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1864 "<TITLE>Error</TITLE>\r\n"
1865 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1867 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1868 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1870 if (nStatus == 200) strStatus = "OK";
1871 else if (nStatus == 400) strStatus = "Bad Request";
1872 else if (nStatus == 403) strStatus = "Forbidden";
1873 else if (nStatus == 404) strStatus = "Not Found";
1874 else if (nStatus == 500) strStatus = "Internal Server Error";
1876 "HTTP/1.1 %d %s\r\n"
1878 "Connection: close\r\n"
1879 "Content-Length: %d\r\n"
1880 "Content-Type: application/json\r\n"
1881 "Server: bitcoin-json-rpc/%s\r\n"
1886 rfc1123Time().c_str(),
1888 FormatFullVersion().c_str(),
1892 int ReadHTTPStatus(std::basic_istream<char>& stream)
1895 getline(stream, str);
1896 vector<string> vWords;
1897 boost::split(vWords, str, boost::is_any_of(" "));
1898 if (vWords.size() < 2)
1900 return atoi(vWords[1].c_str());
1903 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1909 std::getline(stream, str);
1910 if (str.empty() || str == "\r")
1912 string::size_type nColon = str.find(":");
1913 if (nColon != string::npos)
1915 string strHeader = str.substr(0, nColon);
1916 boost::trim(strHeader);
1917 boost::to_lower(strHeader);
1918 string strValue = str.substr(nColon+1);
1919 boost::trim(strValue);
1920 mapHeadersRet[strHeader] = strValue;
1921 if (strHeader == "content-length")
1922 nLen = atoi(strValue.c_str());
1928 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1930 mapHeadersRet.clear();
1934 int nStatus = ReadHTTPStatus(stream);
1937 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1938 if (nLen < 0 || nLen > MAX_SIZE)
1944 vector<char> vch(nLen);
1945 stream.read(&vch[0], nLen);
1946 strMessageRet = string(vch.begin(), vch.end());
1952 bool HTTPAuthorized(map<string, string>& mapHeaders)
1954 string strAuth = mapHeaders["authorization"];
1955 if (strAuth.substr(0,6) != "Basic ")
1957 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1958 string strUserPass = DecodeBase64(strUserPass64);
1959 string::size_type nColon = strUserPass.find(":");
1960 if (nColon == string::npos)
1962 string strUser = strUserPass.substr(0, nColon);
1963 string strPassword = strUserPass.substr(nColon+1);
1964 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1968 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1969 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1970 // unspecified (HTTP errors and contents of 'error').
1972 // 1.0 spec: http://json-rpc.org/wiki/specification
1973 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1974 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1977 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1980 request.push_back(Pair("method", strMethod));
1981 request.push_back(Pair("params", params));
1982 request.push_back(Pair("id", id));
1983 return write_string(Value(request), false) + "\n";
1986 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1989 if (error.type() != null_type)
1990 reply.push_back(Pair("result", Value::null));
1992 reply.push_back(Pair("result", result));
1993 reply.push_back(Pair("error", error));
1994 reply.push_back(Pair("id", id));
1995 return write_string(Value(reply), false) + "\n";
1998 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2000 // Send error reply from json-rpc error object
2002 int code = find_value(objError, "code").get_int();
2003 if (code == -32600) nStatus = 400;
2004 else if (code == -32601) nStatus = 404;
2005 string strReply = JSONRPCReply(Value::null, objError, id);
2006 stream << HTTPReply(nStatus, strReply) << std::flush;
2009 bool ClientAllowed(const string& strAddress)
2011 if (strAddress == asio::ip::address_v4::loopback().to_string())
2013 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2014 BOOST_FOREACH(string strAllow, vAllow)
2015 if (WildcardMatch(strAddress, strAllow))
2022 // IOStream device that speaks SSL but can also speak non-SSL
2024 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2026 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2028 fUseSSL = fUseSSLIn;
2029 fNeedHandshake = fUseSSLIn;
2032 void handshake(ssl::stream_base::handshake_type role)
2034 if (!fNeedHandshake) return;
2035 fNeedHandshake = false;
2036 stream.handshake(role);
2038 std::streamsize read(char* s, std::streamsize n)
2040 handshake(ssl::stream_base::server); // HTTPS servers read first
2041 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2042 return stream.next_layer().read_some(asio::buffer(s, n));
2044 std::streamsize write(const char* s, std::streamsize n)
2046 handshake(ssl::stream_base::client); // HTTPS clients write first
2047 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2048 return asio::write(stream.next_layer(), asio::buffer(s, n));
2050 bool connect(const std::string& server, const std::string& port)
2052 ip::tcp::resolver resolver(stream.get_io_service());
2053 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2054 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2055 ip::tcp::resolver::iterator end;
2056 boost::system::error_code error = asio::error::host_not_found;
2057 while (error && endpoint_iterator != end)
2059 stream.lowest_layer().close();
2060 stream.lowest_layer().connect(*endpoint_iterator++, error);
2068 bool fNeedHandshake;
2074 void ThreadRPCServer(void* parg)
2076 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2079 vnThreadsRunning[4]++;
2080 ThreadRPCServer2(parg);
2081 vnThreadsRunning[4]--;
2083 catch (std::exception& e) {
2084 vnThreadsRunning[4]--;
2085 PrintException(&e, "ThreadRPCServer()");
2087 vnThreadsRunning[4]--;
2088 PrintException(NULL, "ThreadRPCServer()");
2090 printf("ThreadRPCServer exiting\n");
2093 void ThreadRPCServer2(void* parg)
2095 printf("ThreadRPCServer started\n");
2097 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2099 string strWhatAmI = "To use bitcoind";
2100 if (mapArgs.count("-server"))
2101 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2102 else if (mapArgs.count("-daemon"))
2103 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2105 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2106 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2108 GetConfigFile().c_str());
2109 CreateThread(Shutdown, NULL);
2113 bool fUseSSL = GetBoolArg("-rpcssl");
2114 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2116 asio::io_service io_service;
2117 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2118 ip::tcp::acceptor acceptor(io_service, endpoint);
2120 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2123 ssl::context context(io_service, ssl::context::sslv23);
2126 context.set_options(ssl::context::no_sslv2);
2127 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2128 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2129 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2130 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2131 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2132 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2133 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2134 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2136 string ciphers = GetArg("-rpcsslciphers",
2137 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2138 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2142 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2147 // Accept connection
2149 SSLStream sslStream(io_service, context);
2150 SSLIOStreamDevice d(sslStream, fUseSSL);
2151 iostreams::stream<SSLIOStreamDevice> stream(d);
2153 ip::tcp::iostream stream;
2156 ip::tcp::endpoint peer;
2157 vnThreadsRunning[4]--;
2159 acceptor.accept(sslStream.lowest_layer(), peer);
2161 acceptor.accept(*stream.rdbuf(), peer);
2163 vnThreadsRunning[4]++;
2167 // Restrict callers by IP
2168 if (!ClientAllowed(peer.address().to_string()))
2170 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2172 stream << HTTPReply(403, "") << std::flush;
2176 map<string, string> mapHeaders;
2179 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2180 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2183 printf("ThreadRPCServer ReadHTTP timeout\n");
2187 // Check authorization
2188 if (mapHeaders.count("authorization") == 0)
2190 stream << HTTPReply(401, "") << std::flush;
2193 if (!HTTPAuthorized(mapHeaders))
2195 // Deter brute-forcing short passwords
2196 if (mapArgs["-rpcpassword"].size() < 15)
2199 stream << HTTPReply(401, "") << std::flush;
2200 printf("ThreadRPCServer incorrect password attempt\n");
2204 Value id = Value::null;
2209 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2210 throw JSONRPCError(-32700, "Parse error");
2211 const Object& request = valRequest.get_obj();
2213 // Parse id now so errors from here on will have the id
2214 id = find_value(request, "id");
2217 Value valMethod = find_value(request, "method");
2218 if (valMethod.type() == null_type)
2219 throw JSONRPCError(-32600, "Missing method");
2220 if (valMethod.type() != str_type)
2221 throw JSONRPCError(-32600, "Method must be a string");
2222 string strMethod = valMethod.get_str();
2223 if (strMethod != "getwork" && strMethod != "getmemorypool")
2224 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2227 Value valParams = find_value(request, "params");
2229 if (valParams.type() == array_type)
2230 params = valParams.get_array();
2231 else if (valParams.type() == null_type)
2234 throw JSONRPCError(-32600, "Params must be an array");
2237 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2238 if (mi == mapCallTable.end())
2239 throw JSONRPCError(-32601, "Method not found");
2241 // Observe safe mode
2242 string strWarning = GetWarnings("rpc");
2243 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2244 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2250 CRITICAL_BLOCK(cs_main)
2251 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2252 result = (*(*mi).second)(params, false);
2255 string strReply = JSONRPCReply(result, Value::null, id);
2256 stream << HTTPReply(200, strReply) << std::flush;
2258 catch (std::exception& e)
2260 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2263 catch (Object& objError)
2265 ErrorReply(stream, objError, id);
2267 catch (std::exception& e)
2269 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2277 Object CallRPC(const string& strMethod, const Array& params)
2279 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2280 throw runtime_error(strprintf(
2281 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2282 "If the file does not exist, create it with owner-readable-only file permissions."),
2283 GetConfigFile().c_str()));
2285 // Connect to localhost
2286 bool fUseSSL = GetBoolArg("-rpcssl");
2288 asio::io_service io_service;
2289 ssl::context context(io_service, ssl::context::sslv23);
2290 context.set_options(ssl::context::no_sslv2);
2291 SSLStream sslStream(io_service, context);
2292 SSLIOStreamDevice d(sslStream, fUseSSL);
2293 iostreams::stream<SSLIOStreamDevice> stream(d);
2294 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2295 throw runtime_error("couldn't connect to server");
2298 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2300 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2302 throw runtime_error("couldn't connect to server");
2306 // HTTP basic authentication
2307 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2308 map<string, string> mapRequestHeaders;
2309 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2312 string strRequest = JSONRPCRequest(strMethod, params, 1);
2313 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2314 stream << strPost << std::flush;
2317 map<string, string> mapHeaders;
2319 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2321 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2322 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2323 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2324 else if (strReply.empty())
2325 throw runtime_error("no response from server");
2329 if (!read_string(strReply, valReply))
2330 throw runtime_error("couldn't parse reply from server");
2331 const Object& reply = valReply.get_obj();
2333 throw runtime_error("expected reply to have result, error and id properties");
2341 template<typename T>
2342 void ConvertTo(Value& value)
2344 if (value.type() == str_type)
2346 // reinterpret string as unquoted json value
2348 if (!read_string(value.get_str(), value2))
2349 throw runtime_error("type mismatch");
2350 value = value2.get_value<T>();
2354 value = value.get_value<T>();
2358 int CommandLineRPC(int argc, char *argv[])
2365 while (argc > 1 && IsSwitchChar(argv[1][0]))
2373 throw runtime_error("too few parameters");
2374 string strMethod = argv[1];
2376 // Parameters default to strings
2378 for (int i = 2; i < argc; i++)
2379 params.push_back(argv[i]);
2380 int n = params.size();
2383 // Special case non-string parameter types
2385 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2386 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2387 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2388 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2389 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2390 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2391 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2392 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2393 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2394 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2395 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2396 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2397 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2398 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2399 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2400 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2401 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2402 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2403 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2404 if (strMethod == "sendmany" && n > 1)
2406 string s = params[1].get_str();
2408 if (!read_string(s, v) || v.type() != obj_type)
2409 throw runtime_error("type mismatch");
2410 params[1] = v.get_obj();
2412 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2415 Object reply = CallRPC(strMethod, params);
2418 const Value& result = find_value(reply, "result");
2419 const Value& error = find_value(reply, "error");
2421 if (error.type() != null_type)
2424 strPrint = "error: " + write_string(error, false);
2425 int code = find_value(error.get_obj(), "code").get_int();
2431 if (result.type() == null_type)
2433 else if (result.type() == str_type)
2434 strPrint = result.get_str();
2436 strPrint = write_string(result, true);
2439 catch (std::exception& e)
2441 strPrint = string("error: ") + e.what();
2446 PrintException(NULL, "CommandLineRPC()");
2451 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2460 int main(int argc, char *argv[])
2463 // Turn off microsoft heap dump noise
2464 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2465 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2467 setbuf(stdin, NULL);
2468 setbuf(stdout, NULL);
2469 setbuf(stderr, NULL);
2473 if (argc >= 2 && string(argv[1]) == "-server")
2475 printf("server ready\n");
2476 ThreadRPCServer(NULL);
2480 return CommandLineRPC(argc, argv);
2483 catch (std::exception& e) {
2484 PrintException(&e, "main()");
2486 PrintException(NULL, "main()");