1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
7 #include "cryptopp/sha.h"
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
44 Object JSONRPCError(int code, const string& message)
47 error.push_back(Pair("code", code));
48 error.push_back(Pair("message", message));
53 void PrintConsole(const std::string &format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
61 if (ret < 0 || ret >= limit)
67 fprintf(stdout, "%s", buffer);
71 int64 AmountFromValue(const Value& value)
73 double dAmount = value.get_real();
74 if (dAmount <= 0.0 || dAmount > 21000000.0)
75 throw JSONRPCError(-3, "Invalid amount");
76 int64 nAmount = roundint64(dAmount * COIN);
77 if (!MoneyRange(nAmount))
78 throw JSONRPCError(-3, "Invalid amount");
82 Value ValueFromAmount(int64 amount)
84 return (double)amount / (double)COIN;
87 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
89 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
90 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
91 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
92 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
93 entry.push_back(Pair(item.first, item.second));
96 string AccountFromValue(const Value& value)
98 string strAccount = value.get_str();
99 if (strAccount == "*")
100 throw JSONRPCError(-11, "Invalid account name");
107 /// Note: This interface may still be subject to change.
111 Value help(const Array& params, bool fHelp)
113 if (fHelp || params.size() > 1)
116 "List commands, or get help for a command.");
119 if (params.size() > 0)
120 strCommand = params[0].get_str();
123 set<rpcfn_type> setDone;
124 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
126 string strMethod = (*mi).first;
127 // We already filter duplicates, but these deprecated screw up the sort order
128 if (strMethod == "getamountreceived" ||
129 strMethod == "getallreceived" ||
130 (strMethod.find("label") != string::npos))
132 if (strCommand != "" && strMethod != strCommand)
137 rpcfn_type pfn = (*mi).second;
138 if (setDone.insert(pfn).second)
139 (*pfn)(params, true);
141 catch (std::exception& e)
143 // Help text is returned in an exception
144 string strHelp = string(e.what());
145 if (strCommand == "")
146 if (strHelp.find('\n') != -1)
147 strHelp = strHelp.substr(0, strHelp.find('\n'));
148 strRet += strHelp + "\n";
152 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
153 strRet = strRet.substr(0,strRet.size()-1);
158 Value stop(const Array& params, bool fHelp)
160 if (fHelp || params.size() != 0)
163 "Stop bitcoin server.");
165 // Shutdown will take long enough that the response should get back
166 CreateThread(Shutdown, NULL);
167 return "bitcoin server stopping";
171 Value getblockcount(const Array& params, bool fHelp)
173 if (fHelp || params.size() != 0)
176 "Returns the number of blocks in the longest block chain.");
182 Value getblocknumber(const Array& params, bool fHelp)
184 if (fHelp || params.size() != 0)
187 "Returns the block number of the latest block in the longest block chain.");
193 Value getconnectioncount(const Array& params, bool fHelp)
195 if (fHelp || params.size() != 0)
197 "getconnectioncount\n"
198 "Returns the number of connections to other nodes.");
200 return (int)vNodes.size();
204 double GetDifficulty()
206 // Floating point number that is a multiple of the minimum difficulty,
207 // minimum difficulty = 1.0.
209 if (pindexBest == NULL)
211 int nShift = (pindexBest->nBits >> 24) & 0xff;
214 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
230 Value getdifficulty(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
237 return GetDifficulty();
241 Value getgenerate(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Returns true or false.");
248 return (bool)fGenerateBitcoins;
252 Value setgenerate(const Array& params, bool fHelp)
254 if (fHelp || params.size() < 1 || params.size() > 2)
256 "setgenerate <generate> [genproclimit]\n"
257 "<generate> is true or false to turn generation on or off.\n"
258 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
260 bool fGenerate = true;
261 if (params.size() > 0)
262 fGenerate = params[0].get_bool();
264 if (params.size() > 1)
266 int nGenProcLimit = params[1].get_int();
267 fLimitProcessors = (nGenProcLimit != -1);
268 WriteSetting("fLimitProcessors", fLimitProcessors);
269 if (nGenProcLimit != -1)
270 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
271 if (nGenProcLimit == 0)
275 GenerateBitcoins(fGenerate, pwalletMain);
280 Value gethashespersec(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 0)
285 "Returns a recent hashes per second performance measurement while generating.");
287 if (GetTimeMillis() - nHPSTimerStart > 8000)
288 return (boost::int64_t)0;
289 return (boost::int64_t)dHashesPerSec;
293 Value getinfo(const Array& params, bool fHelp)
295 if (fHelp || params.size() != 0)
298 "Returns an object containing various state info.");
301 obj.push_back(Pair("version", (int)VERSION));
302 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
303 obj.push_back(Pair("blocks", (int)nBestHeight));
304 obj.push_back(Pair("connections", (int)vNodes.size()));
305 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
306 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
307 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
308 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
309 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
310 obj.push_back(Pair("testnet", fTestNet));
311 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
312 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
313 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
314 if (pwalletMain->IsCrypted())
315 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
316 obj.push_back(Pair("errors", GetWarnings("statusbar")));
321 Value getnewaddress(const Array& params, bool fHelp)
323 if (fHelp || params.size() > 1)
325 "getnewaddress [account]\n"
326 "Returns a new bitcoin address for receiving payments. "
327 "If [account] is specified (recommended), it is added to the address book "
328 "so payments received with the address will be credited to [account].");
330 // Parse the account first so we don't generate a key if there's an error
332 if (params.size() > 0)
333 strAccount = AccountFromValue(params[0]);
335 if (!pwalletMain->IsLocked())
336 pwalletMain->TopUpKeyPool();
338 // Generate a new key that is added to wallet
339 std::vector<unsigned char> newKey;
340 if (!pwalletMain->GetKeyFromPool(newKey, false))
341 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
342 CBitcoinAddress address(newKey);
344 pwalletMain->SetAddressBookName(address, strAccount);
346 return address.ToString();
350 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
352 CWalletDB walletdb(pwalletMain->strWalletFile);
355 walletdb.ReadAccount(strAccount, account);
357 bool bKeyUsed = false;
359 // Check if the current key has been used
360 if (!account.vchPubKey.empty())
362 CScript scriptPubKey;
363 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
365 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
368 const CWalletTx& wtx = (*it).second;
369 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
370 if (txout.scriptPubKey == scriptPubKey)
375 // Generate a new key
376 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
378 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
379 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
381 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
382 walletdb.WriteAccount(strAccount, account);
385 return CBitcoinAddress(account.vchPubKey);
388 Value getaccountaddress(const Array& params, bool fHelp)
390 if (fHelp || params.size() != 1)
392 "getaccountaddress <account>\n"
393 "Returns the current bitcoin address for receiving payments to this account.");
395 // Parse the account first so we don't generate a key if there's an error
396 string strAccount = AccountFromValue(params[0]);
400 ret = GetAccountAddress(strAccount).ToString();
407 Value setaccount(const Array& params, bool fHelp)
409 if (fHelp || params.size() < 1 || params.size() > 2)
411 "setaccount <bitcoinaddress> <account>\n"
412 "Sets the account associated with the given address.");
414 CBitcoinAddress address(params[0].get_str());
415 if (!address.IsValid())
416 throw JSONRPCError(-5, "Invalid bitcoin address");
420 if (params.size() > 1)
421 strAccount = AccountFromValue(params[1]);
423 // Detect when changing the account of an address that is the 'unused current key' of another account:
424 if (pwalletMain->mapAddressBook.count(address))
426 string strOldAccount = pwalletMain->mapAddressBook[address];
427 if (address == GetAccountAddress(strOldAccount))
428 GetAccountAddress(strOldAccount, true);
431 pwalletMain->SetAddressBookName(address, strAccount);
437 Value getaccount(const Array& params, bool fHelp)
439 if (fHelp || params.size() != 1)
441 "getaccount <bitcoinaddress>\n"
442 "Returns the account associated with the given address.");
444 CBitcoinAddress address(params[0].get_str());
445 if (!address.IsValid())
446 throw JSONRPCError(-5, "Invalid bitcoin address");
449 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
450 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
451 strAccount = (*mi).second;
456 Value getaddressesbyaccount(const Array& params, bool fHelp)
458 if (fHelp || params.size() != 1)
460 "getaddressesbyaccount <account>\n"
461 "Returns the list of addresses for the given account.");
463 string strAccount = AccountFromValue(params[0]);
465 // Find all addresses that have the given account
467 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
469 const CBitcoinAddress& address = item.first;
470 const string& strName = item.second;
471 if (strName == strAccount)
472 ret.push_back(address.ToString());
477 Value settxfee(const Array& params, bool fHelp)
479 if (fHelp || params.size() < 1 || params.size() > 1)
481 "settxfee <amount>\n"
482 "<amount> is a real and is rounded to the nearest 0.00000001");
486 if (params[0].get_real() != 0.0)
487 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
489 nTransactionFee = nAmount;
493 Value sendtoaddress(const Array& params, bool fHelp)
495 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
497 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
498 "<amount> is a real and is rounded to the nearest 0.00000001\n"
499 "requires wallet passphrase to be set with walletpassphrase first");
500 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
502 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503 "<amount> is a real and is rounded to the nearest 0.00000001");
505 CBitcoinAddress address(params[0].get_str());
506 if (!address.IsValid())
507 throw JSONRPCError(-5, "Invalid bitcoin address");
510 int64 nAmount = AmountFromValue(params[1]);
514 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
515 wtx.mapValue["comment"] = params[2].get_str();
516 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
517 wtx.mapValue["to"] = params[3].get_str();
519 if (pwalletMain->IsLocked())
520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
522 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
524 throw JSONRPCError(-4, strError);
526 return wtx.GetHash().GetHex();
529 static const string strMessageMagic = "Bitcoin Signed Message:\n";
531 Value signmessage(const Array& params, bool fHelp)
533 if (fHelp || params.size() != 2)
535 "signmessage <bitcoinaddress> <message>\n"
536 "Sign a message with the private key of an address");
538 if (pwalletMain->IsLocked())
539 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
541 string strAddress = params[0].get_str();
542 string strMessage = params[1].get_str();
544 CBitcoinAddress addr(strAddress);
546 throw JSONRPCError(-3, "Invalid address");
549 if (!pwalletMain->GetKey(addr, key))
550 throw JSONRPCError(-4, "Private key not available");
552 CDataStream ss(SER_GETHASH);
553 ss << strMessageMagic;
556 vector<unsigned char> vchSig;
557 if (!key.Sign(Hash(ss.begin(), ss.end()), vchSig))
558 throw JSONRPCError(-5, "Sign failed");
560 CDataStream sres(SER_NETWORK);
561 sres << key.GetPubKey(); // public key
562 sres << vchSig; // signature;
564 return HexStr(sres.begin(), sres.end());
567 Value verifymessage(const Array& params, bool fHelp)
569 if (fHelp || params.size() != 3)
571 "verifymessage <bitcoinaddress> <signature> <message>\n"
572 "Verify a signed message");
574 string strAddress = params[0].get_str();
575 string strSign = params[1].get_str();
576 string strMessage = params[2].get_str();
578 CBitcoinAddress addr(strAddress);
580 throw JSONRPCError(-3, "Invalid address");
582 vector<unsigned char> vchResult = ParseHex(strSign);
583 CDataStream sres(vchResult);
585 std::vector<unsigned char> vchPubKey;
587 std::vector<unsigned char> vchSig;
591 if (!key.SetPubKey(vchPubKey))
592 throw JSONRPCError(-5, "Invalid public key in signature");
594 if (key.GetAddress() == addr)
596 CDataStream ss(SER_GETHASH);
597 ss << strMessageMagic;
599 return key.Verify(Hash(ss.begin(), ss.end()), vchSig);
606 Value getreceivedbyaddress(const Array& params, bool fHelp)
608 if (fHelp || params.size() < 1 || params.size() > 2)
610 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
611 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
614 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
615 CScript scriptPubKey;
616 if (!address.IsValid())
617 throw JSONRPCError(-5, "Invalid bitcoin address");
618 scriptPubKey.SetBitcoinAddress(address);
619 if (!IsMine(*pwalletMain,scriptPubKey))
622 // Minimum confirmations
624 if (params.size() > 1)
625 nMinDepth = params[1].get_int();
629 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
631 const CWalletTx& wtx = (*it).second;
632 if (wtx.IsCoinBase() || !wtx.IsFinal())
635 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
636 if (txout.scriptPubKey == scriptPubKey)
637 if (wtx.GetDepthInMainChain() >= nMinDepth)
638 nAmount += txout.nValue;
641 return ValueFromAmount(nAmount);
645 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
647 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
649 const CBitcoinAddress& address = item.first;
650 const string& strName = item.second;
651 if (strName == strAccount)
652 setAddress.insert(address);
657 Value getreceivedbyaccount(const Array& params, bool fHelp)
659 if (fHelp || params.size() < 1 || params.size() > 2)
661 "getreceivedbyaccount <account> [minconf=1]\n"
662 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
664 // Minimum confirmations
666 if (params.size() > 1)
667 nMinDepth = params[1].get_int();
669 // Get the set of pub keys that have the label
670 string strAccount = AccountFromValue(params[0]);
671 set<CBitcoinAddress> setAddress;
672 GetAccountAddresses(strAccount, setAddress);
676 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
678 const CWalletTx& wtx = (*it).second;
679 if (wtx.IsCoinBase() || !wtx.IsFinal())
682 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
684 CBitcoinAddress address;
685 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
686 if (wtx.GetDepthInMainChain() >= nMinDepth)
687 nAmount += txout.nValue;
691 return (double)nAmount / (double)COIN;
695 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
699 // Tally wallet transactions
700 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
702 const CWalletTx& wtx = (*it).second;
706 int64 nGenerated, nReceived, nSent, nFee;
707 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
709 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
710 nBalance += nReceived;
711 nBalance += nGenerated - nSent - nFee;
714 // Tally internal accounting entries
715 nBalance += walletdb.GetAccountCreditDebit(strAccount);
720 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
722 CWalletDB walletdb(pwalletMain->strWalletFile);
723 return GetAccountBalance(walletdb, strAccount, nMinDepth);
727 Value getbalance(const Array& params, bool fHelp)
729 if (fHelp || params.size() > 2)
731 "getbalance [account] [minconf=1]\n"
732 "If [account] is not specified, returns the server's total available balance.\n"
733 "If [account] is specified, returns the balance in the account.");
735 if (params.size() == 0)
736 return ValueFromAmount(pwalletMain->GetBalance());
739 if (params.size() > 1)
740 nMinDepth = params[1].get_int();
742 if (params[0].get_str() == "*") {
743 // Calculate total balance a different way from GetBalance()
744 // (GetBalance() sums up all unspent TxOuts)
745 // getbalance and getbalance '*' should always return the same number.
747 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
749 const CWalletTx& wtx = (*it).second;
753 int64 allGeneratedImmature, allGeneratedMature, allFee;
754 allGeneratedImmature = allGeneratedMature = allFee = 0;
755 string strSentAccount;
756 list<pair<CBitcoinAddress, int64> > listReceived;
757 list<pair<CBitcoinAddress, int64> > listSent;
758 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
759 if (wtx.GetDepthInMainChain() >= nMinDepth)
760 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
761 nBalance += r.second;
762 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
763 nBalance -= r.second;
765 nBalance += allGeneratedMature;
767 return ValueFromAmount(nBalance);
770 string strAccount = AccountFromValue(params[0]);
772 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
774 return ValueFromAmount(nBalance);
778 Value movecmd(const Array& params, bool fHelp)
780 if (fHelp || params.size() < 3 || params.size() > 5)
782 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
783 "Move from one account in your wallet to another.");
785 string strFrom = AccountFromValue(params[0]);
786 string strTo = AccountFromValue(params[1]);
787 int64 nAmount = AmountFromValue(params[2]);
788 if (params.size() > 3)
789 // unused parameter, used to be nMinDepth, keep type-checking it though
790 (void)params[3].get_int();
792 if (params.size() > 4)
793 strComment = params[4].get_str();
795 CWalletDB walletdb(pwalletMain->strWalletFile);
798 int64 nNow = GetAdjustedTime();
801 CAccountingEntry debit;
802 debit.strAccount = strFrom;
803 debit.nCreditDebit = -nAmount;
805 debit.strOtherAccount = strTo;
806 debit.strComment = strComment;
807 walletdb.WriteAccountingEntry(debit);
810 CAccountingEntry credit;
811 credit.strAccount = strTo;
812 credit.nCreditDebit = nAmount;
814 credit.strOtherAccount = strFrom;
815 credit.strComment = strComment;
816 walletdb.WriteAccountingEntry(credit);
818 walletdb.TxnCommit();
824 Value sendfrom(const Array& params, bool fHelp)
826 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
828 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
829 "<amount> is a real and is rounded to the nearest 0.00000001\n"
830 "requires wallet passphrase to be set with walletpassphrase first");
831 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
833 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
834 "<amount> is a real and is rounded to the nearest 0.00000001");
836 string strAccount = AccountFromValue(params[0]);
837 CBitcoinAddress address(params[1].get_str());
838 if (!address.IsValid())
839 throw JSONRPCError(-5, "Invalid bitcoin address");
840 int64 nAmount = AmountFromValue(params[2]);
842 if (params.size() > 3)
843 nMinDepth = params[3].get_int();
846 wtx.strFromAccount = strAccount;
847 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
848 wtx.mapValue["comment"] = params[4].get_str();
849 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
850 wtx.mapValue["to"] = params[5].get_str();
852 if (pwalletMain->IsLocked())
853 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
856 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
857 if (nAmount > nBalance)
858 throw JSONRPCError(-6, "Account has insufficient funds");
861 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
863 throw JSONRPCError(-4, strError);
865 return wtx.GetHash().GetHex();
869 Value sendmany(const Array& params, bool fHelp)
871 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
873 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
874 "amounts are double-precision floating point numbers\n"
875 "requires wallet passphrase to be set with walletpassphrase first");
876 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
878 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
879 "amounts are double-precision floating point numbers");
881 string strAccount = AccountFromValue(params[0]);
882 Object sendTo = params[1].get_obj();
884 if (params.size() > 2)
885 nMinDepth = params[2].get_int();
888 wtx.strFromAccount = strAccount;
889 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
890 wtx.mapValue["comment"] = params[3].get_str();
892 set<CBitcoinAddress> setAddress;
893 vector<pair<CScript, int64> > vecSend;
895 int64 totalAmount = 0;
896 BOOST_FOREACH(const Pair& s, sendTo)
898 CBitcoinAddress address(s.name_);
899 if (!address.IsValid())
900 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
902 if (setAddress.count(address))
903 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
904 setAddress.insert(address);
906 CScript scriptPubKey;
907 scriptPubKey.SetBitcoinAddress(address);
908 int64 nAmount = AmountFromValue(s.value_);
909 totalAmount += nAmount;
911 vecSend.push_back(make_pair(scriptPubKey, nAmount));
914 if (pwalletMain->IsLocked())
915 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
918 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
919 if (totalAmount > nBalance)
920 throw JSONRPCError(-6, "Account has insufficient funds");
923 CReserveKey keyChange(pwalletMain);
924 int64 nFeeRequired = 0;
925 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
928 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
929 throw JSONRPCError(-6, "Insufficient funds");
930 throw JSONRPCError(-4, "Transaction creation failed");
932 if (!pwalletMain->CommitTransaction(wtx, keyChange))
933 throw JSONRPCError(-4, "Transaction commit failed");
935 return wtx.GetHash().GetHex();
950 Value ListReceived(const Array& params, bool fByAccounts)
952 // Minimum confirmations
954 if (params.size() > 0)
955 nMinDepth = params[0].get_int();
957 // Whether to include empty accounts
958 bool fIncludeEmpty = false;
959 if (params.size() > 1)
960 fIncludeEmpty = params[1].get_bool();
963 map<CBitcoinAddress, tallyitem> mapTally;
964 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
966 const CWalletTx& wtx = (*it).second;
967 if (wtx.IsCoinBase() || !wtx.IsFinal())
970 int nDepth = wtx.GetDepthInMainChain();
971 if (nDepth < nMinDepth)
974 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
976 CBitcoinAddress address;
977 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
980 tallyitem& item = mapTally[address];
981 item.nAmount += txout.nValue;
982 item.nConf = min(item.nConf, nDepth);
988 map<string, tallyitem> mapAccountTally;
989 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
991 const CBitcoinAddress& address = item.first;
992 const string& strAccount = item.second;
993 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
994 if (it == mapTally.end() && !fIncludeEmpty)
999 if (it != mapTally.end())
1001 nAmount = (*it).second.nAmount;
1002 nConf = (*it).second.nConf;
1007 tallyitem& item = mapAccountTally[strAccount];
1008 item.nAmount += nAmount;
1009 item.nConf = min(item.nConf, nConf);
1014 obj.push_back(Pair("address", address.ToString()));
1015 obj.push_back(Pair("account", strAccount));
1016 obj.push_back(Pair("label", strAccount)); // deprecated
1017 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1018 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1025 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1027 int64 nAmount = (*it).second.nAmount;
1028 int nConf = (*it).second.nConf;
1030 obj.push_back(Pair("account", (*it).first));
1031 obj.push_back(Pair("label", (*it).first)); // deprecated
1032 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1033 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1041 Value listreceivedbyaddress(const Array& params, bool fHelp)
1043 if (fHelp || params.size() > 2)
1044 throw runtime_error(
1045 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1046 "[minconf] is the minimum number of confirmations before payments are included.\n"
1047 "[includeempty] whether to include addresses that haven't received any payments.\n"
1048 "Returns an array of objects containing:\n"
1049 " \"address\" : receiving address\n"
1050 " \"account\" : the account of the receiving address\n"
1051 " \"amount\" : total amount received by the address\n"
1052 " \"confirmations\" : number of confirmations of the most recent transaction included");
1054 return ListReceived(params, false);
1057 Value listreceivedbyaccount(const Array& params, bool fHelp)
1059 if (fHelp || params.size() > 2)
1060 throw runtime_error(
1061 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1062 "[minconf] is the minimum number of confirmations before payments are included.\n"
1063 "[includeempty] whether to include accounts that haven't received any payments.\n"
1064 "Returns an array of objects containing:\n"
1065 " \"account\" : the account of the receiving addresses\n"
1066 " \"amount\" : total amount received by addresses with this account\n"
1067 " \"confirmations\" : number of confirmations of the most recent transaction included");
1069 return ListReceived(params, true);
1072 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1074 int64 nGeneratedImmature, nGeneratedMature, nFee;
1075 string strSentAccount;
1076 list<pair<CBitcoinAddress, int64> > listReceived;
1077 list<pair<CBitcoinAddress, int64> > listSent;
1078 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1080 bool fAllAccounts = (strAccount == string("*"));
1082 // Generated blocks assigned to account ""
1083 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1086 entry.push_back(Pair("account", string("")));
1087 if (nGeneratedImmature)
1089 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1090 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1094 entry.push_back(Pair("category", "generate"));
1095 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1098 WalletTxToJSON(wtx, entry);
1099 ret.push_back(entry);
1103 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1105 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1108 entry.push_back(Pair("account", strSentAccount));
1109 entry.push_back(Pair("address", s.first.ToString()));
1110 entry.push_back(Pair("category", "send"));
1111 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1112 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1114 WalletTxToJSON(wtx, entry);
1115 ret.push_back(entry);
1120 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1121 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1124 if (pwalletMain->mapAddressBook.count(r.first))
1125 account = pwalletMain->mapAddressBook[r.first];
1126 if (fAllAccounts || (account == strAccount))
1129 entry.push_back(Pair("account", account));
1130 entry.push_back(Pair("address", r.first.ToString()));
1131 entry.push_back(Pair("category", "receive"));
1132 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1134 WalletTxToJSON(wtx, entry);
1135 ret.push_back(entry);
1140 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1142 bool fAllAccounts = (strAccount == string("*"));
1144 if (fAllAccounts || acentry.strAccount == strAccount)
1147 entry.push_back(Pair("account", acentry.strAccount));
1148 entry.push_back(Pair("category", "move"));
1149 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1150 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1151 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1152 entry.push_back(Pair("comment", acentry.strComment));
1153 ret.push_back(entry);
1157 Value listtransactions(const Array& params, bool fHelp)
1159 if (fHelp || params.size() > 3)
1160 throw runtime_error(
1161 "listtransactions [account] [count=10] [from=0]\n"
1162 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1164 string strAccount = "*";
1165 if (params.size() > 0)
1166 strAccount = params[0].get_str();
1168 if (params.size() > 1)
1169 nCount = params[1].get_int();
1171 if (params.size() > 2)
1172 nFrom = params[2].get_int();
1175 CWalletDB walletdb(pwalletMain->strWalletFile);
1177 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1178 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1179 typedef multimap<int64, TxPair > TxItems;
1182 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1184 CWalletTx* wtx = &((*it).second);
1185 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1187 list<CAccountingEntry> acentries;
1188 walletdb.ListAccountCreditDebit(strAccount, acentries);
1189 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1191 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1194 // Now: iterate backwards until we have nCount items to return:
1195 TxItems::reverse_iterator it = txByTime.rbegin();
1196 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1197 for (; it != txByTime.rend(); ++it)
1199 CWalletTx *const pwtx = (*it).second.first;
1201 ListTransactions(*pwtx, strAccount, 0, true, ret);
1202 CAccountingEntry *const pacentry = (*it).second.second;
1204 AcentryToJSON(*pacentry, strAccount, ret);
1206 if (ret.size() >= nCount) break;
1208 // ret is now newest to oldest
1210 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1211 if (ret.size() > nCount)
1213 Array::iterator last = ret.begin();
1214 std::advance(last, nCount);
1215 ret.erase(last, ret.end());
1217 std::reverse(ret.begin(), ret.end()); // oldest to newest
1222 Value listaccounts(const Array& params, bool fHelp)
1224 if (fHelp || params.size() > 1)
1225 throw runtime_error(
1226 "listaccounts [minconf=1]\n"
1227 "Returns Object that has account names as keys, account balances as values.");
1230 if (params.size() > 0)
1231 nMinDepth = params[0].get_int();
1233 map<string, int64> mapAccountBalances;
1234 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1235 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1236 mapAccountBalances[entry.second] = 0;
1239 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1241 const CWalletTx& wtx = (*it).second;
1242 int64 nGeneratedImmature, nGeneratedMature, nFee;
1243 string strSentAccount;
1244 list<pair<CBitcoinAddress, int64> > listReceived;
1245 list<pair<CBitcoinAddress, int64> > listSent;
1246 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1247 mapAccountBalances[strSentAccount] -= nFee;
1248 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1249 mapAccountBalances[strSentAccount] -= s.second;
1250 if (wtx.GetDepthInMainChain() >= nMinDepth)
1252 mapAccountBalances[""] += nGeneratedMature;
1253 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1254 if (pwalletMain->mapAddressBook.count(r.first))
1255 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1257 mapAccountBalances[""] += r.second;
1261 list<CAccountingEntry> acentries;
1262 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1263 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1264 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1267 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1268 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1273 Value gettransaction(const Array& params, bool fHelp)
1275 if (fHelp || params.size() != 1)
1276 throw runtime_error(
1277 "gettransaction <txid>\n"
1278 "Get detailed information about <txid>");
1281 hash.SetHex(params[0].get_str());
1285 if (!pwalletMain->mapWallet.count(hash))
1286 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1287 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1289 int64 nCredit = wtx.GetCredit();
1290 int64 nDebit = wtx.GetDebit();
1291 int64 nNet = nCredit - nDebit;
1292 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1294 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1296 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1298 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1301 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1302 entry.push_back(Pair("details", details));
1308 Value backupwallet(const Array& params, bool fHelp)
1310 if (fHelp || params.size() != 1)
1311 throw runtime_error(
1312 "backupwallet <destination>\n"
1313 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1315 string strDest = params[0].get_str();
1316 BackupWallet(*pwalletMain, strDest);
1322 Value keypoolrefill(const Array& params, bool fHelp)
1324 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1325 throw runtime_error(
1327 "Fills the keypool, requires wallet passphrase to be set.");
1328 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1329 throw runtime_error(
1331 "Fills the keypool.");
1333 if (pwalletMain->IsLocked())
1334 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1336 pwalletMain->TopUpKeyPool();
1338 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1339 throw JSONRPCError(-4, "Error refreshing keypool.");
1345 void ThreadTopUpKeyPool(void* parg)
1347 pwalletMain->TopUpKeyPool();
1350 void ThreadCleanWalletPassphrase(void* parg)
1352 int64 nMyWakeTime = GetTime() + *((int*)parg);
1354 if (nWalletUnlockTime == 0)
1356 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1358 nWalletUnlockTime = nMyWakeTime;
1361 while (GetTime() < nWalletUnlockTime)
1362 Sleep(GetTime() - nWalletUnlockTime);
1364 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1366 nWalletUnlockTime = 0;
1371 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1373 if (nWalletUnlockTime < nMyWakeTime)
1374 nWalletUnlockTime = nMyWakeTime;
1380 pwalletMain->Lock();
1385 Value walletpassphrase(const Array& params, bool fHelp)
1387 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1388 throw runtime_error(
1389 "walletpassphrase <passphrase> <timeout>\n"
1390 "Stores the wallet decryption key in memory for <timeout> seconds.");
1393 if (!pwalletMain->IsCrypted())
1394 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1396 if (!pwalletMain->IsLocked())
1397 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1399 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1400 string strWalletPass;
1401 strWalletPass.reserve(100);
1402 mlock(&strWalletPass[0], strWalletPass.capacity());
1403 strWalletPass = params[0].get_str();
1405 if (strWalletPass.length() > 0)
1407 if (!pwalletMain->Unlock(strWalletPass))
1409 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1410 munlock(&strWalletPass[0], strWalletPass.capacity());
1411 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1413 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1414 munlock(&strWalletPass[0], strWalletPass.capacity());
1417 throw runtime_error(
1418 "walletpassphrase <passphrase> <timeout>\n"
1419 "Stores the wallet decryption key in memory for <timeout> seconds.");
1421 CreateThread(ThreadTopUpKeyPool, NULL);
1422 int* pnSleepTime = new int(params[1].get_int());
1423 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1429 Value walletpassphrasechange(const Array& params, bool fHelp)
1431 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1432 throw runtime_error(
1433 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1434 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1437 if (!pwalletMain->IsCrypted())
1438 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1440 string strOldWalletPass;
1441 strOldWalletPass.reserve(100);
1442 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1443 strOldWalletPass = params[0].get_str();
1445 string strNewWalletPass;
1446 strNewWalletPass.reserve(100);
1447 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1448 strNewWalletPass = params[1].get_str();
1450 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1451 throw runtime_error(
1452 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1453 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1455 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1457 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1458 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1459 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1460 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1461 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1463 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1464 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1465 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1466 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1472 Value walletlock(const Array& params, bool fHelp)
1474 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1475 throw runtime_error(
1477 "Removes the wallet encryption key from memory, locking the wallet.\n"
1478 "After calling this method, you will need to call walletpassphrase again\n"
1479 "before being able to call any methods which require the wallet to be unlocked.");
1482 if (!pwalletMain->IsCrypted())
1483 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1485 pwalletMain->Lock();
1486 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1488 nWalletUnlockTime = 0;
1495 Value encryptwallet(const Array& params, bool fHelp)
1497 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1498 throw runtime_error(
1499 "encryptwallet <passphrase>\n"
1500 "Encrypts the wallet with <passphrase>.");
1503 if (pwalletMain->IsCrypted())
1504 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1506 string strWalletPass;
1507 strWalletPass.reserve(100);
1508 mlock(&strWalletPass[0], strWalletPass.capacity());
1509 strWalletPass = params[0].get_str();
1511 if (strWalletPass.length() < 1)
1512 throw runtime_error(
1513 "encryptwallet <passphrase>\n"
1514 "Encrypts the wallet with <passphrase>.");
1516 if (!pwalletMain->EncryptWallet(strWalletPass))
1518 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1519 munlock(&strWalletPass[0], strWalletPass.capacity());
1520 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1522 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1523 munlock(&strWalletPass[0], strWalletPass.capacity());
1529 Value validateaddress(const Array& params, bool fHelp)
1531 if (fHelp || params.size() != 1)
1532 throw runtime_error(
1533 "validateaddress <bitcoinaddress>\n"
1534 "Return information about <bitcoinaddress>.");
1536 CBitcoinAddress address(params[0].get_str());
1537 bool isValid = address.IsValid();
1540 ret.push_back(Pair("isvalid", isValid));
1543 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1544 // version of the address:
1545 string currentAddress = address.ToString();
1546 ret.push_back(Pair("address", currentAddress));
1547 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1548 if (pwalletMain->mapAddressBook.count(address))
1549 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1555 Value getwork(const Array& params, bool fHelp)
1557 if (fHelp || params.size() > 1)
1558 throw runtime_error(
1560 "If [data] is not specified, returns formatted hash data to work on:\n"
1561 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1562 " \"data\" : block data\n"
1563 " \"hash1\" : formatted hash buffer for second hash\n"
1564 " \"target\" : little endian hash target\n"
1565 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1568 throw JSONRPCError(-9, "Bitcoin is not connected!");
1570 if (IsInitialBlockDownload())
1571 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1573 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1574 static mapNewBlock_t mapNewBlock;
1575 static vector<CBlock*> vNewBlock;
1576 static CReserveKey reservekey(pwalletMain);
1578 if (params.size() == 0)
1581 static unsigned int nTransactionsUpdatedLast;
1582 static CBlockIndex* pindexPrev;
1583 static int64 nStart;
1584 static CBlock* pblock;
1585 if (pindexPrev != pindexBest ||
1586 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1588 if (pindexPrev != pindexBest)
1590 // Deallocate old blocks since they're obsolete now
1591 mapNewBlock.clear();
1592 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1596 nTransactionsUpdatedLast = nTransactionsUpdated;
1597 pindexPrev = pindexBest;
1601 pblock = CreateNewBlock(reservekey);
1603 throw JSONRPCError(-7, "Out of memory");
1604 vNewBlock.push_back(pblock);
1608 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1611 // Update nExtraNonce
1612 static unsigned int nExtraNonce = 0;
1613 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1616 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1618 // Prebuild hash buffers
1622 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1624 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1627 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1628 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1629 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1630 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1636 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1637 if (vchData.size() != 128)
1638 throw JSONRPCError(-8, "Invalid parameter");
1639 CBlock* pdata = (CBlock*)&vchData[0];
1642 for (int i = 0; i < 128/4; i++)
1643 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1646 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1648 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1650 pblock->nTime = pdata->nTime;
1651 pblock->nNonce = pdata->nNonce;
1652 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1653 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1655 return CheckWork(pblock, *pwalletMain, reservekey);
1673 pair<string, rpcfn_type> pCallTable[] =
1675 make_pair("help", &help),
1676 make_pair("stop", &stop),
1677 make_pair("getblockcount", &getblockcount),
1678 make_pair("getblocknumber", &getblocknumber),
1679 make_pair("getconnectioncount", &getconnectioncount),
1680 make_pair("getdifficulty", &getdifficulty),
1681 make_pair("getgenerate", &getgenerate),
1682 make_pair("setgenerate", &setgenerate),
1683 make_pair("gethashespersec", &gethashespersec),
1684 make_pair("getinfo", &getinfo),
1685 make_pair("getnewaddress", &getnewaddress),
1686 make_pair("getaccountaddress", &getaccountaddress),
1687 make_pair("setaccount", &setaccount),
1688 make_pair("setlabel", &setaccount), // deprecated
1689 make_pair("getaccount", &getaccount),
1690 make_pair("getlabel", &getaccount), // deprecated
1691 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1692 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1693 make_pair("sendtoaddress", &sendtoaddress),
1694 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1695 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1696 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1697 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1698 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1699 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1700 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1701 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1702 make_pair("backupwallet", &backupwallet),
1703 make_pair("keypoolrefill", &keypoolrefill),
1704 make_pair("walletpassphrase", &walletpassphrase),
1705 make_pair("walletpassphrasechange", &walletpassphrasechange),
1706 make_pair("walletlock", &walletlock),
1707 make_pair("encryptwallet", &encryptwallet),
1708 make_pair("validateaddress", &validateaddress),
1709 make_pair("getbalance", &getbalance),
1710 make_pair("move", &movecmd),
1711 make_pair("sendfrom", &sendfrom),
1712 make_pair("sendmany", &sendmany),
1713 make_pair("gettransaction", &gettransaction),
1714 make_pair("listtransactions", &listtransactions),
1715 make_pair("signmessage", &signmessage),
1716 make_pair("verifymessage", &verifymessage),
1717 make_pair("getwork", &getwork),
1718 make_pair("listaccounts", &listaccounts),
1719 make_pair("settxfee", &settxfee),
1721 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1723 string pAllowInSafeMode[] =
1729 "getconnectioncount",
1736 "getaccountaddress",
1737 "setlabel", // deprecated
1739 "getlabel", // deprecated
1740 "getaddressesbyaccount",
1741 "getaddressesbylabel", // deprecated
1749 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1757 // This ain't Apache. We're just using HTTP header for the length field
1758 // and to be compatible with other JSON-RPC implementations.
1761 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1764 s << "POST / HTTP/1.1\r\n"
1765 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1766 << "Host: 127.0.0.1\r\n"
1767 << "Content-Type: application/json\r\n"
1768 << "Content-Length: " << strMsg.size() << "\r\n"
1769 << "Accept: application/json\r\n";
1770 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1771 s << item.first << ": " << item.second << "\r\n";
1772 s << "\r\n" << strMsg;
1777 string rfc1123Time()
1782 struct tm* now_gmt = gmtime(&now);
1783 string locale(setlocale(LC_TIME, NULL));
1784 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1785 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1786 setlocale(LC_TIME, locale.c_str());
1787 return string(buffer);
1790 static string HTTPReply(int nStatus, const string& strMsg)
1793 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1795 "Server: bitcoin-json-rpc/%s\r\n"
1796 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1797 "Content-Type: text/html\r\n"
1798 "Content-Length: 296\r\n"
1800 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1801 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1804 "<TITLE>Error</TITLE>\r\n"
1805 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1807 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1808 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1810 if (nStatus == 200) strStatus = "OK";
1811 else if (nStatus == 400) strStatus = "Bad Request";
1812 else if (nStatus == 403) strStatus = "Forbidden";
1813 else if (nStatus == 404) strStatus = "Not Found";
1814 else if (nStatus == 500) strStatus = "Internal Server Error";
1816 "HTTP/1.1 %d %s\r\n"
1818 "Connection: close\r\n"
1819 "Content-Length: %d\r\n"
1820 "Content-Type: application/json\r\n"
1821 "Server: bitcoin-json-rpc/%s\r\n"
1826 rfc1123Time().c_str(),
1828 FormatFullVersion().c_str(),
1832 int ReadHTTPStatus(std::basic_istream<char>& stream)
1835 getline(stream, str);
1836 vector<string> vWords;
1837 boost::split(vWords, str, boost::is_any_of(" "));
1838 if (vWords.size() < 2)
1840 return atoi(vWords[1].c_str());
1843 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1849 std::getline(stream, str);
1850 if (str.empty() || str == "\r")
1852 string::size_type nColon = str.find(":");
1853 if (nColon != string::npos)
1855 string strHeader = str.substr(0, nColon);
1856 boost::trim(strHeader);
1857 boost::to_lower(strHeader);
1858 string strValue = str.substr(nColon+1);
1859 boost::trim(strValue);
1860 mapHeadersRet[strHeader] = strValue;
1861 if (strHeader == "content-length")
1862 nLen = atoi(strValue.c_str());
1868 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1870 mapHeadersRet.clear();
1874 int nStatus = ReadHTTPStatus(stream);
1877 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1878 if (nLen < 0 || nLen > MAX_SIZE)
1884 vector<char> vch(nLen);
1885 stream.read(&vch[0], nLen);
1886 strMessageRet = string(vch.begin(), vch.end());
1892 bool HTTPAuthorized(map<string, string>& mapHeaders)
1894 string strAuth = mapHeaders["authorization"];
1895 if (strAuth.substr(0,6) != "Basic ")
1897 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1898 string strUserPass = DecodeBase64(strUserPass64);
1899 string::size_type nColon = strUserPass.find(":");
1900 if (nColon == string::npos)
1902 string strUser = strUserPass.substr(0, nColon);
1903 string strPassword = strUserPass.substr(nColon+1);
1904 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1908 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1909 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1910 // unspecified (HTTP errors and contents of 'error').
1912 // 1.0 spec: http://json-rpc.org/wiki/specification
1913 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1914 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1917 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1920 request.push_back(Pair("method", strMethod));
1921 request.push_back(Pair("params", params));
1922 request.push_back(Pair("id", id));
1923 return write_string(Value(request), false) + "\n";
1926 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1929 if (error.type() != null_type)
1930 reply.push_back(Pair("result", Value::null));
1932 reply.push_back(Pair("result", result));
1933 reply.push_back(Pair("error", error));
1934 reply.push_back(Pair("id", id));
1935 return write_string(Value(reply), false) + "\n";
1938 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1940 // Send error reply from json-rpc error object
1942 int code = find_value(objError, "code").get_int();
1943 if (code == -32600) nStatus = 400;
1944 else if (code == -32601) nStatus = 404;
1945 string strReply = JSONRPCReply(Value::null, objError, id);
1946 stream << HTTPReply(nStatus, strReply) << std::flush;
1949 bool ClientAllowed(const string& strAddress)
1951 if (strAddress == asio::ip::address_v4::loopback().to_string())
1953 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1954 BOOST_FOREACH(string strAllow, vAllow)
1955 if (WildcardMatch(strAddress, strAllow))
1962 // IOStream device that speaks SSL but can also speak non-SSL
1964 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1966 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1968 fUseSSL = fUseSSLIn;
1969 fNeedHandshake = fUseSSLIn;
1972 void handshake(ssl::stream_base::handshake_type role)
1974 if (!fNeedHandshake) return;
1975 fNeedHandshake = false;
1976 stream.handshake(role);
1978 std::streamsize read(char* s, std::streamsize n)
1980 handshake(ssl::stream_base::server); // HTTPS servers read first
1981 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1982 return stream.next_layer().read_some(asio::buffer(s, n));
1984 std::streamsize write(const char* s, std::streamsize n)
1986 handshake(ssl::stream_base::client); // HTTPS clients write first
1987 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1988 return asio::write(stream.next_layer(), asio::buffer(s, n));
1990 bool connect(const std::string& server, const std::string& port)
1992 ip::tcp::resolver resolver(stream.get_io_service());
1993 ip::tcp::resolver::query query(server.c_str(), port.c_str());
1994 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
1995 ip::tcp::resolver::iterator end;
1996 boost::system::error_code error = asio::error::host_not_found;
1997 while (error && endpoint_iterator != end)
1999 stream.lowest_layer().close();
2000 stream.lowest_layer().connect(*endpoint_iterator++, error);
2008 bool fNeedHandshake;
2014 void ThreadRPCServer(void* parg)
2016 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2019 vnThreadsRunning[4]++;
2020 ThreadRPCServer2(parg);
2021 vnThreadsRunning[4]--;
2023 catch (std::exception& e) {
2024 vnThreadsRunning[4]--;
2025 PrintException(&e, "ThreadRPCServer()");
2027 vnThreadsRunning[4]--;
2028 PrintException(NULL, "ThreadRPCServer()");
2030 printf("ThreadRPCServer exiting\n");
2033 void ThreadRPCServer2(void* parg)
2035 printf("ThreadRPCServer started\n");
2037 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2039 string strWhatAmI = "To use bitcoind";
2040 if (mapArgs.count("-server"))
2041 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2042 else if (mapArgs.count("-daemon"))
2043 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2045 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2046 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2048 GetConfigFile().c_str());
2049 CreateThread(Shutdown, NULL);
2053 bool fUseSSL = GetBoolArg("-rpcssl");
2054 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2056 asio::io_service io_service;
2057 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2058 ip::tcp::acceptor acceptor(io_service, endpoint);
2060 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2063 ssl::context context(io_service, ssl::context::sslv23);
2066 context.set_options(ssl::context::no_sslv2);
2067 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2068 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2069 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2070 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2071 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2072 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2073 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2074 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2076 string ciphers = GetArg("-rpcsslciphers",
2077 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2078 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2082 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2087 // Accept connection
2089 SSLStream sslStream(io_service, context);
2090 SSLIOStreamDevice d(sslStream, fUseSSL);
2091 iostreams::stream<SSLIOStreamDevice> stream(d);
2093 ip::tcp::iostream stream;
2096 ip::tcp::endpoint peer;
2097 vnThreadsRunning[4]--;
2099 acceptor.accept(sslStream.lowest_layer(), peer);
2101 acceptor.accept(*stream.rdbuf(), peer);
2103 vnThreadsRunning[4]++;
2107 // Restrict callers by IP
2108 if (!ClientAllowed(peer.address().to_string()))
2110 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2112 stream << HTTPReply(403, "") << std::flush;
2116 map<string, string> mapHeaders;
2119 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2120 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2123 printf("ThreadRPCServer ReadHTTP timeout\n");
2127 // Check authorization
2128 if (mapHeaders.count("authorization") == 0)
2130 stream << HTTPReply(401, "") << std::flush;
2133 if (!HTTPAuthorized(mapHeaders))
2135 // Deter brute-forcing short passwords
2136 if (mapArgs["-rpcpassword"].size() < 15)
2139 stream << HTTPReply(401, "") << std::flush;
2140 printf("ThreadRPCServer incorrect password attempt\n");
2144 Value id = Value::null;
2149 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2150 throw JSONRPCError(-32700, "Parse error");
2151 const Object& request = valRequest.get_obj();
2153 // Parse id now so errors from here on will have the id
2154 id = find_value(request, "id");
2157 Value valMethod = find_value(request, "method");
2158 if (valMethod.type() == null_type)
2159 throw JSONRPCError(-32600, "Missing method");
2160 if (valMethod.type() != str_type)
2161 throw JSONRPCError(-32600, "Method must be a string");
2162 string strMethod = valMethod.get_str();
2163 if (strMethod != "getwork")
2164 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2167 Value valParams = find_value(request, "params");
2169 if (valParams.type() == array_type)
2170 params = valParams.get_array();
2171 else if (valParams.type() == null_type)
2174 throw JSONRPCError(-32600, "Params must be an array");
2177 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2178 if (mi == mapCallTable.end())
2179 throw JSONRPCError(-32601, "Method not found");
2181 // Observe safe mode
2182 string strWarning = GetWarnings("rpc");
2183 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2184 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2190 CRITICAL_BLOCK(cs_main)
2191 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2192 result = (*(*mi).second)(params, false);
2195 string strReply = JSONRPCReply(result, Value::null, id);
2196 stream << HTTPReply(200, strReply) << std::flush;
2198 catch (std::exception& e)
2200 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2203 catch (Object& objError)
2205 ErrorReply(stream, objError, id);
2207 catch (std::exception& e)
2209 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2217 Object CallRPC(const string& strMethod, const Array& params)
2219 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2220 throw runtime_error(strprintf(
2221 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2222 "If the file does not exist, create it with owner-readable-only file permissions."),
2223 GetConfigFile().c_str()));
2225 // Connect to localhost
2226 bool fUseSSL = GetBoolArg("-rpcssl");
2228 asio::io_service io_service;
2229 ssl::context context(io_service, ssl::context::sslv23);
2230 context.set_options(ssl::context::no_sslv2);
2231 SSLStream sslStream(io_service, context);
2232 SSLIOStreamDevice d(sslStream, fUseSSL);
2233 iostreams::stream<SSLIOStreamDevice> stream(d);
2234 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2235 throw runtime_error("couldn't connect to server");
2238 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2240 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2242 throw runtime_error("couldn't connect to server");
2246 // HTTP basic authentication
2247 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2248 map<string, string> mapRequestHeaders;
2249 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2252 string strRequest = JSONRPCRequest(strMethod, params, 1);
2253 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2254 stream << strPost << std::flush;
2257 map<string, string> mapHeaders;
2259 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2261 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2262 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2263 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2264 else if (strReply.empty())
2265 throw runtime_error("no response from server");
2269 if (!read_string(strReply, valReply))
2270 throw runtime_error("couldn't parse reply from server");
2271 const Object& reply = valReply.get_obj();
2273 throw runtime_error("expected reply to have result, error and id properties");
2281 template<typename T>
2282 void ConvertTo(Value& value)
2284 if (value.type() == str_type)
2286 // reinterpret string as unquoted json value
2288 if (!read_string(value.get_str(), value2))
2289 throw runtime_error("type mismatch");
2290 value = value2.get_value<T>();
2294 value = value.get_value<T>();
2298 int CommandLineRPC(int argc, char *argv[])
2305 while (argc > 1 && IsSwitchChar(argv[1][0]))
2313 throw runtime_error("too few parameters");
2314 string strMethod = argv[1];
2316 // Parameters default to strings
2318 for (int i = 2; i < argc; i++)
2319 params.push_back(argv[i]);
2320 int n = params.size();
2323 // Special case non-string parameter types
2325 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2326 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2327 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2328 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2329 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2330 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2331 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2332 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2333 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2334 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2335 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2336 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2337 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2338 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2339 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2340 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2341 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2342 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2343 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2344 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2345 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2346 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2347 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2348 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2349 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2350 if (strMethod == "sendmany" && n > 1)
2352 string s = params[1].get_str();
2354 if (!read_string(s, v) || v.type() != obj_type)
2355 throw runtime_error("type mismatch");
2356 params[1] = v.get_obj();
2358 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2361 Object reply = CallRPC(strMethod, params);
2364 const Value& result = find_value(reply, "result");
2365 const Value& error = find_value(reply, "error");
2367 if (error.type() != null_type)
2370 strPrint = "error: " + write_string(error, false);
2371 int code = find_value(error.get_obj(), "code").get_int();
2377 if (result.type() == null_type)
2379 else if (result.type() == str_type)
2380 strPrint = result.get_str();
2382 strPrint = write_string(result, true);
2385 catch (std::exception& e)
2387 strPrint = string("error: ") + e.what();
2392 PrintException(NULL, "CommandLineRPC()");
2397 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2406 int main(int argc, char *argv[])
2409 // Turn off microsoft heap dump noise
2410 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2411 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2413 setbuf(stdin, NULL);
2414 setbuf(stdout, NULL);
2415 setbuf(stderr, NULL);
2419 if (argc >= 2 && string(argv[1]) == "-server")
2421 printf("server ready\n");
2422 ThreadRPCServer(NULL);
2426 return CommandLineRPC(argc, argv);
2429 catch (std::exception& e) {
2430 PrintException(&e, "main()");
2432 PrintException(NULL, "main()");