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.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
58 void PrintConsole(const std::string &format, ...)
61 int limit = sizeof(buffer);
63 va_start(arg_ptr, format);
64 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
66 if (ret < 0 || ret >= limit)
72 fprintf(stdout, "%s", buffer);
76 int64 AmountFromValue(const Value& value)
78 double dAmount = value.get_real();
79 if (dAmount <= 0.0 || dAmount > 21000000.0)
80 throw JSONRPCError(-3, "Invalid amount");
81 int64 nAmount = roundint64(dAmount * COIN);
82 if (!MoneyRange(nAmount))
83 throw JSONRPCError(-3, "Invalid amount");
87 Value ValueFromAmount(int64 amount)
89 return (double)amount / (double)COIN;
92 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
94 int confirms = wtx.GetDepthInMainChain();
95 entry.push_back(Pair("confirmations", confirms));
98 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
99 entry.push_back(Pair("blockindex", wtx.nIndex));
101 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
102 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
103 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
104 entry.push_back(Pair(item.first, item.second));
107 string AccountFromValue(const Value& value)
109 string strAccount = value.get_str();
110 if (strAccount == "*")
111 throw JSONRPCError(-11, "Invalid account name");
118 /// Note: This interface may still be subject to change.
122 Value help(const Array& params, bool fHelp)
124 if (fHelp || params.size() > 1)
127 "List commands, or get help for a command.");
130 if (params.size() > 0)
131 strCommand = params[0].get_str();
134 set<rpcfn_type> setDone;
135 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
137 string strMethod = (*mi).first;
138 // We already filter duplicates, but these deprecated screw up the sort order
139 if (strMethod == "getamountreceived" ||
140 strMethod == "getallreceived" ||
141 strMethod == "getblocknumber" || // deprecated
142 (strMethod.find("label") != string::npos))
144 if (strCommand != "" && strMethod != strCommand)
149 rpcfn_type pfn = (*mi).second;
150 if (setDone.insert(pfn).second)
151 (*pfn)(params, true);
153 catch (std::exception& e)
155 // Help text is returned in an exception
156 string strHelp = string(e.what());
157 if (strCommand == "")
158 if (strHelp.find('\n') != -1)
159 strHelp = strHelp.substr(0, strHelp.find('\n'));
160 strRet += strHelp + "\n";
164 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
165 strRet = strRet.substr(0,strRet.size()-1);
170 Value stop(const Array& params, bool fHelp)
172 if (fHelp || params.size() != 0)
175 "Stop bitcoin server.");
177 // Shutdown will take long enough that the response should get back
178 CreateThread(Shutdown, NULL);
179 return "bitcoin server stopping";
181 throw runtime_error("NYI: cannot shut down GUI with RPC command");
186 Value getblockcount(const Array& params, bool fHelp)
188 if (fHelp || params.size() != 0)
191 "Returns the number of blocks in the longest block chain.");
198 Value getblocknumber(const Array& params, bool fHelp)
200 if (fHelp || params.size() != 0)
203 "Deprecated. Use getblockcount.");
209 Value getconnectioncount(const Array& params, bool fHelp)
211 if (fHelp || params.size() != 0)
213 "getconnectioncount\n"
214 "Returns the number of connections to other nodes.");
216 return (int)vNodes.size();
220 double GetDifficulty()
222 // Floating point number that is a multiple of the minimum difficulty,
223 // minimum difficulty = 1.0.
225 if (pindexBest == NULL)
227 int nShift = (pindexBest->nBits >> 24) & 0xff;
230 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
246 Value getdifficulty(const Array& params, bool fHelp)
248 if (fHelp || params.size() != 0)
251 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
253 return GetDifficulty();
257 Value getgenerate(const Array& params, bool fHelp)
259 if (fHelp || params.size() != 0)
262 "Returns true or false.");
264 return (bool)fGenerateBitcoins;
268 Value setgenerate(const Array& params, bool fHelp)
270 if (fHelp || params.size() < 1 || params.size() > 2)
272 "setgenerate <generate> [genproclimit]\n"
273 "<generate> is true or false to turn generation on or off.\n"
274 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
276 bool fGenerate = true;
277 if (params.size() > 0)
278 fGenerate = params[0].get_bool();
280 if (params.size() > 1)
282 int nGenProcLimit = params[1].get_int();
283 fLimitProcessors = (nGenProcLimit != -1);
284 WriteSetting("fLimitProcessors", fLimitProcessors);
285 if (nGenProcLimit != -1)
286 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
287 if (nGenProcLimit == 0)
291 GenerateBitcoins(fGenerate, pwalletMain);
296 Value gethashespersec(const Array& params, bool fHelp)
298 if (fHelp || params.size() != 0)
301 "Returns a recent hashes per second performance measurement while generating.");
303 if (GetTimeMillis() - nHPSTimerStart > 8000)
304 return (boost::int64_t)0;
305 return (boost::int64_t)dHashesPerSec;
309 Value getinfo(const Array& params, bool fHelp)
311 if (fHelp || params.size() != 0)
314 "Returns an object containing various state info.");
317 obj.push_back(Pair("version", (int)CLIENT_VERSION));
318 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
319 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
320 obj.push_back(Pair("blocks", (int)nBestHeight));
321 obj.push_back(Pair("connections", (int)vNodes.size()));
322 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
323 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
324 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
325 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
326 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
327 obj.push_back(Pair("testnet", fTestNet));
328 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
329 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
330 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
331 if (pwalletMain->IsCrypted())
332 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
333 obj.push_back(Pair("errors", GetWarnings("statusbar")));
338 Value getnewaddress(const Array& params, bool fHelp)
340 if (fHelp || params.size() > 1)
342 "getnewaddress [account]\n"
343 "Returns a new bitcoin address for receiving payments. "
344 "If [account] is specified (recommended), it is added to the address book "
345 "so payments received with the address will be credited to [account].");
347 // Parse the account first so we don't generate a key if there's an error
349 if (params.size() > 0)
350 strAccount = AccountFromValue(params[0]);
352 if (!pwalletMain->IsLocked())
353 pwalletMain->TopUpKeyPool();
355 // Generate a new key that is added to wallet
356 std::vector<unsigned char> newKey;
357 if (!pwalletMain->GetKeyFromPool(newKey, false))
358 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
359 CBitcoinAddress address(newKey);
361 pwalletMain->SetAddressBookName(address, strAccount);
363 return address.ToString();
367 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
369 CWalletDB walletdb(pwalletMain->strWalletFile);
372 walletdb.ReadAccount(strAccount, account);
374 bool bKeyUsed = false;
376 // Check if the current key has been used
377 if (!account.vchPubKey.empty())
379 CScript scriptPubKey;
380 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
381 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
382 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
385 const CWalletTx& wtx = (*it).second;
386 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
387 if (txout.scriptPubKey == scriptPubKey)
392 // Generate a new key
393 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
395 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
396 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
398 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
399 walletdb.WriteAccount(strAccount, account);
402 return CBitcoinAddress(account.vchPubKey);
405 Value getaccountaddress(const Array& params, bool fHelp)
407 if (fHelp || params.size() != 1)
409 "getaccountaddress <account>\n"
410 "Returns the current bitcoin address for receiving payments to this account.");
412 // Parse the account first so we don't generate a key if there's an error
413 string strAccount = AccountFromValue(params[0]);
417 ret = GetAccountAddress(strAccount).ToString();
424 Value setaccount(const Array& params, bool fHelp)
426 if (fHelp || params.size() < 1 || params.size() > 2)
428 "setaccount <bitcoinaddress> <account>\n"
429 "Sets the account associated with the given address.");
431 CBitcoinAddress address(params[0].get_str());
432 if (!address.IsValid())
433 throw JSONRPCError(-5, "Invalid bitcoin address");
437 if (params.size() > 1)
438 strAccount = AccountFromValue(params[1]);
440 // Detect when changing the account of an address that is the 'unused current key' of another account:
441 if (pwalletMain->mapAddressBook.count(address))
443 string strOldAccount = pwalletMain->mapAddressBook[address];
444 if (address == GetAccountAddress(strOldAccount))
445 GetAccountAddress(strOldAccount, true);
448 pwalletMain->SetAddressBookName(address, strAccount);
454 Value getaccount(const Array& params, bool fHelp)
456 if (fHelp || params.size() != 1)
458 "getaccount <bitcoinaddress>\n"
459 "Returns the account associated with the given address.");
461 CBitcoinAddress address(params[0].get_str());
462 if (!address.IsValid())
463 throw JSONRPCError(-5, "Invalid bitcoin address");
466 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
467 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
468 strAccount = (*mi).second;
473 Value getaddressesbyaccount(const Array& params, bool fHelp)
475 if (fHelp || params.size() != 1)
477 "getaddressesbyaccount <account>\n"
478 "Returns the list of addresses for the given account.");
480 string strAccount = AccountFromValue(params[0]);
482 // Find all addresses that have the given account
484 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
486 const CBitcoinAddress& address = item.first;
487 const string& strName = item.second;
488 if (strName == strAccount)
489 ret.push_back(address.ToString());
494 Value settxfee(const Array& params, bool fHelp)
496 if (fHelp || params.size() < 1 || params.size() > 1)
498 "settxfee <amount>\n"
499 "<amount> is a real and is rounded to the nearest 0.00000001");
503 if (params[0].get_real() != 0.0)
504 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
506 nTransactionFee = nAmount;
510 Value sendtoaddress(const Array& params, bool fHelp)
512 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
514 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
515 "<amount> is a real and is rounded to the nearest 0.00000001\n"
516 "requires wallet passphrase to be set with walletpassphrase first");
517 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
519 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
520 "<amount> is a real and is rounded to the nearest 0.00000001");
522 CBitcoinAddress address(params[0].get_str());
523 if (!address.IsValid())
524 throw JSONRPCError(-5, "Invalid bitcoin address");
527 int64 nAmount = AmountFromValue(params[1]);
531 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
532 wtx.mapValue["comment"] = params[2].get_str();
533 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
534 wtx.mapValue["to"] = params[3].get_str();
536 if (pwalletMain->IsLocked())
537 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
539 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
541 throw JSONRPCError(-4, strError);
543 return wtx.GetHash().GetHex();
546 static const string strMessageMagic = "Bitcoin Signed Message:\n";
548 Value signmessage(const Array& params, bool fHelp)
550 if (fHelp || params.size() != 2)
552 "signmessage <bitcoinaddress> <message>\n"
553 "Sign a message with the private key of an address");
555 if (pwalletMain->IsLocked())
556 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
558 string strAddress = params[0].get_str();
559 string strMessage = params[1].get_str();
561 CBitcoinAddress addr(strAddress);
563 throw JSONRPCError(-3, "Invalid address");
566 if (!pwalletMain->GetKey(addr, key))
567 throw JSONRPCError(-4, "Private key not available");
569 CDataStream ss(SER_GETHASH);
570 ss << strMessageMagic;
573 vector<unsigned char> vchSig;
574 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
575 throw JSONRPCError(-5, "Sign failed");
577 return EncodeBase64(&vchSig[0], vchSig.size());
580 Value verifymessage(const Array& params, bool fHelp)
582 if (fHelp || params.size() != 3)
584 "verifymessage <bitcoinaddress> <signature> <message>\n"
585 "Verify a signed message");
587 string strAddress = params[0].get_str();
588 string strSign = params[1].get_str();
589 string strMessage = params[2].get_str();
591 CBitcoinAddress addr(strAddress);
593 throw JSONRPCError(-3, "Invalid address");
595 bool fInvalid = false;
596 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
599 throw JSONRPCError(-5, "Malformed base64 encoding");
601 CDataStream ss(SER_GETHASH);
602 ss << strMessageMagic;
606 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
609 return (CBitcoinAddress(key.GetPubKey()) == addr);
613 Value getreceivedbyaddress(const Array& params, bool fHelp)
615 if (fHelp || params.size() < 1 || params.size() > 2)
617 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
618 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
621 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
622 CScript scriptPubKey;
623 if (!address.IsValid())
624 throw JSONRPCError(-5, "Invalid bitcoin address");
625 scriptPubKey.SetBitcoinAddress(address);
626 if (!IsMine(*pwalletMain,scriptPubKey))
629 // Minimum confirmations
631 if (params.size() > 1)
632 nMinDepth = params[1].get_int();
636 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
638 const CWalletTx& wtx = (*it).second;
639 if (wtx.IsCoinBase() || !wtx.IsFinal())
642 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
643 if (txout.scriptPubKey == scriptPubKey)
644 if (wtx.GetDepthInMainChain() >= nMinDepth)
645 nAmount += txout.nValue;
648 return ValueFromAmount(nAmount);
652 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
654 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
656 const CBitcoinAddress& address = item.first;
657 const string& strName = item.second;
658 if (strName == strAccount)
659 setAddress.insert(address);
664 Value getreceivedbyaccount(const Array& params, bool fHelp)
666 if (fHelp || params.size() < 1 || params.size() > 2)
668 "getreceivedbyaccount <account> [minconf=1]\n"
669 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
671 // Minimum confirmations
673 if (params.size() > 1)
674 nMinDepth = params[1].get_int();
676 // Get the set of pub keys that have the label
677 string strAccount = AccountFromValue(params[0]);
678 set<CBitcoinAddress> setAddress;
679 GetAccountAddresses(strAccount, setAddress);
683 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
685 const CWalletTx& wtx = (*it).second;
686 if (wtx.IsCoinBase() || !wtx.IsFinal())
689 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
691 CBitcoinAddress address;
692 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
693 if (wtx.GetDepthInMainChain() >= nMinDepth)
694 nAmount += txout.nValue;
698 return (double)nAmount / (double)COIN;
702 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
706 // Tally wallet transactions
707 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
709 const CWalletTx& wtx = (*it).second;
713 int64 nGenerated, nReceived, nSent, nFee;
714 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
716 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
717 nBalance += nReceived;
718 nBalance += nGenerated - nSent - nFee;
721 // Tally internal accounting entries
722 nBalance += walletdb.GetAccountCreditDebit(strAccount);
727 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
729 CWalletDB walletdb(pwalletMain->strWalletFile);
730 return GetAccountBalance(walletdb, strAccount, nMinDepth);
734 Value getbalance(const Array& params, bool fHelp)
736 if (fHelp || params.size() > 2)
738 "getbalance [account] [minconf=1]\n"
739 "If [account] is not specified, returns the server's total available balance.\n"
740 "If [account] is specified, returns the balance in the account.");
742 if (params.size() == 0)
743 return ValueFromAmount(pwalletMain->GetBalance());
746 if (params.size() > 1)
747 nMinDepth = params[1].get_int();
749 if (params[0].get_str() == "*") {
750 // Calculate total balance a different way from GetBalance()
751 // (GetBalance() sums up all unspent TxOuts)
752 // getbalance and getbalance '*' should always return the same number.
754 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
756 const CWalletTx& wtx = (*it).second;
760 int64 allGeneratedImmature, allGeneratedMature, allFee;
761 allGeneratedImmature = allGeneratedMature = allFee = 0;
762 string strSentAccount;
763 list<pair<CBitcoinAddress, int64> > listReceived;
764 list<pair<CBitcoinAddress, int64> > listSent;
765 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
766 if (wtx.GetDepthInMainChain() >= nMinDepth)
767 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
768 nBalance += r.second;
769 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
770 nBalance -= r.second;
772 nBalance += allGeneratedMature;
774 return ValueFromAmount(nBalance);
777 string strAccount = AccountFromValue(params[0]);
779 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
781 return ValueFromAmount(nBalance);
785 Value movecmd(const Array& params, bool fHelp)
787 if (fHelp || params.size() < 3 || params.size() > 5)
789 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
790 "Move from one account in your wallet to another.");
792 string strFrom = AccountFromValue(params[0]);
793 string strTo = AccountFromValue(params[1]);
794 int64 nAmount = AmountFromValue(params[2]);
795 if (params.size() > 3)
796 // unused parameter, used to be nMinDepth, keep type-checking it though
797 (void)params[3].get_int();
799 if (params.size() > 4)
800 strComment = params[4].get_str();
802 CWalletDB walletdb(pwalletMain->strWalletFile);
805 int64 nNow = GetAdjustedTime();
808 CAccountingEntry debit;
809 debit.strAccount = strFrom;
810 debit.nCreditDebit = -nAmount;
812 debit.strOtherAccount = strTo;
813 debit.strComment = strComment;
814 walletdb.WriteAccountingEntry(debit);
817 CAccountingEntry credit;
818 credit.strAccount = strTo;
819 credit.nCreditDebit = nAmount;
821 credit.strOtherAccount = strFrom;
822 credit.strComment = strComment;
823 walletdb.WriteAccountingEntry(credit);
825 walletdb.TxnCommit();
831 Value sendfrom(const Array& params, bool fHelp)
833 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
835 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
836 "<amount> is a real and is rounded to the nearest 0.00000001\n"
837 "requires wallet passphrase to be set with walletpassphrase first");
838 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
840 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
841 "<amount> is a real and is rounded to the nearest 0.00000001");
843 string strAccount = AccountFromValue(params[0]);
844 CBitcoinAddress address(params[1].get_str());
845 if (!address.IsValid())
846 throw JSONRPCError(-5, "Invalid bitcoin address");
847 int64 nAmount = AmountFromValue(params[2]);
849 if (params.size() > 3)
850 nMinDepth = params[3].get_int();
853 wtx.strFromAccount = strAccount;
854 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
855 wtx.mapValue["comment"] = params[4].get_str();
856 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
857 wtx.mapValue["to"] = params[5].get_str();
859 if (pwalletMain->IsLocked())
860 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
863 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
864 if (nAmount > nBalance)
865 throw JSONRPCError(-6, "Account has insufficient funds");
868 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
870 throw JSONRPCError(-4, strError);
872 return wtx.GetHash().GetHex();
876 Value sendmany(const Array& params, bool fHelp)
878 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
880 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
881 "amounts are double-precision floating point numbers\n"
882 "requires wallet passphrase to be set with walletpassphrase first");
883 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
885 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
886 "amounts are double-precision floating point numbers");
888 string strAccount = AccountFromValue(params[0]);
889 Object sendTo = params[1].get_obj();
891 if (params.size() > 2)
892 nMinDepth = params[2].get_int();
895 wtx.strFromAccount = strAccount;
896 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
897 wtx.mapValue["comment"] = params[3].get_str();
899 set<CBitcoinAddress> setAddress;
900 vector<pair<CScript, int64> > vecSend;
902 int64 totalAmount = 0;
903 BOOST_FOREACH(const Pair& s, sendTo)
905 CBitcoinAddress address(s.name_);
906 if (!address.IsValid())
907 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
909 if (setAddress.count(address))
910 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
911 setAddress.insert(address);
913 CScript scriptPubKey;
914 scriptPubKey.SetBitcoinAddress(address);
915 int64 nAmount = AmountFromValue(s.value_);
916 totalAmount += nAmount;
918 vecSend.push_back(make_pair(scriptPubKey, nAmount));
921 if (pwalletMain->IsLocked())
922 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
925 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
926 if (totalAmount > nBalance)
927 throw JSONRPCError(-6, "Account has insufficient funds");
930 CReserveKey keyChange(pwalletMain);
931 int64 nFeeRequired = 0;
932 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
935 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
936 throw JSONRPCError(-6, "Insufficient funds");
937 throw JSONRPCError(-4, "Transaction creation failed");
939 if (!pwalletMain->CommitTransaction(wtx, keyChange))
940 throw JSONRPCError(-4, "Transaction commit failed");
942 return wtx.GetHash().GetHex();
953 nConf = std::numeric_limits<int>::max();
957 Value ListReceived(const Array& params, bool fByAccounts)
959 // Minimum confirmations
961 if (params.size() > 0)
962 nMinDepth = params[0].get_int();
964 // Whether to include empty accounts
965 bool fIncludeEmpty = false;
966 if (params.size() > 1)
967 fIncludeEmpty = params[1].get_bool();
970 map<CBitcoinAddress, tallyitem> mapTally;
971 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
973 const CWalletTx& wtx = (*it).second;
974 if (wtx.IsCoinBase() || !wtx.IsFinal())
977 int nDepth = wtx.GetDepthInMainChain();
978 if (nDepth < nMinDepth)
981 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
983 CBitcoinAddress address;
984 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
987 tallyitem& item = mapTally[address];
988 item.nAmount += txout.nValue;
989 item.nConf = min(item.nConf, nDepth);
995 map<string, tallyitem> mapAccountTally;
996 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
998 const CBitcoinAddress& address = item.first;
999 const string& strAccount = item.second;
1000 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1001 if (it == mapTally.end() && !fIncludeEmpty)
1005 int nConf = std::numeric_limits<int>::max();
1006 if (it != mapTally.end())
1008 nAmount = (*it).second.nAmount;
1009 nConf = (*it).second.nConf;
1014 tallyitem& item = mapAccountTally[strAccount];
1015 item.nAmount += nAmount;
1016 item.nConf = min(item.nConf, nConf);
1021 obj.push_back(Pair("address", address.ToString()));
1022 obj.push_back(Pair("account", strAccount));
1023 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1024 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1031 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1033 int64 nAmount = (*it).second.nAmount;
1034 int nConf = (*it).second.nConf;
1036 obj.push_back(Pair("account", (*it).first));
1037 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1038 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1046 Value listreceivedbyaddress(const Array& params, bool fHelp)
1048 if (fHelp || params.size() > 2)
1049 throw runtime_error(
1050 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1051 "[minconf] is the minimum number of confirmations before payments are included.\n"
1052 "[includeempty] whether to include addresses that haven't received any payments.\n"
1053 "Returns an array of objects containing:\n"
1054 " \"address\" : receiving address\n"
1055 " \"account\" : the account of the receiving address\n"
1056 " \"amount\" : total amount received by the address\n"
1057 " \"confirmations\" : number of confirmations of the most recent transaction included");
1059 return ListReceived(params, false);
1062 Value listreceivedbyaccount(const Array& params, bool fHelp)
1064 if (fHelp || params.size() > 2)
1065 throw runtime_error(
1066 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1067 "[minconf] is the minimum number of confirmations before payments are included.\n"
1068 "[includeempty] whether to include accounts that haven't received any payments.\n"
1069 "Returns an array of objects containing:\n"
1070 " \"account\" : the account of the receiving addresses\n"
1071 " \"amount\" : total amount received by addresses with this account\n"
1072 " \"confirmations\" : number of confirmations of the most recent transaction included");
1074 return ListReceived(params, true);
1077 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1079 int64 nGeneratedImmature, nGeneratedMature, nFee;
1080 string strSentAccount;
1081 list<pair<CBitcoinAddress, int64> > listReceived;
1082 list<pair<CBitcoinAddress, int64> > listSent;
1083 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1085 bool fAllAccounts = (strAccount == string("*"));
1087 // Generated blocks assigned to account ""
1088 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1091 entry.push_back(Pair("account", string("")));
1092 if (nGeneratedImmature)
1094 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1095 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1099 entry.push_back(Pair("category", "generate"));
1100 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1103 WalletTxToJSON(wtx, entry);
1104 ret.push_back(entry);
1108 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1110 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1113 entry.push_back(Pair("account", strSentAccount));
1114 entry.push_back(Pair("address", s.first.ToString()));
1115 entry.push_back(Pair("category", "send"));
1116 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1117 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1119 WalletTxToJSON(wtx, entry);
1120 ret.push_back(entry);
1125 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1126 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1129 if (pwalletMain->mapAddressBook.count(r.first))
1130 account = pwalletMain->mapAddressBook[r.first];
1131 if (fAllAccounts || (account == strAccount))
1134 entry.push_back(Pair("account", account));
1135 entry.push_back(Pair("address", r.first.ToString()));
1136 entry.push_back(Pair("category", "receive"));
1137 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1139 WalletTxToJSON(wtx, entry);
1140 ret.push_back(entry);
1145 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1147 bool fAllAccounts = (strAccount == string("*"));
1149 if (fAllAccounts || acentry.strAccount == strAccount)
1152 entry.push_back(Pair("account", acentry.strAccount));
1153 entry.push_back(Pair("category", "move"));
1154 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1155 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1156 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1157 entry.push_back(Pair("comment", acentry.strComment));
1158 ret.push_back(entry);
1162 Value listtransactions(const Array& params, bool fHelp)
1164 if (fHelp || params.size() > 3)
1165 throw runtime_error(
1166 "listtransactions [account] [count=10] [from=0]\n"
1167 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1169 string strAccount = "*";
1170 if (params.size() > 0)
1171 strAccount = params[0].get_str();
1173 if (params.size() > 1)
1174 nCount = params[1].get_int();
1176 if (params.size() > 2)
1177 nFrom = params[2].get_int();
1180 CWalletDB walletdb(pwalletMain->strWalletFile);
1182 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1183 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1184 typedef multimap<int64, TxPair > TxItems;
1187 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1189 CWalletTx* wtx = &((*it).second);
1190 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1192 list<CAccountingEntry> acentries;
1193 walletdb.ListAccountCreditDebit(strAccount, acentries);
1194 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1196 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1199 // Now: iterate backwards until we have nCount items to return:
1200 TxItems::reverse_iterator it = txByTime.rbegin();
1201 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1202 for (; it != txByTime.rend(); ++it)
1204 CWalletTx *const pwtx = (*it).second.first;
1206 ListTransactions(*pwtx, strAccount, 0, true, ret);
1207 CAccountingEntry *const pacentry = (*it).second.second;
1209 AcentryToJSON(*pacentry, strAccount, ret);
1211 if (ret.size() >= nCount) break;
1213 // ret is now newest to oldest
1215 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1216 if (ret.size() > nCount)
1218 Array::iterator last = ret.begin();
1219 std::advance(last, nCount);
1220 ret.erase(last, ret.end());
1222 std::reverse(ret.begin(), ret.end()); // oldest to newest
1227 Value listaccounts(const Array& params, bool fHelp)
1229 if (fHelp || params.size() > 1)
1230 throw runtime_error(
1231 "listaccounts [minconf=1]\n"
1232 "Returns Object that has account names as keys, account balances as values.");
1235 if (params.size() > 0)
1236 nMinDepth = params[0].get_int();
1238 map<string, int64> mapAccountBalances;
1239 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1240 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1241 mapAccountBalances[entry.second] = 0;
1244 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1246 const CWalletTx& wtx = (*it).second;
1247 int64 nGeneratedImmature, nGeneratedMature, nFee;
1248 string strSentAccount;
1249 list<pair<CBitcoinAddress, int64> > listReceived;
1250 list<pair<CBitcoinAddress, int64> > listSent;
1251 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1252 mapAccountBalances[strSentAccount] -= nFee;
1253 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1254 mapAccountBalances[strSentAccount] -= s.second;
1255 if (wtx.GetDepthInMainChain() >= nMinDepth)
1257 mapAccountBalances[""] += nGeneratedMature;
1258 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1259 if (pwalletMain->mapAddressBook.count(r.first))
1260 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1262 mapAccountBalances[""] += r.second;
1266 list<CAccountingEntry> acentries;
1267 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1268 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1269 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1272 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1273 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1278 Value listsinceblock(const Array& params, bool fHelp)
1281 throw runtime_error(
1282 "listsinceblock [blockid] [target-confirmations]\n"
1283 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1285 CBlockIndex *pindex = NULL;
1286 int target_confirms = 1;
1288 if (params.size() > 0)
1290 uint256 blockId = 0;
1292 blockId.SetHex(params[0].get_str());
1293 pindex = CBlockLocator(blockId).GetBlockIndex();
1296 if (params.size() > 1)
1298 target_confirms = params[1].get_int();
1300 if (target_confirms < 1)
1301 throw JSONRPCError(-8, "Invalid parameter");
1304 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1308 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1310 CWalletTx tx = (*it).second;
1312 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1313 ListTransactions(tx, "*", 0, true, transactions);
1318 if (target_confirms == 1)
1321 lastblock = hashBestChain;
1325 int target_height = pindexBest->nHeight + 1 - target_confirms;
1328 for (block = pindexBest;
1329 block && block->nHeight > target_height;
1330 block = block->pprev);
1332 lastblock = block ? block->GetBlockHash() : 0;
1336 ret.push_back(Pair("transactions", transactions));
1337 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1342 Value gettransaction(const Array& params, bool fHelp)
1344 if (fHelp || params.size() != 1)
1345 throw runtime_error(
1346 "gettransaction <txid>\n"
1347 "Get detailed information about <txid>");
1350 hash.SetHex(params[0].get_str());
1354 if (!pwalletMain->mapWallet.count(hash))
1355 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1356 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1358 int64 nCredit = wtx.GetCredit();
1359 int64 nDebit = wtx.GetDebit();
1360 int64 nNet = nCredit - nDebit;
1361 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1363 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1365 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1367 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1370 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1371 entry.push_back(Pair("details", details));
1377 Value backupwallet(const Array& params, bool fHelp)
1379 if (fHelp || params.size() != 1)
1380 throw runtime_error(
1381 "backupwallet <destination>\n"
1382 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1384 string strDest = params[0].get_str();
1385 BackupWallet(*pwalletMain, strDest);
1391 Value keypoolrefill(const Array& params, bool fHelp)
1393 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1394 throw runtime_error(
1396 "Fills the keypool, requires wallet passphrase to be set.");
1397 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1398 throw runtime_error(
1400 "Fills the keypool.");
1402 if (pwalletMain->IsLocked())
1403 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1405 pwalletMain->TopUpKeyPool();
1407 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1408 throw JSONRPCError(-4, "Error refreshing keypool.");
1414 void ThreadTopUpKeyPool(void* parg)
1416 pwalletMain->TopUpKeyPool();
1419 void ThreadCleanWalletPassphrase(void* parg)
1421 int64 nMyWakeTime = GetTime() + *((int*)parg);
1423 if (nWalletUnlockTime == 0)
1425 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1427 nWalletUnlockTime = nMyWakeTime;
1430 while (GetTime() < nWalletUnlockTime)
1431 Sleep(GetTime() - nWalletUnlockTime);
1433 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1435 nWalletUnlockTime = 0;
1440 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1442 if (nWalletUnlockTime < nMyWakeTime)
1443 nWalletUnlockTime = nMyWakeTime;
1449 pwalletMain->Lock();
1454 Value walletpassphrase(const Array& params, bool fHelp)
1456 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1457 throw runtime_error(
1458 "walletpassphrase <passphrase> <timeout>\n"
1459 "Stores the wallet decryption key in memory for <timeout> seconds.");
1462 if (!pwalletMain->IsCrypted())
1463 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1465 if (!pwalletMain->IsLocked())
1466 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1468 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1469 SecureString strWalletPass;
1470 strWalletPass.reserve(100);
1471 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1472 // Alternately, find a way to make params[0] mlock()'d to begin with.
1473 strWalletPass = params[0].get_str().c_str();
1475 if (strWalletPass.length() > 0)
1477 if (!pwalletMain->Unlock(strWalletPass))
1478 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1481 throw runtime_error(
1482 "walletpassphrase <passphrase> <timeout>\n"
1483 "Stores the wallet decryption key in memory for <timeout> seconds.");
1485 CreateThread(ThreadTopUpKeyPool, NULL);
1486 int* pnSleepTime = new int(params[1].get_int());
1487 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1493 Value walletpassphrasechange(const Array& params, bool fHelp)
1495 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1496 throw runtime_error(
1497 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1498 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1501 if (!pwalletMain->IsCrypted())
1502 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1504 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1505 // Alternately, find a way to make params[0] mlock()'d to begin with.
1506 SecureString strOldWalletPass;
1507 strOldWalletPass.reserve(100);
1508 strOldWalletPass = params[0].get_str().c_str();
1510 SecureString strNewWalletPass;
1511 strNewWalletPass.reserve(100);
1512 strNewWalletPass = params[1].get_str().c_str();
1514 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1515 throw runtime_error(
1516 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1517 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1519 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1520 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1526 Value walletlock(const Array& params, bool fHelp)
1528 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1529 throw runtime_error(
1531 "Removes the wallet encryption key from memory, locking the wallet.\n"
1532 "After calling this method, you will need to call walletpassphrase again\n"
1533 "before being able to call any methods which require the wallet to be unlocked.");
1536 if (!pwalletMain->IsCrypted())
1537 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1539 pwalletMain->Lock();
1540 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1542 nWalletUnlockTime = 0;
1549 Value encryptwallet(const Array& params, bool fHelp)
1551 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1552 throw runtime_error(
1553 "encryptwallet <passphrase>\n"
1554 "Encrypts the wallet with <passphrase>.");
1557 if (pwalletMain->IsCrypted())
1558 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1561 // shutting down via RPC while the GUI is running does not work (yet):
1562 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1565 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1566 // Alternately, find a way to make params[0] mlock()'d to begin with.
1567 SecureString strWalletPass;
1568 strWalletPass.reserve(100);
1569 strWalletPass = params[0].get_str().c_str();
1571 if (strWalletPass.length() < 1)
1572 throw runtime_error(
1573 "encryptwallet <passphrase>\n"
1574 "Encrypts the wallet with <passphrase>.");
1576 if (!pwalletMain->EncryptWallet(strWalletPass))
1577 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1579 // BDB seems to have a bad habit of writing old data into
1580 // slack space in .dat files; that is bad if the old data is
1581 // unencrypted private keys. So:
1582 CreateThread(Shutdown, NULL);
1583 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1587 Value validateaddress(const Array& params, bool fHelp)
1589 if (fHelp || params.size() != 1)
1590 throw runtime_error(
1591 "validateaddress <bitcoinaddress>\n"
1592 "Return information about <bitcoinaddress>.");
1594 CBitcoinAddress address(params[0].get_str());
1595 bool isValid = address.IsValid();
1598 ret.push_back(Pair("isvalid", isValid));
1601 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1602 // version of the address:
1603 string currentAddress = address.ToString();
1604 ret.push_back(Pair("address", currentAddress));
1605 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1606 if (pwalletMain->mapAddressBook.count(address))
1607 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1612 Value getwork(const Array& params, bool fHelp)
1614 if (fHelp || params.size() > 1)
1615 throw runtime_error(
1617 "If [data] is not specified, returns formatted hash data to work on:\n"
1618 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1619 " \"data\" : block data\n"
1620 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1621 " \"target\" : little endian hash target\n"
1622 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1625 throw JSONRPCError(-9, "Bitcoin is not connected!");
1627 if (IsInitialBlockDownload())
1628 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1630 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1631 static mapNewBlock_t mapNewBlock;
1632 static vector<CBlock*> vNewBlock;
1633 static CReserveKey reservekey(pwalletMain);
1635 if (params.size() == 0)
1638 static unsigned int nTransactionsUpdatedLast;
1639 static CBlockIndex* pindexPrev;
1640 static int64 nStart;
1641 static CBlock* pblock;
1642 if (pindexPrev != pindexBest ||
1643 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1645 if (pindexPrev != pindexBest)
1647 // Deallocate old blocks since they're obsolete now
1648 mapNewBlock.clear();
1649 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1653 nTransactionsUpdatedLast = nTransactionsUpdated;
1654 pindexPrev = pindexBest;
1658 pblock = CreateNewBlock(reservekey);
1660 throw JSONRPCError(-7, "Out of memory");
1661 vNewBlock.push_back(pblock);
1665 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1668 // Update nExtraNonce
1669 static unsigned int nExtraNonce = 0;
1670 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1673 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1675 // Prebuild hash buffers
1679 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1681 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1684 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1685 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1686 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1687 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1693 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1694 if (vchData.size() != 128)
1695 throw JSONRPCError(-8, "Invalid parameter");
1696 CBlock* pdata = (CBlock*)&vchData[0];
1699 for (int i = 0; i < 128/4; i++)
1700 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1703 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1705 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1707 pblock->nTime = pdata->nTime;
1708 pblock->nNonce = pdata->nNonce;
1709 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1710 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1712 return CheckWork(pblock, *pwalletMain, reservekey);
1717 Value getmemorypool(const Array& params, bool fHelp)
1719 if (fHelp || params.size() > 1)
1720 throw runtime_error(
1721 "getmemorypool [data]\n"
1722 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1723 " \"version\" : block version\n"
1724 " \"previousblockhash\" : hash of current highest block\n"
1725 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1726 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1727 " \"time\" : timestamp appropriate for next block\n"
1728 " \"bits\" : compressed target of next block\n"
1729 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1731 if (params.size() == 0)
1734 throw JSONRPCError(-9, "Bitcoin is not connected!");
1736 if (IsInitialBlockDownload())
1737 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1739 static CReserveKey reservekey(pwalletMain);
1742 static unsigned int nTransactionsUpdatedLast;
1743 static CBlockIndex* pindexPrev;
1744 static int64 nStart;
1745 static CBlock* pblock;
1746 if (pindexPrev != pindexBest ||
1747 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1749 nTransactionsUpdatedLast = nTransactionsUpdated;
1750 pindexPrev = pindexBest;
1756 pblock = CreateNewBlock(reservekey);
1758 throw JSONRPCError(-7, "Out of memory");
1762 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1766 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1773 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1777 result.push_back(Pair("version", pblock->nVersion));
1778 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1779 result.push_back(Pair("transactions", transactions));
1780 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1781 result.push_back(Pair("time", (int64_t)pblock->nTime));
1787 uBits.nBits = htonl((int32_t)pblock->nBits);
1788 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1795 CDataStream ssBlock(ParseHex(params[0].get_str()));
1799 return ProcessBlock(NULL, &pblock);
1817 pair<string, rpcfn_type> pCallTable[] =
1819 make_pair("help", &help),
1820 make_pair("stop", &stop),
1821 make_pair("getblockcount", &getblockcount),
1822 make_pair("getblocknumber", &getblocknumber),
1823 make_pair("getconnectioncount", &getconnectioncount),
1824 make_pair("getdifficulty", &getdifficulty),
1825 make_pair("getgenerate", &getgenerate),
1826 make_pair("setgenerate", &setgenerate),
1827 make_pair("gethashespersec", &gethashespersec),
1828 make_pair("getinfo", &getinfo),
1829 make_pair("getnewaddress", &getnewaddress),
1830 make_pair("getaccountaddress", &getaccountaddress),
1831 make_pair("setaccount", &setaccount),
1832 make_pair("getaccount", &getaccount),
1833 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1834 make_pair("sendtoaddress", &sendtoaddress),
1835 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1836 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1837 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1838 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1839 make_pair("backupwallet", &backupwallet),
1840 make_pair("keypoolrefill", &keypoolrefill),
1841 make_pair("walletpassphrase", &walletpassphrase),
1842 make_pair("walletpassphrasechange", &walletpassphrasechange),
1843 make_pair("walletlock", &walletlock),
1844 make_pair("encryptwallet", &encryptwallet),
1845 make_pair("validateaddress", &validateaddress),
1846 make_pair("getbalance", &getbalance),
1847 make_pair("move", &movecmd),
1848 make_pair("sendfrom", &sendfrom),
1849 make_pair("sendmany", &sendmany),
1850 make_pair("gettransaction", &gettransaction),
1851 make_pair("listtransactions", &listtransactions),
1852 make_pair("signmessage", &signmessage),
1853 make_pair("verifymessage", &verifymessage),
1854 make_pair("getwork", &getwork),
1855 make_pair("listaccounts", &listaccounts),
1856 make_pair("settxfee", &settxfee),
1857 make_pair("getmemorypool", &getmemorypool),
1858 make_pair("listsinceblock", &listsinceblock),
1859 make_pair("dumpprivkey", &dumpprivkey),
1860 make_pair("importprivkey", &importprivkey)
1862 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1864 string pAllowInSafeMode[] =
1869 "getblocknumber", // deprecated
1870 "getconnectioncount",
1877 "getaccountaddress",
1879 "getaddressesbyaccount",
1888 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1896 // This ain't Apache. We're just using HTTP header for the length field
1897 // and to be compatible with other JSON-RPC implementations.
1900 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1903 s << "POST / HTTP/1.1\r\n"
1904 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1905 << "Host: 127.0.0.1\r\n"
1906 << "Content-Type: application/json\r\n"
1907 << "Content-Length: " << strMsg.size() << "\r\n"
1908 << "Connection: close\r\n"
1909 << "Accept: application/json\r\n";
1910 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1911 s << item.first << ": " << item.second << "\r\n";
1912 s << "\r\n" << strMsg;
1917 string rfc1123Time()
1922 struct tm* now_gmt = gmtime(&now);
1923 string locale(setlocale(LC_TIME, NULL));
1924 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1925 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1926 setlocale(LC_TIME, locale.c_str());
1927 return string(buffer);
1930 static string HTTPReply(int nStatus, const string& strMsg)
1933 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1935 "Server: bitcoin-json-rpc/%s\r\n"
1936 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1937 "Content-Type: text/html\r\n"
1938 "Content-Length: 296\r\n"
1940 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1941 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1944 "<TITLE>Error</TITLE>\r\n"
1945 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1947 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1948 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1949 const char *cStatus;
1950 if (nStatus == 200) cStatus = "OK";
1951 else if (nStatus == 400) cStatus = "Bad Request";
1952 else if (nStatus == 403) cStatus = "Forbidden";
1953 else if (nStatus == 404) cStatus = "Not Found";
1954 else if (nStatus == 500) cStatus = "Internal Server Error";
1957 "HTTP/1.1 %d %s\r\n"
1959 "Connection: close\r\n"
1960 "Content-Length: %d\r\n"
1961 "Content-Type: application/json\r\n"
1962 "Server: bitcoin-json-rpc/%s\r\n"
1967 rfc1123Time().c_str(),
1969 FormatFullVersion().c_str(),
1973 int ReadHTTPStatus(std::basic_istream<char>& stream)
1976 getline(stream, str);
1977 vector<string> vWords;
1978 boost::split(vWords, str, boost::is_any_of(" "));
1979 if (vWords.size() < 2)
1981 return atoi(vWords[1].c_str());
1984 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1990 std::getline(stream, str);
1991 if (str.empty() || str == "\r")
1993 string::size_type nColon = str.find(":");
1994 if (nColon != string::npos)
1996 string strHeader = str.substr(0, nColon);
1997 boost::trim(strHeader);
1998 boost::to_lower(strHeader);
1999 string strValue = str.substr(nColon+1);
2000 boost::trim(strValue);
2001 mapHeadersRet[strHeader] = strValue;
2002 if (strHeader == "content-length")
2003 nLen = atoi(strValue.c_str());
2009 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2011 mapHeadersRet.clear();
2015 int nStatus = ReadHTTPStatus(stream);
2018 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2019 if (nLen < 0 || nLen > MAX_SIZE)
2025 vector<char> vch(nLen);
2026 stream.read(&vch[0], nLen);
2027 strMessageRet = string(vch.begin(), vch.end());
2033 bool HTTPAuthorized(map<string, string>& mapHeaders)
2035 string strAuth = mapHeaders["authorization"];
2036 if (strAuth.substr(0,6) != "Basic ")
2038 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2039 string strUserPass = DecodeBase64(strUserPass64);
2040 return strUserPass == strRPCUserColonPass;
2044 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2045 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2046 // unspecified (HTTP errors and contents of 'error').
2048 // 1.0 spec: http://json-rpc.org/wiki/specification
2049 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2050 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2053 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2056 request.push_back(Pair("method", strMethod));
2057 request.push_back(Pair("params", params));
2058 request.push_back(Pair("id", id));
2059 return write_string(Value(request), false) + "\n";
2062 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2065 if (error.type() != null_type)
2066 reply.push_back(Pair("result", Value::null));
2068 reply.push_back(Pair("result", result));
2069 reply.push_back(Pair("error", error));
2070 reply.push_back(Pair("id", id));
2071 return write_string(Value(reply), false) + "\n";
2074 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2076 // Send error reply from json-rpc error object
2078 int code = find_value(objError, "code").get_int();
2079 if (code == -32600) nStatus = 400;
2080 else if (code == -32601) nStatus = 404;
2081 string strReply = JSONRPCReply(Value::null, objError, id);
2082 stream << HTTPReply(nStatus, strReply) << std::flush;
2085 bool ClientAllowed(const string& strAddress)
2087 if (strAddress == asio::ip::address_v4::loopback().to_string())
2089 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2090 BOOST_FOREACH(string strAllow, vAllow)
2091 if (WildcardMatch(strAddress, strAllow))
2098 // IOStream device that speaks SSL but can also speak non-SSL
2100 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2102 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2104 fUseSSL = fUseSSLIn;
2105 fNeedHandshake = fUseSSLIn;
2108 void handshake(ssl::stream_base::handshake_type role)
2110 if (!fNeedHandshake) return;
2111 fNeedHandshake = false;
2112 stream.handshake(role);
2114 std::streamsize read(char* s, std::streamsize n)
2116 handshake(ssl::stream_base::server); // HTTPS servers read first
2117 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2118 return stream.next_layer().read_some(asio::buffer(s, n));
2120 std::streamsize write(const char* s, std::streamsize n)
2122 handshake(ssl::stream_base::client); // HTTPS clients write first
2123 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2124 return asio::write(stream.next_layer(), asio::buffer(s, n));
2126 bool connect(const std::string& server, const std::string& port)
2128 ip::tcp::resolver resolver(stream.get_io_service());
2129 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2130 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2131 ip::tcp::resolver::iterator end;
2132 boost::system::error_code error = asio::error::host_not_found;
2133 while (error && endpoint_iterator != end)
2135 stream.lowest_layer().close();
2136 stream.lowest_layer().connect(*endpoint_iterator++, error);
2144 bool fNeedHandshake;
2150 void ThreadRPCServer(void* parg)
2152 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2155 vnThreadsRunning[4]++;
2156 ThreadRPCServer2(parg);
2157 vnThreadsRunning[4]--;
2159 catch (std::exception& e) {
2160 vnThreadsRunning[4]--;
2161 PrintException(&e, "ThreadRPCServer()");
2163 vnThreadsRunning[4]--;
2164 PrintException(NULL, "ThreadRPCServer()");
2166 printf("ThreadRPCServer exiting\n");
2169 void ThreadRPCServer2(void* parg)
2171 printf("ThreadRPCServer started\n");
2173 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2174 if (strRPCUserColonPass == ":")
2176 string strWhatAmI = "To use bitcoind";
2177 if (mapArgs.count("-server"))
2178 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2179 else if (mapArgs.count("-daemon"))
2180 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2182 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2183 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2185 GetConfigFile().c_str());
2187 CreateThread(Shutdown, NULL);
2192 bool fUseSSL = GetBoolArg("-rpcssl");
2193 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2195 asio::io_service io_service;
2196 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2197 ip::tcp::acceptor acceptor(io_service, endpoint);
2199 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2202 ssl::context context(io_service, ssl::context::sslv23);
2205 context.set_options(ssl::context::no_sslv2);
2206 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2207 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2208 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2209 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2210 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2211 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2212 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2213 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2215 string ciphers = GetArg("-rpcsslciphers",
2216 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2217 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2221 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2226 // Accept connection
2228 SSLStream sslStream(io_service, context);
2229 SSLIOStreamDevice d(sslStream, fUseSSL);
2230 iostreams::stream<SSLIOStreamDevice> stream(d);
2232 ip::tcp::iostream stream;
2235 ip::tcp::endpoint peer;
2236 vnThreadsRunning[4]--;
2238 acceptor.accept(sslStream.lowest_layer(), peer);
2240 acceptor.accept(*stream.rdbuf(), peer);
2242 vnThreadsRunning[4]++;
2246 // Restrict callers by IP
2247 if (!ClientAllowed(peer.address().to_string()))
2249 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2251 stream << HTTPReply(403, "") << std::flush;
2255 map<string, string> mapHeaders;
2258 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2259 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2262 printf("ThreadRPCServer ReadHTTP timeout\n");
2266 // Check authorization
2267 if (mapHeaders.count("authorization") == 0)
2269 stream << HTTPReply(401, "") << std::flush;
2272 if (!HTTPAuthorized(mapHeaders))
2274 // Deter brute-forcing short passwords
2275 if (mapArgs["-rpcpassword"].size() < 15)
2278 stream << HTTPReply(401, "") << std::flush;
2279 printf("ThreadRPCServer incorrect password attempt\n");
2283 Value id = Value::null;
2288 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2289 throw JSONRPCError(-32700, "Parse error");
2290 const Object& request = valRequest.get_obj();
2292 // Parse id now so errors from here on will have the id
2293 id = find_value(request, "id");
2296 Value valMethod = find_value(request, "method");
2297 if (valMethod.type() == null_type)
2298 throw JSONRPCError(-32600, "Missing method");
2299 if (valMethod.type() != str_type)
2300 throw JSONRPCError(-32600, "Method must be a string");
2301 string strMethod = valMethod.get_str();
2302 if (strMethod != "getwork" && strMethod != "getmemorypool")
2303 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2306 Value valParams = find_value(request, "params");
2308 if (valParams.type() == array_type)
2309 params = valParams.get_array();
2310 else if (valParams.type() == null_type)
2313 throw JSONRPCError(-32600, "Params must be an array");
2316 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2317 if (mi == mapCallTable.end())
2318 throw JSONRPCError(-32601, "Method not found");
2320 // Observe safe mode
2321 string strWarning = GetWarnings("rpc");
2322 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2323 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2329 CRITICAL_BLOCK(cs_main)
2330 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2331 result = (*(*mi).second)(params, false);
2334 string strReply = JSONRPCReply(result, Value::null, id);
2335 stream << HTTPReply(200, strReply) << std::flush;
2337 catch (std::exception& e)
2339 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2342 catch (Object& objError)
2344 ErrorReply(stream, objError, id);
2346 catch (std::exception& e)
2348 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2356 Object CallRPC(const string& strMethod, const Array& params)
2358 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2359 throw runtime_error(strprintf(
2360 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2361 "If the file does not exist, create it with owner-readable-only file permissions."),
2362 GetConfigFile().c_str()));
2364 // Connect to localhost
2365 bool fUseSSL = GetBoolArg("-rpcssl");
2367 asio::io_service io_service;
2368 ssl::context context(io_service, ssl::context::sslv23);
2369 context.set_options(ssl::context::no_sslv2);
2370 SSLStream sslStream(io_service, context);
2371 SSLIOStreamDevice d(sslStream, fUseSSL);
2372 iostreams::stream<SSLIOStreamDevice> stream(d);
2373 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2374 throw runtime_error("couldn't connect to server");
2377 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2379 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2381 throw runtime_error("couldn't connect to server");
2385 // HTTP basic authentication
2386 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2387 map<string, string> mapRequestHeaders;
2388 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2391 string strRequest = JSONRPCRequest(strMethod, params, 1);
2392 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2393 stream << strPost << std::flush;
2396 map<string, string> mapHeaders;
2398 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2400 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2401 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2402 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2403 else if (strReply.empty())
2404 throw runtime_error("no response from server");
2408 if (!read_string(strReply, valReply))
2409 throw runtime_error("couldn't parse reply from server");
2410 const Object& reply = valReply.get_obj();
2412 throw runtime_error("expected reply to have result, error and id properties");
2420 template<typename T>
2421 void ConvertTo(Value& value)
2423 if (value.type() == str_type)
2425 // reinterpret string as unquoted json value
2427 if (!read_string(value.get_str(), value2))
2428 throw runtime_error("type mismatch");
2429 value = value2.get_value<T>();
2433 value = value.get_value<T>();
2437 int CommandLineRPC(int argc, char *argv[])
2444 while (argc > 1 && IsSwitchChar(argv[1][0]))
2452 throw runtime_error("too few parameters");
2453 string strMethod = argv[1];
2455 // Parameters default to strings
2457 for (int i = 2; i < argc; i++)
2458 params.push_back(argv[i]);
2459 int n = params.size();
2462 // Special case non-string parameter types
2464 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2465 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2466 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2467 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2468 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2469 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2470 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2471 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2472 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2473 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2474 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2475 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2476 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2477 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2478 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2479 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2480 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2481 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2482 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2483 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2484 if (strMethod == "sendmany" && n > 1)
2486 string s = params[1].get_str();
2488 if (!read_string(s, v) || v.type() != obj_type)
2489 throw runtime_error("type mismatch");
2490 params[1] = v.get_obj();
2492 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2495 Object reply = CallRPC(strMethod, params);
2498 const Value& result = find_value(reply, "result");
2499 const Value& error = find_value(reply, "error");
2501 if (error.type() != null_type)
2504 strPrint = "error: " + write_string(error, false);
2505 int code = find_value(error.get_obj(), "code").get_int();
2511 if (result.type() == null_type)
2513 else if (result.type() == str_type)
2514 strPrint = result.get_str();
2516 strPrint = write_string(result, true);
2519 catch (std::exception& e)
2521 strPrint = string("error: ") + e.what();
2526 PrintException(NULL, "CommandLineRPC()");
2531 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2540 int main(int argc, char *argv[])
2543 // Turn off microsoft heap dump noise
2544 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2545 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2547 setbuf(stdin, NULL);
2548 setbuf(stdout, NULL);
2549 setbuf(stderr, NULL);
2553 if (argc >= 2 && string(argv[1]) == "-server")
2555 printf("server ready\n");
2556 ThreadRPCServer(NULL);
2560 return CommandLineRPC(argc, argv);
2563 catch (std::exception& e) {
2564 PrintException(&e, "main()");
2566 PrintException(NULL, "main()");