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.
7 #include "cryptopp/sha.h"
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
44 Object JSONRPCError(int code, const string& message)
47 error.push_back(Pair("code", code));
48 error.push_back(Pair("message", message));
53 void PrintConsole(const std::string &format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
61 if (ret < 0 || ret >= limit)
67 fprintf(stdout, "%s", buffer);
71 int64 AmountFromValue(const Value& value)
73 double dAmount = value.get_real();
74 if (dAmount <= 0.0 || dAmount > 21000000.0)
75 throw JSONRPCError(-3, "Invalid amount");
76 int64 nAmount = roundint64(dAmount * COIN);
77 if (!MoneyRange(nAmount))
78 throw JSONRPCError(-3, "Invalid amount");
82 Value ValueFromAmount(int64 amount)
84 return (double)amount / (double)COIN;
87 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
89 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
90 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
91 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
92 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
93 entry.push_back(Pair(item.first, item.second));
96 string AccountFromValue(const Value& value)
98 string strAccount = value.get_str();
99 if (strAccount == "*")
100 throw JSONRPCError(-11, "Invalid account name");
107 /// Note: This interface may still be subject to change.
111 Value help(const Array& params, bool fHelp)
113 if (fHelp || params.size() > 1)
116 "List commands, or get help for a command.");
119 if (params.size() > 0)
120 strCommand = params[0].get_str();
123 set<rpcfn_type> setDone;
124 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
126 string strMethod = (*mi).first;
127 // We already filter duplicates, but these deprecated screw up the sort order
128 if (strMethod == "getamountreceived" ||
129 strMethod == "getallreceived" ||
130 (strMethod.find("label") != string::npos))
132 if (strCommand != "" && strMethod != strCommand)
137 rpcfn_type pfn = (*mi).second;
138 if (setDone.insert(pfn).second)
139 (*pfn)(params, true);
141 catch (std::exception& e)
143 // Help text is returned in an exception
144 string strHelp = string(e.what());
145 if (strCommand == "")
146 if (strHelp.find('\n') != -1)
147 strHelp = strHelp.substr(0, strHelp.find('\n'));
148 strRet += strHelp + "\n";
152 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
153 strRet = strRet.substr(0,strRet.size()-1);
158 Value stop(const Array& params, bool fHelp)
160 if (fHelp || params.size() != 0)
163 "Stop bitcoin server.");
165 // Shutdown will take long enough that the response should get back
166 CreateThread(Shutdown, NULL);
167 return "bitcoin server stopping";
171 Value getblockcount(const Array& params, bool fHelp)
173 if (fHelp || params.size() != 0)
176 "Returns the number of blocks in the longest block chain.");
182 Value getblocknumber(const Array& params, bool fHelp)
184 if (fHelp || params.size() != 0)
187 "Returns the block number of the latest block in the longest block chain.");
193 Value getconnectioncount(const Array& params, bool fHelp)
195 if (fHelp || params.size() != 0)
197 "getconnectioncount\n"
198 "Returns the number of connections to other nodes.");
200 return (int)vNodes.size();
204 double GetDifficulty()
206 // Floating point number that is a multiple of the minimum difficulty,
207 // minimum difficulty = 1.0.
209 if (pindexBest == NULL)
211 int nShift = (pindexBest->nBits >> 24) & 0xff;
214 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
230 Value getdifficulty(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
237 return GetDifficulty();
241 Value getgenerate(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Returns true or false.");
248 return (bool)fGenerateBitcoins;
252 Value setgenerate(const Array& params, bool fHelp)
254 if (fHelp || params.size() < 1 || params.size() > 2)
256 "setgenerate <generate> [genproclimit]\n"
257 "<generate> is true or false to turn generation on or off.\n"
258 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
260 bool fGenerate = true;
261 if (params.size() > 0)
262 fGenerate = params[0].get_bool();
264 if (params.size() > 1)
266 int nGenProcLimit = params[1].get_int();
267 fLimitProcessors = (nGenProcLimit != -1);
268 WriteSetting("fLimitProcessors", fLimitProcessors);
269 if (nGenProcLimit != -1)
270 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
271 if (nGenProcLimit == 0)
275 GenerateBitcoins(fGenerate, pwalletMain);
280 Value gethashespersec(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 0)
285 "Returns a recent hashes per second performance measurement while generating.");
287 if (GetTimeMillis() - nHPSTimerStart > 8000)
288 return (boost::int64_t)0;
289 return (boost::int64_t)dHashesPerSec;
293 Value getinfo(const Array& params, bool fHelp)
295 if (fHelp || params.size() != 0)
298 "Returns an object containing various state info.");
301 obj.push_back(Pair("version", (int)VERSION));
302 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
303 obj.push_back(Pair("blocks", (int)nBestHeight));
304 obj.push_back(Pair("connections", (int)vNodes.size()));
305 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
306 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
307 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
308 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
309 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
310 obj.push_back(Pair("testnet", fTestNet));
311 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
312 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
313 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
314 if (pwalletMain->IsCrypted())
315 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
316 obj.push_back(Pair("errors", GetWarnings("statusbar")));
321 Value getnewaddress(const Array& params, bool fHelp)
323 if (fHelp || params.size() > 1)
325 "getnewaddress [account]\n"
326 "Returns a new bitcoin address for receiving payments. "
327 "If [account] is specified (recommended), it is added to the address book "
328 "so payments received with the address will be credited to [account].");
330 // Parse the account first so we don't generate a key if there's an error
332 if (params.size() > 0)
333 strAccount = AccountFromValue(params[0]);
335 if (!pwalletMain->IsLocked())
336 pwalletMain->TopUpKeyPool();
338 // Generate a new key that is added to wallet
339 std::vector<unsigned char> newKey;
340 if (!pwalletMain->GetKeyFromPool(newKey, false))
341 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
342 CBitcoinAddress address(newKey);
344 pwalletMain->SetAddressBookName(address, strAccount);
346 return address.ToString();
350 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
352 CWalletDB walletdb(pwalletMain->strWalletFile);
355 walletdb.ReadAccount(strAccount, account);
357 bool bKeyUsed = false;
359 // Check if the current key has been used
360 if (!account.vchPubKey.empty())
362 CScript scriptPubKey;
363 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
365 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
368 const CWalletTx& wtx = (*it).second;
369 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
370 if (txout.scriptPubKey == scriptPubKey)
375 // Generate a new key
376 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
378 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
379 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
381 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
382 walletdb.WriteAccount(strAccount, account);
385 return CBitcoinAddress(account.vchPubKey);
388 Value getaccountaddress(const Array& params, bool fHelp)
390 if (fHelp || params.size() != 1)
392 "getaccountaddress <account>\n"
393 "Returns the current bitcoin address for receiving payments to this account.");
395 // Parse the account first so we don't generate a key if there's an error
396 string strAccount = AccountFromValue(params[0]);
400 ret = GetAccountAddress(strAccount).ToString();
407 Value setaccount(const Array& params, bool fHelp)
409 if (fHelp || params.size() < 1 || params.size() > 2)
411 "setaccount <bitcoinaddress> <account>\n"
412 "Sets the account associated with the given address.");
414 CBitcoinAddress address(params[0].get_str());
415 if (!address.IsValid())
416 throw JSONRPCError(-5, "Invalid bitcoin address");
420 if (params.size() > 1)
421 strAccount = AccountFromValue(params[1]);
423 // Detect when changing the account of an address that is the 'unused current key' of another account:
424 if (pwalletMain->mapAddressBook.count(address))
426 string strOldAccount = pwalletMain->mapAddressBook[address];
427 if (address == GetAccountAddress(strOldAccount))
428 GetAccountAddress(strOldAccount, true);
431 pwalletMain->SetAddressBookName(address, strAccount);
437 Value getaccount(const Array& params, bool fHelp)
439 if (fHelp || params.size() != 1)
441 "getaccount <bitcoinaddress>\n"
442 "Returns the account associated with the given address.");
444 CBitcoinAddress address(params[0].get_str());
445 if (!address.IsValid())
446 throw JSONRPCError(-5, "Invalid bitcoin address");
449 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
450 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
451 strAccount = (*mi).second;
456 Value getaddressesbyaccount(const Array& params, bool fHelp)
458 if (fHelp || params.size() != 1)
460 "getaddressesbyaccount <account>\n"
461 "Returns the list of addresses for the given account.");
463 string strAccount = AccountFromValue(params[0]);
465 // Find all addresses that have the given account
467 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
469 const CBitcoinAddress& address = item.first;
470 const string& strName = item.second;
471 if (strName == strAccount)
472 ret.push_back(address.ToString());
477 Value settxfee(const Array& params, bool fHelp)
479 if (fHelp || params.size() < 1 || params.size() > 1)
481 "settxfee <amount>\n"
482 "<amount> is a real and is rounded to the nearest 0.00000001");
486 if (params[0].get_real() != 0.0)
487 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
489 nTransactionFee = nAmount;
493 Value sendtoaddress(const Array& params, bool fHelp)
495 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
497 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
498 "<amount> is a real and is rounded to the nearest 0.00000001\n"
499 "requires wallet passphrase to be set with walletpassphrase first");
500 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
502 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503 "<amount> is a real and is rounded to the nearest 0.00000001");
505 CBitcoinAddress address(params[0].get_str());
506 if (!address.IsValid())
507 throw JSONRPCError(-5, "Invalid bitcoin address");
510 int64 nAmount = AmountFromValue(params[1]);
514 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
515 wtx.mapValue["comment"] = params[2].get_str();
516 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
517 wtx.mapValue["to"] = params[3].get_str();
519 if (pwalletMain->IsLocked())
520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
522 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
524 throw JSONRPCError(-4, strError);
526 return wtx.GetHash().GetHex();
529 static const string strMessageMagic = "Bitcoin Signed Message:\n";
531 Value signmessage(const Array& params, bool fHelp)
533 if (fHelp || params.size() != 2)
535 "signmessage <bitcoinaddress> <message>\n"
536 "Sign a message with the private key of an address");
538 if (pwalletMain->IsLocked())
539 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
541 string strAddress = params[0].get_str();
542 string strMessage = params[1].get_str();
544 CBitcoinAddress addr(strAddress);
546 throw JSONRPCError(-3, "Invalid address");
549 if (!pwalletMain->GetKey(addr, key))
550 throw JSONRPCError(-4, "Private key not available");
552 CDataStream ss(SER_GETHASH);
553 ss << strMessageMagic;
556 vector<unsigned char> vchSig;
557 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
558 throw JSONRPCError(-5, "Sign failed");
560 return EncodeBase64(&vchSig[0], vchSig.size());
563 Value verifymessage(const Array& params, bool fHelp)
565 if (fHelp || params.size() != 3)
567 "verifymessage <bitcoinaddress> <signature> <message>\n"
568 "Verify a signed message");
570 string strAddress = params[0].get_str();
571 string strSign = params[1].get_str();
572 string strMessage = params[2].get_str();
574 CBitcoinAddress addr(strAddress);
576 throw JSONRPCError(-3, "Invalid address");
578 bool fInvalid = false;
579 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
582 throw JSONRPCError(-5, "Malformed base64 encoding");
584 CDataStream ss(SER_GETHASH);
585 ss << strMessageMagic;
589 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
592 return (key.GetAddress() == addr);
596 Value getreceivedbyaddress(const Array& params, bool fHelp)
598 if (fHelp || params.size() < 1 || params.size() > 2)
600 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
601 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
604 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
605 CScript scriptPubKey;
606 if (!address.IsValid())
607 throw JSONRPCError(-5, "Invalid bitcoin address");
608 scriptPubKey.SetBitcoinAddress(address);
609 if (!IsMine(*pwalletMain,scriptPubKey))
612 // Minimum confirmations
614 if (params.size() > 1)
615 nMinDepth = params[1].get_int();
619 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
621 const CWalletTx& wtx = (*it).second;
622 if (wtx.IsCoinBase() || !wtx.IsFinal())
625 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
626 if (txout.scriptPubKey == scriptPubKey)
627 if (wtx.GetDepthInMainChain() >= nMinDepth)
628 nAmount += txout.nValue;
631 return ValueFromAmount(nAmount);
635 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
637 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
639 const CBitcoinAddress& address = item.first;
640 const string& strName = item.second;
641 if (strName == strAccount)
642 setAddress.insert(address);
647 Value getreceivedbyaccount(const Array& params, bool fHelp)
649 if (fHelp || params.size() < 1 || params.size() > 2)
651 "getreceivedbyaccount <account> [minconf=1]\n"
652 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
654 // Minimum confirmations
656 if (params.size() > 1)
657 nMinDepth = params[1].get_int();
659 // Get the set of pub keys that have the label
660 string strAccount = AccountFromValue(params[0]);
661 set<CBitcoinAddress> setAddress;
662 GetAccountAddresses(strAccount, setAddress);
666 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
668 const CWalletTx& wtx = (*it).second;
669 if (wtx.IsCoinBase() || !wtx.IsFinal())
672 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
674 CBitcoinAddress address;
675 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
676 if (wtx.GetDepthInMainChain() >= nMinDepth)
677 nAmount += txout.nValue;
681 return (double)nAmount / (double)COIN;
685 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
689 // Tally wallet transactions
690 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
692 const CWalletTx& wtx = (*it).second;
696 int64 nGenerated, nReceived, nSent, nFee;
697 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
699 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
700 nBalance += nReceived;
701 nBalance += nGenerated - nSent - nFee;
704 // Tally internal accounting entries
705 nBalance += walletdb.GetAccountCreditDebit(strAccount);
710 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
712 CWalletDB walletdb(pwalletMain->strWalletFile);
713 return GetAccountBalance(walletdb, strAccount, nMinDepth);
717 Value getbalance(const Array& params, bool fHelp)
719 if (fHelp || params.size() > 2)
721 "getbalance [account] [minconf=1]\n"
722 "If [account] is not specified, returns the server's total available balance.\n"
723 "If [account] is specified, returns the balance in the account.");
725 if (params.size() == 0)
726 return ValueFromAmount(pwalletMain->GetBalance());
729 if (params.size() > 1)
730 nMinDepth = params[1].get_int();
732 if (params[0].get_str() == "*") {
733 // Calculate total balance a different way from GetBalance()
734 // (GetBalance() sums up all unspent TxOuts)
735 // getbalance and getbalance '*' should always return the same number.
737 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
739 const CWalletTx& wtx = (*it).second;
743 int64 allGeneratedImmature, allGeneratedMature, allFee;
744 allGeneratedImmature = allGeneratedMature = allFee = 0;
745 string strSentAccount;
746 list<pair<CBitcoinAddress, int64> > listReceived;
747 list<pair<CBitcoinAddress, int64> > listSent;
748 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
749 if (wtx.GetDepthInMainChain() >= nMinDepth)
750 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
751 nBalance += r.second;
752 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
753 nBalance -= r.second;
755 nBalance += allGeneratedMature;
757 return ValueFromAmount(nBalance);
760 string strAccount = AccountFromValue(params[0]);
762 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
764 return ValueFromAmount(nBalance);
768 Value movecmd(const Array& params, bool fHelp)
770 if (fHelp || params.size() < 3 || params.size() > 5)
772 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
773 "Move from one account in your wallet to another.");
775 string strFrom = AccountFromValue(params[0]);
776 string strTo = AccountFromValue(params[1]);
777 int64 nAmount = AmountFromValue(params[2]);
778 if (params.size() > 3)
779 // unused parameter, used to be nMinDepth, keep type-checking it though
780 (void)params[3].get_int();
782 if (params.size() > 4)
783 strComment = params[4].get_str();
785 CWalletDB walletdb(pwalletMain->strWalletFile);
788 int64 nNow = GetAdjustedTime();
791 CAccountingEntry debit;
792 debit.strAccount = strFrom;
793 debit.nCreditDebit = -nAmount;
795 debit.strOtherAccount = strTo;
796 debit.strComment = strComment;
797 walletdb.WriteAccountingEntry(debit);
800 CAccountingEntry credit;
801 credit.strAccount = strTo;
802 credit.nCreditDebit = nAmount;
804 credit.strOtherAccount = strFrom;
805 credit.strComment = strComment;
806 walletdb.WriteAccountingEntry(credit);
808 walletdb.TxnCommit();
814 Value sendfrom(const Array& params, bool fHelp)
816 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
818 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
819 "<amount> is a real and is rounded to the nearest 0.00000001\n"
820 "requires wallet passphrase to be set with walletpassphrase first");
821 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
823 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
824 "<amount> is a real and is rounded to the nearest 0.00000001");
826 string strAccount = AccountFromValue(params[0]);
827 CBitcoinAddress address(params[1].get_str());
828 if (!address.IsValid())
829 throw JSONRPCError(-5, "Invalid bitcoin address");
830 int64 nAmount = AmountFromValue(params[2]);
832 if (params.size() > 3)
833 nMinDepth = params[3].get_int();
836 wtx.strFromAccount = strAccount;
837 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
838 wtx.mapValue["comment"] = params[4].get_str();
839 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
840 wtx.mapValue["to"] = params[5].get_str();
842 if (pwalletMain->IsLocked())
843 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
846 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
847 if (nAmount > nBalance)
848 throw JSONRPCError(-6, "Account has insufficient funds");
851 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
853 throw JSONRPCError(-4, strError);
855 return wtx.GetHash().GetHex();
859 Value sendmany(const Array& params, bool fHelp)
861 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
863 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
864 "amounts are double-precision floating point numbers\n"
865 "requires wallet passphrase to be set with walletpassphrase first");
866 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
868 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
869 "amounts are double-precision floating point numbers");
871 string strAccount = AccountFromValue(params[0]);
872 Object sendTo = params[1].get_obj();
874 if (params.size() > 2)
875 nMinDepth = params[2].get_int();
878 wtx.strFromAccount = strAccount;
879 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
880 wtx.mapValue["comment"] = params[3].get_str();
882 set<CBitcoinAddress> setAddress;
883 vector<pair<CScript, int64> > vecSend;
885 int64 totalAmount = 0;
886 BOOST_FOREACH(const Pair& s, sendTo)
888 CBitcoinAddress address(s.name_);
889 if (!address.IsValid())
890 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
892 if (setAddress.count(address))
893 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
894 setAddress.insert(address);
896 CScript scriptPubKey;
897 scriptPubKey.SetBitcoinAddress(address);
898 int64 nAmount = AmountFromValue(s.value_);
899 totalAmount += nAmount;
901 vecSend.push_back(make_pair(scriptPubKey, nAmount));
904 if (pwalletMain->IsLocked())
905 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
908 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
909 if (totalAmount > nBalance)
910 throw JSONRPCError(-6, "Account has insufficient funds");
913 CReserveKey keyChange(pwalletMain);
914 int64 nFeeRequired = 0;
915 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
918 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
919 throw JSONRPCError(-6, "Insufficient funds");
920 throw JSONRPCError(-4, "Transaction creation failed");
922 if (!pwalletMain->CommitTransaction(wtx, keyChange))
923 throw JSONRPCError(-4, "Transaction commit failed");
925 return wtx.GetHash().GetHex();
940 Value ListReceived(const Array& params, bool fByAccounts)
942 // Minimum confirmations
944 if (params.size() > 0)
945 nMinDepth = params[0].get_int();
947 // Whether to include empty accounts
948 bool fIncludeEmpty = false;
949 if (params.size() > 1)
950 fIncludeEmpty = params[1].get_bool();
953 map<CBitcoinAddress, tallyitem> mapTally;
954 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
956 const CWalletTx& wtx = (*it).second;
957 if (wtx.IsCoinBase() || !wtx.IsFinal())
960 int nDepth = wtx.GetDepthInMainChain();
961 if (nDepth < nMinDepth)
964 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
966 CBitcoinAddress address;
967 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
970 tallyitem& item = mapTally[address];
971 item.nAmount += txout.nValue;
972 item.nConf = min(item.nConf, nDepth);
978 map<string, tallyitem> mapAccountTally;
979 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
981 const CBitcoinAddress& address = item.first;
982 const string& strAccount = item.second;
983 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
984 if (it == mapTally.end() && !fIncludeEmpty)
989 if (it != mapTally.end())
991 nAmount = (*it).second.nAmount;
992 nConf = (*it).second.nConf;
997 tallyitem& item = mapAccountTally[strAccount];
998 item.nAmount += nAmount;
999 item.nConf = min(item.nConf, nConf);
1004 obj.push_back(Pair("address", address.ToString()));
1005 obj.push_back(Pair("account", strAccount));
1006 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1007 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1014 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1016 int64 nAmount = (*it).second.nAmount;
1017 int nConf = (*it).second.nConf;
1019 obj.push_back(Pair("account", (*it).first));
1020 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1021 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1029 Value listreceivedbyaddress(const Array& params, bool fHelp)
1031 if (fHelp || params.size() > 2)
1032 throw runtime_error(
1033 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1034 "[minconf] is the minimum number of confirmations before payments are included.\n"
1035 "[includeempty] whether to include addresses that haven't received any payments.\n"
1036 "Returns an array of objects containing:\n"
1037 " \"address\" : receiving address\n"
1038 " \"account\" : the account of the receiving address\n"
1039 " \"amount\" : total amount received by the address\n"
1040 " \"confirmations\" : number of confirmations of the most recent transaction included");
1042 return ListReceived(params, false);
1045 Value listreceivedbyaccount(const Array& params, bool fHelp)
1047 if (fHelp || params.size() > 2)
1048 throw runtime_error(
1049 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1050 "[minconf] is the minimum number of confirmations before payments are included.\n"
1051 "[includeempty] whether to include accounts that haven't received any payments.\n"
1052 "Returns an array of objects containing:\n"
1053 " \"account\" : the account of the receiving addresses\n"
1054 " \"amount\" : total amount received by addresses with this account\n"
1055 " \"confirmations\" : number of confirmations of the most recent transaction included");
1057 return ListReceived(params, true);
1060 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1062 int64 nGeneratedImmature, nGeneratedMature, nFee;
1063 string strSentAccount;
1064 list<pair<CBitcoinAddress, int64> > listReceived;
1065 list<pair<CBitcoinAddress, int64> > listSent;
1066 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1068 bool fAllAccounts = (strAccount == string("*"));
1070 // Generated blocks assigned to account ""
1071 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1074 entry.push_back(Pair("account", string("")));
1075 if (nGeneratedImmature)
1077 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1078 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1082 entry.push_back(Pair("category", "generate"));
1083 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1086 WalletTxToJSON(wtx, entry);
1087 ret.push_back(entry);
1091 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1093 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1096 entry.push_back(Pair("account", strSentAccount));
1097 entry.push_back(Pair("address", s.first.ToString()));
1098 entry.push_back(Pair("category", "send"));
1099 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1100 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1102 WalletTxToJSON(wtx, entry);
1103 ret.push_back(entry);
1108 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1109 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1112 if (pwalletMain->mapAddressBook.count(r.first))
1113 account = pwalletMain->mapAddressBook[r.first];
1114 if (fAllAccounts || (account == strAccount))
1117 entry.push_back(Pair("account", account));
1118 entry.push_back(Pair("address", r.first.ToString()));
1119 entry.push_back(Pair("category", "receive"));
1120 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1122 WalletTxToJSON(wtx, entry);
1123 ret.push_back(entry);
1128 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1130 bool fAllAccounts = (strAccount == string("*"));
1132 if (fAllAccounts || acentry.strAccount == strAccount)
1135 entry.push_back(Pair("account", acentry.strAccount));
1136 entry.push_back(Pair("category", "move"));
1137 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1138 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1139 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1140 entry.push_back(Pair("comment", acentry.strComment));
1141 ret.push_back(entry);
1145 Value listtransactions(const Array& params, bool fHelp)
1147 if (fHelp || params.size() > 3)
1148 throw runtime_error(
1149 "listtransactions [account] [count=10] [from=0]\n"
1150 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1152 string strAccount = "*";
1153 if (params.size() > 0)
1154 strAccount = params[0].get_str();
1156 if (params.size() > 1)
1157 nCount = params[1].get_int();
1159 if (params.size() > 2)
1160 nFrom = params[2].get_int();
1163 CWalletDB walletdb(pwalletMain->strWalletFile);
1165 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1166 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1167 typedef multimap<int64, TxPair > TxItems;
1170 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1172 CWalletTx* wtx = &((*it).second);
1173 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1175 list<CAccountingEntry> acentries;
1176 walletdb.ListAccountCreditDebit(strAccount, acentries);
1177 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1179 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1182 // Now: iterate backwards until we have nCount items to return:
1183 TxItems::reverse_iterator it = txByTime.rbegin();
1184 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1185 for (; it != txByTime.rend(); ++it)
1187 CWalletTx *const pwtx = (*it).second.first;
1189 ListTransactions(*pwtx, strAccount, 0, true, ret);
1190 CAccountingEntry *const pacentry = (*it).second.second;
1192 AcentryToJSON(*pacentry, strAccount, ret);
1194 if (ret.size() >= nCount) break;
1196 // ret is now newest to oldest
1198 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1199 if (ret.size() > nCount)
1201 Array::iterator last = ret.begin();
1202 std::advance(last, nCount);
1203 ret.erase(last, ret.end());
1205 std::reverse(ret.begin(), ret.end()); // oldest to newest
1210 Value listaccounts(const Array& params, bool fHelp)
1212 if (fHelp || params.size() > 1)
1213 throw runtime_error(
1214 "listaccounts [minconf=1]\n"
1215 "Returns Object that has account names as keys, account balances as values.");
1218 if (params.size() > 0)
1219 nMinDepth = params[0].get_int();
1221 map<string, int64> mapAccountBalances;
1222 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1223 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1224 mapAccountBalances[entry.second] = 0;
1227 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1229 const CWalletTx& wtx = (*it).second;
1230 int64 nGeneratedImmature, nGeneratedMature, nFee;
1231 string strSentAccount;
1232 list<pair<CBitcoinAddress, int64> > listReceived;
1233 list<pair<CBitcoinAddress, int64> > listSent;
1234 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1235 mapAccountBalances[strSentAccount] -= nFee;
1236 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1237 mapAccountBalances[strSentAccount] -= s.second;
1238 if (wtx.GetDepthInMainChain() >= nMinDepth)
1240 mapAccountBalances[""] += nGeneratedMature;
1241 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1242 if (pwalletMain->mapAddressBook.count(r.first))
1243 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1245 mapAccountBalances[""] += r.second;
1249 list<CAccountingEntry> acentries;
1250 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1251 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1252 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1255 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1256 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1261 Value gettransaction(const Array& params, bool fHelp)
1263 if (fHelp || params.size() != 1)
1264 throw runtime_error(
1265 "gettransaction <txid>\n"
1266 "Get detailed information about <txid>");
1269 hash.SetHex(params[0].get_str());
1273 if (!pwalletMain->mapWallet.count(hash))
1274 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1275 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1277 int64 nCredit = wtx.GetCredit();
1278 int64 nDebit = wtx.GetDebit();
1279 int64 nNet = nCredit - nDebit;
1280 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1282 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1284 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1286 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1289 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1290 entry.push_back(Pair("details", details));
1296 Value backupwallet(const Array& params, bool fHelp)
1298 if (fHelp || params.size() != 1)
1299 throw runtime_error(
1300 "backupwallet <destination>\n"
1301 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1303 string strDest = params[0].get_str();
1304 BackupWallet(*pwalletMain, strDest);
1310 Value keypoolrefill(const Array& params, bool fHelp)
1312 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1313 throw runtime_error(
1315 "Fills the keypool, requires wallet passphrase to be set.");
1316 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1317 throw runtime_error(
1319 "Fills the keypool.");
1321 if (pwalletMain->IsLocked())
1322 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1324 pwalletMain->TopUpKeyPool();
1326 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1327 throw JSONRPCError(-4, "Error refreshing keypool.");
1333 void ThreadTopUpKeyPool(void* parg)
1335 pwalletMain->TopUpKeyPool();
1338 void ThreadCleanWalletPassphrase(void* parg)
1340 int64 nMyWakeTime = GetTime() + *((int*)parg);
1342 if (nWalletUnlockTime == 0)
1344 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1346 nWalletUnlockTime = nMyWakeTime;
1349 while (GetTime() < nWalletUnlockTime)
1350 Sleep(GetTime() - nWalletUnlockTime);
1352 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1354 nWalletUnlockTime = 0;
1359 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1361 if (nWalletUnlockTime < nMyWakeTime)
1362 nWalletUnlockTime = nMyWakeTime;
1368 pwalletMain->Lock();
1373 Value walletpassphrase(const Array& params, bool fHelp)
1375 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1376 throw runtime_error(
1377 "walletpassphrase <passphrase> <timeout>\n"
1378 "Stores the wallet decryption key in memory for <timeout> seconds.");
1381 if (!pwalletMain->IsCrypted())
1382 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1384 if (!pwalletMain->IsLocked())
1385 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1387 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1388 string strWalletPass;
1389 strWalletPass.reserve(100);
1390 mlock(&strWalletPass[0], strWalletPass.capacity());
1391 strWalletPass = params[0].get_str();
1393 if (strWalletPass.length() > 0)
1395 if (!pwalletMain->Unlock(strWalletPass))
1397 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1398 munlock(&strWalletPass[0], strWalletPass.capacity());
1399 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1401 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1402 munlock(&strWalletPass[0], strWalletPass.capacity());
1405 throw runtime_error(
1406 "walletpassphrase <passphrase> <timeout>\n"
1407 "Stores the wallet decryption key in memory for <timeout> seconds.");
1409 CreateThread(ThreadTopUpKeyPool, NULL);
1410 int* pnSleepTime = new int(params[1].get_int());
1411 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1417 Value walletpassphrasechange(const Array& params, bool fHelp)
1419 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1420 throw runtime_error(
1421 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1422 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1425 if (!pwalletMain->IsCrypted())
1426 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1428 string strOldWalletPass;
1429 strOldWalletPass.reserve(100);
1430 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1431 strOldWalletPass = params[0].get_str();
1433 string strNewWalletPass;
1434 strNewWalletPass.reserve(100);
1435 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1436 strNewWalletPass = params[1].get_str();
1438 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1439 throw runtime_error(
1440 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1441 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1443 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1445 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1446 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1447 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1448 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1449 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1451 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1452 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1453 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1454 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1460 Value walletlock(const Array& params, bool fHelp)
1462 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1463 throw runtime_error(
1465 "Removes the wallet encryption key from memory, locking the wallet.\n"
1466 "After calling this method, you will need to call walletpassphrase again\n"
1467 "before being able to call any methods which require the wallet to be unlocked.");
1470 if (!pwalletMain->IsCrypted())
1471 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1473 pwalletMain->Lock();
1474 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1476 nWalletUnlockTime = 0;
1483 Value encryptwallet(const Array& params, bool fHelp)
1485 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1486 throw runtime_error(
1487 "encryptwallet <passphrase>\n"
1488 "Encrypts the wallet with <passphrase>.");
1491 if (pwalletMain->IsCrypted())
1492 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1494 string strWalletPass;
1495 strWalletPass.reserve(100);
1496 mlock(&strWalletPass[0], strWalletPass.capacity());
1497 strWalletPass = params[0].get_str();
1499 if (strWalletPass.length() < 1)
1500 throw runtime_error(
1501 "encryptwallet <passphrase>\n"
1502 "Encrypts the wallet with <passphrase>.");
1504 if (!pwalletMain->EncryptWallet(strWalletPass))
1506 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1507 munlock(&strWalletPass[0], strWalletPass.capacity());
1508 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1510 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1511 munlock(&strWalletPass[0], strWalletPass.capacity());
1517 Value validateaddress(const Array& params, bool fHelp)
1519 if (fHelp || params.size() != 1)
1520 throw runtime_error(
1521 "validateaddress <bitcoinaddress>\n"
1522 "Return information about <bitcoinaddress>.");
1524 CBitcoinAddress address(params[0].get_str());
1525 bool isValid = address.IsValid();
1528 ret.push_back(Pair("isvalid", isValid));
1531 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1532 // version of the address:
1533 string currentAddress = address.ToString();
1534 ret.push_back(Pair("address", currentAddress));
1535 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1536 if (pwalletMain->mapAddressBook.count(address))
1537 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1543 Value getwork(const Array& params, bool fHelp)
1545 if (fHelp || params.size() > 1)
1546 throw runtime_error(
1548 "If [data] is not specified, returns formatted hash data to work on:\n"
1549 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1550 " \"data\" : block data\n"
1551 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1552 " \"target\" : little endian hash target\n"
1553 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1556 throw JSONRPCError(-9, "Bitcoin is not connected!");
1558 if (IsInitialBlockDownload())
1559 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1561 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1562 static mapNewBlock_t mapNewBlock;
1563 static vector<CBlock*> vNewBlock;
1564 static CReserveKey reservekey(pwalletMain);
1566 if (params.size() == 0)
1569 static unsigned int nTransactionsUpdatedLast;
1570 static CBlockIndex* pindexPrev;
1571 static int64 nStart;
1572 static CBlock* pblock;
1573 if (pindexPrev != pindexBest ||
1574 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1576 if (pindexPrev != pindexBest)
1578 // Deallocate old blocks since they're obsolete now
1579 mapNewBlock.clear();
1580 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1584 nTransactionsUpdatedLast = nTransactionsUpdated;
1585 pindexPrev = pindexBest;
1589 pblock = CreateNewBlock(reservekey);
1591 throw JSONRPCError(-7, "Out of memory");
1592 vNewBlock.push_back(pblock);
1596 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1599 // Update nExtraNonce
1600 static unsigned int nExtraNonce = 0;
1601 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1604 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1606 // Prebuild hash buffers
1610 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1612 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1615 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1616 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1617 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1618 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1624 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1625 if (vchData.size() != 128)
1626 throw JSONRPCError(-8, "Invalid parameter");
1627 CBlock* pdata = (CBlock*)&vchData[0];
1630 for (int i = 0; i < 128/4; i++)
1631 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1634 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1636 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1638 pblock->nTime = pdata->nTime;
1639 pblock->nNonce = pdata->nNonce;
1640 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1641 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1643 return CheckWork(pblock, *pwalletMain, reservekey);
1648 Value getmemorypool(const Array& params, bool fHelp)
1650 if (fHelp || params.size() > 1)
1651 throw runtime_error(
1652 "getmemorypool [data]\n"
1653 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1654 " \"version\" : block version\n"
1655 " \"previousblockhash\" : hash of current highest block\n"
1656 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1657 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1658 " \"time\" : timestamp appropriate for next block\n"
1659 " \"bits\" : compressed target of next block\n"
1660 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1662 if (params.size() == 0)
1665 throw JSONRPCError(-9, "Bitcoin is not connected!");
1667 if (IsInitialBlockDownload())
1668 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1670 static CReserveKey reservekey(pwalletMain);
1673 static unsigned int nTransactionsUpdatedLast;
1674 static CBlockIndex* pindexPrev;
1675 static int64 nStart;
1676 static CBlock* pblock;
1677 if (pindexPrev != pindexBest ||
1678 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1680 nTransactionsUpdatedLast = nTransactionsUpdated;
1681 pindexPrev = pindexBest;
1687 pblock = CreateNewBlock(reservekey);
1689 throw JSONRPCError(-7, "Out of memory");
1693 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1697 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1704 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1708 result.push_back(Pair("version", pblock->nVersion));
1709 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1710 result.push_back(Pair("transactions", transactions));
1711 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1712 result.push_back(Pair("time", (int64_t)pblock->nTime));
1713 result.push_back(Pair("bits", (int64_t)pblock->nBits));
1719 CDataStream ssBlock(ParseHex(params[0].get_str()));
1723 return ProcessBlock(NULL, &pblock);
1741 pair<string, rpcfn_type> pCallTable[] =
1743 make_pair("help", &help),
1744 make_pair("stop", &stop),
1745 make_pair("getblockcount", &getblockcount),
1746 make_pair("getblocknumber", &getblocknumber),
1747 make_pair("getconnectioncount", &getconnectioncount),
1748 make_pair("getdifficulty", &getdifficulty),
1749 make_pair("getgenerate", &getgenerate),
1750 make_pair("setgenerate", &setgenerate),
1751 make_pair("gethashespersec", &gethashespersec),
1752 make_pair("getinfo", &getinfo),
1753 make_pair("getnewaddress", &getnewaddress),
1754 make_pair("getaccountaddress", &getaccountaddress),
1755 make_pair("setaccount", &setaccount),
1756 make_pair("getaccount", &getaccount),
1757 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1758 make_pair("sendtoaddress", &sendtoaddress),
1759 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1760 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1761 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1762 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1763 make_pair("backupwallet", &backupwallet),
1764 make_pair("keypoolrefill", &keypoolrefill),
1765 make_pair("walletpassphrase", &walletpassphrase),
1766 make_pair("walletpassphrasechange", &walletpassphrasechange),
1767 make_pair("walletlock", &walletlock),
1768 make_pair("encryptwallet", &encryptwallet),
1769 make_pair("validateaddress", &validateaddress),
1770 make_pair("getbalance", &getbalance),
1771 make_pair("move", &movecmd),
1772 make_pair("sendfrom", &sendfrom),
1773 make_pair("sendmany", &sendmany),
1774 make_pair("gettransaction", &gettransaction),
1775 make_pair("listtransactions", &listtransactions),
1776 make_pair("signmessage", &signmessage),
1777 make_pair("verifymessage", &verifymessage),
1778 make_pair("getwork", &getwork),
1779 make_pair("listaccounts", &listaccounts),
1780 make_pair("settxfee", &settxfee),
1781 make_pair("getmemorypool", &getmemorypool),
1783 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1785 string pAllowInSafeMode[] =
1791 "getconnectioncount",
1798 "getaccountaddress",
1800 "getaddressesbyaccount",
1809 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1817 // This ain't Apache. We're just using HTTP header for the length field
1818 // and to be compatible with other JSON-RPC implementations.
1821 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1824 s << "POST / HTTP/1.1\r\n"
1825 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1826 << "Host: 127.0.0.1\r\n"
1827 << "Content-Type: application/json\r\n"
1828 << "Content-Length: " << strMsg.size() << "\r\n"
1829 << "Connection: close\r\n"
1830 << "Accept: application/json\r\n";
1831 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1832 s << item.first << ": " << item.second << "\r\n";
1833 s << "\r\n" << strMsg;
1838 string rfc1123Time()
1843 struct tm* now_gmt = gmtime(&now);
1844 string locale(setlocale(LC_TIME, NULL));
1845 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1846 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1847 setlocale(LC_TIME, locale.c_str());
1848 return string(buffer);
1851 static string HTTPReply(int nStatus, const string& strMsg)
1854 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1856 "Server: bitcoin-json-rpc/%s\r\n"
1857 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1858 "Content-Type: text/html\r\n"
1859 "Content-Length: 296\r\n"
1861 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1862 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1865 "<TITLE>Error</TITLE>\r\n"
1866 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1868 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1869 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1871 if (nStatus == 200) strStatus = "OK";
1872 else if (nStatus == 400) strStatus = "Bad Request";
1873 else if (nStatus == 403) strStatus = "Forbidden";
1874 else if (nStatus == 404) strStatus = "Not Found";
1875 else if (nStatus == 500) strStatus = "Internal Server Error";
1877 "HTTP/1.1 %d %s\r\n"
1879 "Connection: close\r\n"
1880 "Content-Length: %d\r\n"
1881 "Content-Type: application/json\r\n"
1882 "Server: bitcoin-json-rpc/%s\r\n"
1887 rfc1123Time().c_str(),
1889 FormatFullVersion().c_str(),
1893 int ReadHTTPStatus(std::basic_istream<char>& stream)
1896 getline(stream, str);
1897 vector<string> vWords;
1898 boost::split(vWords, str, boost::is_any_of(" "));
1899 if (vWords.size() < 2)
1901 return atoi(vWords[1].c_str());
1904 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1910 std::getline(stream, str);
1911 if (str.empty() || str == "\r")
1913 string::size_type nColon = str.find(":");
1914 if (nColon != string::npos)
1916 string strHeader = str.substr(0, nColon);
1917 boost::trim(strHeader);
1918 boost::to_lower(strHeader);
1919 string strValue = str.substr(nColon+1);
1920 boost::trim(strValue);
1921 mapHeadersRet[strHeader] = strValue;
1922 if (strHeader == "content-length")
1923 nLen = atoi(strValue.c_str());
1929 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1931 mapHeadersRet.clear();
1935 int nStatus = ReadHTTPStatus(stream);
1938 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1939 if (nLen < 0 || nLen > MAX_SIZE)
1945 vector<char> vch(nLen);
1946 stream.read(&vch[0], nLen);
1947 strMessageRet = string(vch.begin(), vch.end());
1953 bool HTTPAuthorized(map<string, string>& mapHeaders)
1955 string strAuth = mapHeaders["authorization"];
1956 if (strAuth.substr(0,6) != "Basic ")
1958 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1959 string strUserPass = DecodeBase64(strUserPass64);
1960 string::size_type nColon = strUserPass.find(":");
1961 if (nColon == string::npos)
1963 string strUser = strUserPass.substr(0, nColon);
1964 string strPassword = strUserPass.substr(nColon+1);
1965 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1969 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1970 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1971 // unspecified (HTTP errors and contents of 'error').
1973 // 1.0 spec: http://json-rpc.org/wiki/specification
1974 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1975 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1978 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1981 request.push_back(Pair("method", strMethod));
1982 request.push_back(Pair("params", params));
1983 request.push_back(Pair("id", id));
1984 return write_string(Value(request), false) + "\n";
1987 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1990 if (error.type() != null_type)
1991 reply.push_back(Pair("result", Value::null));
1993 reply.push_back(Pair("result", result));
1994 reply.push_back(Pair("error", error));
1995 reply.push_back(Pair("id", id));
1996 return write_string(Value(reply), false) + "\n";
1999 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2001 // Send error reply from json-rpc error object
2003 int code = find_value(objError, "code").get_int();
2004 if (code == -32600) nStatus = 400;
2005 else if (code == -32601) nStatus = 404;
2006 string strReply = JSONRPCReply(Value::null, objError, id);
2007 stream << HTTPReply(nStatus, strReply) << std::flush;
2010 bool ClientAllowed(const string& strAddress)
2012 if (strAddress == asio::ip::address_v4::loopback().to_string())
2014 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2015 BOOST_FOREACH(string strAllow, vAllow)
2016 if (WildcardMatch(strAddress, strAllow))
2023 // IOStream device that speaks SSL but can also speak non-SSL
2025 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2027 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2029 fUseSSL = fUseSSLIn;
2030 fNeedHandshake = fUseSSLIn;
2033 void handshake(ssl::stream_base::handshake_type role)
2035 if (!fNeedHandshake) return;
2036 fNeedHandshake = false;
2037 stream.handshake(role);
2039 std::streamsize read(char* s, std::streamsize n)
2041 handshake(ssl::stream_base::server); // HTTPS servers read first
2042 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2043 return stream.next_layer().read_some(asio::buffer(s, n));
2045 std::streamsize write(const char* s, std::streamsize n)
2047 handshake(ssl::stream_base::client); // HTTPS clients write first
2048 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2049 return asio::write(stream.next_layer(), asio::buffer(s, n));
2051 bool connect(const std::string& server, const std::string& port)
2053 ip::tcp::resolver resolver(stream.get_io_service());
2054 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2055 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2056 ip::tcp::resolver::iterator end;
2057 boost::system::error_code error = asio::error::host_not_found;
2058 while (error && endpoint_iterator != end)
2060 stream.lowest_layer().close();
2061 stream.lowest_layer().connect(*endpoint_iterator++, error);
2069 bool fNeedHandshake;
2075 void ThreadRPCServer(void* parg)
2077 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2080 vnThreadsRunning[4]++;
2081 ThreadRPCServer2(parg);
2082 vnThreadsRunning[4]--;
2084 catch (std::exception& e) {
2085 vnThreadsRunning[4]--;
2086 PrintException(&e, "ThreadRPCServer()");
2088 vnThreadsRunning[4]--;
2089 PrintException(NULL, "ThreadRPCServer()");
2091 printf("ThreadRPCServer exiting\n");
2094 void ThreadRPCServer2(void* parg)
2096 printf("ThreadRPCServer started\n");
2098 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2100 string strWhatAmI = "To use bitcoind";
2101 if (mapArgs.count("-server"))
2102 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2103 else if (mapArgs.count("-daemon"))
2104 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2106 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2107 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2109 GetConfigFile().c_str());
2110 CreateThread(Shutdown, NULL);
2114 bool fUseSSL = GetBoolArg("-rpcssl");
2115 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2117 asio::io_service io_service;
2118 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2119 ip::tcp::acceptor acceptor(io_service, endpoint);
2121 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2124 ssl::context context(io_service, ssl::context::sslv23);
2127 context.set_options(ssl::context::no_sslv2);
2128 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2129 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2130 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2131 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2132 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2133 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2134 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2135 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2137 string ciphers = GetArg("-rpcsslciphers",
2138 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2139 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2143 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2148 // Accept connection
2150 SSLStream sslStream(io_service, context);
2151 SSLIOStreamDevice d(sslStream, fUseSSL);
2152 iostreams::stream<SSLIOStreamDevice> stream(d);
2154 ip::tcp::iostream stream;
2157 ip::tcp::endpoint peer;
2158 vnThreadsRunning[4]--;
2160 acceptor.accept(sslStream.lowest_layer(), peer);
2162 acceptor.accept(*stream.rdbuf(), peer);
2164 vnThreadsRunning[4]++;
2168 // Restrict callers by IP
2169 if (!ClientAllowed(peer.address().to_string()))
2171 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2173 stream << HTTPReply(403, "") << std::flush;
2177 map<string, string> mapHeaders;
2180 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2181 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2184 printf("ThreadRPCServer ReadHTTP timeout\n");
2188 // Check authorization
2189 if (mapHeaders.count("authorization") == 0)
2191 stream << HTTPReply(401, "") << std::flush;
2194 if (!HTTPAuthorized(mapHeaders))
2196 // Deter brute-forcing short passwords
2197 if (mapArgs["-rpcpassword"].size() < 15)
2200 stream << HTTPReply(401, "") << std::flush;
2201 printf("ThreadRPCServer incorrect password attempt\n");
2205 Value id = Value::null;
2210 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2211 throw JSONRPCError(-32700, "Parse error");
2212 const Object& request = valRequest.get_obj();
2214 // Parse id now so errors from here on will have the id
2215 id = find_value(request, "id");
2218 Value valMethod = find_value(request, "method");
2219 if (valMethod.type() == null_type)
2220 throw JSONRPCError(-32600, "Missing method");
2221 if (valMethod.type() != str_type)
2222 throw JSONRPCError(-32600, "Method must be a string");
2223 string strMethod = valMethod.get_str();
2224 if (strMethod != "getwork" && strMethod != "getmemorypool")
2225 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2228 Value valParams = find_value(request, "params");
2230 if (valParams.type() == array_type)
2231 params = valParams.get_array();
2232 else if (valParams.type() == null_type)
2235 throw JSONRPCError(-32600, "Params must be an array");
2238 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2239 if (mi == mapCallTable.end())
2240 throw JSONRPCError(-32601, "Method not found");
2242 // Observe safe mode
2243 string strWarning = GetWarnings("rpc");
2244 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2245 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2251 CRITICAL_BLOCK(cs_main)
2252 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2253 result = (*(*mi).second)(params, false);
2256 string strReply = JSONRPCReply(result, Value::null, id);
2257 stream << HTTPReply(200, strReply) << std::flush;
2259 catch (std::exception& e)
2261 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2264 catch (Object& objError)
2266 ErrorReply(stream, objError, id);
2268 catch (std::exception& e)
2270 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2278 Object CallRPC(const string& strMethod, const Array& params)
2280 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2281 throw runtime_error(strprintf(
2282 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2283 "If the file does not exist, create it with owner-readable-only file permissions."),
2284 GetConfigFile().c_str()));
2286 // Connect to localhost
2287 bool fUseSSL = GetBoolArg("-rpcssl");
2289 asio::io_service io_service;
2290 ssl::context context(io_service, ssl::context::sslv23);
2291 context.set_options(ssl::context::no_sslv2);
2292 SSLStream sslStream(io_service, context);
2293 SSLIOStreamDevice d(sslStream, fUseSSL);
2294 iostreams::stream<SSLIOStreamDevice> stream(d);
2295 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2296 throw runtime_error("couldn't connect to server");
2299 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2301 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2303 throw runtime_error("couldn't connect to server");
2307 // HTTP basic authentication
2308 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2309 map<string, string> mapRequestHeaders;
2310 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2313 string strRequest = JSONRPCRequest(strMethod, params, 1);
2314 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2315 stream << strPost << std::flush;
2318 map<string, string> mapHeaders;
2320 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2322 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2323 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2324 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2325 else if (strReply.empty())
2326 throw runtime_error("no response from server");
2330 if (!read_string(strReply, valReply))
2331 throw runtime_error("couldn't parse reply from server");
2332 const Object& reply = valReply.get_obj();
2334 throw runtime_error("expected reply to have result, error and id properties");
2342 template<typename T>
2343 void ConvertTo(Value& value)
2345 if (value.type() == str_type)
2347 // reinterpret string as unquoted json value
2349 if (!read_string(value.get_str(), value2))
2350 throw runtime_error("type mismatch");
2351 value = value2.get_value<T>();
2355 value = value.get_value<T>();
2359 int CommandLineRPC(int argc, char *argv[])
2366 while (argc > 1 && IsSwitchChar(argv[1][0]))
2374 throw runtime_error("too few parameters");
2375 string strMethod = argv[1];
2377 // Parameters default to strings
2379 for (int i = 2; i < argc; i++)
2380 params.push_back(argv[i]);
2381 int n = params.size();
2384 // Special case non-string parameter types
2386 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2387 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2388 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2389 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2390 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2391 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2392 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2393 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2394 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2395 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2396 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2397 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2398 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2399 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2400 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2401 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2402 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2403 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2404 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2405 if (strMethod == "sendmany" && n > 1)
2407 string s = params[1].get_str();
2409 if (!read_string(s, v) || v.type() != obj_type)
2410 throw runtime_error("type mismatch");
2411 params[1] = v.get_obj();
2413 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2416 Object reply = CallRPC(strMethod, params);
2419 const Value& result = find_value(reply, "result");
2420 const Value& error = find_value(reply, "error");
2422 if (error.type() != null_type)
2425 strPrint = "error: " + write_string(error, false);
2426 int code = find_value(error.get_obj(), "code").get_int();
2432 if (result.type() == null_type)
2434 else if (result.type() == str_type)
2435 strPrint = result.get_str();
2437 strPrint = write_string(result, true);
2440 catch (std::exception& e)
2442 strPrint = string("error: ") + e.what();
2447 PrintException(NULL, "CommandLineRPC()");
2452 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2461 int main(int argc, char *argv[])
2464 // Turn off microsoft heap dump noise
2465 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2466 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2468 setbuf(stdin, NULL);
2469 setbuf(stdout, NULL);
2470 setbuf(stderr, NULL);
2474 if (argc >= 2 && string(argv[1]) == "-server")
2476 printf("server ready\n");
2477 ThreadRPCServer(NULL);
2481 return CommandLineRPC(argc, argv);
2484 catch (std::exception& e) {
2485 PrintException(&e, "main()");
2487 PrintException(NULL, "main()");