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 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
94 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
95 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
96 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
97 entry.push_back(Pair(item.first, item.second));
100 string AccountFromValue(const Value& value)
102 string strAccount = value.get_str();
103 if (strAccount == "*")
104 throw JSONRPCError(-11, "Invalid account name");
111 /// Note: This interface may still be subject to change.
115 Value help(const Array& params, bool fHelp)
117 if (fHelp || params.size() > 1)
120 "List commands, or get help for a command.");
123 if (params.size() > 0)
124 strCommand = params[0].get_str();
127 set<rpcfn_type> setDone;
128 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
130 string strMethod = (*mi).first;
131 // We already filter duplicates, but these deprecated screw up the sort order
132 if (strMethod == "getamountreceived" ||
133 strMethod == "getallreceived" ||
134 (strMethod.find("label") != string::npos))
136 if (strCommand != "" && strMethod != strCommand)
141 rpcfn_type pfn = (*mi).second;
142 if (setDone.insert(pfn).second)
143 (*pfn)(params, true);
145 catch (std::exception& e)
147 // Help text is returned in an exception
148 string strHelp = string(e.what());
149 if (strCommand == "")
150 if (strHelp.find('\n') != -1)
151 strHelp = strHelp.substr(0, strHelp.find('\n'));
152 strRet += strHelp + "\n";
156 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
157 strRet = strRet.substr(0,strRet.size()-1);
162 Value stop(const Array& params, bool fHelp)
164 if (fHelp || params.size() != 0)
167 "Stop bitcoin server.");
169 // Shutdown will take long enough that the response should get back
170 CreateThread(Shutdown, NULL);
171 return "bitcoin server stopping";
175 Value getblockcount(const Array& params, bool fHelp)
177 if (fHelp || params.size() != 0)
180 "Returns the number of blocks in the longest block chain.");
186 Value getblocknumber(const Array& params, bool fHelp)
188 if (fHelp || params.size() != 0)
191 "Returns the block number of the latest block in the longest block chain.");
197 Value getconnectioncount(const Array& params, bool fHelp)
199 if (fHelp || params.size() != 0)
201 "getconnectioncount\n"
202 "Returns the number of connections to other nodes.");
204 return (int)vNodes.size();
208 double GetDifficulty()
210 // Floating point number that is a multiple of the minimum difficulty,
211 // minimum difficulty = 1.0.
213 if (pindexBest == NULL)
215 int nShift = (pindexBest->nBits >> 24) & 0xff;
218 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
234 Value getdifficulty(const Array& params, bool fHelp)
236 if (fHelp || params.size() != 0)
239 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
241 return GetDifficulty();
245 Value getgenerate(const Array& params, bool fHelp)
247 if (fHelp || params.size() != 0)
250 "Returns true or false.");
252 return (bool)fGenerateBitcoins;
256 Value setgenerate(const Array& params, bool fHelp)
258 if (fHelp || params.size() < 1 || params.size() > 2)
260 "setgenerate <generate> [genproclimit]\n"
261 "<generate> is true or false to turn generation on or off.\n"
262 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
264 bool fGenerate = true;
265 if (params.size() > 0)
266 fGenerate = params[0].get_bool();
268 if (params.size() > 1)
270 int nGenProcLimit = params[1].get_int();
271 fLimitProcessors = (nGenProcLimit != -1);
272 WriteSetting("fLimitProcessors", fLimitProcessors);
273 if (nGenProcLimit != -1)
274 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
275 if (nGenProcLimit == 0)
279 GenerateBitcoins(fGenerate, pwalletMain);
284 Value gethashespersec(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns a recent hashes per second performance measurement while generating.");
291 if (GetTimeMillis() - nHPSTimerStart > 8000)
292 return (boost::int64_t)0;
293 return (boost::int64_t)dHashesPerSec;
297 Value getinfo(const Array& params, bool fHelp)
299 if (fHelp || params.size() != 0)
302 "Returns an object containing various state info.");
305 obj.push_back(Pair("version", (int)VERSION));
306 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
307 obj.push_back(Pair("blocks", (int)nBestHeight));
308 obj.push_back(Pair("connections", (int)vNodes.size()));
309 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
310 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
311 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
312 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
313 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
314 obj.push_back(Pair("testnet", fTestNet));
315 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
316 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
317 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
318 if (pwalletMain->IsCrypted())
319 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
320 obj.push_back(Pair("errors", GetWarnings("statusbar")));
325 Value getnewaddress(const Array& params, bool fHelp)
327 if (fHelp || params.size() > 1)
329 "getnewaddress [account]\n"
330 "Returns a new bitcoin address for receiving payments. "
331 "If [account] is specified (recommended), it is added to the address book "
332 "so payments received with the address will be credited to [account].");
334 // Parse the account first so we don't generate a key if there's an error
336 if (params.size() > 0)
337 strAccount = AccountFromValue(params[0]);
339 if (!pwalletMain->IsLocked())
340 pwalletMain->TopUpKeyPool();
342 // Generate a new key that is added to wallet
343 std::vector<unsigned char> newKey;
344 if (!pwalletMain->GetKeyFromPool(newKey, false))
345 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
346 CBitcoinAddress address(newKey);
348 pwalletMain->SetAddressBookName(address, strAccount);
350 return address.ToString();
354 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
356 CWalletDB walletdb(pwalletMain->strWalletFile);
359 walletdb.ReadAccount(strAccount, account);
361 bool bKeyUsed = false;
363 // Check if the current key has been used
364 if (!account.vchPubKey.empty())
366 CScript scriptPubKey;
367 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
368 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
369 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
372 const CWalletTx& wtx = (*it).second;
373 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
374 if (txout.scriptPubKey == scriptPubKey)
379 // Generate a new key
380 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
382 if (pwalletMain->GetKeyPoolSize() < 1)
384 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
385 throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
387 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
388 walletdb.WriteAccount(strAccount, account);
392 return CBitcoinAddress(account.vchPubKey);
395 Value getaccountaddress(const Array& params, bool fHelp)
397 if (fHelp || params.size() != 1)
399 "getaccountaddress <account>\n"
400 "Returns the current bitcoin address for receiving payments to this account.");
402 // Parse the account first so we don't generate a key if there's an error
403 string strAccount = AccountFromValue(params[0]);
407 ret = GetAccountAddress(strAccount).ToString();
414 Value setaccount(const Array& params, bool fHelp)
416 if (fHelp || params.size() < 1 || params.size() > 2)
418 "setaccount <bitcoinaddress> <account>\n"
419 "Sets the account associated with the given address.");
421 CBitcoinAddress address(params[0].get_str());
422 if (!address.IsValid())
423 throw JSONRPCError(-5, "Invalid bitcoin address");
427 if (params.size() > 1)
428 strAccount = AccountFromValue(params[1]);
430 // Detect when changing the account of an address that is the 'unused current key' of another account:
431 if (pwalletMain->mapAddressBook.count(address))
433 string strOldAccount = pwalletMain->mapAddressBook[address];
434 if (address == GetAccountAddress(strOldAccount))
435 GetAccountAddress(strOldAccount, true);
438 pwalletMain->SetAddressBookName(address, strAccount);
444 Value getaccount(const Array& params, bool fHelp)
446 if (fHelp || params.size() != 1)
448 "getaccount <bitcoinaddress>\n"
449 "Returns the account associated with the given address.");
451 CBitcoinAddress address(params[0].get_str());
452 if (!address.IsValid())
453 throw JSONRPCError(-5, "Invalid bitcoin address");
456 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
457 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
458 strAccount = (*mi).second;
463 Value getaddressesbyaccount(const Array& params, bool fHelp)
465 if (fHelp || params.size() != 1)
467 "getaddressesbyaccount <account>\n"
468 "Returns the list of addresses for the given account.");
470 string strAccount = AccountFromValue(params[0]);
472 // Find all addresses that have the given account
474 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
476 const CBitcoinAddress& address = item.first;
477 const string& strName = item.second;
478 if (strName == strAccount)
479 ret.push_back(address.ToString());
484 Value settxfee(const Array& params, bool fHelp)
486 if (fHelp || params.size() < 1 || params.size() > 1)
488 "settxfee <amount>\n"
489 "<amount> is a real and is rounded to the nearest 0.00000001");
493 if (params[0].get_real() != 0.0)
494 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
496 nTransactionFee = nAmount;
500 Value sendtoaddress(const Array& params, bool fHelp)
502 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
504 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
505 "<amount> is a real and is rounded to the nearest 0.00000001\n"
506 "requires wallet passphrase to be set with walletpassphrase first");
507 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
509 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
510 "<amount> is a real and is rounded to the nearest 0.00000001");
512 CBitcoinAddress address(params[0].get_str());
513 if (!address.IsValid())
514 throw JSONRPCError(-5, "Invalid bitcoin address");
517 int64 nAmount = AmountFromValue(params[1]);
521 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
522 wtx.mapValue["comment"] = params[2].get_str();
523 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
524 wtx.mapValue["to"] = params[3].get_str();
526 if (pwalletMain->IsLocked())
527 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
529 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
531 throw JSONRPCError(-4, strError);
533 return wtx.GetHash().GetHex();
537 Value getreceivedbyaddress(const Array& params, bool fHelp)
539 if (fHelp || params.size() < 1 || params.size() > 2)
541 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
542 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
545 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
546 CScript scriptPubKey;
547 if (!address.IsValid())
548 throw JSONRPCError(-5, "Invalid bitcoin address");
549 scriptPubKey.SetBitcoinAddress(address);
550 if (!IsMine(*pwalletMain,scriptPubKey))
553 // Minimum confirmations
555 if (params.size() > 1)
556 nMinDepth = params[1].get_int();
560 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
562 const CWalletTx& wtx = (*it).second;
563 if (wtx.IsCoinBase() || !wtx.IsFinal())
566 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
567 if (txout.scriptPubKey == scriptPubKey)
568 if (wtx.GetDepthInMainChain() >= nMinDepth)
569 nAmount += txout.nValue;
572 return ValueFromAmount(nAmount);
576 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
578 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
580 const CBitcoinAddress& address = item.first;
581 const string& strName = item.second;
582 if (strName == strAccount)
583 setAddress.insert(address);
588 Value getreceivedbyaccount(const Array& params, bool fHelp)
590 if (fHelp || params.size() < 1 || params.size() > 2)
592 "getreceivedbyaccount <account> [minconf=1]\n"
593 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
595 // Minimum confirmations
597 if (params.size() > 1)
598 nMinDepth = params[1].get_int();
600 // Get the set of pub keys that have the label
601 string strAccount = AccountFromValue(params[0]);
602 set<CBitcoinAddress> setAddress;
603 GetAccountAddresses(strAccount, setAddress);
607 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
609 const CWalletTx& wtx = (*it).second;
610 if (wtx.IsCoinBase() || !wtx.IsFinal())
613 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
615 CBitcoinAddress address;
616 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
617 if (wtx.GetDepthInMainChain() >= nMinDepth)
618 nAmount += txout.nValue;
622 return (double)nAmount / (double)COIN;
626 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
630 // Tally wallet transactions
631 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
633 const CWalletTx& wtx = (*it).second;
637 int64 nGenerated, nReceived, nSent, nFee;
638 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
640 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
641 nBalance += nReceived;
642 nBalance += nGenerated - nSent - nFee;
645 // Tally internal accounting entries
646 nBalance += walletdb.GetAccountCreditDebit(strAccount);
651 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
653 CWalletDB walletdb(pwalletMain->strWalletFile);
654 return GetAccountBalance(walletdb, strAccount, nMinDepth);
658 Value getbalance(const Array& params, bool fHelp)
660 if (fHelp || params.size() > 2)
662 "getbalance [account] [minconf=1]\n"
663 "If [account] is not specified, returns the server's total available balance.\n"
664 "If [account] is specified, returns the balance in the account.");
666 if (params.size() == 0)
667 return ValueFromAmount(pwalletMain->GetBalance());
670 if (params.size() > 1)
671 nMinDepth = params[1].get_int();
673 if (params[0].get_str() == "*") {
674 // Calculate total balance a different way from GetBalance()
675 // (GetBalance() sums up all unspent TxOuts)
676 // getbalance and getbalance '*' should always return the same number.
678 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
680 const CWalletTx& wtx = (*it).second;
684 int64 allGeneratedImmature, allGeneratedMature, allFee;
685 allGeneratedImmature = allGeneratedMature = allFee = 0;
686 string strSentAccount;
687 list<pair<CBitcoinAddress, int64> > listReceived;
688 list<pair<CBitcoinAddress, int64> > listSent;
689 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
690 if (wtx.GetDepthInMainChain() >= nMinDepth)
691 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
692 nBalance += r.second;
693 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
694 nBalance -= r.second;
696 nBalance += allGeneratedMature;
698 return ValueFromAmount(nBalance);
701 string strAccount = AccountFromValue(params[0]);
703 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
705 return ValueFromAmount(nBalance);
709 Value movecmd(const Array& params, bool fHelp)
711 if (fHelp || params.size() < 3 || params.size() > 5)
713 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
714 "Move from one account in your wallet to another.");
716 string strFrom = AccountFromValue(params[0]);
717 string strTo = AccountFromValue(params[1]);
718 int64 nAmount = AmountFromValue(params[2]);
719 if (params.size() > 3)
720 // unused parameter, used to be nMinDepth, keep type-checking it though
721 (void)params[3].get_int();
723 if (params.size() > 4)
724 strComment = params[4].get_str();
726 CWalletDB walletdb(pwalletMain->strWalletFile);
729 int64 nNow = GetAdjustedTime();
732 CAccountingEntry debit;
733 debit.strAccount = strFrom;
734 debit.nCreditDebit = -nAmount;
736 debit.strOtherAccount = strTo;
737 debit.strComment = strComment;
738 walletdb.WriteAccountingEntry(debit);
741 CAccountingEntry credit;
742 credit.strAccount = strTo;
743 credit.nCreditDebit = nAmount;
745 credit.strOtherAccount = strFrom;
746 credit.strComment = strComment;
747 walletdb.WriteAccountingEntry(credit);
749 walletdb.TxnCommit();
755 Value sendfrom(const Array& params, bool fHelp)
757 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
759 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
760 "<amount> is a real and is rounded to the nearest 0.00000001\n"
761 "requires wallet passphrase to be set with walletpassphrase first");
762 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
764 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
765 "<amount> is a real and is rounded to the nearest 0.00000001");
767 string strAccount = AccountFromValue(params[0]);
768 CBitcoinAddress address(params[1].get_str());
769 if (!address.IsValid())
770 throw JSONRPCError(-5, "Invalid bitcoin address");
771 int64 nAmount = AmountFromValue(params[2]);
773 if (params.size() > 3)
774 nMinDepth = params[3].get_int();
777 wtx.strFromAccount = strAccount;
778 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
779 wtx.mapValue["comment"] = params[4].get_str();
780 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
781 wtx.mapValue["to"] = params[5].get_str();
783 if (pwalletMain->IsLocked())
784 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
787 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
788 if (nAmount > nBalance)
789 throw JSONRPCError(-6, "Account has insufficient funds");
792 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
794 throw JSONRPCError(-4, strError);
796 return wtx.GetHash().GetHex();
800 Value sendmany(const Array& params, bool fHelp)
802 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
804 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
805 "amounts are double-precision floating point numbers\n"
806 "requires wallet passphrase to be set with walletpassphrase first");
807 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
809 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
810 "amounts are double-precision floating point numbers");
812 string strAccount = AccountFromValue(params[0]);
813 Object sendTo = params[1].get_obj();
815 if (params.size() > 2)
816 nMinDepth = params[2].get_int();
819 wtx.strFromAccount = strAccount;
820 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
821 wtx.mapValue["comment"] = params[3].get_str();
823 set<CBitcoinAddress> setAddress;
824 vector<pair<CScript, int64> > vecSend;
826 int64 totalAmount = 0;
827 BOOST_FOREACH(const Pair& s, sendTo)
829 CBitcoinAddress address(s.name_);
830 if (!address.IsValid())
831 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
833 if (setAddress.count(address))
834 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
835 setAddress.insert(address);
837 CScript scriptPubKey;
838 scriptPubKey.SetBitcoinAddress(address);
839 int64 nAmount = AmountFromValue(s.value_);
840 totalAmount += nAmount;
842 vecSend.push_back(make_pair(scriptPubKey, nAmount));
845 if (pwalletMain->IsLocked())
846 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
849 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
850 if (totalAmount > nBalance)
851 throw JSONRPCError(-6, "Account has insufficient funds");
854 CReserveKey keyChange(pwalletMain);
855 int64 nFeeRequired = 0;
856 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
859 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
860 throw JSONRPCError(-6, "Insufficient funds");
861 throw JSONRPCError(-4, "Transaction creation failed");
863 if (!pwalletMain->CommitTransaction(wtx, keyChange))
864 throw JSONRPCError(-4, "Transaction commit failed");
866 return wtx.GetHash().GetHex();
881 Value ListReceived(const Array& params, bool fByAccounts)
883 // Minimum confirmations
885 if (params.size() > 0)
886 nMinDepth = params[0].get_int();
888 // Whether to include empty accounts
889 bool fIncludeEmpty = false;
890 if (params.size() > 1)
891 fIncludeEmpty = params[1].get_bool();
894 map<CBitcoinAddress, tallyitem> mapTally;
895 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
897 const CWalletTx& wtx = (*it).second;
898 if (wtx.IsCoinBase() || !wtx.IsFinal())
901 int nDepth = wtx.GetDepthInMainChain();
902 if (nDepth < nMinDepth)
905 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
907 CBitcoinAddress address;
908 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
911 tallyitem& item = mapTally[address];
912 item.nAmount += txout.nValue;
913 item.nConf = min(item.nConf, nDepth);
919 map<string, tallyitem> mapAccountTally;
920 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
922 const CBitcoinAddress& address = item.first;
923 const string& strAccount = item.second;
924 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
925 if (it == mapTally.end() && !fIncludeEmpty)
930 if (it != mapTally.end())
932 nAmount = (*it).second.nAmount;
933 nConf = (*it).second.nConf;
938 tallyitem& item = mapAccountTally[strAccount];
939 item.nAmount += nAmount;
940 item.nConf = min(item.nConf, nConf);
945 obj.push_back(Pair("address", address.ToString()));
946 obj.push_back(Pair("account", strAccount));
947 obj.push_back(Pair("label", strAccount)); // deprecated
948 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
949 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
956 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
958 int64 nAmount = (*it).second.nAmount;
959 int nConf = (*it).second.nConf;
961 obj.push_back(Pair("account", (*it).first));
962 obj.push_back(Pair("label", (*it).first)); // deprecated
963 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
964 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
972 Value listreceivedbyaddress(const Array& params, bool fHelp)
974 if (fHelp || params.size() > 2)
976 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
977 "[minconf] is the minimum number of confirmations before payments are included.\n"
978 "[includeempty] whether to include addresses that haven't received any payments.\n"
979 "Returns an array of objects containing:\n"
980 " \"address\" : receiving address\n"
981 " \"account\" : the account of the receiving address\n"
982 " \"amount\" : total amount received by the address\n"
983 " \"confirmations\" : number of confirmations of the most recent transaction included");
985 return ListReceived(params, false);
988 Value listreceivedbyaccount(const Array& params, bool fHelp)
990 if (fHelp || params.size() > 2)
992 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
993 "[minconf] is the minimum number of confirmations before payments are included.\n"
994 "[includeempty] whether to include accounts that haven't received any payments.\n"
995 "Returns an array of objects containing:\n"
996 " \"account\" : the account of the receiving addresses\n"
997 " \"amount\" : total amount received by addresses with this account\n"
998 " \"confirmations\" : number of confirmations of the most recent transaction included");
1000 return ListReceived(params, true);
1003 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1005 int64 nGeneratedImmature, nGeneratedMature, nFee;
1006 string strSentAccount;
1007 list<pair<CBitcoinAddress, int64> > listReceived;
1008 list<pair<CBitcoinAddress, int64> > listSent;
1009 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1011 bool fAllAccounts = (strAccount == string("*"));
1013 // Generated blocks assigned to account ""
1014 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1017 entry.push_back(Pair("account", string("")));
1018 if (nGeneratedImmature)
1020 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1021 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1025 entry.push_back(Pair("category", "generate"));
1026 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1029 WalletTxToJSON(wtx, entry);
1030 ret.push_back(entry);
1034 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1036 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1039 entry.push_back(Pair("account", strSentAccount));
1040 entry.push_back(Pair("address", s.first.ToString()));
1041 entry.push_back(Pair("category", "send"));
1042 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1043 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1045 WalletTxToJSON(wtx, entry);
1046 ret.push_back(entry);
1051 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1052 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1055 if (pwalletMain->mapAddressBook.count(r.first))
1056 account = pwalletMain->mapAddressBook[r.first];
1057 if (fAllAccounts || (account == strAccount))
1060 entry.push_back(Pair("account", account));
1061 entry.push_back(Pair("address", r.first.ToString()));
1062 entry.push_back(Pair("category", "receive"));
1063 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1065 WalletTxToJSON(wtx, entry);
1066 ret.push_back(entry);
1071 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1073 bool fAllAccounts = (strAccount == string("*"));
1075 if (fAllAccounts || acentry.strAccount == strAccount)
1078 entry.push_back(Pair("account", acentry.strAccount));
1079 entry.push_back(Pair("category", "move"));
1080 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1081 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1082 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1083 entry.push_back(Pair("comment", acentry.strComment));
1084 ret.push_back(entry);
1088 Value listtransactions(const Array& params, bool fHelp)
1090 if (fHelp || params.size() > 3)
1091 throw runtime_error(
1092 "listtransactions [account] [count=10] [from=0]\n"
1093 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1095 string strAccount = "*";
1096 if (params.size() > 0)
1097 strAccount = params[0].get_str();
1099 if (params.size() > 1)
1100 nCount = params[1].get_int();
1102 if (params.size() > 2)
1103 nFrom = params[2].get_int();
1106 CWalletDB walletdb(pwalletMain->strWalletFile);
1108 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1109 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1110 typedef multimap<int64, TxPair > TxItems;
1113 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1115 CWalletTx* wtx = &((*it).second);
1116 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1118 list<CAccountingEntry> acentries;
1119 walletdb.ListAccountCreditDebit(strAccount, acentries);
1120 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1122 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1125 // Now: iterate backwards until we have nCount items to return:
1126 TxItems::reverse_iterator it = txByTime.rbegin();
1127 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1128 for (; it != txByTime.rend(); ++it)
1130 CWalletTx *const pwtx = (*it).second.first;
1132 ListTransactions(*pwtx, strAccount, 0, true, ret);
1133 CAccountingEntry *const pacentry = (*it).second.second;
1135 AcentryToJSON(*pacentry, strAccount, ret);
1137 if (ret.size() >= nCount) break;
1139 // ret is now newest to oldest
1141 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1142 if (ret.size() > nCount)
1144 Array::iterator last = ret.begin();
1145 std::advance(last, nCount);
1146 ret.erase(last, ret.end());
1148 std::reverse(ret.begin(), ret.end()); // oldest to newest
1153 Value listaccounts(const Array& params, bool fHelp)
1155 if (fHelp || params.size() > 1)
1156 throw runtime_error(
1157 "listaccounts [minconf=1]\n"
1158 "Returns Object that has account names as keys, account balances as values.");
1161 if (params.size() > 0)
1162 nMinDepth = params[0].get_int();
1164 map<string, int64> mapAccountBalances;
1165 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1166 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1167 mapAccountBalances[entry.second] = 0;
1170 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1172 const CWalletTx& wtx = (*it).second;
1173 int64 nGeneratedImmature, nGeneratedMature, nFee;
1174 string strSentAccount;
1175 list<pair<CBitcoinAddress, int64> > listReceived;
1176 list<pair<CBitcoinAddress, int64> > listSent;
1177 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1178 mapAccountBalances[strSentAccount] -= nFee;
1179 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1180 mapAccountBalances[strSentAccount] -= s.second;
1181 if (wtx.GetDepthInMainChain() >= nMinDepth)
1183 mapAccountBalances[""] += nGeneratedMature;
1184 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1185 if (pwalletMain->mapAddressBook.count(r.first))
1186 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1188 mapAccountBalances[""] += r.second;
1192 list<CAccountingEntry> acentries;
1193 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1194 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1195 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1198 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1199 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1204 Value gettransaction(const Array& params, bool fHelp)
1206 if (fHelp || params.size() != 1)
1207 throw runtime_error(
1208 "gettransaction <txid>\n"
1209 "Get detailed information about <txid>");
1212 hash.SetHex(params[0].get_str());
1216 if (!pwalletMain->mapWallet.count(hash))
1217 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1218 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1220 int64 nCredit = wtx.GetCredit();
1221 int64 nDebit = wtx.GetDebit();
1222 int64 nNet = nCredit - nDebit;
1223 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1225 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1227 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1229 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1232 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1233 entry.push_back(Pair("details", details));
1239 Value backupwallet(const Array& params, bool fHelp)
1241 if (fHelp || params.size() != 1)
1242 throw runtime_error(
1243 "backupwallet <destination>\n"
1244 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1246 string strDest = params[0].get_str();
1247 BackupWallet(*pwalletMain, strDest);
1253 Value keypoolrefill(const Array& params, bool fHelp)
1255 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1256 throw runtime_error(
1258 "Fills the keypool, requires wallet passphrase to be set.");
1259 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1260 throw runtime_error(
1262 "Fills the keypool.");
1264 if (pwalletMain->IsLocked())
1265 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1267 pwalletMain->TopUpKeyPool();
1269 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1270 throw JSONRPCError(-4, "Error refreshing keypool.");
1276 void ThreadTopUpKeyPool(void* parg)
1278 pwalletMain->TopUpKeyPool();
1281 void ThreadCleanWalletPassphrase(void* parg)
1283 int64 nMyWakeTime = GetTime() + *((int*)parg);
1285 if (nWalletUnlockTime == 0)
1287 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1289 nWalletUnlockTime = nMyWakeTime;
1292 while (GetTime() < nWalletUnlockTime)
1293 Sleep(GetTime() - nWalletUnlockTime);
1295 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1297 nWalletUnlockTime = 0;
1302 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1304 if (nWalletUnlockTime < nMyWakeTime)
1305 nWalletUnlockTime = nMyWakeTime;
1311 pwalletMain->Lock();
1316 Value walletpassphrase(const Array& params, bool fHelp)
1318 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1319 throw runtime_error(
1320 "walletpassphrase <passphrase> <timeout>\n"
1321 "Stores the wallet decryption key in memory for <timeout> seconds.");
1324 if (!pwalletMain->IsCrypted())
1325 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1327 if (!pwalletMain->IsLocked())
1328 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1330 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1331 string strWalletPass;
1332 strWalletPass.reserve(100);
1333 mlock(&strWalletPass[0], strWalletPass.capacity());
1334 strWalletPass = params[0].get_str();
1336 if (strWalletPass.length() > 0)
1338 if (!pwalletMain->Unlock(strWalletPass))
1340 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1341 munlock(&strWalletPass[0], strWalletPass.capacity());
1342 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1344 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1345 munlock(&strWalletPass[0], strWalletPass.capacity());
1348 throw runtime_error(
1349 "walletpassphrase <passphrase> <timeout>\n"
1350 "Stores the wallet decryption key in memory for <timeout> seconds.");
1352 CreateThread(ThreadTopUpKeyPool, NULL);
1353 int* pnSleepTime = new int(params[1].get_int());
1354 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1360 Value walletpassphrasechange(const Array& params, bool fHelp)
1362 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1363 throw runtime_error(
1364 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1365 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1368 if (!pwalletMain->IsCrypted())
1369 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1371 string strOldWalletPass;
1372 strOldWalletPass.reserve(100);
1373 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1374 strOldWalletPass = params[0].get_str();
1376 string strNewWalletPass;
1377 strNewWalletPass.reserve(100);
1378 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1379 strNewWalletPass = params[1].get_str();
1381 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1382 throw runtime_error(
1383 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1384 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1386 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1388 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1389 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1390 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1391 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1392 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1394 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1395 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1396 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1397 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1403 Value walletlock(const Array& params, bool fHelp)
1405 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1406 throw runtime_error(
1408 "Removes the wallet encryption key from memory, locking the wallet.\n"
1409 "After calling this method, you will need to call walletpassphrase again\n"
1410 "before being able to call any methods which require the wallet to be unlocked.");
1413 if (!pwalletMain->IsCrypted())
1414 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1416 pwalletMain->Lock();
1417 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1419 nWalletUnlockTime = 0;
1426 Value encryptwallet(const Array& params, bool fHelp)
1428 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1429 throw runtime_error(
1430 "encryptwallet <passphrase>\n"
1431 "Encrypts the wallet with <passphrase>.");
1434 if (pwalletMain->IsCrypted())
1435 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1437 string strWalletPass;
1438 strWalletPass.reserve(100);
1439 mlock(&strWalletPass[0], strWalletPass.capacity());
1440 strWalletPass = params[0].get_str();
1442 if (strWalletPass.length() < 1)
1443 throw runtime_error(
1444 "encryptwallet <passphrase>\n"
1445 "Encrypts the wallet with <passphrase>.");
1447 if (!pwalletMain->EncryptWallet(strWalletPass))
1449 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1450 munlock(&strWalletPass[0], strWalletPass.capacity());
1451 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1453 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1454 munlock(&strWalletPass[0], strWalletPass.capacity());
1460 Value validateaddress(const Array& params, bool fHelp)
1462 if (fHelp || params.size() != 1)
1463 throw runtime_error(
1464 "validateaddress <bitcoinaddress>\n"
1465 "Return information about <bitcoinaddress>.");
1467 CBitcoinAddress address(params[0].get_str());
1468 bool isValid = address.IsValid();
1471 ret.push_back(Pair("isvalid", isValid));
1474 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1475 // version of the address:
1476 string currentAddress = address.ToString();
1477 ret.push_back(Pair("address", currentAddress));
1478 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1479 if (pwalletMain->mapAddressBook.count(address))
1480 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1486 Value getwork(const Array& params, bool fHelp)
1488 if (fHelp || params.size() > 1)
1489 throw runtime_error(
1491 "If [data] is not specified, returns formatted hash data to work on:\n"
1492 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1493 " \"data\" : block data\n"
1494 " \"hash1\" : formatted hash buffer for second hash\n"
1495 " \"target\" : little endian hash target\n"
1496 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1499 throw JSONRPCError(-9, "Bitcoin is not connected!");
1501 if (IsInitialBlockDownload())
1502 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1504 static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1505 static vector<CBlock*> vNewBlock;
1506 static CReserveKey reservekey(pwalletMain);
1508 if (params.size() == 0)
1511 static unsigned int nTransactionsUpdatedLast;
1512 static CBlockIndex* pindexPrev;
1513 static int64 nStart;
1514 static CBlock* pblock;
1515 if (pindexPrev != pindexBest ||
1516 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1518 if (pindexPrev != pindexBest)
1520 // Deallocate old blocks since they're obsolete now
1521 mapNewBlock.clear();
1522 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1526 nTransactionsUpdatedLast = nTransactionsUpdated;
1527 pindexPrev = pindexBest;
1531 pblock = CreateNewBlock(reservekey);
1533 throw JSONRPCError(-7, "Out of memory");
1534 vNewBlock.push_back(pblock);
1538 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1541 // Update nExtraNonce
1542 static unsigned int nExtraNonce = 0;
1543 static int64 nPrevTime = 0;
1544 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1547 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1549 // Prebuild hash buffers
1553 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1555 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1558 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1559 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1560 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1561 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1567 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1568 if (vchData.size() != 128)
1569 throw JSONRPCError(-8, "Invalid parameter");
1570 CBlock* pdata = (CBlock*)&vchData[0];
1573 for (int i = 0; i < 128/4; i++)
1574 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1577 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1579 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1580 unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1582 pblock->nTime = pdata->nTime;
1583 pblock->nNonce = pdata->nNonce;
1584 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1585 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1587 return CheckWork(pblock, *pwalletMain, reservekey);
1605 pair<string, rpcfn_type> pCallTable[] =
1607 make_pair("help", &help),
1608 make_pair("stop", &stop),
1609 make_pair("getblockcount", &getblockcount),
1610 make_pair("getblocknumber", &getblocknumber),
1611 make_pair("getconnectioncount", &getconnectioncount),
1612 make_pair("getdifficulty", &getdifficulty),
1613 make_pair("getgenerate", &getgenerate),
1614 make_pair("setgenerate", &setgenerate),
1615 make_pair("gethashespersec", &gethashespersec),
1616 make_pair("getinfo", &getinfo),
1617 make_pair("getnewaddress", &getnewaddress),
1618 make_pair("getaccountaddress", &getaccountaddress),
1619 make_pair("setaccount", &setaccount),
1620 make_pair("setlabel", &setaccount), // deprecated
1621 make_pair("getaccount", &getaccount),
1622 make_pair("getlabel", &getaccount), // deprecated
1623 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1624 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1625 make_pair("sendtoaddress", &sendtoaddress),
1626 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1627 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1628 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1629 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1630 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1631 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1632 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1633 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1634 make_pair("backupwallet", &backupwallet),
1635 make_pair("keypoolrefill", &keypoolrefill),
1636 make_pair("walletpassphrase", &walletpassphrase),
1637 make_pair("walletpassphrasechange", &walletpassphrasechange),
1638 make_pair("walletlock", &walletlock),
1639 make_pair("encryptwallet", &encryptwallet),
1640 make_pair("validateaddress", &validateaddress),
1641 make_pair("getbalance", &getbalance),
1642 make_pair("move", &movecmd),
1643 make_pair("sendfrom", &sendfrom),
1644 make_pair("sendmany", &sendmany),
1645 make_pair("gettransaction", &gettransaction),
1646 make_pair("listtransactions", &listtransactions),
1647 make_pair("getwork", &getwork),
1648 make_pair("listaccounts", &listaccounts),
1649 make_pair("settxfee", &settxfee),
1651 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1653 string pAllowInSafeMode[] =
1659 "getconnectioncount",
1666 "getaccountaddress",
1667 "setlabel", // deprecated
1669 "getlabel", // deprecated
1670 "getaddressesbyaccount",
1671 "getaddressesbylabel", // deprecated
1679 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1687 // This ain't Apache. We're just using HTTP header for the length field
1688 // and to be compatible with other JSON-RPC implementations.
1691 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1694 s << "POST / HTTP/1.1\r\n"
1695 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1696 << "Host: 127.0.0.1\r\n"
1697 << "Content-Type: application/json\r\n"
1698 << "Content-Length: " << strMsg.size() << "\r\n"
1699 << "Accept: application/json\r\n";
1700 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1701 s << item.first << ": " << item.second << "\r\n";
1702 s << "\r\n" << strMsg;
1707 string rfc1123Time()
1712 struct tm* now_gmt = gmtime(&now);
1713 string locale(setlocale(LC_TIME, NULL));
1714 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1715 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1716 setlocale(LC_TIME, locale.c_str());
1717 return string(buffer);
1720 static string HTTPReply(int nStatus, const string& strMsg)
1723 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1725 "Server: bitcoin-json-rpc/%s\r\n"
1726 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1727 "Content-Type: text/html\r\n"
1728 "Content-Length: 296\r\n"
1730 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1731 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1734 "<TITLE>Error</TITLE>\r\n"
1735 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1737 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1738 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1740 if (nStatus == 200) strStatus = "OK";
1741 else if (nStatus == 400) strStatus = "Bad Request";
1742 else if (nStatus == 403) strStatus = "Forbidden";
1743 else if (nStatus == 404) strStatus = "Not Found";
1744 else if (nStatus == 500) strStatus = "Internal Server Error";
1746 "HTTP/1.1 %d %s\r\n"
1748 "Connection: close\r\n"
1749 "Content-Length: %d\r\n"
1750 "Content-Type: application/json\r\n"
1751 "Server: bitcoin-json-rpc/%s\r\n"
1756 rfc1123Time().c_str(),
1758 FormatFullVersion().c_str(),
1762 int ReadHTTPStatus(std::basic_istream<char>& stream)
1765 getline(stream, str);
1766 vector<string> vWords;
1767 boost::split(vWords, str, boost::is_any_of(" "));
1768 if (vWords.size() < 2)
1770 return atoi(vWords[1].c_str());
1773 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1779 std::getline(stream, str);
1780 if (str.empty() || str == "\r")
1782 string::size_type nColon = str.find(":");
1783 if (nColon != string::npos)
1785 string strHeader = str.substr(0, nColon);
1786 boost::trim(strHeader);
1787 boost::to_lower(strHeader);
1788 string strValue = str.substr(nColon+1);
1789 boost::trim(strValue);
1790 mapHeadersRet[strHeader] = strValue;
1791 if (strHeader == "content-length")
1792 nLen = atoi(strValue.c_str());
1798 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1800 mapHeadersRet.clear();
1804 int nStatus = ReadHTTPStatus(stream);
1807 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1808 if (nLen < 0 || nLen > MAX_SIZE)
1814 vector<char> vch(nLen);
1815 stream.read(&vch[0], nLen);
1816 strMessageRet = string(vch.begin(), vch.end());
1822 string EncodeBase64(string s)
1827 b64 = BIO_new(BIO_f_base64());
1828 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1829 bmem = BIO_new(BIO_s_mem());
1830 b64 = BIO_push(b64, bmem);
1831 BIO_write(b64, s.c_str(), s.size());
1833 BIO_get_mem_ptr(b64, &bptr);
1835 string result(bptr->data, bptr->length);
1841 string DecodeBase64(string s)
1845 char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1847 b64 = BIO_new(BIO_f_base64());
1848 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1849 bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1850 bmem = BIO_push(b64, bmem);
1851 BIO_read(bmem, buffer, s.size());
1854 string result(buffer);
1859 bool HTTPAuthorized(map<string, string>& mapHeaders)
1861 string strAuth = mapHeaders["authorization"];
1862 if (strAuth.substr(0,6) != "Basic ")
1864 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1865 string strUserPass = DecodeBase64(strUserPass64);
1866 string::size_type nColon = strUserPass.find(":");
1867 if (nColon == string::npos)
1869 string strUser = strUserPass.substr(0, nColon);
1870 string strPassword = strUserPass.substr(nColon+1);
1871 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1875 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1876 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1877 // unspecified (HTTP errors and contents of 'error').
1879 // 1.0 spec: http://json-rpc.org/wiki/specification
1880 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1881 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1884 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1887 request.push_back(Pair("method", strMethod));
1888 request.push_back(Pair("params", params));
1889 request.push_back(Pair("id", id));
1890 return write_string(Value(request), false) + "\n";
1893 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1896 if (error.type() != null_type)
1897 reply.push_back(Pair("result", Value::null));
1899 reply.push_back(Pair("result", result));
1900 reply.push_back(Pair("error", error));
1901 reply.push_back(Pair("id", id));
1902 return write_string(Value(reply), false) + "\n";
1905 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1907 // Send error reply from json-rpc error object
1909 int code = find_value(objError, "code").get_int();
1910 if (code == -32600) nStatus = 400;
1911 else if (code == -32601) nStatus = 404;
1912 string strReply = JSONRPCReply(Value::null, objError, id);
1913 stream << HTTPReply(nStatus, strReply) << std::flush;
1916 bool ClientAllowed(const string& strAddress)
1918 if (strAddress == asio::ip::address_v4::loopback().to_string())
1920 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1921 BOOST_FOREACH(string strAllow, vAllow)
1922 if (WildcardMatch(strAddress, strAllow))
1929 // IOStream device that speaks SSL but can also speak non-SSL
1931 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1933 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1935 fUseSSL = fUseSSLIn;
1936 fNeedHandshake = fUseSSLIn;
1939 void handshake(ssl::stream_base::handshake_type role)
1941 if (!fNeedHandshake) return;
1942 fNeedHandshake = false;
1943 stream.handshake(role);
1945 std::streamsize read(char* s, std::streamsize n)
1947 handshake(ssl::stream_base::server); // HTTPS servers read first
1948 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1949 return stream.next_layer().read_some(asio::buffer(s, n));
1951 std::streamsize write(const char* s, std::streamsize n)
1953 handshake(ssl::stream_base::client); // HTTPS clients write first
1954 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1955 return asio::write(stream.next_layer(), asio::buffer(s, n));
1957 bool connect(const std::string& server, const std::string& port)
1959 ip::tcp::resolver resolver(stream.get_io_service());
1960 ip::tcp::resolver::query query(server.c_str(), port.c_str());
1961 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
1962 ip::tcp::resolver::iterator end;
1963 boost::system::error_code error = asio::error::host_not_found;
1964 while (error && endpoint_iterator != end)
1966 stream.lowest_layer().close();
1967 stream.lowest_layer().connect(*endpoint_iterator++, error);
1975 bool fNeedHandshake;
1981 void ThreadRPCServer(void* parg)
1983 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
1986 vnThreadsRunning[4]++;
1987 ThreadRPCServer2(parg);
1988 vnThreadsRunning[4]--;
1990 catch (std::exception& e) {
1991 vnThreadsRunning[4]--;
1992 PrintException(&e, "ThreadRPCServer()");
1994 vnThreadsRunning[4]--;
1995 PrintException(NULL, "ThreadRPCServer()");
1997 printf("ThreadRPCServer exiting\n");
2000 void ThreadRPCServer2(void* parg)
2002 printf("ThreadRPCServer started\n");
2004 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2006 string strWhatAmI = "To use bitcoind";
2007 if (mapArgs.count("-server"))
2008 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2009 else if (mapArgs.count("-daemon"))
2010 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2012 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2013 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2015 GetConfigFile().c_str());
2016 CreateThread(Shutdown, NULL);
2020 bool fUseSSL = GetBoolArg("-rpcssl");
2021 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2023 asio::io_service io_service;
2024 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2025 ip::tcp::acceptor acceptor(io_service, endpoint);
2027 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2030 ssl::context context(io_service, ssl::context::sslv23);
2033 context.set_options(ssl::context::no_sslv2);
2034 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2035 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2036 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2037 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2038 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2039 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2040 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2041 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2043 string ciphers = GetArg("-rpcsslciphers",
2044 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2045 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2049 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2054 // Accept connection
2056 SSLStream sslStream(io_service, context);
2057 SSLIOStreamDevice d(sslStream, fUseSSL);
2058 iostreams::stream<SSLIOStreamDevice> stream(d);
2060 ip::tcp::iostream stream;
2063 ip::tcp::endpoint peer;
2064 vnThreadsRunning[4]--;
2066 acceptor.accept(sslStream.lowest_layer(), peer);
2068 acceptor.accept(*stream.rdbuf(), peer);
2070 vnThreadsRunning[4]++;
2074 // Restrict callers by IP
2075 if (!ClientAllowed(peer.address().to_string()))
2077 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2079 stream << HTTPReply(403, "") << std::flush;
2083 map<string, string> mapHeaders;
2086 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2087 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2090 printf("ThreadRPCServer ReadHTTP timeout\n");
2094 // Check authorization
2095 if (mapHeaders.count("authorization") == 0)
2097 stream << HTTPReply(401, "") << std::flush;
2100 if (!HTTPAuthorized(mapHeaders))
2102 // Deter brute-forcing short passwords
2103 if (mapArgs["-rpcpassword"].size() < 15)
2106 stream << HTTPReply(401, "") << std::flush;
2107 printf("ThreadRPCServer incorrect password attempt\n");
2111 Value id = Value::null;
2116 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2117 throw JSONRPCError(-32700, "Parse error");
2118 const Object& request = valRequest.get_obj();
2120 // Parse id now so errors from here on will have the id
2121 id = find_value(request, "id");
2124 Value valMethod = find_value(request, "method");
2125 if (valMethod.type() == null_type)
2126 throw JSONRPCError(-32600, "Missing method");
2127 if (valMethod.type() != str_type)
2128 throw JSONRPCError(-32600, "Method must be a string");
2129 string strMethod = valMethod.get_str();
2130 if (strMethod != "getwork")
2131 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2134 Value valParams = find_value(request, "params");
2136 if (valParams.type() == array_type)
2137 params = valParams.get_array();
2138 else if (valParams.type() == null_type)
2141 throw JSONRPCError(-32600, "Params must be an array");
2144 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2145 if (mi == mapCallTable.end())
2146 throw JSONRPCError(-32601, "Method not found");
2148 // Observe safe mode
2149 string strWarning = GetWarnings("rpc");
2150 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2151 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2157 CRITICAL_BLOCK(cs_main)
2158 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2159 result = (*(*mi).second)(params, false);
2162 string strReply = JSONRPCReply(result, Value::null, id);
2163 stream << HTTPReply(200, strReply) << std::flush;
2165 catch (std::exception& e)
2167 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2170 catch (Object& objError)
2172 ErrorReply(stream, objError, id);
2174 catch (std::exception& e)
2176 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2184 Object CallRPC(const string& strMethod, const Array& params)
2186 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2187 throw runtime_error(strprintf(
2188 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2189 "If the file does not exist, create it with owner-readable-only file permissions."),
2190 GetConfigFile().c_str()));
2192 // Connect to localhost
2193 bool fUseSSL = GetBoolArg("-rpcssl");
2195 asio::io_service io_service;
2196 ssl::context context(io_service, ssl::context::sslv23);
2197 context.set_options(ssl::context::no_sslv2);
2198 SSLStream sslStream(io_service, context);
2199 SSLIOStreamDevice d(sslStream, fUseSSL);
2200 iostreams::stream<SSLIOStreamDevice> stream(d);
2201 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2202 throw runtime_error("couldn't connect to server");
2205 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2207 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2209 throw runtime_error("couldn't connect to server");
2213 // HTTP basic authentication
2214 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2215 map<string, string> mapRequestHeaders;
2216 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2219 string strRequest = JSONRPCRequest(strMethod, params, 1);
2220 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2221 stream << strPost << std::flush;
2224 map<string, string> mapHeaders;
2226 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2228 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2229 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2230 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2231 else if (strReply.empty())
2232 throw runtime_error("no response from server");
2236 if (!read_string(strReply, valReply))
2237 throw runtime_error("couldn't parse reply from server");
2238 const Object& reply = valReply.get_obj();
2240 throw runtime_error("expected reply to have result, error and id properties");
2248 template<typename T>
2249 void ConvertTo(Value& value)
2251 if (value.type() == str_type)
2253 // reinterpret string as unquoted json value
2255 if (!read_string(value.get_str(), value2))
2256 throw runtime_error("type mismatch");
2257 value = value2.get_value<T>();
2261 value = value.get_value<T>();
2265 int CommandLineRPC(int argc, char *argv[])
2272 while (argc > 1 && IsSwitchChar(argv[1][0]))
2280 throw runtime_error("too few parameters");
2281 string strMethod = argv[1];
2283 // Parameters default to strings
2285 for (int i = 2; i < argc; i++)
2286 params.push_back(argv[i]);
2287 int n = params.size();
2290 // Special case non-string parameter types
2292 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2293 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2294 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2295 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2296 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2297 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2298 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2299 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2300 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2301 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2302 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2303 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2304 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2305 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2306 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2307 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2308 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2309 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2310 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2311 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2312 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2313 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2314 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2315 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2316 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2317 if (strMethod == "sendmany" && n > 1)
2319 string s = params[1].get_str();
2321 if (!read_string(s, v) || v.type() != obj_type)
2322 throw runtime_error("type mismatch");
2323 params[1] = v.get_obj();
2325 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2328 Object reply = CallRPC(strMethod, params);
2331 const Value& result = find_value(reply, "result");
2332 const Value& error = find_value(reply, "error");
2334 if (error.type() != null_type)
2337 strPrint = "error: " + write_string(error, false);
2338 int code = find_value(error.get_obj(), "code").get_int();
2344 if (result.type() == null_type)
2346 else if (result.type() == str_type)
2347 strPrint = result.get_str();
2349 strPrint = write_string(result, true);
2352 catch (std::exception& e)
2354 strPrint = string("error: ") + e.what();
2359 PrintException(NULL, "CommandLineRPC()");
2364 #if defined(__WXMSW__) && defined(GUI)
2365 // Windows GUI apps can't print to command line,
2366 // so settle for a message box yuck
2367 MyMessageBox(strPrint, "Bitcoin", wxOK);
2369 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2379 int main(int argc, char *argv[])
2382 // Turn off microsoft heap dump noise
2383 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2384 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2386 setbuf(stdin, NULL);
2387 setbuf(stdout, NULL);
2388 setbuf(stderr, NULL);
2392 if (argc >= 2 && string(argv[1]) == "-server")
2394 printf("server ready\n");
2395 ThreadRPCServer(NULL);
2399 return CommandLineRPC(argc, argv);
2402 catch (std::exception& e) {
2403 PrintException(&e, "main()");
2405 PrintException(NULL, "main()");