1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/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 std::string strRPCUserColonPass;
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
45 Object JSONRPCError(int code, const string& message)
48 error.push_back(Pair("code", code));
49 error.push_back(Pair("message", message));
54 void PrintConsole(const std::string &format, ...)
57 int limit = sizeof(buffer);
59 va_start(arg_ptr, format);
60 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
62 if (ret < 0 || ret >= limit)
68 fprintf(stdout, "%s", buffer);
72 int64 AmountFromValue(const Value& value)
74 double dAmount = value.get_real();
75 if (dAmount <= 0.0 || dAmount > 21000000.0)
76 throw JSONRPCError(-3, "Invalid amount");
77 int64 nAmount = roundint64(dAmount * COIN);
78 if (!MoneyRange(nAmount))
79 throw JSONRPCError(-3, "Invalid amount");
83 Value ValueFromAmount(int64 amount)
85 return (double)amount / (double)COIN;
88 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
90 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
91 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
92 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
93 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
94 entry.push_back(Pair(item.first, item.second));
97 string AccountFromValue(const Value& value)
99 string strAccount = value.get_str();
100 if (strAccount == "*")
101 throw JSONRPCError(-11, "Invalid account name");
108 /// Note: This interface may still be subject to change.
112 Value help(const Array& params, bool fHelp)
114 if (fHelp || params.size() > 1)
117 "List commands, or get help for a command.");
120 if (params.size() > 0)
121 strCommand = params[0].get_str();
124 set<rpcfn_type> setDone;
125 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
127 string strMethod = (*mi).first;
128 // We already filter duplicates, but these deprecated screw up the sort order
129 if (strMethod == "getamountreceived" ||
130 strMethod == "getallreceived" ||
131 strMethod == "getblocknumber" || // deprecated
132 (strMethod.find("label") != string::npos))
134 if (strCommand != "" && strMethod != strCommand)
139 rpcfn_type pfn = (*mi).second;
140 if (setDone.insert(pfn).second)
141 (*pfn)(params, true);
143 catch (std::exception& e)
145 // Help text is returned in an exception
146 string strHelp = string(e.what());
147 if (strCommand == "")
148 if (strHelp.find('\n') != -1)
149 strHelp = strHelp.substr(0, strHelp.find('\n'));
150 strRet += strHelp + "\n";
154 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
155 strRet = strRet.substr(0,strRet.size()-1);
160 Value stop(const Array& params, bool fHelp)
162 if (fHelp || params.size() != 0)
165 "Stop bitcoin server.");
167 // Shutdown will take long enough that the response should get back
168 CreateThread(Shutdown, NULL);
169 return "bitcoin server stopping";
171 throw runtime_error("NYI: cannot shut down GUI with RPC command");
176 Value getblockcount(const Array& params, bool fHelp)
178 if (fHelp || params.size() != 0)
181 "Returns the number of blocks in the longest block chain.");
188 Value getblocknumber(const Array& params, bool fHelp)
190 if (fHelp || params.size() != 0)
193 "Deprecated. Use getblockcount.");
199 Value getconnectioncount(const Array& params, bool fHelp)
201 if (fHelp || params.size() != 0)
203 "getconnectioncount\n"
204 "Returns the number of connections to other nodes.");
206 return (int)vNodes.size();
210 double GetDifficulty()
212 // Floating point number that is a multiple of the minimum difficulty,
213 // minimum difficulty = 1.0.
215 if (pindexBest == NULL)
217 int nShift = (pindexBest->nBits >> 24) & 0xff;
220 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
236 Value getdifficulty(const Array& params, bool fHelp)
238 if (fHelp || params.size() != 0)
241 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
243 return GetDifficulty();
247 Value getgenerate(const Array& params, bool fHelp)
249 if (fHelp || params.size() != 0)
252 "Returns true or false.");
254 return (bool)fGenerateBitcoins;
258 Value setgenerate(const Array& params, bool fHelp)
260 if (fHelp || params.size() < 1 || params.size() > 2)
262 "setgenerate <generate> [genproclimit]\n"
263 "<generate> is true or false to turn generation on or off.\n"
264 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
266 bool fGenerate = true;
267 if (params.size() > 0)
268 fGenerate = params[0].get_bool();
270 if (params.size() > 1)
272 int nGenProcLimit = params[1].get_int();
273 fLimitProcessors = (nGenProcLimit != -1);
274 WriteSetting("fLimitProcessors", fLimitProcessors);
275 if (nGenProcLimit != -1)
276 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
277 if (nGenProcLimit == 0)
281 GenerateBitcoins(fGenerate, pwalletMain);
286 Value gethashespersec(const Array& params, bool fHelp)
288 if (fHelp || params.size() != 0)
291 "Returns a recent hashes per second performance measurement while generating.");
293 if (GetTimeMillis() - nHPSTimerStart > 8000)
294 return (boost::int64_t)0;
295 return (boost::int64_t)dHashesPerSec;
299 Value getinfo(const Array& params, bool fHelp)
301 if (fHelp || params.size() != 0)
304 "Returns an object containing various state info.");
307 obj.push_back(Pair("version", (int)VERSION));
308 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
309 obj.push_back(Pair("blocks", (int)nBestHeight));
310 obj.push_back(Pair("connections", (int)vNodes.size()));
311 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
312 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
313 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
314 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
315 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
316 obj.push_back(Pair("testnet", fTestNet));
317 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
318 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
319 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
320 if (pwalletMain->IsCrypted())
321 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
322 obj.push_back(Pair("errors", GetWarnings("statusbar")));
327 Value getnewaddress(const Array& params, bool fHelp)
329 if (fHelp || params.size() > 1)
331 "getnewaddress [account]\n"
332 "Returns a new bitcoin address for receiving payments. "
333 "If [account] is specified (recommended), it is added to the address book "
334 "so payments received with the address will be credited to [account].");
336 // Parse the account first so we don't generate a key if there's an error
338 if (params.size() > 0)
339 strAccount = AccountFromValue(params[0]);
341 if (!pwalletMain->IsLocked())
342 pwalletMain->TopUpKeyPool();
344 // Generate a new key that is added to wallet
345 std::vector<unsigned char> newKey;
346 if (!pwalletMain->GetKeyFromPool(newKey, false))
347 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
348 CBitcoinAddress address(newKey);
350 pwalletMain->SetAddressBookName(address, strAccount);
352 return address.ToString();
356 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
358 CWalletDB walletdb(pwalletMain->strWalletFile);
361 walletdb.ReadAccount(strAccount, account);
363 bool bKeyUsed = false;
365 // Check if the current key has been used
366 if (!account.vchPubKey.empty())
368 CScript scriptPubKey;
369 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
370 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
371 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
374 const CWalletTx& wtx = (*it).second;
375 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
376 if (txout.scriptPubKey == scriptPubKey)
381 // Generate a new key
382 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
384 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
385 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
387 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
388 walletdb.WriteAccount(strAccount, account);
391 return CBitcoinAddress(account.vchPubKey);
394 Value getaccountaddress(const Array& params, bool fHelp)
396 if (fHelp || params.size() != 1)
398 "getaccountaddress <account>\n"
399 "Returns the current bitcoin address for receiving payments to this account.");
401 // Parse the account first so we don't generate a key if there's an error
402 string strAccount = AccountFromValue(params[0]);
406 ret = GetAccountAddress(strAccount).ToString();
413 Value setaccount(const Array& params, bool fHelp)
415 if (fHelp || params.size() < 1 || params.size() > 2)
417 "setaccount <bitcoinaddress> <account>\n"
418 "Sets the account associated with the given address.");
420 CBitcoinAddress address(params[0].get_str());
421 if (!address.IsValid())
422 throw JSONRPCError(-5, "Invalid bitcoin address");
426 if (params.size() > 1)
427 strAccount = AccountFromValue(params[1]);
429 // Detect when changing the account of an address that is the 'unused current key' of another account:
430 if (pwalletMain->mapAddressBook.count(address))
432 string strOldAccount = pwalletMain->mapAddressBook[address];
433 if (address == GetAccountAddress(strOldAccount))
434 GetAccountAddress(strOldAccount, true);
437 pwalletMain->SetAddressBookName(address, strAccount);
443 Value getaccount(const Array& params, bool fHelp)
445 if (fHelp || params.size() != 1)
447 "getaccount <bitcoinaddress>\n"
448 "Returns the account associated with the given address.");
450 CBitcoinAddress address(params[0].get_str());
451 if (!address.IsValid())
452 throw JSONRPCError(-5, "Invalid bitcoin address");
455 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
456 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
457 strAccount = (*mi).second;
462 Value getaddressesbyaccount(const Array& params, bool fHelp)
464 if (fHelp || params.size() != 1)
466 "getaddressesbyaccount <account>\n"
467 "Returns the list of addresses for the given account.");
469 string strAccount = AccountFromValue(params[0]);
471 // Find all addresses that have the given account
473 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
475 const CBitcoinAddress& address = item.first;
476 const string& strName = item.second;
477 if (strName == strAccount)
478 ret.push_back(address.ToString());
483 Value settxfee(const Array& params, bool fHelp)
485 if (fHelp || params.size() < 1 || params.size() > 1)
487 "settxfee <amount>\n"
488 "<amount> is a real and is rounded to the nearest 0.00000001");
492 if (params[0].get_real() != 0.0)
493 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
495 nTransactionFee = nAmount;
499 Value sendtoaddress(const Array& params, bool fHelp)
501 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
503 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
504 "<amount> is a real and is rounded to the nearest 0.00000001\n"
505 "requires wallet passphrase to be set with walletpassphrase first");
506 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
508 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
509 "<amount> is a real and is rounded to the nearest 0.00000001");
511 CBitcoinAddress address(params[0].get_str());
512 if (!address.IsValid())
513 throw JSONRPCError(-5, "Invalid bitcoin address");
516 int64 nAmount = AmountFromValue(params[1]);
520 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
521 wtx.mapValue["comment"] = params[2].get_str();
522 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
523 wtx.mapValue["to"] = params[3].get_str();
525 if (pwalletMain->IsLocked())
526 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
528 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
530 throw JSONRPCError(-4, strError);
532 return wtx.GetHash().GetHex();
535 static const string strMessageMagic = "Bitcoin Signed Message:\n";
537 Value signmessage(const Array& params, bool fHelp)
539 if (fHelp || params.size() != 2)
541 "signmessage <bitcoinaddress> <message>\n"
542 "Sign a message with the private key of an address");
544 if (pwalletMain->IsLocked())
545 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
547 string strAddress = params[0].get_str();
548 string strMessage = params[1].get_str();
550 CBitcoinAddress addr(strAddress);
552 throw JSONRPCError(-3, "Invalid address");
555 if (!pwalletMain->GetKey(addr, key))
556 throw JSONRPCError(-4, "Private key not available");
558 CDataStream ss(SER_GETHASH);
559 ss << strMessageMagic;
562 vector<unsigned char> vchSig;
563 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
564 throw JSONRPCError(-5, "Sign failed");
566 return EncodeBase64(&vchSig[0], vchSig.size());
569 Value verifymessage(const Array& params, bool fHelp)
571 if (fHelp || params.size() != 3)
573 "verifymessage <bitcoinaddress> <signature> <message>\n"
574 "Verify a signed message");
576 string strAddress = params[0].get_str();
577 string strSign = params[1].get_str();
578 string strMessage = params[2].get_str();
580 CBitcoinAddress addr(strAddress);
582 throw JSONRPCError(-3, "Invalid address");
584 bool fInvalid = false;
585 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
588 throw JSONRPCError(-5, "Malformed base64 encoding");
590 CDataStream ss(SER_GETHASH);
591 ss << strMessageMagic;
595 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
598 return (key.GetAddress() == addr);
602 Value getreceivedbyaddress(const Array& params, bool fHelp)
604 if (fHelp || params.size() < 1 || params.size() > 2)
606 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
607 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
610 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
611 CScript scriptPubKey;
612 if (!address.IsValid())
613 throw JSONRPCError(-5, "Invalid bitcoin address");
614 scriptPubKey.SetBitcoinAddress(address);
615 if (!IsMine(*pwalletMain,scriptPubKey))
618 // Minimum confirmations
620 if (params.size() > 1)
621 nMinDepth = params[1].get_int();
625 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
627 const CWalletTx& wtx = (*it).second;
628 if (wtx.IsCoinBase() || !wtx.IsFinal())
631 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
632 if (txout.scriptPubKey == scriptPubKey)
633 if (wtx.GetDepthInMainChain() >= nMinDepth)
634 nAmount += txout.nValue;
637 return ValueFromAmount(nAmount);
641 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
643 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
645 const CBitcoinAddress& address = item.first;
646 const string& strName = item.second;
647 if (strName == strAccount)
648 setAddress.insert(address);
653 Value getreceivedbyaccount(const Array& params, bool fHelp)
655 if (fHelp || params.size() < 1 || params.size() > 2)
657 "getreceivedbyaccount <account> [minconf=1]\n"
658 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
660 // Minimum confirmations
662 if (params.size() > 1)
663 nMinDepth = params[1].get_int();
665 // Get the set of pub keys that have the label
666 string strAccount = AccountFromValue(params[0]);
667 set<CBitcoinAddress> setAddress;
668 GetAccountAddresses(strAccount, setAddress);
672 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
674 const CWalletTx& wtx = (*it).second;
675 if (wtx.IsCoinBase() || !wtx.IsFinal())
678 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
680 CBitcoinAddress address;
681 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
682 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 nAmount += txout.nValue;
687 return (double)nAmount / (double)COIN;
691 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
695 // Tally wallet transactions
696 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
698 const CWalletTx& wtx = (*it).second;
702 int64 nGenerated, nReceived, nSent, nFee;
703 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
705 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
706 nBalance += nReceived;
707 nBalance += nGenerated - nSent - nFee;
710 // Tally internal accounting entries
711 nBalance += walletdb.GetAccountCreditDebit(strAccount);
716 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
718 CWalletDB walletdb(pwalletMain->strWalletFile);
719 return GetAccountBalance(walletdb, strAccount, nMinDepth);
723 Value getbalance(const Array& params, bool fHelp)
725 if (fHelp || params.size() > 2)
727 "getbalance [account] [minconf=1]\n"
728 "If [account] is not specified, returns the server's total available balance.\n"
729 "If [account] is specified, returns the balance in the account.");
731 if (params.size() == 0)
732 return ValueFromAmount(pwalletMain->GetBalance());
735 if (params.size() > 1)
736 nMinDepth = params[1].get_int();
738 if (params[0].get_str() == "*") {
739 // Calculate total balance a different way from GetBalance()
740 // (GetBalance() sums up all unspent TxOuts)
741 // getbalance and getbalance '*' should always return the same number.
743 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
745 const CWalletTx& wtx = (*it).second;
749 int64 allGeneratedImmature, allGeneratedMature, allFee;
750 allGeneratedImmature = allGeneratedMature = allFee = 0;
751 string strSentAccount;
752 list<pair<CBitcoinAddress, int64> > listReceived;
753 list<pair<CBitcoinAddress, int64> > listSent;
754 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
755 if (wtx.GetDepthInMainChain() >= nMinDepth)
756 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
757 nBalance += r.second;
758 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
759 nBalance -= r.second;
761 nBalance += allGeneratedMature;
763 return ValueFromAmount(nBalance);
766 string strAccount = AccountFromValue(params[0]);
768 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
770 return ValueFromAmount(nBalance);
774 Value movecmd(const Array& params, bool fHelp)
776 if (fHelp || params.size() < 3 || params.size() > 5)
778 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
779 "Move from one account in your wallet to another.");
781 string strFrom = AccountFromValue(params[0]);
782 string strTo = AccountFromValue(params[1]);
783 int64 nAmount = AmountFromValue(params[2]);
784 if (params.size() > 3)
785 // unused parameter, used to be nMinDepth, keep type-checking it though
786 (void)params[3].get_int();
788 if (params.size() > 4)
789 strComment = params[4].get_str();
791 CWalletDB walletdb(pwalletMain->strWalletFile);
794 int64 nNow = GetAdjustedTime();
797 CAccountingEntry debit;
798 debit.strAccount = strFrom;
799 debit.nCreditDebit = -nAmount;
801 debit.strOtherAccount = strTo;
802 debit.strComment = strComment;
803 walletdb.WriteAccountingEntry(debit);
806 CAccountingEntry credit;
807 credit.strAccount = strTo;
808 credit.nCreditDebit = nAmount;
810 credit.strOtherAccount = strFrom;
811 credit.strComment = strComment;
812 walletdb.WriteAccountingEntry(credit);
814 walletdb.TxnCommit();
820 Value sendfrom(const Array& params, bool fHelp)
822 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
824 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
825 "<amount> is a real and is rounded to the nearest 0.00000001\n"
826 "requires wallet passphrase to be set with walletpassphrase first");
827 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
829 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
830 "<amount> is a real and is rounded to the nearest 0.00000001");
832 string strAccount = AccountFromValue(params[0]);
833 CBitcoinAddress address(params[1].get_str());
834 if (!address.IsValid())
835 throw JSONRPCError(-5, "Invalid bitcoin address");
836 int64 nAmount = AmountFromValue(params[2]);
838 if (params.size() > 3)
839 nMinDepth = params[3].get_int();
842 wtx.strFromAccount = strAccount;
843 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
844 wtx.mapValue["comment"] = params[4].get_str();
845 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
846 wtx.mapValue["to"] = params[5].get_str();
848 if (pwalletMain->IsLocked())
849 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
852 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
853 if (nAmount > nBalance)
854 throw JSONRPCError(-6, "Account has insufficient funds");
857 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
859 throw JSONRPCError(-4, strError);
861 return wtx.GetHash().GetHex();
865 Value sendmany(const Array& params, bool fHelp)
867 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
869 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
870 "amounts are double-precision floating point numbers\n"
871 "requires wallet passphrase to be set with walletpassphrase first");
872 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
874 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
875 "amounts are double-precision floating point numbers");
877 string strAccount = AccountFromValue(params[0]);
878 Object sendTo = params[1].get_obj();
880 if (params.size() > 2)
881 nMinDepth = params[2].get_int();
884 wtx.strFromAccount = strAccount;
885 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
886 wtx.mapValue["comment"] = params[3].get_str();
888 set<CBitcoinAddress> setAddress;
889 vector<pair<CScript, int64> > vecSend;
891 int64 totalAmount = 0;
892 BOOST_FOREACH(const Pair& s, sendTo)
894 CBitcoinAddress address(s.name_);
895 if (!address.IsValid())
896 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
898 if (setAddress.count(address))
899 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
900 setAddress.insert(address);
902 CScript scriptPubKey;
903 scriptPubKey.SetBitcoinAddress(address);
904 int64 nAmount = AmountFromValue(s.value_);
905 totalAmount += nAmount;
907 vecSend.push_back(make_pair(scriptPubKey, nAmount));
910 if (pwalletMain->IsLocked())
911 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
914 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
915 if (totalAmount > nBalance)
916 throw JSONRPCError(-6, "Account has insufficient funds");
919 CReserveKey keyChange(pwalletMain);
920 int64 nFeeRequired = 0;
921 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
924 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
925 throw JSONRPCError(-6, "Insufficient funds");
926 throw JSONRPCError(-4, "Transaction creation failed");
928 if (!pwalletMain->CommitTransaction(wtx, keyChange))
929 throw JSONRPCError(-4, "Transaction commit failed");
931 return wtx.GetHash().GetHex();
946 Value ListReceived(const Array& params, bool fByAccounts)
948 // Minimum confirmations
950 if (params.size() > 0)
951 nMinDepth = params[0].get_int();
953 // Whether to include empty accounts
954 bool fIncludeEmpty = false;
955 if (params.size() > 1)
956 fIncludeEmpty = params[1].get_bool();
959 map<CBitcoinAddress, tallyitem> mapTally;
960 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
962 const CWalletTx& wtx = (*it).second;
963 if (wtx.IsCoinBase() || !wtx.IsFinal())
966 int nDepth = wtx.GetDepthInMainChain();
967 if (nDepth < nMinDepth)
970 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
972 CBitcoinAddress address;
973 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
976 tallyitem& item = mapTally[address];
977 item.nAmount += txout.nValue;
978 item.nConf = min(item.nConf, nDepth);
984 map<string, tallyitem> mapAccountTally;
985 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
987 const CBitcoinAddress& address = item.first;
988 const string& strAccount = item.second;
989 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
990 if (it == mapTally.end() && !fIncludeEmpty)
995 if (it != mapTally.end())
997 nAmount = (*it).second.nAmount;
998 nConf = (*it).second.nConf;
1003 tallyitem& item = mapAccountTally[strAccount];
1004 item.nAmount += nAmount;
1005 item.nConf = min(item.nConf, nConf);
1010 obj.push_back(Pair("address", address.ToString()));
1011 obj.push_back(Pair("account", strAccount));
1012 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1013 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1020 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1022 int64 nAmount = (*it).second.nAmount;
1023 int nConf = (*it).second.nConf;
1025 obj.push_back(Pair("account", (*it).first));
1026 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1027 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1035 Value listreceivedbyaddress(const Array& params, bool fHelp)
1037 if (fHelp || params.size() > 2)
1038 throw runtime_error(
1039 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1040 "[minconf] is the minimum number of confirmations before payments are included.\n"
1041 "[includeempty] whether to include addresses that haven't received any payments.\n"
1042 "Returns an array of objects containing:\n"
1043 " \"address\" : receiving address\n"
1044 " \"account\" : the account of the receiving address\n"
1045 " \"amount\" : total amount received by the address\n"
1046 " \"confirmations\" : number of confirmations of the most recent transaction included");
1048 return ListReceived(params, false);
1051 Value listreceivedbyaccount(const Array& params, bool fHelp)
1053 if (fHelp || params.size() > 2)
1054 throw runtime_error(
1055 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1056 "[minconf] is the minimum number of confirmations before payments are included.\n"
1057 "[includeempty] whether to include accounts that haven't received any payments.\n"
1058 "Returns an array of objects containing:\n"
1059 " \"account\" : the account of the receiving addresses\n"
1060 " \"amount\" : total amount received by addresses with this account\n"
1061 " \"confirmations\" : number of confirmations of the most recent transaction included");
1063 return ListReceived(params, true);
1066 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1068 int64 nGeneratedImmature, nGeneratedMature, nFee;
1069 string strSentAccount;
1070 list<pair<CBitcoinAddress, int64> > listReceived;
1071 list<pair<CBitcoinAddress, int64> > listSent;
1072 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1074 bool fAllAccounts = (strAccount == string("*"));
1076 // Generated blocks assigned to account ""
1077 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1080 entry.push_back(Pair("account", string("")));
1081 if (nGeneratedImmature)
1083 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1084 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1088 entry.push_back(Pair("category", "generate"));
1089 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1092 WalletTxToJSON(wtx, entry);
1093 ret.push_back(entry);
1097 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1099 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1102 entry.push_back(Pair("account", strSentAccount));
1103 entry.push_back(Pair("address", s.first.ToString()));
1104 entry.push_back(Pair("category", "send"));
1105 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1106 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1108 WalletTxToJSON(wtx, entry);
1109 ret.push_back(entry);
1114 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1115 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1118 if (pwalletMain->mapAddressBook.count(r.first))
1119 account = pwalletMain->mapAddressBook[r.first];
1120 if (fAllAccounts || (account == strAccount))
1123 entry.push_back(Pair("account", account));
1124 entry.push_back(Pair("address", r.first.ToString()));
1125 entry.push_back(Pair("category", "receive"));
1126 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1128 WalletTxToJSON(wtx, entry);
1129 ret.push_back(entry);
1134 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1136 bool fAllAccounts = (strAccount == string("*"));
1138 if (fAllAccounts || acentry.strAccount == strAccount)
1141 entry.push_back(Pair("account", acentry.strAccount));
1142 entry.push_back(Pair("category", "move"));
1143 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1144 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1145 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1146 entry.push_back(Pair("comment", acentry.strComment));
1147 ret.push_back(entry);
1151 Value listtransactions(const Array& params, bool fHelp)
1153 if (fHelp || params.size() > 3)
1154 throw runtime_error(
1155 "listtransactions [account] [count=10] [from=0]\n"
1156 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1158 string strAccount = "*";
1159 if (params.size() > 0)
1160 strAccount = params[0].get_str();
1162 if (params.size() > 1)
1163 nCount = params[1].get_int();
1165 if (params.size() > 2)
1166 nFrom = params[2].get_int();
1169 CWalletDB walletdb(pwalletMain->strWalletFile);
1171 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1172 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1173 typedef multimap<int64, TxPair > TxItems;
1176 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1178 CWalletTx* wtx = &((*it).second);
1179 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1181 list<CAccountingEntry> acentries;
1182 walletdb.ListAccountCreditDebit(strAccount, acentries);
1183 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1185 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1188 // Now: iterate backwards until we have nCount items to return:
1189 TxItems::reverse_iterator it = txByTime.rbegin();
1190 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1191 for (; it != txByTime.rend(); ++it)
1193 CWalletTx *const pwtx = (*it).second.first;
1195 ListTransactions(*pwtx, strAccount, 0, true, ret);
1196 CAccountingEntry *const pacentry = (*it).second.second;
1198 AcentryToJSON(*pacentry, strAccount, ret);
1200 if (ret.size() >= nCount) break;
1202 // ret is now newest to oldest
1204 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1205 if (ret.size() > nCount)
1207 Array::iterator last = ret.begin();
1208 std::advance(last, nCount);
1209 ret.erase(last, ret.end());
1211 std::reverse(ret.begin(), ret.end()); // oldest to newest
1216 Value listaccounts(const Array& params, bool fHelp)
1218 if (fHelp || params.size() > 1)
1219 throw runtime_error(
1220 "listaccounts [minconf=1]\n"
1221 "Returns Object that has account names as keys, account balances as values.");
1224 if (params.size() > 0)
1225 nMinDepth = params[0].get_int();
1227 map<string, int64> mapAccountBalances;
1228 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1229 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1230 mapAccountBalances[entry.second] = 0;
1233 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1235 const CWalletTx& wtx = (*it).second;
1236 int64 nGeneratedImmature, nGeneratedMature, nFee;
1237 string strSentAccount;
1238 list<pair<CBitcoinAddress, int64> > listReceived;
1239 list<pair<CBitcoinAddress, int64> > listSent;
1240 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1241 mapAccountBalances[strSentAccount] -= nFee;
1242 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1243 mapAccountBalances[strSentAccount] -= s.second;
1244 if (wtx.GetDepthInMainChain() >= nMinDepth)
1246 mapAccountBalances[""] += nGeneratedMature;
1247 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1248 if (pwalletMain->mapAddressBook.count(r.first))
1249 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1251 mapAccountBalances[""] += r.second;
1255 list<CAccountingEntry> acentries;
1256 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1257 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1258 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1261 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1262 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1267 Value listsinceblock(const Array& params, bool fHelp)
1270 throw runtime_error(
1271 "listsinceblock [blockid] [target-confirmations]\n"
1272 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1274 CBlockIndex *pindex = NULL;
1275 int target_confirms = 1;
1277 if (params.size() > 0)
1279 uint256 blockId = 0;
1281 blockId.SetHex(params[0].get_str());
1282 pindex = CBlockLocator(blockId).GetBlockIndex();
1285 if (params.size() > 1)
1287 target_confirms = params[1].get_int();
1289 if (target_confirms < 1)
1290 throw JSONRPCError(-8, "Invalid parameter");
1293 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1297 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1299 CWalletTx tx = (*it).second;
1301 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1302 ListTransactions(tx, "*", 0, true, transactions);
1307 if (target_confirms == 1)
1310 lastblock = hashBestChain;
1314 int target_height = pindexBest->nHeight + 1 - target_confirms;
1317 for (block = pindexBest;
1318 block && block->nHeight > target_height;
1319 block = block->pprev) { }
1321 lastblock = block ? block->GetBlockHash() : 0;
1325 ret.push_back(Pair("transactions", transactions));
1326 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1331 Value gettransaction(const Array& params, bool fHelp)
1333 if (fHelp || params.size() != 1)
1334 throw runtime_error(
1335 "gettransaction <txid>\n"
1336 "Get detailed information about <txid>");
1339 hash.SetHex(params[0].get_str());
1343 if (!pwalletMain->mapWallet.count(hash))
1344 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1345 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1347 int64 nCredit = wtx.GetCredit();
1348 int64 nDebit = wtx.GetDebit();
1349 int64 nNet = nCredit - nDebit;
1350 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1352 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1354 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1356 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1359 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1360 entry.push_back(Pair("details", details));
1366 Value backupwallet(const Array& params, bool fHelp)
1368 if (fHelp || params.size() != 1)
1369 throw runtime_error(
1370 "backupwallet <destination>\n"
1371 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1373 string strDest = params[0].get_str();
1374 BackupWallet(*pwalletMain, strDest);
1380 Value keypoolrefill(const Array& params, bool fHelp)
1382 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1383 throw runtime_error(
1385 "Fills the keypool, requires wallet passphrase to be set.");
1386 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1387 throw runtime_error(
1389 "Fills the keypool.");
1391 if (pwalletMain->IsLocked())
1392 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1394 pwalletMain->TopUpKeyPool();
1396 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1397 throw JSONRPCError(-4, "Error refreshing keypool.");
1403 void ThreadTopUpKeyPool(void* parg)
1405 pwalletMain->TopUpKeyPool();
1408 void ThreadCleanWalletPassphrase(void* parg)
1410 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1412 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1414 if (nWalletUnlockTime == 0)
1416 nWalletUnlockTime = nMyWakeTime;
1420 if (nWalletUnlockTime==0)
1422 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1426 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1428 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1432 if (nWalletUnlockTime)
1434 nWalletUnlockTime = 0;
1435 pwalletMain->Lock();
1440 if (nWalletUnlockTime < nMyWakeTime)
1441 nWalletUnlockTime = nMyWakeTime;
1444 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1446 delete (int64*)parg;
1449 Value walletpassphrase(const Array& params, bool fHelp)
1451 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1452 throw runtime_error(
1453 "walletpassphrase <passphrase> <timeout>\n"
1454 "Stores the wallet decryption key in memory for <timeout> seconds.");
1457 if (!pwalletMain->IsCrypted())
1458 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1460 if (!pwalletMain->IsLocked())
1461 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1463 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1464 SecureString strWalletPass;
1465 strWalletPass.reserve(100);
1466 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1467 // Alternately, find a way to make params[0] mlock()'d to begin with.
1468 strWalletPass = params[0].get_str().c_str();
1470 if (strWalletPass.length() > 0)
1472 if (!pwalletMain->Unlock(strWalletPass))
1473 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1476 throw runtime_error(
1477 "walletpassphrase <passphrase> <timeout>\n"
1478 "Stores the wallet decryption key in memory for <timeout> seconds.");
1480 CreateThread(ThreadTopUpKeyPool, NULL);
1481 int64* pnSleepTime = new int64(params[1].get_int64());
1482 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1488 Value walletpassphrasechange(const Array& params, bool fHelp)
1490 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1491 throw runtime_error(
1492 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1493 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1496 if (!pwalletMain->IsCrypted())
1497 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1499 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1500 // Alternately, find a way to make params[0] mlock()'d to begin with.
1501 SecureString strOldWalletPass;
1502 strOldWalletPass.reserve(100);
1503 strOldWalletPass = params[0].get_str().c_str();
1505 SecureString strNewWalletPass;
1506 strNewWalletPass.reserve(100);
1507 strNewWalletPass = params[1].get_str().c_str();
1509 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1510 throw runtime_error(
1511 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1512 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1514 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1515 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1521 Value walletlock(const Array& params, bool fHelp)
1523 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1524 throw runtime_error(
1526 "Removes the wallet encryption key from memory, locking the wallet.\n"
1527 "After calling this method, you will need to call walletpassphrase again\n"
1528 "before being able to call any methods which require the wallet to be unlocked.");
1531 if (!pwalletMain->IsCrypted())
1532 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1534 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1536 pwalletMain->Lock();
1537 nWalletUnlockTime = 0;
1544 Value encryptwallet(const Array& params, bool fHelp)
1546 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1547 throw runtime_error(
1548 "encryptwallet <passphrase>\n"
1549 "Encrypts the wallet with <passphrase>.");
1552 if (pwalletMain->IsCrypted())
1553 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1556 // shutting down via RPC while the GUI is running does not work (yet):
1557 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1560 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1561 // Alternately, find a way to make params[0] mlock()'d to begin with.
1562 SecureString strWalletPass;
1563 strWalletPass.reserve(100);
1564 strWalletPass = params[0].get_str().c_str();
1566 if (strWalletPass.length() < 1)
1567 throw runtime_error(
1568 "encryptwallet <passphrase>\n"
1569 "Encrypts the wallet with <passphrase>.");
1571 if (!pwalletMain->EncryptWallet(strWalletPass))
1572 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1574 // BDB seems to have a bad habit of writing old data into
1575 // slack space in .dat files; that is bad if the old data is
1576 // unencrypted private keys. So:
1577 CreateThread(Shutdown, NULL);
1578 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1582 Value validateaddress(const Array& params, bool fHelp)
1584 if (fHelp || params.size() != 1)
1585 throw runtime_error(
1586 "validateaddress <bitcoinaddress>\n"
1587 "Return information about <bitcoinaddress>.");
1589 CBitcoinAddress address(params[0].get_str());
1590 bool isValid = address.IsValid();
1593 ret.push_back(Pair("isvalid", isValid));
1596 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1597 // version of the address:
1598 string currentAddress = address.ToString();
1599 ret.push_back(Pair("address", currentAddress));
1600 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1601 if (pwalletMain->mapAddressBook.count(address))
1602 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1608 Value getwork(const Array& params, bool fHelp)
1610 if (fHelp || params.size() > 1)
1611 throw runtime_error(
1613 "If [data] is not specified, returns formatted hash data to work on:\n"
1614 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1615 " \"data\" : block data\n"
1616 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1617 " \"target\" : little endian hash target\n"
1618 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1621 throw JSONRPCError(-9, "Bitcoin is not connected!");
1623 if (IsInitialBlockDownload())
1624 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1626 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1627 static mapNewBlock_t mapNewBlock;
1628 static vector<CBlock*> vNewBlock;
1629 static CReserveKey reservekey(pwalletMain);
1631 if (params.size() == 0)
1634 static unsigned int nTransactionsUpdatedLast;
1635 static CBlockIndex* pindexPrev;
1636 static int64 nStart;
1637 static CBlock* pblock;
1638 if (pindexPrev != pindexBest ||
1639 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1641 if (pindexPrev != pindexBest)
1643 // Deallocate old blocks since they're obsolete now
1644 mapNewBlock.clear();
1645 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1649 nTransactionsUpdatedLast = nTransactionsUpdated;
1650 pindexPrev = pindexBest;
1654 pblock = CreateNewBlock(reservekey);
1656 throw JSONRPCError(-7, "Out of memory");
1657 vNewBlock.push_back(pblock);
1661 pblock->UpdateTime(pindexPrev);
1664 // Update nExtraNonce
1665 static unsigned int nExtraNonce = 0;
1666 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1669 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1671 // Prebuild hash buffers
1675 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1677 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1680 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1681 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1682 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1683 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1689 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1690 if (vchData.size() != 128)
1691 throw JSONRPCError(-8, "Invalid parameter");
1692 CBlock* pdata = (CBlock*)&vchData[0];
1695 for (int i = 0; i < 128/4; i++)
1696 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1699 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1701 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1703 pblock->nTime = pdata->nTime;
1704 pblock->nNonce = pdata->nNonce;
1705 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1706 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1708 return CheckWork(pblock, *pwalletMain, reservekey);
1713 Value getmemorypool(const Array& params, bool fHelp)
1715 if (fHelp || params.size() > 1)
1716 throw runtime_error(
1717 "getmemorypool [data]\n"
1718 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1719 " \"version\" : block version\n"
1720 " \"previousblockhash\" : hash of current highest block\n"
1721 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1722 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1723 " \"time\" : timestamp appropriate for next block\n"
1724 " \"bits\" : compressed target of next block\n"
1725 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1727 if (params.size() == 0)
1730 throw JSONRPCError(-9, "Bitcoin is not connected!");
1732 if (IsInitialBlockDownload())
1733 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1735 static CReserveKey reservekey(pwalletMain);
1738 static unsigned int nTransactionsUpdatedLast;
1739 static CBlockIndex* pindexPrev;
1740 static int64 nStart;
1741 static CBlock* pblock;
1742 if (pindexPrev != pindexBest ||
1743 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1745 nTransactionsUpdatedLast = nTransactionsUpdated;
1746 pindexPrev = pindexBest;
1752 pblock = CreateNewBlock(reservekey);
1754 throw JSONRPCError(-7, "Out of memory");
1758 pblock->UpdateTime(pindexPrev);
1762 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1769 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1773 result.push_back(Pair("version", pblock->nVersion));
1774 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1775 result.push_back(Pair("transactions", transactions));
1776 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1777 result.push_back(Pair("time", (int64_t)pblock->nTime));
1783 uBits.nBits = htonl((int32_t)pblock->nBits);
1784 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1791 CDataStream ssBlock(ParseHex(params[0].get_str()));
1795 return ProcessBlock(NULL, &pblock);
1813 pair<string, rpcfn_type> pCallTable[] =
1815 make_pair("help", &help),
1816 make_pair("stop", &stop),
1817 make_pair("getblockcount", &getblockcount),
1818 make_pair("getblocknumber", &getblocknumber),
1819 make_pair("getconnectioncount", &getconnectioncount),
1820 make_pair("getdifficulty", &getdifficulty),
1821 make_pair("getgenerate", &getgenerate),
1822 make_pair("setgenerate", &setgenerate),
1823 make_pair("gethashespersec", &gethashespersec),
1824 make_pair("getinfo", &getinfo),
1825 make_pair("getnewaddress", &getnewaddress),
1826 make_pair("getaccountaddress", &getaccountaddress),
1827 make_pair("setaccount", &setaccount),
1828 make_pair("getaccount", &getaccount),
1829 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1830 make_pair("sendtoaddress", &sendtoaddress),
1831 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1832 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1833 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1834 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1835 make_pair("backupwallet", &backupwallet),
1836 make_pair("keypoolrefill", &keypoolrefill),
1837 make_pair("walletpassphrase", &walletpassphrase),
1838 make_pair("walletpassphrasechange", &walletpassphrasechange),
1839 make_pair("walletlock", &walletlock),
1840 make_pair("encryptwallet", &encryptwallet),
1841 make_pair("validateaddress", &validateaddress),
1842 make_pair("getbalance", &getbalance),
1843 make_pair("move", &movecmd),
1844 make_pair("sendfrom", &sendfrom),
1845 make_pair("sendmany", &sendmany),
1846 make_pair("gettransaction", &gettransaction),
1847 make_pair("listtransactions", &listtransactions),
1848 make_pair("signmessage", &signmessage),
1849 make_pair("verifymessage", &verifymessage),
1850 make_pair("getwork", &getwork),
1851 make_pair("listaccounts", &listaccounts),
1852 make_pair("settxfee", &settxfee),
1853 make_pair("getmemorypool", &getmemorypool),
1854 make_pair("listsinceblock", &listsinceblock),
1856 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1858 string pAllowInSafeMode[] =
1863 "getblocknumber", // deprecated
1864 "getconnectioncount",
1871 "getaccountaddress",
1873 "getaddressesbyaccount",
1882 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1890 // This ain't Apache. We're just using HTTP header for the length field
1891 // and to be compatible with other JSON-RPC implementations.
1894 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1897 s << "POST / HTTP/1.1\r\n"
1898 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1899 << "Host: 127.0.0.1\r\n"
1900 << "Content-Type: application/json\r\n"
1901 << "Content-Length: " << strMsg.size() << "\r\n"
1902 << "Connection: close\r\n"
1903 << "Accept: application/json\r\n";
1904 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1905 s << item.first << ": " << item.second << "\r\n";
1906 s << "\r\n" << strMsg;
1911 string rfc1123Time()
1916 struct tm* now_gmt = gmtime(&now);
1917 string locale(setlocale(LC_TIME, NULL));
1918 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1919 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1920 setlocale(LC_TIME, locale.c_str());
1921 return string(buffer);
1924 static string HTTPReply(int nStatus, const string& strMsg)
1927 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1929 "Server: bitcoin-json-rpc/%s\r\n"
1930 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1931 "Content-Type: text/html\r\n"
1932 "Content-Length: 296\r\n"
1934 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1935 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1938 "<TITLE>Error</TITLE>\r\n"
1939 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1941 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1942 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1943 const char *cStatus;
1944 if (nStatus == 200) cStatus = "OK";
1945 else if (nStatus == 400) cStatus = "Bad Request";
1946 else if (nStatus == 403) cStatus = "Forbidden";
1947 else if (nStatus == 404) cStatus = "Not Found";
1948 else if (nStatus == 500) cStatus = "Internal Server Error";
1951 "HTTP/1.1 %d %s\r\n"
1953 "Connection: close\r\n"
1954 "Content-Length: %d\r\n"
1955 "Content-Type: application/json\r\n"
1956 "Server: bitcoin-json-rpc/%s\r\n"
1961 rfc1123Time().c_str(),
1963 FormatFullVersion().c_str(),
1967 int ReadHTTPStatus(std::basic_istream<char>& stream)
1970 getline(stream, str);
1971 vector<string> vWords;
1972 boost::split(vWords, str, boost::is_any_of(" "));
1973 if (vWords.size() < 2)
1975 return atoi(vWords[1].c_str());
1978 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1984 std::getline(stream, str);
1985 if (str.empty() || str == "\r")
1987 string::size_type nColon = str.find(":");
1988 if (nColon != string::npos)
1990 string strHeader = str.substr(0, nColon);
1991 boost::trim(strHeader);
1992 boost::to_lower(strHeader);
1993 string strValue = str.substr(nColon+1);
1994 boost::trim(strValue);
1995 mapHeadersRet[strHeader] = strValue;
1996 if (strHeader == "content-length")
1997 nLen = atoi(strValue.c_str());
2003 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2005 mapHeadersRet.clear();
2009 int nStatus = ReadHTTPStatus(stream);
2012 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2013 if (nLen < 0 || nLen > MAX_SIZE)
2019 vector<char> vch(nLen);
2020 stream.read(&vch[0], nLen);
2021 strMessageRet = string(vch.begin(), vch.end());
2027 bool HTTPAuthorized(map<string, string>& mapHeaders)
2029 string strAuth = mapHeaders["authorization"];
2030 if (strAuth.substr(0,6) != "Basic ")
2032 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2033 string strUserPass = DecodeBase64(strUserPass64);
2034 return strUserPass == strRPCUserColonPass;
2038 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2039 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2040 // unspecified (HTTP errors and contents of 'error').
2042 // 1.0 spec: http://json-rpc.org/wiki/specification
2043 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2044 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2047 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2050 request.push_back(Pair("method", strMethod));
2051 request.push_back(Pair("params", params));
2052 request.push_back(Pair("id", id));
2053 return write_string(Value(request), false) + "\n";
2056 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2059 if (error.type() != null_type)
2060 reply.push_back(Pair("result", Value::null));
2062 reply.push_back(Pair("result", result));
2063 reply.push_back(Pair("error", error));
2064 reply.push_back(Pair("id", id));
2065 return write_string(Value(reply), false) + "\n";
2068 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2070 // Send error reply from json-rpc error object
2072 int code = find_value(objError, "code").get_int();
2073 if (code == -32600) nStatus = 400;
2074 else if (code == -32601) nStatus = 404;
2075 string strReply = JSONRPCReply(Value::null, objError, id);
2076 stream << HTTPReply(nStatus, strReply) << std::flush;
2079 bool ClientAllowed(const string& strAddress)
2081 if (strAddress == asio::ip::address_v4::loopback().to_string())
2083 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2084 BOOST_FOREACH(string strAllow, vAllow)
2085 if (WildcardMatch(strAddress, strAllow))
2092 // IOStream device that speaks SSL but can also speak non-SSL
2094 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2096 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2098 fUseSSL = fUseSSLIn;
2099 fNeedHandshake = fUseSSLIn;
2102 void handshake(ssl::stream_base::handshake_type role)
2104 if (!fNeedHandshake) return;
2105 fNeedHandshake = false;
2106 stream.handshake(role);
2108 std::streamsize read(char* s, std::streamsize n)
2110 handshake(ssl::stream_base::server); // HTTPS servers read first
2111 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2112 return stream.next_layer().read_some(asio::buffer(s, n));
2114 std::streamsize write(const char* s, std::streamsize n)
2116 handshake(ssl::stream_base::client); // HTTPS clients write first
2117 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2118 return asio::write(stream.next_layer(), asio::buffer(s, n));
2120 bool connect(const std::string& server, const std::string& port)
2122 ip::tcp::resolver resolver(stream.get_io_service());
2123 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2124 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2125 ip::tcp::resolver::iterator end;
2126 boost::system::error_code error = asio::error::host_not_found;
2127 while (error && endpoint_iterator != end)
2129 stream.lowest_layer().close();
2130 stream.lowest_layer().connect(*endpoint_iterator++, error);
2138 bool fNeedHandshake;
2144 void ThreadRPCServer(void* parg)
2146 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2149 vnThreadsRunning[4]++;
2150 ThreadRPCServer2(parg);
2151 vnThreadsRunning[4]--;
2153 catch (std::exception& e) {
2154 vnThreadsRunning[4]--;
2155 PrintException(&e, "ThreadRPCServer()");
2157 vnThreadsRunning[4]--;
2158 PrintException(NULL, "ThreadRPCServer()");
2160 printf("ThreadRPCServer exiting\n");
2163 void ThreadRPCServer2(void* parg)
2165 printf("ThreadRPCServer started\n");
2167 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2168 if (strRPCUserColonPass == ":")
2170 unsigned char rand_pwd[32];
2171 RAND_bytes(rand_pwd, 32);
2172 string strWhatAmI = "To use bitcoind";
2173 if (mapArgs.count("-server"))
2174 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2175 else if (mapArgs.count("-daemon"))
2176 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2177 ThreadSafeMessageBox(strprintf(
2178 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2179 "It is recommended you use the following random password:\n"
2180 "rpcuser=bitcoinrpc\n"
2182 "(you do not need to remember this password)\n"
2183 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2185 GetConfigFile().c_str(),
2186 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2187 _("Error"), wxOK | wxMODAL);
2189 CreateThread(Shutdown, NULL);
2194 bool fUseSSL = GetBoolArg("-rpcssl");
2195 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2197 asio::io_service io_service;
2198 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2199 ip::tcp::acceptor acceptor(io_service, endpoint);
2201 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2204 ssl::context context(io_service, ssl::context::sslv23);
2207 context.set_options(ssl::context::no_sslv2);
2208 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2209 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2210 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2211 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2212 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2213 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2214 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2215 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2217 string ciphers = GetArg("-rpcsslciphers",
2218 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2219 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2223 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2228 // Accept connection
2230 SSLStream sslStream(io_service, context);
2231 SSLIOStreamDevice d(sslStream, fUseSSL);
2232 iostreams::stream<SSLIOStreamDevice> stream(d);
2234 ip::tcp::iostream stream;
2237 ip::tcp::endpoint peer;
2238 vnThreadsRunning[4]--;
2240 acceptor.accept(sslStream.lowest_layer(), peer);
2242 acceptor.accept(*stream.rdbuf(), peer);
2244 vnThreadsRunning[4]++;
2248 // Restrict callers by IP
2249 if (!ClientAllowed(peer.address().to_string()))
2251 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2253 stream << HTTPReply(403, "") << std::flush;
2257 map<string, string> mapHeaders;
2260 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2261 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2264 printf("ThreadRPCServer ReadHTTP timeout\n");
2268 // Check authorization
2269 if (mapHeaders.count("authorization") == 0)
2271 stream << HTTPReply(401, "") << std::flush;
2274 if (!HTTPAuthorized(mapHeaders))
2276 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2277 /* Deter brute-forcing short passwords.
2278 If this results in a DOS the user really
2279 shouldn't have their RPC port exposed.*/
2280 if (mapArgs["-rpcpassword"].size() < 20)
2283 stream << HTTPReply(401, "") << std::flush;
2287 Value id = Value::null;
2292 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2293 throw JSONRPCError(-32700, "Parse error");
2294 const Object& request = valRequest.get_obj();
2296 // Parse id now so errors from here on will have the id
2297 id = find_value(request, "id");
2300 Value valMethod = find_value(request, "method");
2301 if (valMethod.type() == null_type)
2302 throw JSONRPCError(-32600, "Missing method");
2303 if (valMethod.type() != str_type)
2304 throw JSONRPCError(-32600, "Method must be a string");
2305 string strMethod = valMethod.get_str();
2306 if (strMethod != "getwork" && strMethod != "getmemorypool")
2307 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2310 Value valParams = find_value(request, "params");
2312 if (valParams.type() == array_type)
2313 params = valParams.get_array();
2314 else if (valParams.type() == null_type)
2317 throw JSONRPCError(-32600, "Params must be an array");
2320 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2321 if (mi == mapCallTable.end())
2322 throw JSONRPCError(-32601, "Method not found");
2324 // Observe safe mode
2325 string strWarning = GetWarnings("rpc");
2326 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2327 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2333 CRITICAL_BLOCK(cs_main)
2334 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2335 result = (*(*mi).second)(params, false);
2338 string strReply = JSONRPCReply(result, Value::null, id);
2339 stream << HTTPReply(200, strReply) << std::flush;
2341 catch (std::exception& e)
2343 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2346 catch (Object& objError)
2348 ErrorReply(stream, objError, id);
2350 catch (std::exception& e)
2352 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2360 Object CallRPC(const string& strMethod, const Array& params)
2362 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2363 throw runtime_error(strprintf(
2364 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2365 "If the file does not exist, create it with owner-readable-only file permissions."),
2366 GetConfigFile().c_str()));
2368 // Connect to localhost
2369 bool fUseSSL = GetBoolArg("-rpcssl");
2371 asio::io_service io_service;
2372 ssl::context context(io_service, ssl::context::sslv23);
2373 context.set_options(ssl::context::no_sslv2);
2374 SSLStream sslStream(io_service, context);
2375 SSLIOStreamDevice d(sslStream, fUseSSL);
2376 iostreams::stream<SSLIOStreamDevice> stream(d);
2377 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2378 throw runtime_error("couldn't connect to server");
2381 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2383 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2385 throw runtime_error("couldn't connect to server");
2389 // HTTP basic authentication
2390 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2391 map<string, string> mapRequestHeaders;
2392 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2395 string strRequest = JSONRPCRequest(strMethod, params, 1);
2396 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2397 stream << strPost << std::flush;
2400 map<string, string> mapHeaders;
2402 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2404 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2405 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2406 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2407 else if (strReply.empty())
2408 throw runtime_error("no response from server");
2412 if (!read_string(strReply, valReply))
2413 throw runtime_error("couldn't parse reply from server");
2414 const Object& reply = valReply.get_obj();
2416 throw runtime_error("expected reply to have result, error and id properties");
2424 template<typename T>
2425 void ConvertTo(Value& value)
2427 if (value.type() == str_type)
2429 // reinterpret string as unquoted json value
2431 if (!read_string(value.get_str(), value2))
2432 throw runtime_error("type mismatch");
2433 value = value2.get_value<T>();
2437 value = value.get_value<T>();
2441 int CommandLineRPC(int argc, char *argv[])
2448 while (argc > 1 && IsSwitchChar(argv[1][0]))
2456 throw runtime_error("too few parameters");
2457 string strMethod = argv[1];
2459 // Parameters default to strings
2461 for (int i = 2; i < argc; i++)
2462 params.push_back(argv[i]);
2463 int n = params.size();
2466 // Special case non-string parameter types
2468 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2469 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2470 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2471 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2472 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2473 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2474 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2475 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2476 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2477 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2478 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2479 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2480 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2481 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2482 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2483 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2484 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2485 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2486 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2487 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2488 if (strMethod == "sendmany" && n > 1)
2490 string s = params[1].get_str();
2492 if (!read_string(s, v) || v.type() != obj_type)
2493 throw runtime_error("type mismatch");
2494 params[1] = v.get_obj();
2496 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2499 Object reply = CallRPC(strMethod, params);
2502 const Value& result = find_value(reply, "result");
2503 const Value& error = find_value(reply, "error");
2505 if (error.type() != null_type)
2508 strPrint = "error: " + write_string(error, false);
2509 int code = find_value(error.get_obj(), "code").get_int();
2515 if (result.type() == null_type)
2517 else if (result.type() == str_type)
2518 strPrint = result.get_str();
2520 strPrint = write_string(result, true);
2523 catch (std::exception& e)
2525 strPrint = string("error: ") + e.what();
2530 PrintException(NULL, "CommandLineRPC()");
2535 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2544 int main(int argc, char *argv[])
2547 // Turn off microsoft heap dump noise
2548 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2549 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2551 setbuf(stdin, NULL);
2552 setbuf(stdout, NULL);
2553 setbuf(stderr, NULL);
2557 if (argc >= 2 && string(argv[1]) == "-server")
2559 printf("server ready\n");
2560 ThreadRPCServer(NULL);
2564 return CommandLineRPC(argc, argv);
2567 catch (std::exception& e) {
2568 PrintException(&e, "main()");
2570 PrintException(NULL, "main()");