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 char* format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
61 if (ret < 0 || ret >= limit)
67 #if defined(__WXMSW__) && defined(GUI)
68 MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
70 fprintf(stdout, "%s", buffer);
75 int64 AmountFromValue(const Value& value)
77 double dAmount = value.get_real();
78 if (dAmount <= 0.0 || dAmount > 21000000.0)
79 throw JSONRPCError(-3, "Invalid amount");
80 int64 nAmount = roundint64(dAmount * COIN);
81 if (!MoneyRange(nAmount))
82 throw JSONRPCError(-3, "Invalid amount");
86 Value ValueFromAmount(int64 amount)
88 return (double)amount / (double)COIN;
91 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
93 int confirms = wtx.GetDepthInMainChain();
94 entry.push_back(Pair("confirmations", confirms));
97 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
98 entry.push_back(Pair("blockindex", wtx.nIndex));
100 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
101 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
102 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
103 entry.push_back(Pair(item.first, item.second));
106 string AccountFromValue(const Value& value)
108 string strAccount = value.get_str();
109 if (strAccount == "*")
110 throw JSONRPCError(-11, "Invalid account name");
117 /// Note: This interface may still be subject to change.
121 Value help(const Array& params, bool fHelp)
123 if (fHelp || params.size() > 1)
126 "List commands, or get help for a command.");
129 if (params.size() > 0)
130 strCommand = params[0].get_str();
133 set<rpcfn_type> setDone;
134 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
136 string strMethod = (*mi).first;
137 // We already filter duplicates, but these deprecated screw up the sort order
138 if (strMethod == "getamountreceived" ||
139 strMethod == "getallreceived" ||
140 (strMethod.find("label") != string::npos))
142 if (strCommand != "" && strMethod != strCommand)
147 rpcfn_type pfn = (*mi).second;
148 if (setDone.insert(pfn).second)
149 (*pfn)(params, true);
151 catch (std::exception& e)
153 // Help text is returned in an exception
154 string strHelp = string(e.what());
155 if (strCommand == "")
156 if (strHelp.find('\n') != -1)
157 strHelp = strHelp.substr(0, strHelp.find('\n'));
158 strRet += strHelp + "\n";
162 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
163 strRet = strRet.substr(0,strRet.size()-1);
168 Value stop(const Array& params, bool fHelp)
170 if (fHelp || params.size() != 0)
173 "Stop bitcoin server.");
175 // Shutdown will take long enough that the response should get back
176 CreateThread(Shutdown, NULL);
177 return "bitcoin server stopping";
181 Value getblockcount(const Array& params, bool fHelp)
183 if (fHelp || params.size() != 0)
186 "Returns the number of blocks in the longest block chain.");
192 Value getblocknumber(const Array& params, bool fHelp)
194 if (fHelp || params.size() != 0)
197 "Returns the block number of the latest block in the longest block chain.");
203 Value getconnectioncount(const Array& params, bool fHelp)
205 if (fHelp || params.size() != 0)
207 "getconnectioncount\n"
208 "Returns the number of connections to other nodes.");
210 return (int)vNodes.size();
214 double GetDifficulty()
216 // Floating point number that is a multiple of the minimum difficulty,
217 // minimum difficulty = 1.0.
219 if (pindexBest == NULL)
221 int nShift = (pindexBest->nBits >> 24) & 0xff;
224 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
240 Value getdifficulty(const Array& params, bool fHelp)
242 if (fHelp || params.size() != 0)
245 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
247 return GetDifficulty();
251 Value getgenerate(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Returns true or false.");
258 return (bool)fGenerateBitcoins;
262 Value setgenerate(const Array& params, bool fHelp)
264 if (fHelp || params.size() < 1 || params.size() > 2)
266 "setgenerate <generate> [genproclimit]\n"
267 "<generate> is true or false to turn generation on or off.\n"
268 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
270 bool fGenerate = true;
271 if (params.size() > 0)
272 fGenerate = params[0].get_bool();
274 if (params.size() > 1)
276 int nGenProcLimit = params[1].get_int();
277 fLimitProcessors = (nGenProcLimit != -1);
278 WriteSetting("fLimitProcessors", fLimitProcessors);
279 if (nGenProcLimit != -1)
280 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
281 if (nGenProcLimit == 0)
285 GenerateBitcoins(fGenerate, pwalletMain);
290 Value gethashespersec(const Array& params, bool fHelp)
292 if (fHelp || params.size() != 0)
295 "Returns a recent hashes per second performance measurement while generating.");
297 if (GetTimeMillis() - nHPSTimerStart > 8000)
298 return (boost::int64_t)0;
299 return (boost::int64_t)dHashesPerSec;
303 Value getinfo(const Array& params, bool fHelp)
305 if (fHelp || params.size() != 0)
308 "Returns an object containing various state info.");
311 obj.push_back(Pair("version", (int)VERSION));
312 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
313 obj.push_back(Pair("blocks", (int)nBestHeight));
314 obj.push_back(Pair("connections", (int)vNodes.size()));
315 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
316 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
317 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
318 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
319 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
320 obj.push_back(Pair("testnet", fTestNet));
321 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
322 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
323 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
324 if (pwalletMain->IsCrypted())
325 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
326 obj.push_back(Pair("errors", GetWarnings("statusbar")));
331 Value getnewaddress(const Array& params, bool fHelp)
333 if (fHelp || params.size() > 1)
335 "getnewaddress [account]\n"
336 "Returns a new bitcoin address for receiving payments. "
337 "If [account] is specified (recommended), it is added to the address book "
338 "so payments received with the address will be credited to [account].");
340 // Parse the account first so we don't generate a key if there's an error
342 if (params.size() > 0)
343 strAccount = AccountFromValue(params[0]);
345 if (!pwalletMain->IsLocked())
346 pwalletMain->TopUpKeyPool();
348 // Generate a new key that is added to wallet
349 std::vector<unsigned char> newKey;
350 if (!pwalletMain->GetKeyFromPool(newKey, false))
351 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
352 CBitcoinAddress address(newKey);
354 pwalletMain->SetAddressBookName(address, strAccount);
356 return address.ToString();
360 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
362 CWalletDB walletdb(pwalletMain->strWalletFile);
365 walletdb.ReadAccount(strAccount, account);
367 bool bKeyUsed = false;
369 // Check if the current key has been used
370 if (!account.vchPubKey.empty())
372 CScript scriptPubKey;
373 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
374 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
375 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
378 const CWalletTx& wtx = (*it).second;
379 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
380 if (txout.scriptPubKey == scriptPubKey)
385 // Generate a new key
386 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
388 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
389 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
391 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
392 walletdb.WriteAccount(strAccount, account);
395 return CBitcoinAddress(account.vchPubKey);
398 Value getaccountaddress(const Array& params, bool fHelp)
400 if (fHelp || params.size() != 1)
402 "getaccountaddress <account>\n"
403 "Returns the current bitcoin address for receiving payments to this account.");
405 // Parse the account first so we don't generate a key if there's an error
406 string strAccount = AccountFromValue(params[0]);
410 ret = GetAccountAddress(strAccount).ToString();
417 Value setaccount(const Array& params, bool fHelp)
419 if (fHelp || params.size() < 1 || params.size() > 2)
421 "setaccount <bitcoinaddress> <account>\n"
422 "Sets the account associated with the given address.");
424 CBitcoinAddress address(params[0].get_str());
425 if (!address.IsValid())
426 throw JSONRPCError(-5, "Invalid bitcoin address");
430 if (params.size() > 1)
431 strAccount = AccountFromValue(params[1]);
433 // Detect when changing the account of an address that is the 'unused current key' of another account:
434 if (pwalletMain->mapAddressBook.count(address))
436 string strOldAccount = pwalletMain->mapAddressBook[address];
437 if (address == GetAccountAddress(strOldAccount))
438 GetAccountAddress(strOldAccount, true);
441 pwalletMain->SetAddressBookName(address, strAccount);
447 Value getaccount(const Array& params, bool fHelp)
449 if (fHelp || params.size() != 1)
451 "getaccount <bitcoinaddress>\n"
452 "Returns the account associated with the given address.");
454 CBitcoinAddress address(params[0].get_str());
455 if (!address.IsValid())
456 throw JSONRPCError(-5, "Invalid bitcoin address");
459 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
460 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
461 strAccount = (*mi).second;
466 Value getaddressesbyaccount(const Array& params, bool fHelp)
468 if (fHelp || params.size() != 1)
470 "getaddressesbyaccount <account>\n"
471 "Returns the list of addresses for the given account.");
473 string strAccount = AccountFromValue(params[0]);
475 // Find all addresses that have the given account
477 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
479 const CBitcoinAddress& address = item.first;
480 const string& strName = item.second;
481 if (strName == strAccount)
482 ret.push_back(address.ToString());
487 Value settxfee(const Array& params, bool fHelp)
489 if (fHelp || params.size() < 1 || params.size() > 1)
491 "settxfee <amount>\n"
492 "<amount> is a real and is rounded to the nearest 0.00000001");
496 if (params[0].get_real() != 0.0)
497 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
499 nTransactionFee = nAmount;
503 Value sendtoaddress(const Array& params, bool fHelp)
505 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
507 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
508 "<amount> is a real and is rounded to the nearest 0.00000001\n"
509 "requires wallet passphrase to be set with walletpassphrase first");
510 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
512 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
513 "<amount> is a real and is rounded to the nearest 0.00000001");
515 CBitcoinAddress address(params[0].get_str());
516 if (!address.IsValid())
517 throw JSONRPCError(-5, "Invalid bitcoin address");
520 int64 nAmount = AmountFromValue(params[1]);
524 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
525 wtx.mapValue["comment"] = params[2].get_str();
526 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
527 wtx.mapValue["to"] = params[3].get_str();
529 if (pwalletMain->IsLocked())
530 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
532 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
534 throw JSONRPCError(-4, strError);
536 return wtx.GetHash().GetHex();
540 Value getreceivedbyaddress(const Array& params, bool fHelp)
542 if (fHelp || params.size() < 1 || params.size() > 2)
544 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
545 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
548 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
549 CScript scriptPubKey;
550 if (!address.IsValid())
551 throw JSONRPCError(-5, "Invalid bitcoin address");
552 scriptPubKey.SetBitcoinAddress(address);
553 if (!IsMine(*pwalletMain,scriptPubKey))
556 // Minimum confirmations
558 if (params.size() > 1)
559 nMinDepth = params[1].get_int();
563 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
565 const CWalletTx& wtx = (*it).second;
566 if (wtx.IsCoinBase() || !wtx.IsFinal())
569 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
570 if (txout.scriptPubKey == scriptPubKey)
571 if (wtx.GetDepthInMainChain() >= nMinDepth)
572 nAmount += txout.nValue;
575 return ValueFromAmount(nAmount);
579 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
581 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
583 const CBitcoinAddress& address = item.first;
584 const string& strName = item.second;
585 if (strName == strAccount)
586 setAddress.insert(address);
591 Value getreceivedbyaccount(const Array& params, bool fHelp)
593 if (fHelp || params.size() < 1 || params.size() > 2)
595 "getreceivedbyaccount <account> [minconf=1]\n"
596 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
598 // Minimum confirmations
600 if (params.size() > 1)
601 nMinDepth = params[1].get_int();
603 // Get the set of pub keys that have the label
604 string strAccount = AccountFromValue(params[0]);
605 set<CBitcoinAddress> setAddress;
606 GetAccountAddresses(strAccount, setAddress);
610 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
612 const CWalletTx& wtx = (*it).second;
613 if (wtx.IsCoinBase() || !wtx.IsFinal())
616 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
618 CBitcoinAddress address;
619 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
620 if (wtx.GetDepthInMainChain() >= nMinDepth)
621 nAmount += txout.nValue;
625 return (double)nAmount / (double)COIN;
629 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
633 // Tally wallet transactions
634 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
636 const CWalletTx& wtx = (*it).second;
640 int64 nGenerated, nReceived, nSent, nFee;
641 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
643 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
644 nBalance += nReceived;
645 nBalance += nGenerated - nSent - nFee;
648 // Tally internal accounting entries
649 nBalance += walletdb.GetAccountCreditDebit(strAccount);
654 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
656 CWalletDB walletdb(pwalletMain->strWalletFile);
657 return GetAccountBalance(walletdb, strAccount, nMinDepth);
661 Value getbalance(const Array& params, bool fHelp)
663 if (fHelp || params.size() > 2)
665 "getbalance [account] [minconf=1]\n"
666 "If [account] is not specified, returns the server's total available balance.\n"
667 "If [account] is specified, returns the balance in the account.");
669 if (params.size() == 0)
670 return ValueFromAmount(pwalletMain->GetBalance());
673 if (params.size() > 1)
674 nMinDepth = params[1].get_int();
676 if (params[0].get_str() == "*") {
677 // Calculate total balance a different way from GetBalance()
678 // (GetBalance() sums up all unspent TxOuts)
679 // getbalance and getbalance '*' should always return the same number.
681 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
683 const CWalletTx& wtx = (*it).second;
687 int64 allGeneratedImmature, allGeneratedMature, allFee;
688 allGeneratedImmature = allGeneratedMature = allFee = 0;
689 string strSentAccount;
690 list<pair<CBitcoinAddress, int64> > listReceived;
691 list<pair<CBitcoinAddress, int64> > listSent;
692 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
693 if (wtx.GetDepthInMainChain() >= nMinDepth)
694 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
695 nBalance += r.second;
696 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
697 nBalance -= r.second;
699 nBalance += allGeneratedMature;
701 return ValueFromAmount(nBalance);
704 string strAccount = AccountFromValue(params[0]);
706 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
708 return ValueFromAmount(nBalance);
712 Value movecmd(const Array& params, bool fHelp)
714 if (fHelp || params.size() < 3 || params.size() > 5)
716 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
717 "Move from one account in your wallet to another.");
719 string strFrom = AccountFromValue(params[0]);
720 string strTo = AccountFromValue(params[1]);
721 int64 nAmount = AmountFromValue(params[2]);
722 if (params.size() > 3)
723 // unused parameter, used to be nMinDepth, keep type-checking it though
724 (void)params[3].get_int();
726 if (params.size() > 4)
727 strComment = params[4].get_str();
729 CWalletDB walletdb(pwalletMain->strWalletFile);
732 int64 nNow = GetAdjustedTime();
735 CAccountingEntry debit;
736 debit.strAccount = strFrom;
737 debit.nCreditDebit = -nAmount;
739 debit.strOtherAccount = strTo;
740 debit.strComment = strComment;
741 walletdb.WriteAccountingEntry(debit);
744 CAccountingEntry credit;
745 credit.strAccount = strTo;
746 credit.nCreditDebit = nAmount;
748 credit.strOtherAccount = strFrom;
749 credit.strComment = strComment;
750 walletdb.WriteAccountingEntry(credit);
752 walletdb.TxnCommit();
758 Value sendfrom(const Array& params, bool fHelp)
760 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
762 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
763 "<amount> is a real and is rounded to the nearest 0.00000001\n"
764 "requires wallet passphrase to be set with walletpassphrase first");
765 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
767 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
768 "<amount> is a real and is rounded to the nearest 0.00000001");
770 string strAccount = AccountFromValue(params[0]);
771 CBitcoinAddress address(params[1].get_str());
772 if (!address.IsValid())
773 throw JSONRPCError(-5, "Invalid bitcoin address");
774 int64 nAmount = AmountFromValue(params[2]);
776 if (params.size() > 3)
777 nMinDepth = params[3].get_int();
780 wtx.strFromAccount = strAccount;
781 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
782 wtx.mapValue["comment"] = params[4].get_str();
783 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
784 wtx.mapValue["to"] = params[5].get_str();
786 if (pwalletMain->IsLocked())
787 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
790 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
791 if (nAmount > nBalance)
792 throw JSONRPCError(-6, "Account has insufficient funds");
795 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
797 throw JSONRPCError(-4, strError);
799 return wtx.GetHash().GetHex();
803 Value sendmany(const Array& params, bool fHelp)
805 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
807 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
808 "amounts are double-precision floating point numbers\n"
809 "requires wallet passphrase to be set with walletpassphrase first");
810 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
812 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
813 "amounts are double-precision floating point numbers");
815 string strAccount = AccountFromValue(params[0]);
816 Object sendTo = params[1].get_obj();
818 if (params.size() > 2)
819 nMinDepth = params[2].get_int();
822 wtx.strFromAccount = strAccount;
823 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
824 wtx.mapValue["comment"] = params[3].get_str();
826 set<CBitcoinAddress> setAddress;
827 vector<pair<CScript, int64> > vecSend;
829 int64 totalAmount = 0;
830 BOOST_FOREACH(const Pair& s, sendTo)
832 CBitcoinAddress address(s.name_);
833 if (!address.IsValid())
834 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
836 if (setAddress.count(address))
837 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
838 setAddress.insert(address);
840 CScript scriptPubKey;
841 scriptPubKey.SetBitcoinAddress(address);
842 int64 nAmount = AmountFromValue(s.value_);
843 totalAmount += nAmount;
845 vecSend.push_back(make_pair(scriptPubKey, nAmount));
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 (totalAmount > nBalance)
854 throw JSONRPCError(-6, "Account has insufficient funds");
857 CReserveKey keyChange(pwalletMain);
858 int64 nFeeRequired = 0;
859 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
862 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
863 throw JSONRPCError(-6, "Insufficient funds");
864 throw JSONRPCError(-4, "Transaction creation failed");
866 if (!pwalletMain->CommitTransaction(wtx, keyChange))
867 throw JSONRPCError(-4, "Transaction commit failed");
869 return wtx.GetHash().GetHex();
884 Value ListReceived(const Array& params, bool fByAccounts)
886 // Minimum confirmations
888 if (params.size() > 0)
889 nMinDepth = params[0].get_int();
891 // Whether to include empty accounts
892 bool fIncludeEmpty = false;
893 if (params.size() > 1)
894 fIncludeEmpty = params[1].get_bool();
897 map<CBitcoinAddress, tallyitem> mapTally;
898 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
900 const CWalletTx& wtx = (*it).second;
901 if (wtx.IsCoinBase() || !wtx.IsFinal())
904 int nDepth = wtx.GetDepthInMainChain();
905 if (nDepth < nMinDepth)
908 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
910 CBitcoinAddress address;
911 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
914 tallyitem& item = mapTally[address];
915 item.nAmount += txout.nValue;
916 item.nConf = min(item.nConf, nDepth);
922 map<string, tallyitem> mapAccountTally;
923 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
925 const CBitcoinAddress& address = item.first;
926 const string& strAccount = item.second;
927 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
928 if (it == mapTally.end() && !fIncludeEmpty)
933 if (it != mapTally.end())
935 nAmount = (*it).second.nAmount;
936 nConf = (*it).second.nConf;
941 tallyitem& item = mapAccountTally[strAccount];
942 item.nAmount += nAmount;
943 item.nConf = min(item.nConf, nConf);
948 obj.push_back(Pair("address", address.ToString()));
949 obj.push_back(Pair("account", strAccount));
950 obj.push_back(Pair("label", strAccount)); // deprecated
951 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
952 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
959 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
961 int64 nAmount = (*it).second.nAmount;
962 int nConf = (*it).second.nConf;
964 obj.push_back(Pair("account", (*it).first));
965 obj.push_back(Pair("label", (*it).first)); // deprecated
966 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
967 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
975 Value listreceivedbyaddress(const Array& params, bool fHelp)
977 if (fHelp || params.size() > 2)
979 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
980 "[minconf] is the minimum number of confirmations before payments are included.\n"
981 "[includeempty] whether to include addresses that haven't received any payments.\n"
982 "Returns an array of objects containing:\n"
983 " \"address\" : receiving address\n"
984 " \"account\" : the account of the receiving address\n"
985 " \"amount\" : total amount received by the address\n"
986 " \"confirmations\" : number of confirmations of the most recent transaction included");
988 return ListReceived(params, false);
991 Value listreceivedbyaccount(const Array& params, bool fHelp)
993 if (fHelp || params.size() > 2)
995 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
996 "[minconf] is the minimum number of confirmations before payments are included.\n"
997 "[includeempty] whether to include accounts that haven't received any payments.\n"
998 "Returns an array of objects containing:\n"
999 " \"account\" : the account of the receiving addresses\n"
1000 " \"amount\" : total amount received by addresses with this account\n"
1001 " \"confirmations\" : number of confirmations of the most recent transaction included");
1003 return ListReceived(params, true);
1006 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1008 int64 nGeneratedImmature, nGeneratedMature, nFee;
1009 string strSentAccount;
1010 list<pair<CBitcoinAddress, int64> > listReceived;
1011 list<pair<CBitcoinAddress, int64> > listSent;
1012 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1014 bool fAllAccounts = (strAccount == string("*"));
1016 // Generated blocks assigned to account ""
1017 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1020 entry.push_back(Pair("account", string("")));
1021 if (nGeneratedImmature)
1023 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1024 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1028 entry.push_back(Pair("category", "generate"));
1029 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1032 WalletTxToJSON(wtx, entry);
1033 ret.push_back(entry);
1037 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1039 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1042 entry.push_back(Pair("account", strSentAccount));
1043 entry.push_back(Pair("address", s.first.ToString()));
1044 entry.push_back(Pair("category", "send"));
1045 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1046 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1048 WalletTxToJSON(wtx, entry);
1049 ret.push_back(entry);
1054 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1055 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1058 if (pwalletMain->mapAddressBook.count(r.first))
1059 account = pwalletMain->mapAddressBook[r.first];
1060 if (fAllAccounts || (account == strAccount))
1063 entry.push_back(Pair("account", account));
1064 entry.push_back(Pair("address", r.first.ToString()));
1065 entry.push_back(Pair("category", "receive"));
1066 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1068 WalletTxToJSON(wtx, entry);
1069 ret.push_back(entry);
1074 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1076 bool fAllAccounts = (strAccount == string("*"));
1078 if (fAllAccounts || acentry.strAccount == strAccount)
1081 entry.push_back(Pair("account", acentry.strAccount));
1082 entry.push_back(Pair("category", "move"));
1083 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1084 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1085 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1086 entry.push_back(Pair("comment", acentry.strComment));
1087 ret.push_back(entry);
1091 Value listtransactions(const Array& params, bool fHelp)
1093 if (fHelp || params.size() > 3)
1094 throw runtime_error(
1095 "listtransactions [account] [count=10] [from=0]\n"
1096 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1098 string strAccount = "*";
1099 if (params.size() > 0)
1100 strAccount = params[0].get_str();
1102 if (params.size() > 1)
1103 nCount = params[1].get_int();
1105 if (params.size() > 2)
1106 nFrom = params[2].get_int();
1109 CWalletDB walletdb(pwalletMain->strWalletFile);
1111 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1112 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1113 typedef multimap<int64, TxPair > TxItems;
1116 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1118 CWalletTx* wtx = &((*it).second);
1119 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1121 list<CAccountingEntry> acentries;
1122 walletdb.ListAccountCreditDebit(strAccount, acentries);
1123 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1125 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1128 // Now: iterate backwards until we have nCount items to return:
1129 TxItems::reverse_iterator it = txByTime.rbegin();
1130 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1131 for (; it != txByTime.rend(); ++it)
1133 CWalletTx *const pwtx = (*it).second.first;
1135 ListTransactions(*pwtx, strAccount, 0, true, ret);
1136 CAccountingEntry *const pacentry = (*it).second.second;
1138 AcentryToJSON(*pacentry, strAccount, ret);
1140 if (ret.size() >= nCount) break;
1142 // ret is now newest to oldest
1144 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1145 if (ret.size() > nCount)
1147 Array::iterator last = ret.begin();
1148 std::advance(last, nCount);
1149 ret.erase(last, ret.end());
1151 std::reverse(ret.begin(), ret.end()); // oldest to newest
1156 Value listaccounts(const Array& params, bool fHelp)
1158 if (fHelp || params.size() > 1)
1159 throw runtime_error(
1160 "listaccounts [minconf=1]\n"
1161 "Returns Object that has account names as keys, account balances as values.");
1164 if (params.size() > 0)
1165 nMinDepth = params[0].get_int();
1167 map<string, int64> mapAccountBalances;
1168 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1169 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1170 mapAccountBalances[entry.second] = 0;
1173 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1175 const CWalletTx& wtx = (*it).second;
1176 int64 nGeneratedImmature, nGeneratedMature, nFee;
1177 string strSentAccount;
1178 list<pair<CBitcoinAddress, int64> > listReceived;
1179 list<pair<CBitcoinAddress, int64> > listSent;
1180 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1181 mapAccountBalances[strSentAccount] -= nFee;
1182 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1183 mapAccountBalances[strSentAccount] -= s.second;
1184 if (wtx.GetDepthInMainChain() >= nMinDepth)
1186 mapAccountBalances[""] += nGeneratedMature;
1187 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1188 if (pwalletMain->mapAddressBook.count(r.first))
1189 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1191 mapAccountBalances[""] += r.second;
1195 list<CAccountingEntry> acentries;
1196 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1197 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1198 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1201 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1202 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1207 Value gettransaction(const Array& params, bool fHelp)
1209 if (fHelp || params.size() != 1)
1210 throw runtime_error(
1211 "gettransaction <txid>\n"
1212 "Get detailed information about <txid>");
1215 hash.SetHex(params[0].get_str());
1219 if (!pwalletMain->mapWallet.count(hash))
1220 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1221 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1223 int64 nCredit = wtx.GetCredit();
1224 int64 nDebit = wtx.GetDebit();
1225 int64 nNet = nCredit - nDebit;
1226 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1228 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1230 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1232 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1235 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1236 entry.push_back(Pair("details", details));
1242 Value backupwallet(const Array& params, bool fHelp)
1244 if (fHelp || params.size() != 1)
1245 throw runtime_error(
1246 "backupwallet <destination>\n"
1247 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1249 string strDest = params[0].get_str();
1250 BackupWallet(*pwalletMain, strDest);
1256 Value keypoolrefill(const Array& params, bool fHelp)
1258 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1259 throw runtime_error(
1261 "Fills the keypool, requires wallet passphrase to be set.");
1262 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1263 throw runtime_error(
1265 "Fills the keypool.");
1267 if (pwalletMain->IsLocked())
1268 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1270 pwalletMain->TopUpKeyPool();
1272 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1273 throw JSONRPCError(-4, "Error refreshing keypool.");
1279 void ThreadTopUpKeyPool(void* parg)
1281 pwalletMain->TopUpKeyPool();
1284 void ThreadCleanWalletPassphrase(void* parg)
1286 int64 nMyWakeTime = GetTime() + *((int*)parg);
1288 if (nWalletUnlockTime == 0)
1290 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1292 nWalletUnlockTime = nMyWakeTime;
1295 while (GetTime() < nWalletUnlockTime)
1296 Sleep(GetTime() - nWalletUnlockTime);
1298 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1300 nWalletUnlockTime = 0;
1305 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1307 if (nWalletUnlockTime < nMyWakeTime)
1308 nWalletUnlockTime = nMyWakeTime;
1314 pwalletMain->Lock();
1319 Value walletpassphrase(const Array& params, bool fHelp)
1321 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1322 throw runtime_error(
1323 "walletpassphrase <passphrase> <timeout>\n"
1324 "Stores the wallet decryption key in memory for <timeout> seconds.");
1327 if (!pwalletMain->IsCrypted())
1328 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1330 if (!pwalletMain->IsLocked())
1331 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1333 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1334 string strWalletPass;
1335 strWalletPass.reserve(100);
1336 mlock(&strWalletPass[0], strWalletPass.capacity());
1337 strWalletPass = params[0].get_str();
1339 if (strWalletPass.length() > 0)
1341 if (!pwalletMain->Unlock(strWalletPass))
1343 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1344 munlock(&strWalletPass[0], strWalletPass.capacity());
1345 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1347 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1348 munlock(&strWalletPass[0], strWalletPass.capacity());
1351 throw runtime_error(
1352 "walletpassphrase <passphrase> <timeout>\n"
1353 "Stores the wallet decryption key in memory for <timeout> seconds.");
1355 CreateThread(ThreadTopUpKeyPool, NULL);
1356 int* pnSleepTime = new int(params[1].get_int());
1357 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1363 Value walletpassphrasechange(const Array& params, bool fHelp)
1365 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1366 throw runtime_error(
1367 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1368 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1371 if (!pwalletMain->IsCrypted())
1372 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1374 string strOldWalletPass;
1375 strOldWalletPass.reserve(100);
1376 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1377 strOldWalletPass = params[0].get_str();
1379 string strNewWalletPass;
1380 strNewWalletPass.reserve(100);
1381 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1382 strNewWalletPass = params[1].get_str();
1384 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1385 throw runtime_error(
1386 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1387 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1389 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1391 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1392 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1393 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1394 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1395 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1397 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1398 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1399 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1400 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1406 Value walletlock(const Array& params, bool fHelp)
1408 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1409 throw runtime_error(
1411 "Removes the wallet encryption key from memory, locking the wallet.\n"
1412 "After calling this method, you will need to call walletpassphrase again\n"
1413 "before being able to call any methods which require the wallet to be unlocked.");
1416 if (!pwalletMain->IsCrypted())
1417 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1419 pwalletMain->Lock();
1420 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1422 nWalletUnlockTime = 0;
1429 Value encryptwallet(const Array& params, bool fHelp)
1431 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1432 throw runtime_error(
1433 "encryptwallet <passphrase>\n"
1434 "Encrypts the wallet with <passphrase>.");
1437 if (pwalletMain->IsCrypted())
1438 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1440 string strWalletPass;
1441 strWalletPass.reserve(100);
1442 mlock(&strWalletPass[0], strWalletPass.capacity());
1443 strWalletPass = params[0].get_str();
1445 if (strWalletPass.length() < 1)
1446 throw runtime_error(
1447 "encryptwallet <passphrase>\n"
1448 "Encrypts the wallet with <passphrase>.");
1450 if (!pwalletMain->EncryptWallet(strWalletPass))
1452 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1453 munlock(&strWalletPass[0], strWalletPass.capacity());
1454 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1456 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1457 munlock(&strWalletPass[0], strWalletPass.capacity());
1463 Value validateaddress(const Array& params, bool fHelp)
1465 if (fHelp || params.size() != 1)
1466 throw runtime_error(
1467 "validateaddress <bitcoinaddress>\n"
1468 "Return information about <bitcoinaddress>.");
1470 CBitcoinAddress address(params[0].get_str());
1471 bool isValid = address.IsValid();
1474 ret.push_back(Pair("isvalid", isValid));
1477 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1478 // version of the address:
1479 string currentAddress = address.ToString();
1480 ret.push_back(Pair("address", currentAddress));
1481 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1482 if (pwalletMain->mapAddressBook.count(address))
1483 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1489 Value getwork(const Array& params, bool fHelp)
1491 if (fHelp || params.size() > 1)
1492 throw runtime_error(
1494 "If [data] is not specified, returns formatted hash data to work on:\n"
1495 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1496 " \"data\" : block data\n"
1497 " \"hash1\" : formatted hash buffer for second hash\n"
1498 " \"target\" : little endian hash target\n"
1499 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1502 throw JSONRPCError(-9, "Bitcoin is not connected!");
1504 if (IsInitialBlockDownload())
1505 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1507 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1508 static mapNewBlock_t mapNewBlock;
1509 static vector<CBlock*> vNewBlock;
1510 static CReserveKey reservekey(pwalletMain);
1512 if (params.size() == 0)
1515 static unsigned int nTransactionsUpdatedLast;
1516 static CBlockIndex* pindexPrev;
1517 static int64 nStart;
1518 static CBlock* pblock;
1519 if (pindexPrev != pindexBest ||
1520 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1522 if (pindexPrev != pindexBest)
1524 // Deallocate old blocks since they're obsolete now
1525 mapNewBlock.clear();
1526 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1530 nTransactionsUpdatedLast = nTransactionsUpdated;
1531 pindexPrev = pindexBest;
1535 pblock = CreateNewBlock(reservekey);
1537 throw JSONRPCError(-7, "Out of memory");
1538 vNewBlock.push_back(pblock);
1542 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1545 // Update nExtraNonce
1546 static unsigned int nExtraNonce = 0;
1547 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1550 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1552 // Prebuild hash buffers
1556 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1558 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1561 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1562 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1563 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1564 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1570 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1571 if (vchData.size() != 128)
1572 throw JSONRPCError(-8, "Invalid parameter");
1573 CBlock* pdata = (CBlock*)&vchData[0];
1576 for (int i = 0; i < 128/4; i++)
1577 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1580 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1582 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1584 pblock->nTime = pdata->nTime;
1585 pblock->nNonce = pdata->nNonce;
1586 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1587 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1589 return CheckWork(pblock, *pwalletMain, reservekey);
1607 pair<string, rpcfn_type> pCallTable[] =
1609 make_pair("help", &help),
1610 make_pair("stop", &stop),
1611 make_pair("getblockcount", &getblockcount),
1612 make_pair("getblocknumber", &getblocknumber),
1613 make_pair("getconnectioncount", &getconnectioncount),
1614 make_pair("getdifficulty", &getdifficulty),
1615 make_pair("getgenerate", &getgenerate),
1616 make_pair("setgenerate", &setgenerate),
1617 make_pair("gethashespersec", &gethashespersec),
1618 make_pair("getinfo", &getinfo),
1619 make_pair("getnewaddress", &getnewaddress),
1620 make_pair("getaccountaddress", &getaccountaddress),
1621 make_pair("setaccount", &setaccount),
1622 make_pair("setlabel", &setaccount), // deprecated
1623 make_pair("getaccount", &getaccount),
1624 make_pair("getlabel", &getaccount), // deprecated
1625 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1626 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1627 make_pair("sendtoaddress", &sendtoaddress),
1628 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1629 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1630 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1631 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1632 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1633 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1634 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1635 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1636 make_pair("backupwallet", &backupwallet),
1637 make_pair("keypoolrefill", &keypoolrefill),
1638 make_pair("walletpassphrase", &walletpassphrase),
1639 make_pair("walletpassphrasechange", &walletpassphrasechange),
1640 make_pair("walletlock", &walletlock),
1641 make_pair("encryptwallet", &encryptwallet),
1642 make_pair("validateaddress", &validateaddress),
1643 make_pair("getbalance", &getbalance),
1644 make_pair("move", &movecmd),
1645 make_pair("sendfrom", &sendfrom),
1646 make_pair("sendmany", &sendmany),
1647 make_pair("gettransaction", &gettransaction),
1648 make_pair("listtransactions", &listtransactions),
1649 make_pair("getwork", &getwork),
1650 make_pair("listaccounts", &listaccounts),
1651 make_pair("settxfee", &settxfee),
1653 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1655 string pAllowInSafeMode[] =
1661 "getconnectioncount",
1668 "getaccountaddress",
1669 "setlabel", // deprecated
1671 "getlabel", // deprecated
1672 "getaddressesbyaccount",
1673 "getaddressesbylabel", // deprecated
1681 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1689 // This ain't Apache. We're just using HTTP header for the length field
1690 // and to be compatible with other JSON-RPC implementations.
1693 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1696 s << "POST / HTTP/1.1\r\n"
1697 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1698 << "Host: 127.0.0.1\r\n"
1699 << "Content-Type: application/json\r\n"
1700 << "Content-Length: " << strMsg.size() << "\r\n"
1701 << "Accept: application/json\r\n";
1702 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1703 s << item.first << ": " << item.second << "\r\n";
1704 s << "\r\n" << strMsg;
1709 string rfc1123Time()
1714 struct tm* now_gmt = gmtime(&now);
1715 string locale(setlocale(LC_TIME, NULL));
1716 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1717 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1718 setlocale(LC_TIME, locale.c_str());
1719 return string(buffer);
1722 static string HTTPReply(int nStatus, const string& strMsg)
1725 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1727 "Server: bitcoin-json-rpc/%s\r\n"
1728 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1729 "Content-Type: text/html\r\n"
1730 "Content-Length: 296\r\n"
1732 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1733 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1736 "<TITLE>Error</TITLE>\r\n"
1737 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1739 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1740 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1742 if (nStatus == 200) strStatus = "OK";
1743 else if (nStatus == 400) strStatus = "Bad Request";
1744 else if (nStatus == 403) strStatus = "Forbidden";
1745 else if (nStatus == 404) strStatus = "Not Found";
1746 else if (nStatus == 500) strStatus = "Internal Server Error";
1748 "HTTP/1.1 %d %s\r\n"
1750 "Connection: close\r\n"
1751 "Content-Length: %d\r\n"
1752 "Content-Type: application/json\r\n"
1753 "Server: bitcoin-json-rpc/%s\r\n"
1758 rfc1123Time().c_str(),
1760 FormatFullVersion().c_str(),
1764 int ReadHTTPStatus(std::basic_istream<char>& stream)
1767 getline(stream, str);
1768 vector<string> vWords;
1769 boost::split(vWords, str, boost::is_any_of(" "));
1770 if (vWords.size() < 2)
1772 return atoi(vWords[1].c_str());
1775 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1781 std::getline(stream, str);
1782 if (str.empty() || str == "\r")
1784 string::size_type nColon = str.find(":");
1785 if (nColon != string::npos)
1787 string strHeader = str.substr(0, nColon);
1788 boost::trim(strHeader);
1789 boost::to_lower(strHeader);
1790 string strValue = str.substr(nColon+1);
1791 boost::trim(strValue);
1792 mapHeadersRet[strHeader] = strValue;
1793 if (strHeader == "content-length")
1794 nLen = atoi(strValue.c_str());
1800 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1802 mapHeadersRet.clear();
1806 int nStatus = ReadHTTPStatus(stream);
1809 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1810 if (nLen < 0 || nLen > MAX_SIZE)
1816 vector<char> vch(nLen);
1817 stream.read(&vch[0], nLen);
1818 strMessageRet = string(vch.begin(), vch.end());
1824 string EncodeBase64(string s)
1829 b64 = BIO_new(BIO_f_base64());
1830 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1831 bmem = BIO_new(BIO_s_mem());
1832 b64 = BIO_push(b64, bmem);
1833 BIO_write(b64, s.c_str(), s.size());
1835 BIO_get_mem_ptr(b64, &bptr);
1837 string result(bptr->data, bptr->length);
1843 string DecodeBase64(string s)
1847 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1849 b64 = BIO_new(BIO_f_base64());
1850 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1851 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1852 bmem = BIO_push(b64, bmem);
1853 BIO_read(bmem, buffer, s.size());
1856 string result(buffer);
1861 bool HTTPAuthorized(map<string, string>& mapHeaders)
1863 string strAuth = mapHeaders["authorization"];
1864 if (strAuth.substr(0,6) != "Basic ")
1866 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1867 string strUserPass = DecodeBase64(strUserPass64);
1868 string::size_type nColon = strUserPass.find(":");
1869 if (nColon == string::npos)
1871 string strUser = strUserPass.substr(0, nColon);
1872 string strPassword = strUserPass.substr(nColon+1);
1873 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1877 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1878 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1879 // unspecified (HTTP errors and contents of 'error').
1881 // 1.0 spec: http://json-rpc.org/wiki/specification
1882 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1883 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1886 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1889 request.push_back(Pair("method", strMethod));
1890 request.push_back(Pair("params", params));
1891 request.push_back(Pair("id", id));
1892 return write_string(Value(request), false) + "\n";
1895 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1898 if (error.type() != null_type)
1899 reply.push_back(Pair("result", Value::null));
1901 reply.push_back(Pair("result", result));
1902 reply.push_back(Pair("error", error));
1903 reply.push_back(Pair("id", id));
1904 return write_string(Value(reply), false) + "\n";
1907 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1909 // Send error reply from json-rpc error object
1911 int code = find_value(objError, "code").get_int();
1912 if (code == -32600) nStatus = 400;
1913 else if (code == -32601) nStatus = 404;
1914 string strReply = JSONRPCReply(Value::null, objError, id);
1915 stream << HTTPReply(nStatus, strReply) << std::flush;
1918 bool ClientAllowed(const string& strAddress)
1920 if (strAddress == asio::ip::address_v4::loopback().to_string())
1922 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1923 BOOST_FOREACH(string strAllow, vAllow)
1924 if (WildcardMatch(strAddress, strAllow))
1931 // IOStream device that speaks SSL but can also speak non-SSL
1933 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1935 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1937 fUseSSL = fUseSSLIn;
1938 fNeedHandshake = fUseSSLIn;
1941 void handshake(ssl::stream_base::handshake_type role)
1943 if (!fNeedHandshake) return;
1944 fNeedHandshake = false;
1945 stream.handshake(role);
1947 std::streamsize read(char* s, std::streamsize n)
1949 handshake(ssl::stream_base::server); // HTTPS servers read first
1950 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1951 return stream.next_layer().read_some(asio::buffer(s, n));
1953 std::streamsize write(const char* s, std::streamsize n)
1955 handshake(ssl::stream_base::client); // HTTPS clients write first
1956 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1957 return asio::write(stream.next_layer(), asio::buffer(s, n));
1959 bool connect(const std::string& server, const std::string& port)
1961 ip::tcp::resolver resolver(stream.get_io_service());
1962 ip::tcp::resolver::query query(server.c_str(), port.c_str());
1963 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
1964 ip::tcp::resolver::iterator end;
1965 boost::system::error_code error = asio::error::host_not_found;
1966 while (error && endpoint_iterator != end)
1968 stream.lowest_layer().close();
1969 stream.lowest_layer().connect(*endpoint_iterator++, error);
1977 bool fNeedHandshake;
1983 void ThreadRPCServer(void* parg)
1985 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
1988 vnThreadsRunning[4]++;
1989 ThreadRPCServer2(parg);
1990 vnThreadsRunning[4]--;
1992 catch (std::exception& e) {
1993 vnThreadsRunning[4]--;
1994 PrintException(&e, "ThreadRPCServer()");
1996 vnThreadsRunning[4]--;
1997 PrintException(NULL, "ThreadRPCServer()");
1999 printf("ThreadRPCServer exiting\n");
2002 void ThreadRPCServer2(void* parg)
2004 printf("ThreadRPCServer started\n");
2006 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2008 string strWhatAmI = "To use bitcoind";
2009 if (mapArgs.count("-server"))
2010 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2011 else if (mapArgs.count("-daemon"))
2012 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2014 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2015 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2017 GetConfigFile().c_str());
2018 CreateThread(Shutdown, NULL);
2022 bool fUseSSL = GetBoolArg("-rpcssl");
2023 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2025 asio::io_service io_service;
2026 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2027 ip::tcp::acceptor acceptor(io_service, endpoint);
2029 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2032 ssl::context context(io_service, ssl::context::sslv23);
2035 context.set_options(ssl::context::no_sslv2);
2036 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2037 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2038 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2039 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2040 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2041 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2042 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2043 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2045 string ciphers = GetArg("-rpcsslciphers",
2046 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2047 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2051 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2056 // Accept connection
2058 SSLStream sslStream(io_service, context);
2059 SSLIOStreamDevice d(sslStream, fUseSSL);
2060 iostreams::stream<SSLIOStreamDevice> stream(d);
2062 ip::tcp::iostream stream;
2065 ip::tcp::endpoint peer;
2066 vnThreadsRunning[4]--;
2068 acceptor.accept(sslStream.lowest_layer(), peer);
2070 acceptor.accept(*stream.rdbuf(), peer);
2072 vnThreadsRunning[4]++;
2076 // Restrict callers by IP
2077 if (!ClientAllowed(peer.address().to_string()))
2079 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2081 stream << HTTPReply(403, "") << std::flush;
2085 map<string, string> mapHeaders;
2088 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2089 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2092 printf("ThreadRPCServer ReadHTTP timeout\n");
2096 // Check authorization
2097 if (mapHeaders.count("authorization") == 0)
2099 stream << HTTPReply(401, "") << std::flush;
2102 if (!HTTPAuthorized(mapHeaders))
2104 // Deter brute-forcing short passwords
2105 if (mapArgs["-rpcpassword"].size() < 15)
2108 stream << HTTPReply(401, "") << std::flush;
2109 printf("ThreadRPCServer incorrect password attempt\n");
2113 Value id = Value::null;
2118 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2119 throw JSONRPCError(-32700, "Parse error");
2120 const Object& request = valRequest.get_obj();
2122 // Parse id now so errors from here on will have the id
2123 id = find_value(request, "id");
2126 Value valMethod = find_value(request, "method");
2127 if (valMethod.type() == null_type)
2128 throw JSONRPCError(-32600, "Missing method");
2129 if (valMethod.type() != str_type)
2130 throw JSONRPCError(-32600, "Method must be a string");
2131 string strMethod = valMethod.get_str();
2132 if (strMethod != "getwork")
2133 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2136 Value valParams = find_value(request, "params");
2138 if (valParams.type() == array_type)
2139 params = valParams.get_array();
2140 else if (valParams.type() == null_type)
2143 throw JSONRPCError(-32600, "Params must be an array");
2146 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2147 if (mi == mapCallTable.end())
2148 throw JSONRPCError(-32601, "Method not found");
2150 // Observe safe mode
2151 string strWarning = GetWarnings("rpc");
2152 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2153 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2159 CRITICAL_BLOCK(cs_main)
2160 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2161 result = (*(*mi).second)(params, false);
2164 string strReply = JSONRPCReply(result, Value::null, id);
2165 stream << HTTPReply(200, strReply) << std::flush;
2167 catch (std::exception& e)
2169 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2172 catch (Object& objError)
2174 ErrorReply(stream, objError, id);
2176 catch (std::exception& e)
2178 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2186 Object CallRPC(const string& strMethod, const Array& params)
2188 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2189 throw runtime_error(strprintf(
2190 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2191 "If the file does not exist, create it with owner-readable-only file permissions."),
2192 GetConfigFile().c_str()));
2194 // Connect to localhost
2195 bool fUseSSL = GetBoolArg("-rpcssl");
2197 asio::io_service io_service;
2198 ssl::context context(io_service, ssl::context::sslv23);
2199 context.set_options(ssl::context::no_sslv2);
2200 SSLStream sslStream(io_service, context);
2201 SSLIOStreamDevice d(sslStream, fUseSSL);
2202 iostreams::stream<SSLIOStreamDevice> stream(d);
2203 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2204 throw runtime_error("couldn't connect to server");
2207 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2209 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2211 throw runtime_error("couldn't connect to server");
2215 // HTTP basic authentication
2216 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2217 map<string, string> mapRequestHeaders;
2218 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2221 string strRequest = JSONRPCRequest(strMethod, params, 1);
2222 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2223 stream << strPost << std::flush;
2226 map<string, string> mapHeaders;
2228 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2230 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2231 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2232 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2233 else if (strReply.empty())
2234 throw runtime_error("no response from server");
2238 if (!read_string(strReply, valReply))
2239 throw runtime_error("couldn't parse reply from server");
2240 const Object& reply = valReply.get_obj();
2242 throw runtime_error("expected reply to have result, error and id properties");
2250 template<typename T>
2251 void ConvertTo(Value& value)
2253 if (value.type() == str_type)
2255 // reinterpret string as unquoted json value
2257 if (!read_string(value.get_str(), value2))
2258 throw runtime_error("type mismatch");
2259 value = value2.get_value<T>();
2263 value = value.get_value<T>();
2267 int CommandLineRPC(int argc, char *argv[])
2274 while (argc > 1 && IsSwitchChar(argv[1][0]))
2282 throw runtime_error("too few parameters");
2283 string strMethod = argv[1];
2285 // Parameters default to strings
2287 for (int i = 2; i < argc; i++)
2288 params.push_back(argv[i]);
2289 int n = params.size();
2292 // Special case non-string parameter types
2294 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2295 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2296 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2297 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2298 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2299 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2300 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2301 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2302 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2303 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2304 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2305 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2306 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2307 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2308 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2309 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2310 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2311 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2312 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2313 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2314 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2315 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2316 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2317 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2318 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2319 if (strMethod == "sendmany" && n > 1)
2321 string s = params[1].get_str();
2323 if (!read_string(s, v) || v.type() != obj_type)
2324 throw runtime_error("type mismatch");
2325 params[1] = v.get_obj();
2327 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2330 Object reply = CallRPC(strMethod, params);
2333 const Value& result = find_value(reply, "result");
2334 const Value& error = find_value(reply, "error");
2336 if (error.type() != null_type)
2339 strPrint = "error: " + write_string(error, false);
2340 int code = find_value(error.get_obj(), "code").get_int();
2346 if (result.type() == null_type)
2348 else if (result.type() == str_type)
2349 strPrint = result.get_str();
2351 strPrint = write_string(result, true);
2354 catch (std::exception& e)
2356 strPrint = string("error: ") + e.what();
2361 PrintException(NULL, "CommandLineRPC()");
2366 #if defined(__WXMSW__) && defined(GUI)
2367 // Windows GUI apps can't print to command line,
2368 // so settle for a message box yuck
2369 MyMessageBox(strPrint, "Bitcoin", wxOK);
2371 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2381 int main(int argc, char *argv[])
2384 // Turn off microsoft heap dump noise
2385 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2386 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2388 setbuf(stdin, NULL);
2389 setbuf(stdout, NULL);
2390 setbuf(stderr, NULL);
2394 if (argc >= 2 && string(argv[1]) == "-server")
2396 printf("server ready\n");
2397 ThreadRPCServer(NULL);
2401 return CommandLineRPC(argc, argv);
2404 catch (std::exception& e) {
2405 PrintException(&e, "main()");
2407 PrintException(NULL, "main()");