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);
75 double GetDifficulty(const CBlockIndex* blockindex = NULL)
77 // Floating point number that is a multiple of the minimum difficulty,
78 // minimum difficulty = 1.0.
79 if (blockindex == NULL)
81 if (pindexBest == NULL)
84 blockindex = pindexBest;
87 int nShift = (blockindex->nBits >> 24) & 0xff;
90 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
107 int64 AmountFromValue(const Value& value)
109 double dAmount = value.get_real();
110 if (dAmount <= 0.0 || dAmount > 21000000.0)
111 throw JSONRPCError(-3, "Invalid amount");
112 int64 nAmount = roundint64(dAmount * COIN);
113 if (!MoneyRange(nAmount))
114 throw JSONRPCError(-3, "Invalid amount");
118 Value ValueFromAmount(int64 amount)
120 return (double)amount / (double)COIN;
123 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
125 int confirms = wtx.GetDepthInMainChain();
126 entry.push_back(Pair("confirmations", confirms));
129 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
130 entry.push_back(Pair("blockindex", wtx.nIndex));
132 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
133 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
134 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
135 entry.push_back(Pair(item.first, item.second));
138 string AccountFromValue(const Value& value)
140 string strAccount = value.get_str();
141 if (strAccount == "*")
142 throw JSONRPCError(-11, "Invalid account name");
146 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
149 result.push_back(Pair("hash", block.GetHash().GetHex()));
150 result.push_back(Pair("blockcount", blockindex->nHeight));
151 result.push_back(Pair("version", block.nVersion));
152 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
153 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
154 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
155 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
157 BOOST_FOREACH (const CTransaction&tx, block.vtx)
158 txhashes.push_back(tx.GetHash().GetHex());
159 result.push_back(Pair("tx", txhashes));
161 if (blockindex->pprev)
162 result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex()));
163 if (blockindex->pnext)
164 result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex()));
171 /// Note: This interface may still be subject to change.
175 Value help(const Array& params, bool fHelp)
177 if (fHelp || params.size() > 1)
180 "List commands, or get help for a command.");
183 if (params.size() > 0)
184 strCommand = params[0].get_str();
187 set<rpcfn_type> setDone;
188 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
190 string strMethod = (*mi).first;
191 // We already filter duplicates, but these deprecated screw up the sort order
192 if (strMethod == "getamountreceived" ||
193 strMethod == "getallreceived" ||
194 strMethod == "getblocknumber" || // deprecated
195 (strMethod.find("label") != string::npos))
197 if (strCommand != "" && strMethod != strCommand)
202 rpcfn_type pfn = (*mi).second;
203 if (setDone.insert(pfn).second)
204 (*pfn)(params, true);
206 catch (std::exception& e)
208 // Help text is returned in an exception
209 string strHelp = string(e.what());
210 if (strCommand == "")
211 if (strHelp.find('\n') != -1)
212 strHelp = strHelp.substr(0, strHelp.find('\n'));
213 strRet += strHelp + "\n";
217 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
218 strRet = strRet.substr(0,strRet.size()-1);
223 Value stop(const Array& params, bool fHelp)
225 if (fHelp || params.size() != 0)
228 "Stop bitcoin server.");
230 // Shutdown will take long enough that the response should get back
231 CreateThread(Shutdown, NULL);
232 return "bitcoin server stopping";
234 throw runtime_error("NYI: cannot shut down GUI with RPC command");
239 Value getblockcount(const Array& params, bool fHelp)
241 if (fHelp || params.size() != 0)
244 "Returns the number of blocks in the longest block chain.");
251 Value getblocknumber(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Deprecated. Use getblockcount.");
262 Value getconnectioncount(const Array& params, bool fHelp)
264 if (fHelp || params.size() != 0)
266 "getconnectioncount\n"
267 "Returns the number of connections to other nodes.");
269 return (int)vNodes.size();
273 Value getdifficulty(const Array& params, bool fHelp)
275 if (fHelp || params.size() != 0)
278 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
280 return GetDifficulty();
284 Value getgenerate(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns true or false.");
291 return (bool)fGenerateBitcoins;
295 Value setgenerate(const Array& params, bool fHelp)
297 if (fHelp || params.size() < 1 || params.size() > 2)
299 "setgenerate <generate> [genproclimit]\n"
300 "<generate> is true or false to turn generation on or off.\n"
301 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
303 bool fGenerate = true;
304 if (params.size() > 0)
305 fGenerate = params[0].get_bool();
307 if (params.size() > 1)
309 int nGenProcLimit = params[1].get_int();
310 fLimitProcessors = (nGenProcLimit != -1);
311 WriteSetting("fLimitProcessors", fLimitProcessors);
312 if (nGenProcLimit != -1)
313 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
314 if (nGenProcLimit == 0)
318 GenerateBitcoins(fGenerate, pwalletMain);
323 Value gethashespersec(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 0)
328 "Returns a recent hashes per second performance measurement while generating.");
330 if (GetTimeMillis() - nHPSTimerStart > 8000)
331 return (boost::int64_t)0;
332 return (boost::int64_t)dHashesPerSec;
336 Value getinfo(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 0)
341 "Returns an object containing various state info.");
344 obj.push_back(Pair("version", (int)CLIENT_VERSION));
345 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
346 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
347 obj.push_back(Pair("blocks", (int)nBestHeight));
348 obj.push_back(Pair("connections", (int)vNodes.size()));
349 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
350 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
351 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
352 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
353 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
354 obj.push_back(Pair("testnet", fTestNet));
355 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
356 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
357 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
358 if (pwalletMain->IsCrypted())
359 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
360 obj.push_back(Pair("errors", GetWarnings("statusbar")));
365 Value getnewaddress(const Array& params, bool fHelp)
367 if (fHelp || params.size() > 1)
369 "getnewaddress [account]\n"
370 "Returns a new bitcoin address for receiving payments. "
371 "If [account] is specified (recommended), it is added to the address book "
372 "so payments received with the address will be credited to [account].");
374 // Parse the account first so we don't generate a key if there's an error
376 if (params.size() > 0)
377 strAccount = AccountFromValue(params[0]);
379 if (!pwalletMain->IsLocked())
380 pwalletMain->TopUpKeyPool();
382 // Generate a new key that is added to wallet
383 std::vector<unsigned char> newKey;
384 if (!pwalletMain->GetKeyFromPool(newKey, false))
385 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
386 CBitcoinAddress address(newKey);
388 pwalletMain->SetAddressBookName(address, strAccount);
390 return address.ToString();
394 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
396 CWalletDB walletdb(pwalletMain->strWalletFile);
399 walletdb.ReadAccount(strAccount, account);
401 bool bKeyUsed = false;
403 // Check if the current key has been used
404 if (!account.vchPubKey.empty())
406 CScript scriptPubKey;
407 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
408 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
409 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
412 const CWalletTx& wtx = (*it).second;
413 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
414 if (txout.scriptPubKey == scriptPubKey)
419 // Generate a new key
420 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
422 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
423 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
425 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
426 walletdb.WriteAccount(strAccount, account);
429 return CBitcoinAddress(account.vchPubKey);
432 Value getaccountaddress(const Array& params, bool fHelp)
434 if (fHelp || params.size() != 1)
436 "getaccountaddress <account>\n"
437 "Returns the current bitcoin address for receiving payments to this account.");
439 // Parse the account first so we don't generate a key if there's an error
440 string strAccount = AccountFromValue(params[0]);
444 ret = GetAccountAddress(strAccount).ToString();
451 Value setaccount(const Array& params, bool fHelp)
453 if (fHelp || params.size() < 1 || params.size() > 2)
455 "setaccount <bitcoinaddress> <account>\n"
456 "Sets the account associated with the given address.");
458 CBitcoinAddress address(params[0].get_str());
459 if (!address.IsValid())
460 throw JSONRPCError(-5, "Invalid bitcoin address");
464 if (params.size() > 1)
465 strAccount = AccountFromValue(params[1]);
467 // Detect when changing the account of an address that is the 'unused current key' of another account:
468 if (pwalletMain->mapAddressBook.count(address))
470 string strOldAccount = pwalletMain->mapAddressBook[address];
471 if (address == GetAccountAddress(strOldAccount))
472 GetAccountAddress(strOldAccount, true);
475 pwalletMain->SetAddressBookName(address, strAccount);
481 Value getaccount(const Array& params, bool fHelp)
483 if (fHelp || params.size() != 1)
485 "getaccount <bitcoinaddress>\n"
486 "Returns the account associated with the given address.");
488 CBitcoinAddress address(params[0].get_str());
489 if (!address.IsValid())
490 throw JSONRPCError(-5, "Invalid bitcoin address");
493 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
494 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
495 strAccount = (*mi).second;
500 Value getaddressesbyaccount(const Array& params, bool fHelp)
502 if (fHelp || params.size() != 1)
504 "getaddressesbyaccount <account>\n"
505 "Returns the list of addresses for the given account.");
507 string strAccount = AccountFromValue(params[0]);
509 // Find all addresses that have the given account
511 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
513 const CBitcoinAddress& address = item.first;
514 const string& strName = item.second;
515 if (strName == strAccount)
516 ret.push_back(address.ToString());
521 Value settxfee(const Array& params, bool fHelp)
523 if (fHelp || params.size() < 1 || params.size() > 1)
525 "settxfee <amount>\n"
526 "<amount> is a real and is rounded to the nearest 0.00000001");
530 if (params[0].get_real() != 0.0)
531 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
533 nTransactionFee = nAmount;
537 Value sendtoaddress(const Array& params, bool fHelp)
539 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
541 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
542 "<amount> is a real and is rounded to the nearest 0.00000001\n"
543 "requires wallet passphrase to be set with walletpassphrase first");
544 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
546 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
547 "<amount> is a real and is rounded to the nearest 0.00000001");
549 CBitcoinAddress address(params[0].get_str());
550 if (!address.IsValid())
551 throw JSONRPCError(-5, "Invalid bitcoin address");
554 int64 nAmount = AmountFromValue(params[1]);
558 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
559 wtx.mapValue["comment"] = params[2].get_str();
560 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
561 wtx.mapValue["to"] = params[3].get_str();
563 if (pwalletMain->IsLocked())
564 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
566 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
568 throw JSONRPCError(-4, strError);
570 return wtx.GetHash().GetHex();
573 static const string strMessageMagic = "Bitcoin Signed Message:\n";
575 Value signmessage(const Array& params, bool fHelp)
577 if (fHelp || params.size() != 2)
579 "signmessage <bitcoinaddress> <message>\n"
580 "Sign a message with the private key of an address");
582 if (pwalletMain->IsLocked())
583 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
585 string strAddress = params[0].get_str();
586 string strMessage = params[1].get_str();
588 CBitcoinAddress addr(strAddress);
590 throw JSONRPCError(-3, "Invalid address");
593 if (!pwalletMain->GetKey(addr, key))
594 throw JSONRPCError(-4, "Private key not available");
596 CDataStream ss(SER_GETHASH);
597 ss << strMessageMagic;
600 vector<unsigned char> vchSig;
601 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
602 throw JSONRPCError(-5, "Sign failed");
604 return EncodeBase64(&vchSig[0], vchSig.size());
607 Value verifymessage(const Array& params, bool fHelp)
609 if (fHelp || params.size() != 3)
611 "verifymessage <bitcoinaddress> <signature> <message>\n"
612 "Verify a signed message");
614 string strAddress = params[0].get_str();
615 string strSign = params[1].get_str();
616 string strMessage = params[2].get_str();
618 CBitcoinAddress addr(strAddress);
620 throw JSONRPCError(-3, "Invalid address");
622 bool fInvalid = false;
623 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
626 throw JSONRPCError(-5, "Malformed base64 encoding");
628 CDataStream ss(SER_GETHASH);
629 ss << strMessageMagic;
633 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
636 return (CBitcoinAddress(key.GetPubKey()) == addr);
640 Value getreceivedbyaddress(const Array& params, bool fHelp)
642 if (fHelp || params.size() < 1 || params.size() > 2)
644 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
645 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
648 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
649 CScript scriptPubKey;
650 if (!address.IsValid())
651 throw JSONRPCError(-5, "Invalid bitcoin address");
652 scriptPubKey.SetBitcoinAddress(address);
653 if (!IsMine(*pwalletMain,scriptPubKey))
656 // Minimum confirmations
658 if (params.size() > 1)
659 nMinDepth = params[1].get_int();
663 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
665 const CWalletTx& wtx = (*it).second;
666 if (wtx.IsCoinBase() || !wtx.IsFinal())
669 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
670 if (txout.scriptPubKey == scriptPubKey)
671 if (wtx.GetDepthInMainChain() >= nMinDepth)
672 nAmount += txout.nValue;
675 return ValueFromAmount(nAmount);
679 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
681 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
683 const CBitcoinAddress& address = item.first;
684 const string& strName = item.second;
685 if (strName == strAccount)
686 setAddress.insert(address);
691 Value getreceivedbyaccount(const Array& params, bool fHelp)
693 if (fHelp || params.size() < 1 || params.size() > 2)
695 "getreceivedbyaccount <account> [minconf=1]\n"
696 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
698 // Minimum confirmations
700 if (params.size() > 1)
701 nMinDepth = params[1].get_int();
703 // Get the set of pub keys assigned to account
704 string strAccount = AccountFromValue(params[0]);
705 set<CBitcoinAddress> setAddress;
706 GetAccountAddresses(strAccount, setAddress);
710 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
712 const CWalletTx& wtx = (*it).second;
713 if (wtx.IsCoinBase() || !wtx.IsFinal())
716 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
718 CBitcoinAddress address;
719 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
720 if (wtx.GetDepthInMainChain() >= nMinDepth)
721 nAmount += txout.nValue;
725 return (double)nAmount / (double)COIN;
729 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
733 // Tally wallet transactions
734 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
736 const CWalletTx& wtx = (*it).second;
740 int64 nGenerated, nReceived, nSent, nFee;
741 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
743 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
744 nBalance += nReceived;
745 nBalance += nGenerated - nSent - nFee;
748 // Tally internal accounting entries
749 nBalance += walletdb.GetAccountCreditDebit(strAccount);
754 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
756 CWalletDB walletdb(pwalletMain->strWalletFile);
757 return GetAccountBalance(walletdb, strAccount, nMinDepth);
761 Value getbalance(const Array& params, bool fHelp)
763 if (fHelp || params.size() > 2)
765 "getbalance [account] [minconf=1]\n"
766 "If [account] is not specified, returns the server's total available balance.\n"
767 "If [account] is specified, returns the balance in the account.");
769 if (params.size() == 0)
770 return ValueFromAmount(pwalletMain->GetBalance());
773 if (params.size() > 1)
774 nMinDepth = params[1].get_int();
776 if (params[0].get_str() == "*") {
777 // Calculate total balance a different way from GetBalance()
778 // (GetBalance() sums up all unspent TxOuts)
779 // getbalance and getbalance '*' should always return the same number.
781 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
783 const CWalletTx& wtx = (*it).second;
787 int64 allGeneratedImmature, allGeneratedMature, allFee;
788 allGeneratedImmature = allGeneratedMature = allFee = 0;
789 string strSentAccount;
790 list<pair<CBitcoinAddress, int64> > listReceived;
791 list<pair<CBitcoinAddress, int64> > listSent;
792 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
793 if (wtx.GetDepthInMainChain() >= nMinDepth)
794 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
795 nBalance += r.second;
796 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
797 nBalance -= r.second;
799 nBalance += allGeneratedMature;
801 return ValueFromAmount(nBalance);
804 string strAccount = AccountFromValue(params[0]);
806 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
808 return ValueFromAmount(nBalance);
812 Value movecmd(const Array& params, bool fHelp)
814 if (fHelp || params.size() < 3 || params.size() > 5)
816 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
817 "Move from one account in your wallet to another.");
819 string strFrom = AccountFromValue(params[0]);
820 string strTo = AccountFromValue(params[1]);
821 int64 nAmount = AmountFromValue(params[2]);
822 if (params.size() > 3)
823 // unused parameter, used to be nMinDepth, keep type-checking it though
824 (void)params[3].get_int();
826 if (params.size() > 4)
827 strComment = params[4].get_str();
829 CWalletDB walletdb(pwalletMain->strWalletFile);
832 int64 nNow = GetAdjustedTime();
835 CAccountingEntry debit;
836 debit.strAccount = strFrom;
837 debit.nCreditDebit = -nAmount;
839 debit.strOtherAccount = strTo;
840 debit.strComment = strComment;
841 walletdb.WriteAccountingEntry(debit);
844 CAccountingEntry credit;
845 credit.strAccount = strTo;
846 credit.nCreditDebit = nAmount;
848 credit.strOtherAccount = strFrom;
849 credit.strComment = strComment;
850 walletdb.WriteAccountingEntry(credit);
852 walletdb.TxnCommit();
858 Value sendfrom(const Array& params, bool fHelp)
860 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
862 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
863 "<amount> is a real and is rounded to the nearest 0.00000001\n"
864 "requires wallet passphrase to be set with walletpassphrase first");
865 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
867 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
868 "<amount> is a real and is rounded to the nearest 0.00000001");
870 string strAccount = AccountFromValue(params[0]);
871 CBitcoinAddress address(params[1].get_str());
872 if (!address.IsValid())
873 throw JSONRPCError(-5, "Invalid bitcoin address");
874 int64 nAmount = AmountFromValue(params[2]);
876 if (params.size() > 3)
877 nMinDepth = params[3].get_int();
880 wtx.strFromAccount = strAccount;
881 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
882 wtx.mapValue["comment"] = params[4].get_str();
883 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
884 wtx.mapValue["to"] = params[5].get_str();
886 if (pwalletMain->IsLocked())
887 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
890 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
891 if (nAmount > nBalance)
892 throw JSONRPCError(-6, "Account has insufficient funds");
895 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
897 throw JSONRPCError(-4, strError);
899 return wtx.GetHash().GetHex();
903 Value sendmany(const Array& params, bool fHelp)
905 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
907 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
908 "amounts are double-precision floating point numbers\n"
909 "requires wallet passphrase to be set with walletpassphrase first");
910 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
912 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
913 "amounts are double-precision floating point numbers");
915 string strAccount = AccountFromValue(params[0]);
916 Object sendTo = params[1].get_obj();
918 if (params.size() > 2)
919 nMinDepth = params[2].get_int();
922 wtx.strFromAccount = strAccount;
923 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
924 wtx.mapValue["comment"] = params[3].get_str();
926 set<CBitcoinAddress> setAddress;
927 vector<pair<CScript, int64> > vecSend;
929 int64 totalAmount = 0;
930 BOOST_FOREACH(const Pair& s, sendTo)
932 CBitcoinAddress address(s.name_);
933 if (!address.IsValid())
934 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
936 if (setAddress.count(address))
937 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
938 setAddress.insert(address);
940 CScript scriptPubKey;
941 scriptPubKey.SetBitcoinAddress(address);
942 int64 nAmount = AmountFromValue(s.value_);
943 totalAmount += nAmount;
945 vecSend.push_back(make_pair(scriptPubKey, nAmount));
948 if (pwalletMain->IsLocked())
949 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
952 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
953 if (totalAmount > nBalance)
954 throw JSONRPCError(-6, "Account has insufficient funds");
957 CReserveKey keyChange(pwalletMain);
958 int64 nFeeRequired = 0;
959 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
962 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
963 throw JSONRPCError(-6, "Insufficient funds");
964 throw JSONRPCError(-4, "Transaction creation failed");
966 if (!pwalletMain->CommitTransaction(wtx, keyChange))
967 throw JSONRPCError(-4, "Transaction commit failed");
969 return wtx.GetHash().GetHex();
972 Value addmultisigaddress(const Array& params, bool fHelp)
974 if (fHelp || params.size() < 2 || params.size() > 3)
976 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
977 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
978 "each key is a bitcoin address, hex or base58 public key\n"
979 "If [account] is specified, assign address to [account].";
980 throw runtime_error(msg);
983 throw runtime_error("addmultisigaddress available only when running -testnet\n");
985 int nRequired = params[0].get_int();
986 const Array& keys = params[1].get_array();
988 if (params.size() > 2)
989 strAccount = AccountFromValue(params[2]);
991 // Gather public keys
992 if (keys.size() < nRequired)
994 strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
995 std::vector<CKey> pubkeys;
996 pubkeys.resize(keys.size());
997 for (int i = 0; i < keys.size(); i++)
999 const std::string& ks = keys[i].get_str();
1000 if (ks.size() == 130) // hex public key
1001 pubkeys[i].SetPubKey(ParseHex(ks));
1002 else if (ks.size() > 34) // base58-encoded
1004 std::vector<unsigned char> vchPubKey;
1005 if (DecodeBase58(ks, vchPubKey))
1006 pubkeys[i].SetPubKey(vchPubKey);
1008 throw runtime_error("Error base58 decoding key: "+ks);
1010 else // bitcoin address for key in this wallet
1012 CBitcoinAddress address(ks);
1013 if (!pwalletMain->GetKey(address, pubkeys[i]))
1014 throw runtime_error(
1015 strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
1019 // Construct using OP_EVAL
1021 inner.SetMultisig(nRequired, pubkeys);
1023 uint160 scriptHash = Hash160(inner);
1024 CScript scriptPubKey;
1025 scriptPubKey.SetEval(inner);
1026 pwalletMain->AddCScript(scriptHash, inner);
1027 CBitcoinAddress address;
1028 address.SetScriptHash160(scriptHash);
1030 pwalletMain->SetAddressBookName(address, strAccount);
1031 return address.ToString();
1042 nConf = std::numeric_limits<int>::max();
1046 Value ListReceived(const Array& params, bool fByAccounts)
1048 // Minimum confirmations
1050 if (params.size() > 0)
1051 nMinDepth = params[0].get_int();
1053 // Whether to include empty accounts
1054 bool fIncludeEmpty = false;
1055 if (params.size() > 1)
1056 fIncludeEmpty = params[1].get_bool();
1059 map<CBitcoinAddress, tallyitem> mapTally;
1060 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1062 const CWalletTx& wtx = (*it).second;
1064 if (wtx.IsCoinBase() || !wtx.IsFinal())
1067 int nDepth = wtx.GetDepthInMainChain();
1068 if (nDepth < nMinDepth)
1071 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1073 CBitcoinAddress address;
1074 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1077 tallyitem& item = mapTally[address];
1078 item.nAmount += txout.nValue;
1079 item.nConf = min(item.nConf, nDepth);
1085 map<string, tallyitem> mapAccountTally;
1086 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1088 const CBitcoinAddress& address = item.first;
1089 const string& strAccount = item.second;
1090 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1091 if (it == mapTally.end() && !fIncludeEmpty)
1095 int nConf = std::numeric_limits<int>::max();
1096 if (it != mapTally.end())
1098 nAmount = (*it).second.nAmount;
1099 nConf = (*it).second.nConf;
1104 tallyitem& item = mapAccountTally[strAccount];
1105 item.nAmount += nAmount;
1106 item.nConf = min(item.nConf, nConf);
1111 obj.push_back(Pair("address", address.ToString()));
1112 obj.push_back(Pair("account", strAccount));
1113 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1114 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1121 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1123 int64 nAmount = (*it).second.nAmount;
1124 int nConf = (*it).second.nConf;
1126 obj.push_back(Pair("account", (*it).first));
1127 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1128 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1136 Value listreceivedbyaddress(const Array& params, bool fHelp)
1138 if (fHelp || params.size() > 2)
1139 throw runtime_error(
1140 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1141 "[minconf] is the minimum number of confirmations before payments are included.\n"
1142 "[includeempty] whether to include addresses that haven't received any payments.\n"
1143 "Returns an array of objects containing:\n"
1144 " \"address\" : receiving address\n"
1145 " \"account\" : the account of the receiving address\n"
1146 " \"amount\" : total amount received by the address\n"
1147 " \"confirmations\" : number of confirmations of the most recent transaction included");
1149 return ListReceived(params, false);
1152 Value listreceivedbyaccount(const Array& params, bool fHelp)
1154 if (fHelp || params.size() > 2)
1155 throw runtime_error(
1156 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1157 "[minconf] is the minimum number of confirmations before payments are included.\n"
1158 "[includeempty] whether to include accounts that haven't received any payments.\n"
1159 "Returns an array of objects containing:\n"
1160 " \"account\" : the account of the receiving addresses\n"
1161 " \"amount\" : total amount received by addresses with this account\n"
1162 " \"confirmations\" : number of confirmations of the most recent transaction included");
1164 return ListReceived(params, true);
1167 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1169 int64 nGeneratedImmature, nGeneratedMature, nFee;
1170 string strSentAccount;
1171 list<pair<CBitcoinAddress, int64> > listReceived;
1172 list<pair<CBitcoinAddress, int64> > listSent;
1174 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1176 bool fAllAccounts = (strAccount == string("*"));
1178 // Generated blocks assigned to account ""
1179 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1182 entry.push_back(Pair("account", string("")));
1183 if (nGeneratedImmature)
1185 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1186 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1190 entry.push_back(Pair("category", "generate"));
1191 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1194 WalletTxToJSON(wtx, entry);
1195 ret.push_back(entry);
1199 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1201 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1204 entry.push_back(Pair("account", strSentAccount));
1205 entry.push_back(Pair("address", s.first.ToString()));
1206 entry.push_back(Pair("category", "send"));
1207 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1208 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1210 WalletTxToJSON(wtx, entry);
1211 ret.push_back(entry);
1216 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1217 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1220 if (pwalletMain->mapAddressBook.count(r.first))
1221 account = pwalletMain->mapAddressBook[r.first];
1222 if (fAllAccounts || (account == strAccount))
1225 entry.push_back(Pair("account", account));
1226 entry.push_back(Pair("address", r.first.ToString()));
1227 entry.push_back(Pair("category", "receive"));
1228 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1230 WalletTxToJSON(wtx, entry);
1231 ret.push_back(entry);
1236 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1238 bool fAllAccounts = (strAccount == string("*"));
1240 if (fAllAccounts || acentry.strAccount == strAccount)
1243 entry.push_back(Pair("account", acentry.strAccount));
1244 entry.push_back(Pair("category", "move"));
1245 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1246 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1247 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1248 entry.push_back(Pair("comment", acentry.strComment));
1249 ret.push_back(entry);
1253 Value listtransactions(const Array& params, bool fHelp)
1255 if (fHelp || params.size() > 3)
1256 throw runtime_error(
1257 "listtransactions [account] [count=10] [from=0]\n"
1258 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1260 string strAccount = "*";
1261 if (params.size() > 0)
1262 strAccount = params[0].get_str();
1264 if (params.size() > 1)
1265 nCount = params[1].get_int();
1267 if (params.size() > 2)
1268 nFrom = params[2].get_int();
1271 CWalletDB walletdb(pwalletMain->strWalletFile);
1273 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1274 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1275 typedef multimap<int64, TxPair > TxItems;
1278 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1280 CWalletTx* wtx = &((*it).second);
1281 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1283 list<CAccountingEntry> acentries;
1284 walletdb.ListAccountCreditDebit(strAccount, acentries);
1285 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1287 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1290 // Now: iterate backwards until we have nCount items to return:
1291 TxItems::reverse_iterator it = txByTime.rbegin();
1292 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1293 for (; it != txByTime.rend(); ++it)
1295 CWalletTx *const pwtx = (*it).second.first;
1297 ListTransactions(*pwtx, strAccount, 0, true, ret);
1298 CAccountingEntry *const pacentry = (*it).second.second;
1300 AcentryToJSON(*pacentry, strAccount, ret);
1302 if (ret.size() >= nCount) break;
1304 // ret is now newest to oldest
1306 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1307 if (ret.size() > nCount)
1309 Array::iterator last = ret.begin();
1310 std::advance(last, nCount);
1311 ret.erase(last, ret.end());
1313 std::reverse(ret.begin(), ret.end()); // oldest to newest
1318 Value listaccounts(const Array& params, bool fHelp)
1320 if (fHelp || params.size() > 1)
1321 throw runtime_error(
1322 "listaccounts [minconf=1]\n"
1323 "Returns Object that has account names as keys, account balances as values.");
1326 if (params.size() > 0)
1327 nMinDepth = params[0].get_int();
1329 map<string, int64> mapAccountBalances;
1330 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1331 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1332 mapAccountBalances[entry.second] = 0;
1335 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1337 const CWalletTx& wtx = (*it).second;
1338 int64 nGeneratedImmature, nGeneratedMature, nFee;
1339 string strSentAccount;
1340 list<pair<CBitcoinAddress, int64> > listReceived;
1341 list<pair<CBitcoinAddress, int64> > listSent;
1342 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1343 mapAccountBalances[strSentAccount] -= nFee;
1344 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1345 mapAccountBalances[strSentAccount] -= s.second;
1346 if (wtx.GetDepthInMainChain() >= nMinDepth)
1348 mapAccountBalances[""] += nGeneratedMature;
1349 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1350 if (pwalletMain->mapAddressBook.count(r.first))
1351 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1353 mapAccountBalances[""] += r.second;
1357 list<CAccountingEntry> acentries;
1358 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1359 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1360 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1363 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1364 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1369 Value listsinceblock(const Array& params, bool fHelp)
1372 throw runtime_error(
1373 "listsinceblock [blockid] [target-confirmations]\n"
1374 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1376 CBlockIndex *pindex = NULL;
1377 int target_confirms = 1;
1379 if (params.size() > 0)
1381 uint256 blockId = 0;
1383 blockId.SetHex(params[0].get_str());
1384 pindex = CBlockLocator(blockId).GetBlockIndex();
1387 if (params.size() > 1)
1389 target_confirms = params[1].get_int();
1391 if (target_confirms < 1)
1392 throw JSONRPCError(-8, "Invalid parameter");
1395 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1399 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1401 CWalletTx tx = (*it).second;
1403 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1404 ListTransactions(tx, "*", 0, true, transactions);
1409 if (target_confirms == 1)
1412 lastblock = hashBestChain;
1416 int target_height = pindexBest->nHeight + 1 - target_confirms;
1419 for (block = pindexBest;
1420 block && block->nHeight > target_height;
1421 block = block->pprev);
1423 lastblock = block ? block->GetBlockHash() : 0;
1427 ret.push_back(Pair("transactions", transactions));
1428 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1433 Value gettransaction(const Array& params, bool fHelp)
1435 if (fHelp || params.size() != 1)
1436 throw runtime_error(
1437 "gettransaction <txid>\n"
1438 "Get detailed information about <txid>");
1441 hash.SetHex(params[0].get_str());
1445 if (!pwalletMain->mapWallet.count(hash))
1446 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1447 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1449 int64 nCredit = wtx.GetCredit();
1450 int64 nDebit = wtx.GetDebit();
1451 int64 nNet = nCredit - nDebit;
1452 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1454 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1456 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1458 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1461 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1462 entry.push_back(Pair("details", details));
1468 Value backupwallet(const Array& params, bool fHelp)
1470 if (fHelp || params.size() != 1)
1471 throw runtime_error(
1472 "backupwallet <destination>\n"
1473 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1475 string strDest = params[0].get_str();
1476 BackupWallet(*pwalletMain, strDest);
1482 Value keypoolrefill(const Array& params, bool fHelp)
1484 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1485 throw runtime_error(
1487 "Fills the keypool, requires wallet passphrase to be set.");
1488 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1489 throw runtime_error(
1491 "Fills the keypool.");
1493 if (pwalletMain->IsLocked())
1494 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1496 pwalletMain->TopUpKeyPool();
1498 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1499 throw JSONRPCError(-4, "Error refreshing keypool.");
1505 void ThreadTopUpKeyPool(void* parg)
1507 pwalletMain->TopUpKeyPool();
1510 void ThreadCleanWalletPassphrase(void* parg)
1512 int64 nMyWakeTime = GetTime() + *((int*)parg);
1514 if (nWalletUnlockTime == 0)
1516 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1518 nWalletUnlockTime = nMyWakeTime;
1521 while (GetTime() < nWalletUnlockTime)
1522 Sleep(GetTime() - nWalletUnlockTime);
1524 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1526 nWalletUnlockTime = 0;
1531 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1533 if (nWalletUnlockTime < nMyWakeTime)
1534 nWalletUnlockTime = nMyWakeTime;
1540 pwalletMain->Lock();
1545 Value walletpassphrase(const Array& params, bool fHelp)
1547 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1548 throw runtime_error(
1549 "walletpassphrase <passphrase> <timeout>\n"
1550 "Stores the wallet decryption key in memory for <timeout> seconds.");
1553 if (!pwalletMain->IsCrypted())
1554 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1556 if (!pwalletMain->IsLocked())
1557 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1559 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1560 SecureString strWalletPass;
1561 strWalletPass.reserve(100);
1562 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1563 // Alternately, find a way to make params[0] mlock()'d to begin with.
1564 strWalletPass = params[0].get_str().c_str();
1566 if (strWalletPass.length() > 0)
1568 if (!pwalletMain->Unlock(strWalletPass))
1569 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1572 throw runtime_error(
1573 "walletpassphrase <passphrase> <timeout>\n"
1574 "Stores the wallet decryption key in memory for <timeout> seconds.");
1576 CreateThread(ThreadTopUpKeyPool, NULL);
1577 int* pnSleepTime = new int(params[1].get_int());
1578 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1584 Value walletpassphrasechange(const Array& params, bool fHelp)
1586 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1587 throw runtime_error(
1588 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1589 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1592 if (!pwalletMain->IsCrypted())
1593 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1595 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1596 // Alternately, find a way to make params[0] mlock()'d to begin with.
1597 SecureString strOldWalletPass;
1598 strOldWalletPass.reserve(100);
1599 strOldWalletPass = params[0].get_str().c_str();
1601 SecureString strNewWalletPass;
1602 strNewWalletPass.reserve(100);
1603 strNewWalletPass = params[1].get_str().c_str();
1605 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1606 throw runtime_error(
1607 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1608 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1610 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1611 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1617 Value walletlock(const Array& params, bool fHelp)
1619 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1620 throw runtime_error(
1622 "Removes the wallet encryption key from memory, locking the wallet.\n"
1623 "After calling this method, you will need to call walletpassphrase again\n"
1624 "before being able to call any methods which require the wallet to be unlocked.");
1627 if (!pwalletMain->IsCrypted())
1628 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1630 pwalletMain->Lock();
1631 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1633 nWalletUnlockTime = 0;
1640 Value encryptwallet(const Array& params, bool fHelp)
1642 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1643 throw runtime_error(
1644 "encryptwallet <passphrase>\n"
1645 "Encrypts the wallet with <passphrase>.");
1648 if (pwalletMain->IsCrypted())
1649 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1652 // shutting down via RPC while the GUI is running does not work (yet):
1653 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1656 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1657 // Alternately, find a way to make params[0] mlock()'d to begin with.
1658 SecureString strWalletPass;
1659 strWalletPass.reserve(100);
1660 strWalletPass = params[0].get_str().c_str();
1662 if (strWalletPass.length() < 1)
1663 throw runtime_error(
1664 "encryptwallet <passphrase>\n"
1665 "Encrypts the wallet with <passphrase>.");
1667 if (!pwalletMain->EncryptWallet(strWalletPass))
1668 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1670 // BDB seems to have a bad habit of writing old data into
1671 // slack space in .dat files; that is bad if the old data is
1672 // unencrypted private keys. So:
1673 CreateThread(Shutdown, NULL);
1674 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1678 Value validateaddress(const Array& params, bool fHelp)
1680 if (fHelp || params.size() != 1)
1681 throw runtime_error(
1682 "validateaddress <bitcoinaddress>\n"
1683 "Return information about <bitcoinaddress>.");
1685 CBitcoinAddress address(params[0].get_str());
1686 bool isValid = address.IsValid();
1689 ret.push_back(Pair("isvalid", isValid));
1692 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1693 // version of the address:
1694 string currentAddress = address.ToString();
1695 ret.push_back(Pair("address", currentAddress));
1696 if (pwalletMain->HaveKey(address))
1698 ret.push_back(Pair("ismine", true));
1699 std::vector<unsigned char> vchPubKey;
1700 pwalletMain->GetPubKey(address, vchPubKey);
1701 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1702 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1703 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1705 key.SetPubKey(vchPubKey);
1706 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1708 else if (pwalletMain->HaveCScript(address.GetHash160()))
1710 ret.push_back(Pair("isscript", true));
1712 pwalletMain->GetCScript(address.GetHash160(), subscript);
1713 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1714 std::vector<CBitcoinAddress> addresses;
1715 txnouttype whichType;
1717 ExtractAddresses(subscript, whichType, addresses, nRequired);
1718 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1720 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1721 a.push_back(addr.ToString());
1722 ret.push_back(Pair("addresses", a));
1723 if (whichType == TX_MULTISIG)
1724 ret.push_back(Pair("sigsrequired", nRequired));
1727 ret.push_back(Pair("ismine", false));
1728 if (pwalletMain->mapAddressBook.count(address))
1729 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1734 Value getwork(const Array& params, bool fHelp)
1736 if (fHelp || params.size() > 1)
1737 throw runtime_error(
1739 "If [data] is not specified, returns formatted hash data to work on:\n"
1740 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1741 " \"data\" : block data\n"
1742 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1743 " \"target\" : little endian hash target\n"
1744 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1747 throw JSONRPCError(-9, "Bitcoin is not connected!");
1749 if (IsInitialBlockDownload())
1750 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1752 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1753 static mapNewBlock_t mapNewBlock;
1754 static vector<CBlock*> vNewBlock;
1755 static CReserveKey reservekey(pwalletMain);
1757 if (params.size() == 0)
1760 static unsigned int nTransactionsUpdatedLast;
1761 static CBlockIndex* pindexPrev;
1762 static int64 nStart;
1763 static CBlock* pblock;
1764 if (pindexPrev != pindexBest ||
1765 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1767 if (pindexPrev != pindexBest)
1769 // Deallocate old blocks since they're obsolete now
1770 mapNewBlock.clear();
1771 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1775 nTransactionsUpdatedLast = nTransactionsUpdated;
1776 pindexPrev = pindexBest;
1780 pblock = CreateNewBlock(reservekey);
1782 throw JSONRPCError(-7, "Out of memory");
1783 vNewBlock.push_back(pblock);
1787 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1790 // Update nExtraNonce
1791 static unsigned int nExtraNonce = 0;
1792 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1795 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1797 // Prebuild hash buffers
1801 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1803 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1806 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1807 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1808 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1809 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1815 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1816 if (vchData.size() != 128)
1817 throw JSONRPCError(-8, "Invalid parameter");
1818 CBlock* pdata = (CBlock*)&vchData[0];
1821 for (int i = 0; i < 128/4; i++)
1822 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1825 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1827 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1829 pblock->nTime = pdata->nTime;
1830 pblock->nNonce = pdata->nNonce;
1831 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1832 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1834 return CheckWork(pblock, *pwalletMain, reservekey);
1839 Value getmemorypool(const Array& params, bool fHelp)
1841 if (fHelp || params.size() > 1)
1842 throw runtime_error(
1843 "getmemorypool [data]\n"
1844 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1845 " \"version\" : block version\n"
1846 " \"previousblockhash\" : hash of current highest block\n"
1847 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1848 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1849 " \"time\" : timestamp appropriate for next block\n"
1850 " \"bits\" : compressed target of next block\n"
1851 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1853 if (params.size() == 0)
1856 throw JSONRPCError(-9, "Bitcoin is not connected!");
1858 if (IsInitialBlockDownload())
1859 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1861 static CReserveKey reservekey(pwalletMain);
1864 static unsigned int nTransactionsUpdatedLast;
1865 static CBlockIndex* pindexPrev;
1866 static int64 nStart;
1867 static CBlock* pblock;
1868 if (pindexPrev != pindexBest ||
1869 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1871 nTransactionsUpdatedLast = nTransactionsUpdated;
1872 pindexPrev = pindexBest;
1878 pblock = CreateNewBlock(reservekey);
1880 throw JSONRPCError(-7, "Out of memory");
1884 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1888 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1895 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1899 result.push_back(Pair("version", pblock->nVersion));
1900 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1901 result.push_back(Pair("transactions", transactions));
1902 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1903 result.push_back(Pair("time", (int64_t)pblock->nTime));
1909 uBits.nBits = htonl((int32_t)pblock->nBits);
1910 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1917 CDataStream ssBlock(ParseHex(params[0].get_str()));
1921 return ProcessBlock(NULL, &pblock);
1925 Value getblockhash(const Array& params, bool fHelp)
1927 if (fHelp || params.size() != 1)
1928 throw runtime_error(
1929 "getblockhash <index>\n"
1930 "Returns hash of block in best-block-chain at <index>.");
1932 int nHeight = params[0].get_int();
1933 if (nHeight < 0 || nHeight > nBestHeight)
1934 throw runtime_error("Block number out of range.");
1937 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1938 while (pblockindex->nHeight > nHeight)
1939 pblockindex = pblockindex->pprev;
1940 return pblockindex->phashBlock->GetHex();
1943 Value getblock(const Array& params, bool fHelp)
1945 if (fHelp || params.size() != 1)
1946 throw runtime_error(
1948 "Returns details of a block with given block-hash.");
1950 std::string strHash = params[0].get_str();
1951 uint256 hash(strHash);
1953 if (mapBlockIndex.count(hash) == 0)
1954 throw JSONRPCError(-5, "Block not found");
1957 CBlockIndex* pblockindex = mapBlockIndex[hash];
1958 block.ReadFromDisk(pblockindex, true);
1960 return blockToJSON(block, pblockindex);
1977 pair<string, rpcfn_type> pCallTable[] =
1979 make_pair("help", &help),
1980 make_pair("stop", &stop),
1981 make_pair("getblockcount", &getblockcount),
1982 make_pair("getblocknumber", &getblocknumber),
1983 make_pair("getconnectioncount", &getconnectioncount),
1984 make_pair("getdifficulty", &getdifficulty),
1985 make_pair("getgenerate", &getgenerate),
1986 make_pair("setgenerate", &setgenerate),
1987 make_pair("gethashespersec", &gethashespersec),
1988 make_pair("getinfo", &getinfo),
1989 make_pair("getnewaddress", &getnewaddress),
1990 make_pair("getaccountaddress", &getaccountaddress),
1991 make_pair("setaccount", &setaccount),
1992 make_pair("getaccount", &getaccount),
1993 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1994 make_pair("sendtoaddress", &sendtoaddress),
1995 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1996 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1997 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1998 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1999 make_pair("backupwallet", &backupwallet),
2000 make_pair("keypoolrefill", &keypoolrefill),
2001 make_pair("walletpassphrase", &walletpassphrase),
2002 make_pair("walletpassphrasechange", &walletpassphrasechange),
2003 make_pair("walletlock", &walletlock),
2004 make_pair("encryptwallet", &encryptwallet),
2005 make_pair("validateaddress", &validateaddress),
2006 make_pair("getbalance", &getbalance),
2007 make_pair("move", &movecmd),
2008 make_pair("sendfrom", &sendfrom),
2009 make_pair("sendmany", &sendmany),
2010 make_pair("addmultisigaddress", &addmultisigaddress),
2011 make_pair("getblock", &getblock),
2012 make_pair("getblockhash", &getblockhash),
2013 make_pair("gettransaction", &gettransaction),
2014 make_pair("listtransactions", &listtransactions),
2015 make_pair("signmessage", &signmessage),
2016 make_pair("verifymessage", &verifymessage),
2017 make_pair("getwork", &getwork),
2018 make_pair("listaccounts", &listaccounts),
2019 make_pair("settxfee", &settxfee),
2020 make_pair("getmemorypool", &getmemorypool),
2021 make_pair("listsinceblock", &listsinceblock),
2022 make_pair("dumpprivkey", &dumpprivkey),
2023 make_pair("importprivkey", &importprivkey)
2025 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2027 string pAllowInSafeMode[] =
2032 "getblocknumber", // deprecated
2033 "getconnectioncount",
2040 "getaccountaddress",
2042 "getaddressesbyaccount",
2051 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2059 // This ain't Apache. We're just using HTTP header for the length field
2060 // and to be compatible with other JSON-RPC implementations.
2063 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2066 s << "POST / HTTP/1.1\r\n"
2067 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2068 << "Host: 127.0.0.1\r\n"
2069 << "Content-Type: application/json\r\n"
2070 << "Content-Length: " << strMsg.size() << "\r\n"
2071 << "Connection: close\r\n"
2072 << "Accept: application/json\r\n";
2073 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2074 s << item.first << ": " << item.second << "\r\n";
2075 s << "\r\n" << strMsg;
2080 string rfc1123Time()
2085 struct tm* now_gmt = gmtime(&now);
2086 string locale(setlocale(LC_TIME, NULL));
2087 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2088 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2089 setlocale(LC_TIME, locale.c_str());
2090 return string(buffer);
2093 static string HTTPReply(int nStatus, const string& strMsg)
2096 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2098 "Server: bitcoin-json-rpc/%s\r\n"
2099 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2100 "Content-Type: text/html\r\n"
2101 "Content-Length: 296\r\n"
2103 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2104 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2107 "<TITLE>Error</TITLE>\r\n"
2108 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2110 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2111 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2112 const char *cStatus;
2113 if (nStatus == 200) cStatus = "OK";
2114 else if (nStatus == 400) cStatus = "Bad Request";
2115 else if (nStatus == 403) cStatus = "Forbidden";
2116 else if (nStatus == 404) cStatus = "Not Found";
2117 else if (nStatus == 500) cStatus = "Internal Server Error";
2120 "HTTP/1.1 %d %s\r\n"
2122 "Connection: close\r\n"
2123 "Content-Length: %d\r\n"
2124 "Content-Type: application/json\r\n"
2125 "Server: bitcoin-json-rpc/%s\r\n"
2130 rfc1123Time().c_str(),
2132 FormatFullVersion().c_str(),
2136 int ReadHTTPStatus(std::basic_istream<char>& stream)
2139 getline(stream, str);
2140 vector<string> vWords;
2141 boost::split(vWords, str, boost::is_any_of(" "));
2142 if (vWords.size() < 2)
2144 return atoi(vWords[1].c_str());
2147 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2153 std::getline(stream, str);
2154 if (str.empty() || str == "\r")
2156 string::size_type nColon = str.find(":");
2157 if (nColon != string::npos)
2159 string strHeader = str.substr(0, nColon);
2160 boost::trim(strHeader);
2161 boost::to_lower(strHeader);
2162 string strValue = str.substr(nColon+1);
2163 boost::trim(strValue);
2164 mapHeadersRet[strHeader] = strValue;
2165 if (strHeader == "content-length")
2166 nLen = atoi(strValue.c_str());
2172 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2174 mapHeadersRet.clear();
2178 int nStatus = ReadHTTPStatus(stream);
2181 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2182 if (nLen < 0 || nLen > MAX_SIZE)
2188 vector<char> vch(nLen);
2189 stream.read(&vch[0], nLen);
2190 strMessageRet = string(vch.begin(), vch.end());
2196 bool HTTPAuthorized(map<string, string>& mapHeaders)
2198 string strAuth = mapHeaders["authorization"];
2199 if (strAuth.substr(0,6) != "Basic ")
2201 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2202 string strUserPass = DecodeBase64(strUserPass64);
2203 return strUserPass == strRPCUserColonPass;
2207 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2208 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2209 // unspecified (HTTP errors and contents of 'error').
2211 // 1.0 spec: http://json-rpc.org/wiki/specification
2212 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2213 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2216 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2219 request.push_back(Pair("method", strMethod));
2220 request.push_back(Pair("params", params));
2221 request.push_back(Pair("id", id));
2222 return write_string(Value(request), false) + "\n";
2225 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2228 if (error.type() != null_type)
2229 reply.push_back(Pair("result", Value::null));
2231 reply.push_back(Pair("result", result));
2232 reply.push_back(Pair("error", error));
2233 reply.push_back(Pair("id", id));
2234 return write_string(Value(reply), false) + "\n";
2237 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2239 // Send error reply from json-rpc error object
2241 int code = find_value(objError, "code").get_int();
2242 if (code == -32600) nStatus = 400;
2243 else if (code == -32601) nStatus = 404;
2244 string strReply = JSONRPCReply(Value::null, objError, id);
2245 stream << HTTPReply(nStatus, strReply) << std::flush;
2248 bool ClientAllowed(const string& strAddress)
2250 if (strAddress == asio::ip::address_v4::loopback().to_string())
2252 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2253 BOOST_FOREACH(string strAllow, vAllow)
2254 if (WildcardMatch(strAddress, strAllow))
2261 // IOStream device that speaks SSL but can also speak non-SSL
2263 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2265 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2267 fUseSSL = fUseSSLIn;
2268 fNeedHandshake = fUseSSLIn;
2271 void handshake(ssl::stream_base::handshake_type role)
2273 if (!fNeedHandshake) return;
2274 fNeedHandshake = false;
2275 stream.handshake(role);
2277 std::streamsize read(char* s, std::streamsize n)
2279 handshake(ssl::stream_base::server); // HTTPS servers read first
2280 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2281 return stream.next_layer().read_some(asio::buffer(s, n));
2283 std::streamsize write(const char* s, std::streamsize n)
2285 handshake(ssl::stream_base::client); // HTTPS clients write first
2286 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2287 return asio::write(stream.next_layer(), asio::buffer(s, n));
2289 bool connect(const std::string& server, const std::string& port)
2291 ip::tcp::resolver resolver(stream.get_io_service());
2292 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2293 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2294 ip::tcp::resolver::iterator end;
2295 boost::system::error_code error = asio::error::host_not_found;
2296 while (error && endpoint_iterator != end)
2298 stream.lowest_layer().close();
2299 stream.lowest_layer().connect(*endpoint_iterator++, error);
2307 bool fNeedHandshake;
2313 void ThreadRPCServer(void* parg)
2315 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2318 vnThreadsRunning[4]++;
2319 ThreadRPCServer2(parg);
2320 vnThreadsRunning[4]--;
2322 catch (std::exception& e) {
2323 vnThreadsRunning[4]--;
2324 PrintException(&e, "ThreadRPCServer()");
2326 vnThreadsRunning[4]--;
2327 PrintException(NULL, "ThreadRPCServer()");
2329 printf("ThreadRPCServer exiting\n");
2332 void ThreadRPCServer2(void* parg)
2334 printf("ThreadRPCServer started\n");
2336 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2337 if (strRPCUserColonPass == ":")
2339 string strWhatAmI = "To use bitcoind";
2340 if (mapArgs.count("-server"))
2341 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2342 else if (mapArgs.count("-daemon"))
2343 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2345 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2346 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2348 GetConfigFile().c_str());
2350 CreateThread(Shutdown, NULL);
2355 bool fUseSSL = GetBoolArg("-rpcssl");
2356 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2358 asio::io_service io_service;
2359 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2360 ip::tcp::acceptor acceptor(io_service, endpoint);
2362 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2365 ssl::context context(io_service, ssl::context::sslv23);
2368 context.set_options(ssl::context::no_sslv2);
2369 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2370 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2371 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2372 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2373 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2374 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2375 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2376 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2378 string ciphers = GetArg("-rpcsslciphers",
2379 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2380 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2384 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2389 // Accept connection
2391 SSLStream sslStream(io_service, context);
2392 SSLIOStreamDevice d(sslStream, fUseSSL);
2393 iostreams::stream<SSLIOStreamDevice> stream(d);
2395 ip::tcp::iostream stream;
2398 ip::tcp::endpoint peer;
2399 vnThreadsRunning[4]--;
2401 acceptor.accept(sslStream.lowest_layer(), peer);
2403 acceptor.accept(*stream.rdbuf(), peer);
2405 vnThreadsRunning[4]++;
2409 // Restrict callers by IP
2410 if (!ClientAllowed(peer.address().to_string()))
2412 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2414 stream << HTTPReply(403, "") << std::flush;
2418 map<string, string> mapHeaders;
2421 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2422 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2425 printf("ThreadRPCServer ReadHTTP timeout\n");
2429 // Check authorization
2430 if (mapHeaders.count("authorization") == 0)
2432 stream << HTTPReply(401, "") << std::flush;
2435 if (!HTTPAuthorized(mapHeaders))
2437 // Deter brute-forcing short passwords
2438 if (mapArgs["-rpcpassword"].size() < 15)
2441 stream << HTTPReply(401, "") << std::flush;
2442 printf("ThreadRPCServer incorrect password attempt\n");
2446 Value id = Value::null;
2451 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2452 throw JSONRPCError(-32700, "Parse error");
2453 const Object& request = valRequest.get_obj();
2455 // Parse id now so errors from here on will have the id
2456 id = find_value(request, "id");
2459 Value valMethod = find_value(request, "method");
2460 if (valMethod.type() == null_type)
2461 throw JSONRPCError(-32600, "Missing method");
2462 if (valMethod.type() != str_type)
2463 throw JSONRPCError(-32600, "Method must be a string");
2464 string strMethod = valMethod.get_str();
2465 if (strMethod != "getwork" && strMethod != "getmemorypool")
2466 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2469 Value valParams = find_value(request, "params");
2471 if (valParams.type() == array_type)
2472 params = valParams.get_array();
2473 else if (valParams.type() == null_type)
2476 throw JSONRPCError(-32600, "Params must be an array");
2479 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2480 if (mi == mapCallTable.end())
2481 throw JSONRPCError(-32601, "Method not found");
2483 // Observe safe mode
2484 string strWarning = GetWarnings("rpc");
2485 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2486 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2492 CRITICAL_BLOCK(cs_main)
2493 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2494 result = (*(*mi).second)(params, false);
2497 string strReply = JSONRPCReply(result, Value::null, id);
2498 stream << HTTPReply(200, strReply) << std::flush;
2500 catch (std::exception& e)
2502 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2505 catch (Object& objError)
2507 ErrorReply(stream, objError, id);
2509 catch (std::exception& e)
2511 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2519 Object CallRPC(const string& strMethod, const Array& params)
2521 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2522 throw runtime_error(strprintf(
2523 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2524 "If the file does not exist, create it with owner-readable-only file permissions."),
2525 GetConfigFile().c_str()));
2527 // Connect to localhost
2528 bool fUseSSL = GetBoolArg("-rpcssl");
2530 asio::io_service io_service;
2531 ssl::context context(io_service, ssl::context::sslv23);
2532 context.set_options(ssl::context::no_sslv2);
2533 SSLStream sslStream(io_service, context);
2534 SSLIOStreamDevice d(sslStream, fUseSSL);
2535 iostreams::stream<SSLIOStreamDevice> stream(d);
2536 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2537 throw runtime_error("couldn't connect to server");
2540 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2542 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2544 throw runtime_error("couldn't connect to server");
2548 // HTTP basic authentication
2549 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2550 map<string, string> mapRequestHeaders;
2551 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2554 string strRequest = JSONRPCRequest(strMethod, params, 1);
2555 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2556 stream << strPost << std::flush;
2559 map<string, string> mapHeaders;
2561 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2563 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2564 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2565 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2566 else if (strReply.empty())
2567 throw runtime_error("no response from server");
2571 if (!read_string(strReply, valReply))
2572 throw runtime_error("couldn't parse reply from server");
2573 const Object& reply = valReply.get_obj();
2575 throw runtime_error("expected reply to have result, error and id properties");
2583 template<typename T>
2584 void ConvertTo(Value& value)
2586 if (value.type() == str_type)
2588 // reinterpret string as unquoted json value
2590 if (!read_string(value.get_str(), value2))
2591 throw runtime_error("type mismatch");
2592 value = value2.get_value<T>();
2596 value = value.get_value<T>();
2600 int CommandLineRPC(int argc, char *argv[])
2607 while (argc > 1 && IsSwitchChar(argv[1][0]))
2615 throw runtime_error("too few parameters");
2616 string strMethod = argv[1];
2618 // Parameters default to strings
2620 for (int i = 2; i < argc; i++)
2621 params.push_back(argv[i]);
2622 int n = params.size();
2625 // Special case non-string parameter types
2627 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2628 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2629 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2630 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2631 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2632 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2633 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2634 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2635 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2636 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2637 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2638 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2639 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2640 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2641 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2642 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2643 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2644 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2645 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2646 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2647 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2648 if (strMethod == "sendmany" && n > 1)
2650 string s = params[1].get_str();
2652 if (!read_string(s, v) || v.type() != obj_type)
2653 throw runtime_error("type mismatch");
2654 params[1] = v.get_obj();
2656 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2657 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2658 if (strMethod == "addmultisigaddress" && n > 1)
2660 string s = params[1].get_str();
2662 if (!read_string(s, v) || v.type() != array_type)
2663 throw runtime_error("addmultisigaddress: type mismatch "+s);
2664 params[1] = v.get_array();
2668 Object reply = CallRPC(strMethod, params);
2671 const Value& result = find_value(reply, "result");
2672 const Value& error = find_value(reply, "error");
2674 if (error.type() != null_type)
2677 strPrint = "error: " + write_string(error, false);
2678 int code = find_value(error.get_obj(), "code").get_int();
2684 if (result.type() == null_type)
2686 else if (result.type() == str_type)
2687 strPrint = result.get_str();
2689 strPrint = write_string(result, true);
2692 catch (std::exception& e)
2694 strPrint = string("error: ") + e.what();
2699 PrintException(NULL, "CommandLineRPC()");
2704 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2713 int main(int argc, char *argv[])
2716 // Turn off microsoft heap dump noise
2717 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2718 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2720 setbuf(stdin, NULL);
2721 setbuf(stdout, NULL);
2722 setbuf(stderr, NULL);
2726 if (argc >= 2 && string(argv[1]) == "-server")
2728 printf("server ready\n");
2729 ThreadRPCServer(NULL);
2733 return CommandLineRPC(argc, argv);
2736 catch (std::exception& e) {
2737 PrintException(&e, "main()");
2739 PrintException(NULL, "main()");