1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
7 #include "cryptopp/sha.h"
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
44 Object JSONRPCError(int code, const string& message)
47 error.push_back(Pair("code", code));
48 error.push_back(Pair("message", message));
53 void PrintConsole(const std::string &format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
61 if (ret < 0 || ret >= limit)
67 fprintf(stdout, "%s", buffer);
71 int64 AmountFromValue(const Value& value)
73 double dAmount = value.get_real();
74 if (dAmount <= 0.0 || dAmount > 21000000.0)
75 throw JSONRPCError(-3, "Invalid amount");
76 int64 nAmount = roundint64(dAmount * COIN);
77 if (!MoneyRange(nAmount))
78 throw JSONRPCError(-3, "Invalid amount");
82 Value ValueFromAmount(int64 amount)
84 return (double)amount / (double)COIN;
87 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
89 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
90 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
91 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
92 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
93 entry.push_back(Pair(item.first, item.second));
96 string AccountFromValue(const Value& value)
98 string strAccount = value.get_str();
99 if (strAccount == "*")
100 throw JSONRPCError(-11, "Invalid account name");
107 /// Note: This interface may still be subject to change.
111 Value help(const Array& params, bool fHelp)
113 if (fHelp || params.size() > 1)
116 "List commands, or get help for a command.");
119 if (params.size() > 0)
120 strCommand = params[0].get_str();
123 set<rpcfn_type> setDone;
124 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
126 string strMethod = (*mi).first;
127 // We already filter duplicates, but these deprecated screw up the sort order
128 if (strMethod == "getamountreceived" ||
129 strMethod == "getallreceived" ||
130 (strMethod.find("label") != string::npos))
132 if (strCommand != "" && strMethod != strCommand)
137 rpcfn_type pfn = (*mi).second;
138 if (setDone.insert(pfn).second)
139 (*pfn)(params, true);
141 catch (std::exception& e)
143 // Help text is returned in an exception
144 string strHelp = string(e.what());
145 if (strCommand == "")
146 if (strHelp.find('\n') != -1)
147 strHelp = strHelp.substr(0, strHelp.find('\n'));
148 strRet += strHelp + "\n";
152 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
153 strRet = strRet.substr(0,strRet.size()-1);
158 Value stop(const Array& params, bool fHelp)
160 if (fHelp || params.size() != 0)
163 "Stop bitcoin server.");
165 // Shutdown will take long enough that the response should get back
166 CreateThread(Shutdown, NULL);
167 return "bitcoin server stopping";
171 Value getblockcount(const Array& params, bool fHelp)
173 if (fHelp || params.size() != 0)
176 "Returns the number of blocks in the longest block chain.");
182 Value getblocknumber(const Array& params, bool fHelp)
184 if (fHelp || params.size() != 0)
187 "Returns the block number of the latest block in the longest block chain.");
193 Value getconnectioncount(const Array& params, bool fHelp)
195 if (fHelp || params.size() != 0)
197 "getconnectioncount\n"
198 "Returns the number of connections to other nodes.");
200 return (int)vNodes.size();
204 double GetDifficulty()
206 // Floating point number that is a multiple of the minimum difficulty,
207 // minimum difficulty = 1.0.
209 if (pindexBest == NULL)
211 int nShift = (pindexBest->nBits >> 24) & 0xff;
214 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
230 Value getdifficulty(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
237 return GetDifficulty();
241 Value getgenerate(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Returns true or false.");
248 return (bool)fGenerateBitcoins;
252 Value setgenerate(const Array& params, bool fHelp)
254 if (fHelp || params.size() < 1 || params.size() > 2)
256 "setgenerate <generate> [genproclimit]\n"
257 "<generate> is true or false to turn generation on or off.\n"
258 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
260 bool fGenerate = true;
261 if (params.size() > 0)
262 fGenerate = params[0].get_bool();
264 if (params.size() > 1)
266 int nGenProcLimit = params[1].get_int();
267 fLimitProcessors = (nGenProcLimit != -1);
268 WriteSetting("fLimitProcessors", fLimitProcessors);
269 if (nGenProcLimit != -1)
270 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
271 if (nGenProcLimit == 0)
275 GenerateBitcoins(fGenerate, pwalletMain);
280 Value gethashespersec(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 0)
285 "Returns a recent hashes per second performance measurement while generating.");
287 if (GetTimeMillis() - nHPSTimerStart > 8000)
288 return (boost::int64_t)0;
289 return (boost::int64_t)dHashesPerSec;
293 Value getinfo(const Array& params, bool fHelp)
295 if (fHelp || params.size() != 0)
298 "Returns an object containing various state info.");
301 obj.push_back(Pair("version", (int)VERSION));
302 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
303 obj.push_back(Pair("blocks", (int)nBestHeight));
304 obj.push_back(Pair("connections", (int)vNodes.size()));
305 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
306 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
307 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
308 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
309 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
310 obj.push_back(Pair("testnet", fTestNet));
311 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
312 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
313 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
314 if (pwalletMain->IsCrypted())
315 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
316 obj.push_back(Pair("errors", GetWarnings("statusbar")));
321 Value getnewaddress(const Array& params, bool fHelp)
323 if (fHelp || params.size() > 1)
325 "getnewaddress [account]\n"
326 "Returns a new bitcoin address for receiving payments. "
327 "If [account] is specified (recommended), it is added to the address book "
328 "so payments received with the address will be credited to [account].");
330 // Parse the account first so we don't generate a key if there's an error
332 if (params.size() > 0)
333 strAccount = AccountFromValue(params[0]);
335 if (!pwalletMain->IsLocked())
336 pwalletMain->TopUpKeyPool();
338 // Generate a new key that is added to wallet
339 std::vector<unsigned char> newKey;
340 if (!pwalletMain->GetKeyFromPool(newKey, false))
341 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
342 CBitcoinAddress address(newKey);
344 pwalletMain->SetAddressBookName(address, strAccount);
346 return address.ToString();
350 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
352 CWalletDB walletdb(pwalletMain->strWalletFile);
355 walletdb.ReadAccount(strAccount, account);
357 bool bKeyUsed = false;
359 // Check if the current key has been used
360 if (!account.vchPubKey.empty())
362 CScript scriptPubKey;
363 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
365 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
368 const CWalletTx& wtx = (*it).second;
369 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
370 if (txout.scriptPubKey == scriptPubKey)
375 // Generate a new key
376 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
378 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
379 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
381 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
382 walletdb.WriteAccount(strAccount, account);
385 return CBitcoinAddress(account.vchPubKey);
388 Value getaccountaddress(const Array& params, bool fHelp)
390 if (fHelp || params.size() != 1)
392 "getaccountaddress <account>\n"
393 "Returns the current bitcoin address for receiving payments to this account.");
395 // Parse the account first so we don't generate a key if there's an error
396 string strAccount = AccountFromValue(params[0]);
400 ret = GetAccountAddress(strAccount).ToString();
407 Value setaccount(const Array& params, bool fHelp)
409 if (fHelp || params.size() < 1 || params.size() > 2)
411 "setaccount <bitcoinaddress> <account>\n"
412 "Sets the account associated with the given address.");
414 CBitcoinAddress address(params[0].get_str());
415 if (!address.IsValid())
416 throw JSONRPCError(-5, "Invalid bitcoin address");
420 if (params.size() > 1)
421 strAccount = AccountFromValue(params[1]);
423 // Detect when changing the account of an address that is the 'unused current key' of another account:
424 if (pwalletMain->mapAddressBook.count(address))
426 string strOldAccount = pwalletMain->mapAddressBook[address];
427 if (address == GetAccountAddress(strOldAccount))
428 GetAccountAddress(strOldAccount, true);
431 pwalletMain->SetAddressBookName(address, strAccount);
437 Value getaccount(const Array& params, bool fHelp)
439 if (fHelp || params.size() != 1)
441 "getaccount <bitcoinaddress>\n"
442 "Returns the account associated with the given address.");
444 CBitcoinAddress address(params[0].get_str());
445 if (!address.IsValid())
446 throw JSONRPCError(-5, "Invalid bitcoin address");
449 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
450 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
451 strAccount = (*mi).second;
456 Value getaddressesbyaccount(const Array& params, bool fHelp)
458 if (fHelp || params.size() != 1)
460 "getaddressesbyaccount <account>\n"
461 "Returns the list of addresses for the given account.");
463 string strAccount = AccountFromValue(params[0]);
465 // Find all addresses that have the given account
467 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
469 const CBitcoinAddress& address = item.first;
470 const string& strName = item.second;
471 if (strName == strAccount)
472 ret.push_back(address.ToString());
477 Value settxfee(const Array& params, bool fHelp)
479 if (fHelp || params.size() < 1 || params.size() > 1)
481 "settxfee <amount>\n"
482 "<amount> is a real and is rounded to the nearest 0.00000001");
486 if (params[0].get_real() != 0.0)
487 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
489 nTransactionFee = nAmount;
493 Value sendtoaddress(const Array& params, bool fHelp)
495 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
497 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
498 "<amount> is a real and is rounded to the nearest 0.00000001\n"
499 "requires wallet passphrase to be set with walletpassphrase first");
500 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
502 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503 "<amount> is a real and is rounded to the nearest 0.00000001");
505 CBitcoinAddress address(params[0].get_str());
506 if (!address.IsValid())
507 throw JSONRPCError(-5, "Invalid bitcoin address");
510 int64 nAmount = AmountFromValue(params[1]);
514 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
515 wtx.mapValue["comment"] = params[2].get_str();
516 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
517 wtx.mapValue["to"] = params[3].get_str();
519 if (pwalletMain->IsLocked())
520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
522 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
524 throw JSONRPCError(-4, strError);
526 return wtx.GetHash().GetHex();
529 static const string strMessageMagic = "Bitcoin Signed Message:\n";
531 Value signmessage(const Array& params, bool fHelp)
533 if (fHelp || params.size() != 2)
535 "signmessage <bitcoinaddress> <message>\n"
536 "Sign a message with the private key of an address");
538 if (pwalletMain->IsLocked())
539 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
541 string strAddress = params[0].get_str();
542 string strMessage = params[1].get_str();
544 CBitcoinAddress addr(strAddress);
546 throw JSONRPCError(-3, "Invalid address");
549 if (!pwalletMain->GetKey(addr, key))
550 throw JSONRPCError(-4, "Private key not available");
552 CDataStream ss(SER_GETHASH);
553 ss << strMessageMagic;
556 vector<unsigned char> vchSig;
557 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
558 throw JSONRPCError(-5, "Sign failed");
560 return EncodeBase64(&vchSig[0], vchSig.size());
563 Value verifymessage(const Array& params, bool fHelp)
565 if (fHelp || params.size() != 3)
567 "verifymessage <bitcoinaddress> <signature> <message>\n"
568 "Verify a signed message");
570 string strAddress = params[0].get_str();
571 string strSign = params[1].get_str();
572 string strMessage = params[2].get_str();
574 CBitcoinAddress addr(strAddress);
576 throw JSONRPCError(-3, "Invalid address");
578 bool fInvalid = false;
579 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
582 throw JSONRPCError(-5, "Malformed base64 encoding");
584 CDataStream ss(SER_GETHASH);
585 ss << strMessageMagic;
589 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
592 return (key.GetAddress() == addr);
596 Value getreceivedbyaddress(const Array& params, bool fHelp)
598 if (fHelp || params.size() < 1 || params.size() > 2)
600 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
601 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
604 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
605 CScript scriptPubKey;
606 if (!address.IsValid())
607 throw JSONRPCError(-5, "Invalid bitcoin address");
608 scriptPubKey.SetBitcoinAddress(address);
609 if (!IsMine(*pwalletMain,scriptPubKey))
612 // Minimum confirmations
614 if (params.size() > 1)
615 nMinDepth = params[1].get_int();
619 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
621 const CWalletTx& wtx = (*it).second;
622 if (wtx.IsCoinBase() || !wtx.IsFinal())
625 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
626 if (txout.scriptPubKey == scriptPubKey)
627 if (wtx.GetDepthInMainChain() >= nMinDepth)
628 nAmount += txout.nValue;
631 return ValueFromAmount(nAmount);
635 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
637 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
639 const CBitcoinAddress& address = item.first;
640 const string& strName = item.second;
641 if (strName == strAccount)
642 setAddress.insert(address);
647 Value getreceivedbyaccount(const Array& params, bool fHelp)
649 if (fHelp || params.size() < 1 || params.size() > 2)
651 "getreceivedbyaccount <account> [minconf=1]\n"
652 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
654 // Minimum confirmations
656 if (params.size() > 1)
657 nMinDepth = params[1].get_int();
659 // Get the set of pub keys that have the label
660 string strAccount = AccountFromValue(params[0]);
661 set<CBitcoinAddress> setAddress;
662 GetAccountAddresses(strAccount, setAddress);
666 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
668 const CWalletTx& wtx = (*it).second;
669 if (wtx.IsCoinBase() || !wtx.IsFinal())
672 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
674 CBitcoinAddress address;
675 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
676 if (wtx.GetDepthInMainChain() >= nMinDepth)
677 nAmount += txout.nValue;
681 return (double)nAmount / (double)COIN;
685 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
689 // Tally wallet transactions
690 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
692 const CWalletTx& wtx = (*it).second;
696 int64 nGenerated, nReceived, nSent, nFee;
697 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
699 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
700 nBalance += nReceived;
701 nBalance += nGenerated - nSent - nFee;
704 // Tally internal accounting entries
705 nBalance += walletdb.GetAccountCreditDebit(strAccount);
710 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
712 CWalletDB walletdb(pwalletMain->strWalletFile);
713 return GetAccountBalance(walletdb, strAccount, nMinDepth);
717 Value getbalance(const Array& params, bool fHelp)
719 if (fHelp || params.size() > 2)
721 "getbalance [account] [minconf=1]\n"
722 "If [account] is not specified, returns the server's total available balance.\n"
723 "If [account] is specified, returns the balance in the account.");
725 if (params.size() == 0)
726 return ValueFromAmount(pwalletMain->GetBalance());
729 if (params.size() > 1)
730 nMinDepth = params[1].get_int();
732 if (params[0].get_str() == "*") {
733 // Calculate total balance a different way from GetBalance()
734 // (GetBalance() sums up all unspent TxOuts)
735 // getbalance and getbalance '*' should always return the same number.
737 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
739 const CWalletTx& wtx = (*it).second;
743 int64 allGeneratedImmature, allGeneratedMature, allFee;
744 allGeneratedImmature = allGeneratedMature = allFee = 0;
745 string strSentAccount;
746 list<pair<CBitcoinAddress, int64> > listReceived;
747 list<pair<CBitcoinAddress, int64> > listSent;
748 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
749 if (wtx.GetDepthInMainChain() >= nMinDepth)
750 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
751 nBalance += r.second;
752 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
753 nBalance -= r.second;
755 nBalance += allGeneratedMature;
757 return ValueFromAmount(nBalance);
760 string strAccount = AccountFromValue(params[0]);
762 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
764 return ValueFromAmount(nBalance);
768 Value movecmd(const Array& params, bool fHelp)
770 if (fHelp || params.size() < 3 || params.size() > 5)
772 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
773 "Move from one account in your wallet to another.");
775 string strFrom = AccountFromValue(params[0]);
776 string strTo = AccountFromValue(params[1]);
777 int64 nAmount = AmountFromValue(params[2]);
778 if (params.size() > 3)
779 // unused parameter, used to be nMinDepth, keep type-checking it though
780 (void)params[3].get_int();
782 if (params.size() > 4)
783 strComment = params[4].get_str();
785 CWalletDB walletdb(pwalletMain->strWalletFile);
788 int64 nNow = GetAdjustedTime();
791 CAccountingEntry debit;
792 debit.strAccount = strFrom;
793 debit.nCreditDebit = -nAmount;
795 debit.strOtherAccount = strTo;
796 debit.strComment = strComment;
797 walletdb.WriteAccountingEntry(debit);
800 CAccountingEntry credit;
801 credit.strAccount = strTo;
802 credit.nCreditDebit = nAmount;
804 credit.strOtherAccount = strFrom;
805 credit.strComment = strComment;
806 walletdb.WriteAccountingEntry(credit);
808 walletdb.TxnCommit();
814 Value sendfrom(const Array& params, bool fHelp)
816 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
818 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
819 "<amount> is a real and is rounded to the nearest 0.00000001\n"
820 "requires wallet passphrase to be set with walletpassphrase first");
821 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
823 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
824 "<amount> is a real and is rounded to the nearest 0.00000001");
826 string strAccount = AccountFromValue(params[0]);
827 CBitcoinAddress address(params[1].get_str());
828 if (!address.IsValid())
829 throw JSONRPCError(-5, "Invalid bitcoin address");
830 int64 nAmount = AmountFromValue(params[2]);
832 if (params.size() > 3)
833 nMinDepth = params[3].get_int();
836 wtx.strFromAccount = strAccount;
837 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
838 wtx.mapValue["comment"] = params[4].get_str();
839 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
840 wtx.mapValue["to"] = params[5].get_str();
842 if (pwalletMain->IsLocked())
843 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
846 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
847 if (nAmount > nBalance)
848 throw JSONRPCError(-6, "Account has insufficient funds");
851 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
853 throw JSONRPCError(-4, strError);
855 return wtx.GetHash().GetHex();
859 Value sendmany(const Array& params, bool fHelp)
861 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
863 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
864 "amounts are double-precision floating point numbers\n"
865 "requires wallet passphrase to be set with walletpassphrase first");
866 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
868 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
869 "amounts are double-precision floating point numbers");
871 string strAccount = AccountFromValue(params[0]);
872 Object sendTo = params[1].get_obj();
874 if (params.size() > 2)
875 nMinDepth = params[2].get_int();
878 wtx.strFromAccount = strAccount;
879 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
880 wtx.mapValue["comment"] = params[3].get_str();
882 set<CBitcoinAddress> setAddress;
883 vector<pair<CScript, int64> > vecSend;
885 int64 totalAmount = 0;
886 BOOST_FOREACH(const Pair& s, sendTo)
888 CBitcoinAddress address(s.name_);
889 if (!address.IsValid())
890 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
892 if (setAddress.count(address))
893 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
894 setAddress.insert(address);
896 CScript scriptPubKey;
897 scriptPubKey.SetBitcoinAddress(address);
898 int64 nAmount = AmountFromValue(s.value_);
899 totalAmount += nAmount;
901 vecSend.push_back(make_pair(scriptPubKey, nAmount));
904 if (pwalletMain->IsLocked())
905 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
908 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
909 if (totalAmount > nBalance)
910 throw JSONRPCError(-6, "Account has insufficient funds");
913 CReserveKey keyChange(pwalletMain);
914 int64 nFeeRequired = 0;
915 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
918 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
919 throw JSONRPCError(-6, "Insufficient funds");
920 throw JSONRPCError(-4, "Transaction creation failed");
922 if (!pwalletMain->CommitTransaction(wtx, keyChange))
923 throw JSONRPCError(-4, "Transaction commit failed");
925 return wtx.GetHash().GetHex();
940 Value ListReceived(const Array& params, bool fByAccounts)
942 // Minimum confirmations
944 if (params.size() > 0)
945 nMinDepth = params[0].get_int();
947 // Whether to include empty accounts
948 bool fIncludeEmpty = false;
949 if (params.size() > 1)
950 fIncludeEmpty = params[1].get_bool();
953 map<CBitcoinAddress, tallyitem> mapTally;
954 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
956 const CWalletTx& wtx = (*it).second;
957 if (wtx.IsCoinBase() || !wtx.IsFinal())
960 int nDepth = wtx.GetDepthInMainChain();
961 if (nDepth < nMinDepth)
964 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
966 CBitcoinAddress address;
967 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
970 tallyitem& item = mapTally[address];
971 item.nAmount += txout.nValue;
972 item.nConf = min(item.nConf, nDepth);
978 map<string, tallyitem> mapAccountTally;
979 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
981 const CBitcoinAddress& address = item.first;
982 const string& strAccount = item.second;
983 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
984 if (it == mapTally.end() && !fIncludeEmpty)
989 if (it != mapTally.end())
991 nAmount = (*it).second.nAmount;
992 nConf = (*it).second.nConf;
997 tallyitem& item = mapAccountTally[strAccount];
998 item.nAmount += nAmount;
999 item.nConf = min(item.nConf, nConf);
1004 obj.push_back(Pair("address", address.ToString()));
1005 obj.push_back(Pair("account", strAccount));
1006 obj.push_back(Pair("label", strAccount)); // deprecated
1007 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1008 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1015 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1017 int64 nAmount = (*it).second.nAmount;
1018 int nConf = (*it).second.nConf;
1020 obj.push_back(Pair("account", (*it).first));
1021 obj.push_back(Pair("label", (*it).first)); // deprecated
1022 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1023 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1031 Value listreceivedbyaddress(const Array& params, bool fHelp)
1033 if (fHelp || params.size() > 2)
1034 throw runtime_error(
1035 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1036 "[minconf] is the minimum number of confirmations before payments are included.\n"
1037 "[includeempty] whether to include addresses that haven't received any payments.\n"
1038 "Returns an array of objects containing:\n"
1039 " \"address\" : receiving address\n"
1040 " \"account\" : the account of the receiving address\n"
1041 " \"amount\" : total amount received by the address\n"
1042 " \"confirmations\" : number of confirmations of the most recent transaction included");
1044 return ListReceived(params, false);
1047 Value listreceivedbyaccount(const Array& params, bool fHelp)
1049 if (fHelp || params.size() > 2)
1050 throw runtime_error(
1051 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1052 "[minconf] is the minimum number of confirmations before payments are included.\n"
1053 "[includeempty] whether to include accounts that haven't received any payments.\n"
1054 "Returns an array of objects containing:\n"
1055 " \"account\" : the account of the receiving addresses\n"
1056 " \"amount\" : total amount received by addresses with this account\n"
1057 " \"confirmations\" : number of confirmations of the most recent transaction included");
1059 return ListReceived(params, true);
1062 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1064 int64 nGeneratedImmature, nGeneratedMature, nFee;
1065 string strSentAccount;
1066 list<pair<CBitcoinAddress, int64> > listReceived;
1067 list<pair<CBitcoinAddress, int64> > listSent;
1068 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1070 bool fAllAccounts = (strAccount == string("*"));
1072 // Generated blocks assigned to account ""
1073 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1076 entry.push_back(Pair("account", string("")));
1077 if (nGeneratedImmature)
1079 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1080 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1084 entry.push_back(Pair("category", "generate"));
1085 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1088 WalletTxToJSON(wtx, entry);
1089 ret.push_back(entry);
1093 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1095 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1098 entry.push_back(Pair("account", strSentAccount));
1099 entry.push_back(Pair("address", s.first.ToString()));
1100 entry.push_back(Pair("category", "send"));
1101 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1102 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1104 WalletTxToJSON(wtx, entry);
1105 ret.push_back(entry);
1110 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1111 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1114 if (pwalletMain->mapAddressBook.count(r.first))
1115 account = pwalletMain->mapAddressBook[r.first];
1116 if (fAllAccounts || (account == strAccount))
1119 entry.push_back(Pair("account", account));
1120 entry.push_back(Pair("address", r.first.ToString()));
1121 entry.push_back(Pair("category", "receive"));
1122 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1124 WalletTxToJSON(wtx, entry);
1125 ret.push_back(entry);
1130 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1132 bool fAllAccounts = (strAccount == string("*"));
1134 if (fAllAccounts || acentry.strAccount == strAccount)
1137 entry.push_back(Pair("account", acentry.strAccount));
1138 entry.push_back(Pair("category", "move"));
1139 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1140 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1141 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1142 entry.push_back(Pair("comment", acentry.strComment));
1143 ret.push_back(entry);
1147 Value listtransactions(const Array& params, bool fHelp)
1149 if (fHelp || params.size() > 3)
1150 throw runtime_error(
1151 "listtransactions [account] [count=10] [from=0]\n"
1152 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1154 string strAccount = "*";
1155 if (params.size() > 0)
1156 strAccount = params[0].get_str();
1158 if (params.size() > 1)
1159 nCount = params[1].get_int();
1161 if (params.size() > 2)
1162 nFrom = params[2].get_int();
1165 CWalletDB walletdb(pwalletMain->strWalletFile);
1167 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1168 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1169 typedef multimap<int64, TxPair > TxItems;
1172 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1174 CWalletTx* wtx = &((*it).second);
1175 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1177 list<CAccountingEntry> acentries;
1178 walletdb.ListAccountCreditDebit(strAccount, acentries);
1179 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1181 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1184 // Now: iterate backwards until we have nCount items to return:
1185 TxItems::reverse_iterator it = txByTime.rbegin();
1186 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1187 for (; it != txByTime.rend(); ++it)
1189 CWalletTx *const pwtx = (*it).second.first;
1191 ListTransactions(*pwtx, strAccount, 0, true, ret);
1192 CAccountingEntry *const pacentry = (*it).second.second;
1194 AcentryToJSON(*pacentry, strAccount, ret);
1196 if (ret.size() >= nCount) break;
1198 // ret is now newest to oldest
1200 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1201 if (ret.size() > nCount)
1203 Array::iterator last = ret.begin();
1204 std::advance(last, nCount);
1205 ret.erase(last, ret.end());
1207 std::reverse(ret.begin(), ret.end()); // oldest to newest
1212 Value listaccounts(const Array& params, bool fHelp)
1214 if (fHelp || params.size() > 1)
1215 throw runtime_error(
1216 "listaccounts [minconf=1]\n"
1217 "Returns Object that has account names as keys, account balances as values.");
1220 if (params.size() > 0)
1221 nMinDepth = params[0].get_int();
1223 map<string, int64> mapAccountBalances;
1224 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1225 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1226 mapAccountBalances[entry.second] = 0;
1229 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1231 const CWalletTx& wtx = (*it).second;
1232 int64 nGeneratedImmature, nGeneratedMature, nFee;
1233 string strSentAccount;
1234 list<pair<CBitcoinAddress, int64> > listReceived;
1235 list<pair<CBitcoinAddress, int64> > listSent;
1236 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1237 mapAccountBalances[strSentAccount] -= nFee;
1238 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1239 mapAccountBalances[strSentAccount] -= s.second;
1240 if (wtx.GetDepthInMainChain() >= nMinDepth)
1242 mapAccountBalances[""] += nGeneratedMature;
1243 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1244 if (pwalletMain->mapAddressBook.count(r.first))
1245 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1247 mapAccountBalances[""] += r.second;
1251 list<CAccountingEntry> acentries;
1252 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1253 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1254 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1257 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1258 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1263 Value gettransaction(const Array& params, bool fHelp)
1265 if (fHelp || params.size() != 1)
1266 throw runtime_error(
1267 "gettransaction <txid>\n"
1268 "Get detailed information about <txid>");
1271 hash.SetHex(params[0].get_str());
1275 if (!pwalletMain->mapWallet.count(hash))
1276 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1277 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1279 int64 nCredit = wtx.GetCredit();
1280 int64 nDebit = wtx.GetDebit();
1281 int64 nNet = nCredit - nDebit;
1282 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1284 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1286 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1288 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1291 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1292 entry.push_back(Pair("details", details));
1298 Value backupwallet(const Array& params, bool fHelp)
1300 if (fHelp || params.size() != 1)
1301 throw runtime_error(
1302 "backupwallet <destination>\n"
1303 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1305 string strDest = params[0].get_str();
1306 BackupWallet(*pwalletMain, strDest);
1312 Value keypoolrefill(const Array& params, bool fHelp)
1314 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1315 throw runtime_error(
1317 "Fills the keypool, requires wallet passphrase to be set.");
1318 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1319 throw runtime_error(
1321 "Fills the keypool.");
1323 if (pwalletMain->IsLocked())
1324 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1326 pwalletMain->TopUpKeyPool();
1328 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1329 throw JSONRPCError(-4, "Error refreshing keypool.");
1335 void ThreadTopUpKeyPool(void* parg)
1337 pwalletMain->TopUpKeyPool();
1340 void ThreadCleanWalletPassphrase(void* parg)
1342 int64 nMyWakeTime = GetTime() + *((int*)parg);
1344 if (nWalletUnlockTime == 0)
1346 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1348 nWalletUnlockTime = nMyWakeTime;
1351 while (GetTime() < nWalletUnlockTime)
1352 Sleep(GetTime() - nWalletUnlockTime);
1354 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1356 nWalletUnlockTime = 0;
1361 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1363 if (nWalletUnlockTime < nMyWakeTime)
1364 nWalletUnlockTime = nMyWakeTime;
1370 pwalletMain->Lock();
1375 Value walletpassphrase(const Array& params, bool fHelp)
1377 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1378 throw runtime_error(
1379 "walletpassphrase <passphrase> <timeout>\n"
1380 "Stores the wallet decryption key in memory for <timeout> seconds.");
1383 if (!pwalletMain->IsCrypted())
1384 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1386 if (!pwalletMain->IsLocked())
1387 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1389 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1390 string strWalletPass;
1391 strWalletPass.reserve(100);
1392 mlock(&strWalletPass[0], strWalletPass.capacity());
1393 strWalletPass = params[0].get_str();
1395 if (strWalletPass.length() > 0)
1397 if (!pwalletMain->Unlock(strWalletPass))
1399 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1400 munlock(&strWalletPass[0], strWalletPass.capacity());
1401 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1403 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1404 munlock(&strWalletPass[0], strWalletPass.capacity());
1407 throw runtime_error(
1408 "walletpassphrase <passphrase> <timeout>\n"
1409 "Stores the wallet decryption key in memory for <timeout> seconds.");
1411 CreateThread(ThreadTopUpKeyPool, NULL);
1412 int* pnSleepTime = new int(params[1].get_int());
1413 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1419 Value walletpassphrasechange(const Array& params, bool fHelp)
1421 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1422 throw runtime_error(
1423 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1424 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1427 if (!pwalletMain->IsCrypted())
1428 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1430 string strOldWalletPass;
1431 strOldWalletPass.reserve(100);
1432 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1433 strOldWalletPass = params[0].get_str();
1435 string strNewWalletPass;
1436 strNewWalletPass.reserve(100);
1437 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1438 strNewWalletPass = params[1].get_str();
1440 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1441 throw runtime_error(
1442 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1443 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1445 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1447 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1448 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1449 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1450 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1451 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1453 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1454 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1455 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1456 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1462 Value walletlock(const Array& params, bool fHelp)
1464 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1465 throw runtime_error(
1467 "Removes the wallet encryption key from memory, locking the wallet.\n"
1468 "After calling this method, you will need to call walletpassphrase again\n"
1469 "before being able to call any methods which require the wallet to be unlocked.");
1472 if (!pwalletMain->IsCrypted())
1473 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1475 pwalletMain->Lock();
1476 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1478 nWalletUnlockTime = 0;
1485 Value encryptwallet(const Array& params, bool fHelp)
1487 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1488 throw runtime_error(
1489 "encryptwallet <passphrase>\n"
1490 "Encrypts the wallet with <passphrase>.");
1493 if (pwalletMain->IsCrypted())
1494 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1496 string strWalletPass;
1497 strWalletPass.reserve(100);
1498 mlock(&strWalletPass[0], strWalletPass.capacity());
1499 strWalletPass = params[0].get_str();
1501 if (strWalletPass.length() < 1)
1502 throw runtime_error(
1503 "encryptwallet <passphrase>\n"
1504 "Encrypts the wallet with <passphrase>.");
1506 if (!pwalletMain->EncryptWallet(strWalletPass))
1508 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1509 munlock(&strWalletPass[0], strWalletPass.capacity());
1510 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1512 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1513 munlock(&strWalletPass[0], strWalletPass.capacity());
1519 Value validateaddress(const Array& params, bool fHelp)
1521 if (fHelp || params.size() != 1)
1522 throw runtime_error(
1523 "validateaddress <bitcoinaddress>\n"
1524 "Return information about <bitcoinaddress>.");
1526 CBitcoinAddress address(params[0].get_str());
1527 bool isValid = address.IsValid();
1530 ret.push_back(Pair("isvalid", isValid));
1533 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1534 // version of the address:
1535 string currentAddress = address.ToString();
1536 ret.push_back(Pair("address", currentAddress));
1537 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1538 if (pwalletMain->mapAddressBook.count(address))
1539 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1545 Value getwork(const Array& params, bool fHelp)
1547 if (fHelp || params.size() > 1)
1548 throw runtime_error(
1550 "If [data] is not specified, returns formatted hash data to work on:\n"
1551 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1552 " \"data\" : block data\n"
1553 " \"hash1\" : formatted hash buffer for second hash\n"
1554 " \"target\" : little endian hash target\n"
1555 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1558 throw JSONRPCError(-9, "Bitcoin is not connected!");
1560 if (IsInitialBlockDownload())
1561 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1563 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1564 static mapNewBlock_t mapNewBlock;
1565 static vector<CBlock*> vNewBlock;
1566 static CReserveKey reservekey(pwalletMain);
1568 if (params.size() == 0)
1571 static unsigned int nTransactionsUpdatedLast;
1572 static CBlockIndex* pindexPrev;
1573 static int64 nStart;
1574 static CBlock* pblock;
1575 if (pindexPrev != pindexBest ||
1576 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1578 if (pindexPrev != pindexBest)
1580 // Deallocate old blocks since they're obsolete now
1581 mapNewBlock.clear();
1582 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1586 nTransactionsUpdatedLast = nTransactionsUpdated;
1587 pindexPrev = pindexBest;
1591 pblock = CreateNewBlock(reservekey);
1593 throw JSONRPCError(-7, "Out of memory");
1594 vNewBlock.push_back(pblock);
1598 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1601 // Update nExtraNonce
1602 static unsigned int nExtraNonce = 0;
1603 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1606 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1608 // Prebuild hash buffers
1612 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1614 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1617 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1618 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1619 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1620 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1626 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1627 if (vchData.size() != 128)
1628 throw JSONRPCError(-8, "Invalid parameter");
1629 CBlock* pdata = (CBlock*)&vchData[0];
1632 for (int i = 0; i < 128/4; i++)
1633 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1636 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1638 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1640 pblock->nTime = pdata->nTime;
1641 pblock->nNonce = pdata->nNonce;
1642 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1643 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1645 return CheckWork(pblock, *pwalletMain, reservekey);
1663 pair<string, rpcfn_type> pCallTable[] =
1665 make_pair("help", &help),
1666 make_pair("stop", &stop),
1667 make_pair("getblockcount", &getblockcount),
1668 make_pair("getblocknumber", &getblocknumber),
1669 make_pair("getconnectioncount", &getconnectioncount),
1670 make_pair("getdifficulty", &getdifficulty),
1671 make_pair("getgenerate", &getgenerate),
1672 make_pair("setgenerate", &setgenerate),
1673 make_pair("gethashespersec", &gethashespersec),
1674 make_pair("getinfo", &getinfo),
1675 make_pair("getnewaddress", &getnewaddress),
1676 make_pair("getaccountaddress", &getaccountaddress),
1677 make_pair("setaccount", &setaccount),
1678 make_pair("setlabel", &setaccount), // deprecated
1679 make_pair("getaccount", &getaccount),
1680 make_pair("getlabel", &getaccount), // deprecated
1681 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1682 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1683 make_pair("sendtoaddress", &sendtoaddress),
1684 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1685 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1686 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1687 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1688 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1689 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1690 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1691 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1692 make_pair("backupwallet", &backupwallet),
1693 make_pair("keypoolrefill", &keypoolrefill),
1694 make_pair("walletpassphrase", &walletpassphrase),
1695 make_pair("walletpassphrasechange", &walletpassphrasechange),
1696 make_pair("walletlock", &walletlock),
1697 make_pair("encryptwallet", &encryptwallet),
1698 make_pair("validateaddress", &validateaddress),
1699 make_pair("getbalance", &getbalance),
1700 make_pair("move", &movecmd),
1701 make_pair("sendfrom", &sendfrom),
1702 make_pair("sendmany", &sendmany),
1703 make_pair("gettransaction", &gettransaction),
1704 make_pair("listtransactions", &listtransactions),
1705 make_pair("signmessage", &signmessage),
1706 make_pair("verifymessage", &verifymessage),
1707 make_pair("getwork", &getwork),
1708 make_pair("listaccounts", &listaccounts),
1709 make_pair("settxfee", &settxfee),
1711 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1713 string pAllowInSafeMode[] =
1719 "getconnectioncount",
1726 "getaccountaddress",
1727 "setlabel", // deprecated
1729 "getlabel", // deprecated
1730 "getaddressesbyaccount",
1731 "getaddressesbylabel", // deprecated
1739 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1747 // This ain't Apache. We're just using HTTP header for the length field
1748 // and to be compatible with other JSON-RPC implementations.
1751 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1754 s << "POST / HTTP/1.1\r\n"
1755 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1756 << "Host: 127.0.0.1\r\n"
1757 << "Content-Type: application/json\r\n"
1758 << "Content-Length: " << strMsg.size() << "\r\n"
1759 << "Accept: application/json\r\n";
1760 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1761 s << item.first << ": " << item.second << "\r\n";
1762 s << "\r\n" << strMsg;
1767 string rfc1123Time()
1772 struct tm* now_gmt = gmtime(&now);
1773 string locale(setlocale(LC_TIME, NULL));
1774 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1775 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1776 setlocale(LC_TIME, locale.c_str());
1777 return string(buffer);
1780 static string HTTPReply(int nStatus, const string& strMsg)
1783 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1785 "Server: bitcoin-json-rpc/%s\r\n"
1786 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1787 "Content-Type: text/html\r\n"
1788 "Content-Length: 296\r\n"
1790 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1791 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1794 "<TITLE>Error</TITLE>\r\n"
1795 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1797 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1798 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1800 if (nStatus == 200) strStatus = "OK";
1801 else if (nStatus == 400) strStatus = "Bad Request";
1802 else if (nStatus == 403) strStatus = "Forbidden";
1803 else if (nStatus == 404) strStatus = "Not Found";
1804 else if (nStatus == 500) strStatus = "Internal Server Error";
1806 "HTTP/1.1 %d %s\r\n"
1808 "Connection: close\r\n"
1809 "Content-Length: %d\r\n"
1810 "Content-Type: application/json\r\n"
1811 "Server: bitcoin-json-rpc/%s\r\n"
1816 rfc1123Time().c_str(),
1818 FormatFullVersion().c_str(),
1822 int ReadHTTPStatus(std::basic_istream<char>& stream)
1825 getline(stream, str);
1826 vector<string> vWords;
1827 boost::split(vWords, str, boost::is_any_of(" "));
1828 if (vWords.size() < 2)
1830 return atoi(vWords[1].c_str());
1833 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1839 std::getline(stream, str);
1840 if (str.empty() || str == "\r")
1842 string::size_type nColon = str.find(":");
1843 if (nColon != string::npos)
1845 string strHeader = str.substr(0, nColon);
1846 boost::trim(strHeader);
1847 boost::to_lower(strHeader);
1848 string strValue = str.substr(nColon+1);
1849 boost::trim(strValue);
1850 mapHeadersRet[strHeader] = strValue;
1851 if (strHeader == "content-length")
1852 nLen = atoi(strValue.c_str());
1858 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1860 mapHeadersRet.clear();
1864 int nStatus = ReadHTTPStatus(stream);
1867 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1868 if (nLen < 0 || nLen > MAX_SIZE)
1874 vector<char> vch(nLen);
1875 stream.read(&vch[0], nLen);
1876 strMessageRet = string(vch.begin(), vch.end());
1882 bool HTTPAuthorized(map<string, string>& mapHeaders)
1884 string strAuth = mapHeaders["authorization"];
1885 if (strAuth.substr(0,6) != "Basic ")
1887 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1888 string strUserPass = DecodeBase64(strUserPass64);
1889 string::size_type nColon = strUserPass.find(":");
1890 if (nColon == string::npos)
1892 string strUser = strUserPass.substr(0, nColon);
1893 string strPassword = strUserPass.substr(nColon+1);
1894 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1898 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1899 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1900 // unspecified (HTTP errors and contents of 'error').
1902 // 1.0 spec: http://json-rpc.org/wiki/specification
1903 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1904 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1907 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1910 request.push_back(Pair("method", strMethod));
1911 request.push_back(Pair("params", params));
1912 request.push_back(Pair("id", id));
1913 return write_string(Value(request), false) + "\n";
1916 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1919 if (error.type() != null_type)
1920 reply.push_back(Pair("result", Value::null));
1922 reply.push_back(Pair("result", result));
1923 reply.push_back(Pair("error", error));
1924 reply.push_back(Pair("id", id));
1925 return write_string(Value(reply), false) + "\n";
1928 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1930 // Send error reply from json-rpc error object
1932 int code = find_value(objError, "code").get_int();
1933 if (code == -32600) nStatus = 400;
1934 else if (code == -32601) nStatus = 404;
1935 string strReply = JSONRPCReply(Value::null, objError, id);
1936 stream << HTTPReply(nStatus, strReply) << std::flush;
1939 bool ClientAllowed(const string& strAddress)
1941 if (strAddress == asio::ip::address_v4::loopback().to_string())
1943 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1944 BOOST_FOREACH(string strAllow, vAllow)
1945 if (WildcardMatch(strAddress, strAllow))
1952 // IOStream device that speaks SSL but can also speak non-SSL
1954 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1956 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1958 fUseSSL = fUseSSLIn;
1959 fNeedHandshake = fUseSSLIn;
1962 void handshake(ssl::stream_base::handshake_type role)
1964 if (!fNeedHandshake) return;
1965 fNeedHandshake = false;
1966 stream.handshake(role);
1968 std::streamsize read(char* s, std::streamsize n)
1970 handshake(ssl::stream_base::server); // HTTPS servers read first
1971 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1972 return stream.next_layer().read_some(asio::buffer(s, n));
1974 std::streamsize write(const char* s, std::streamsize n)
1976 handshake(ssl::stream_base::client); // HTTPS clients write first
1977 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1978 return asio::write(stream.next_layer(), asio::buffer(s, n));
1980 bool connect(const std::string& server, const std::string& port)
1982 ip::tcp::resolver resolver(stream.get_io_service());
1983 ip::tcp::resolver::query query(server.c_str(), port.c_str());
1984 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
1985 ip::tcp::resolver::iterator end;
1986 boost::system::error_code error = asio::error::host_not_found;
1987 while (error && endpoint_iterator != end)
1989 stream.lowest_layer().close();
1990 stream.lowest_layer().connect(*endpoint_iterator++, error);
1998 bool fNeedHandshake;
2004 void ThreadRPCServer(void* parg)
2006 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2009 vnThreadsRunning[4]++;
2010 ThreadRPCServer2(parg);
2011 vnThreadsRunning[4]--;
2013 catch (std::exception& e) {
2014 vnThreadsRunning[4]--;
2015 PrintException(&e, "ThreadRPCServer()");
2017 vnThreadsRunning[4]--;
2018 PrintException(NULL, "ThreadRPCServer()");
2020 printf("ThreadRPCServer exiting\n");
2023 void ThreadRPCServer2(void* parg)
2025 printf("ThreadRPCServer started\n");
2027 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2029 string strWhatAmI = "To use bitcoind";
2030 if (mapArgs.count("-server"))
2031 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2032 else if (mapArgs.count("-daemon"))
2033 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2035 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2036 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2038 GetConfigFile().c_str());
2039 CreateThread(Shutdown, NULL);
2043 bool fUseSSL = GetBoolArg("-rpcssl");
2044 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2046 asio::io_service io_service;
2047 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2048 ip::tcp::acceptor acceptor(io_service, endpoint);
2050 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2053 ssl::context context(io_service, ssl::context::sslv23);
2056 context.set_options(ssl::context::no_sslv2);
2057 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2058 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2059 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2060 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2061 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2062 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2063 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2064 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2066 string ciphers = GetArg("-rpcsslciphers",
2067 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2068 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2072 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2077 // Accept connection
2079 SSLStream sslStream(io_service, context);
2080 SSLIOStreamDevice d(sslStream, fUseSSL);
2081 iostreams::stream<SSLIOStreamDevice> stream(d);
2083 ip::tcp::iostream stream;
2086 ip::tcp::endpoint peer;
2087 vnThreadsRunning[4]--;
2089 acceptor.accept(sslStream.lowest_layer(), peer);
2091 acceptor.accept(*stream.rdbuf(), peer);
2093 vnThreadsRunning[4]++;
2097 // Restrict callers by IP
2098 if (!ClientAllowed(peer.address().to_string()))
2100 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2102 stream << HTTPReply(403, "") << std::flush;
2106 map<string, string> mapHeaders;
2109 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2110 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2113 printf("ThreadRPCServer ReadHTTP timeout\n");
2117 // Check authorization
2118 if (mapHeaders.count("authorization") == 0)
2120 stream << HTTPReply(401, "") << std::flush;
2123 if (!HTTPAuthorized(mapHeaders))
2125 // Deter brute-forcing short passwords
2126 if (mapArgs["-rpcpassword"].size() < 15)
2129 stream << HTTPReply(401, "") << std::flush;
2130 printf("ThreadRPCServer incorrect password attempt\n");
2134 Value id = Value::null;
2139 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2140 throw JSONRPCError(-32700, "Parse error");
2141 const Object& request = valRequest.get_obj();
2143 // Parse id now so errors from here on will have the id
2144 id = find_value(request, "id");
2147 Value valMethod = find_value(request, "method");
2148 if (valMethod.type() == null_type)
2149 throw JSONRPCError(-32600, "Missing method");
2150 if (valMethod.type() != str_type)
2151 throw JSONRPCError(-32600, "Method must be a string");
2152 string strMethod = valMethod.get_str();
2153 if (strMethod != "getwork")
2154 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2157 Value valParams = find_value(request, "params");
2159 if (valParams.type() == array_type)
2160 params = valParams.get_array();
2161 else if (valParams.type() == null_type)
2164 throw JSONRPCError(-32600, "Params must be an array");
2167 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2168 if (mi == mapCallTable.end())
2169 throw JSONRPCError(-32601, "Method not found");
2171 // Observe safe mode
2172 string strWarning = GetWarnings("rpc");
2173 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2174 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2180 CRITICAL_BLOCK(cs_main)
2181 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2182 result = (*(*mi).second)(params, false);
2185 string strReply = JSONRPCReply(result, Value::null, id);
2186 stream << HTTPReply(200, strReply) << std::flush;
2188 catch (std::exception& e)
2190 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2193 catch (Object& objError)
2195 ErrorReply(stream, objError, id);
2197 catch (std::exception& e)
2199 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2207 Object CallRPC(const string& strMethod, const Array& params)
2209 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2210 throw runtime_error(strprintf(
2211 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2212 "If the file does not exist, create it with owner-readable-only file permissions."),
2213 GetConfigFile().c_str()));
2215 // Connect to localhost
2216 bool fUseSSL = GetBoolArg("-rpcssl");
2218 asio::io_service io_service;
2219 ssl::context context(io_service, ssl::context::sslv23);
2220 context.set_options(ssl::context::no_sslv2);
2221 SSLStream sslStream(io_service, context);
2222 SSLIOStreamDevice d(sslStream, fUseSSL);
2223 iostreams::stream<SSLIOStreamDevice> stream(d);
2224 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2225 throw runtime_error("couldn't connect to server");
2228 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2230 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2232 throw runtime_error("couldn't connect to server");
2236 // HTTP basic authentication
2237 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2238 map<string, string> mapRequestHeaders;
2239 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2242 string strRequest = JSONRPCRequest(strMethod, params, 1);
2243 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2244 stream << strPost << std::flush;
2247 map<string, string> mapHeaders;
2249 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2251 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2252 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2253 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2254 else if (strReply.empty())
2255 throw runtime_error("no response from server");
2259 if (!read_string(strReply, valReply))
2260 throw runtime_error("couldn't parse reply from server");
2261 const Object& reply = valReply.get_obj();
2263 throw runtime_error("expected reply to have result, error and id properties");
2271 template<typename T>
2272 void ConvertTo(Value& value)
2274 if (value.type() == str_type)
2276 // reinterpret string as unquoted json value
2278 if (!read_string(value.get_str(), value2))
2279 throw runtime_error("type mismatch");
2280 value = value2.get_value<T>();
2284 value = value.get_value<T>();
2288 int CommandLineRPC(int argc, char *argv[])
2295 while (argc > 1 && IsSwitchChar(argv[1][0]))
2303 throw runtime_error("too few parameters");
2304 string strMethod = argv[1];
2306 // Parameters default to strings
2308 for (int i = 2; i < argc; i++)
2309 params.push_back(argv[i]);
2310 int n = params.size();
2313 // Special case non-string parameter types
2315 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2316 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2317 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2318 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2319 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2320 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2321 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2322 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2323 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2324 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2325 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2326 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2327 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2328 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2329 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2330 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2331 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2332 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2333 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2334 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2335 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2336 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2337 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2338 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2339 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2340 if (strMethod == "sendmany" && n > 1)
2342 string s = params[1].get_str();
2344 if (!read_string(s, v) || v.type() != obj_type)
2345 throw runtime_error("type mismatch");
2346 params[1] = v.get_obj();
2348 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2351 Object reply = CallRPC(strMethod, params);
2354 const Value& result = find_value(reply, "result");
2355 const Value& error = find_value(reply, "error");
2357 if (error.type() != null_type)
2360 strPrint = "error: " + write_string(error, false);
2361 int code = find_value(error.get_obj(), "code").get_int();
2367 if (result.type() == null_type)
2369 else if (result.type() == str_type)
2370 strPrint = result.get_str();
2372 strPrint = write_string(result, true);
2375 catch (std::exception& e)
2377 strPrint = string("error: ") + e.what();
2382 PrintException(NULL, "CommandLineRPC()");
2387 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2396 int main(int argc, char *argv[])
2399 // Turn off microsoft heap dump noise
2400 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2401 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2403 setbuf(stdin, NULL);
2404 setbuf(stdout, NULL);
2405 setbuf(stderr, NULL);
2409 if (argc >= 2 && string(argv[1]) == "-server")
2411 printf("server ready\n");
2412 ThreadRPCServer(NULL);
2416 return CommandLineRPC(argc, argv);
2419 catch (std::exception& e) {
2420 PrintException(&e, "main()");
2422 PrintException(NULL, "main()");