1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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("difficulty", (double)GetDifficulty()));
351 obj.push_back(Pair("testnet", fTestNet));
352 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
353 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
354 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
355 if (pwalletMain->IsCrypted())
356 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
357 obj.push_back(Pair("errors", GetWarnings("statusbar")));
362 Value getmininginfo(const Array& params, bool fHelp)
364 if (fHelp || params.size() != 0)
367 "Returns an object containing mining-related information.");
370 obj.push_back(Pair("blocks", (int)nBestHeight));
371 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
372 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
373 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
374 obj.push_back(Pair("errors", GetWarnings("statusbar")));
375 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
376 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
377 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
378 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
379 obj.push_back(Pair("testnet", fTestNet));
384 Value getnewaddress(const Array& params, bool fHelp)
386 if (fHelp || params.size() > 1)
388 "getnewaddress [account]\n"
389 "Returns a new bitcoin address for receiving payments. "
390 "If [account] is specified (recommended), it is added to the address book "
391 "so payments received with the address will be credited to [account].");
393 // Parse the account first so we don't generate a key if there's an error
395 if (params.size() > 0)
396 strAccount = AccountFromValue(params[0]);
398 if (!pwalletMain->IsLocked())
399 pwalletMain->TopUpKeyPool();
401 // Generate a new key that is added to wallet
402 std::vector<unsigned char> newKey;
403 if (!pwalletMain->GetKeyFromPool(newKey, false))
404 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
405 CBitcoinAddress address(newKey);
407 pwalletMain->SetAddressBookName(address, strAccount);
409 return address.ToString();
413 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
415 CWalletDB walletdb(pwalletMain->strWalletFile);
418 walletdb.ReadAccount(strAccount, account);
420 bool bKeyUsed = false;
422 // Check if the current key has been used
423 if (!account.vchPubKey.empty())
425 CScript scriptPubKey;
426 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
427 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
428 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
431 const CWalletTx& wtx = (*it).second;
432 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
433 if (txout.scriptPubKey == scriptPubKey)
438 // Generate a new key
439 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
441 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
442 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
444 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
445 walletdb.WriteAccount(strAccount, account);
448 return CBitcoinAddress(account.vchPubKey);
451 Value getaccountaddress(const Array& params, bool fHelp)
453 if (fHelp || params.size() != 1)
455 "getaccountaddress <account>\n"
456 "Returns the current bitcoin address for receiving payments to this account.");
458 // Parse the account first so we don't generate a key if there's an error
459 string strAccount = AccountFromValue(params[0]);
463 ret = GetAccountAddress(strAccount).ToString();
470 Value setaccount(const Array& params, bool fHelp)
472 if (fHelp || params.size() < 1 || params.size() > 2)
474 "setaccount <bitcoinaddress> <account>\n"
475 "Sets the account associated with the given address.");
477 CBitcoinAddress address(params[0].get_str());
478 if (!address.IsValid())
479 throw JSONRPCError(-5, "Invalid bitcoin address");
483 if (params.size() > 1)
484 strAccount = AccountFromValue(params[1]);
486 // Detect when changing the account of an address that is the 'unused current key' of another account:
487 if (pwalletMain->mapAddressBook.count(address))
489 string strOldAccount = pwalletMain->mapAddressBook[address];
490 if (address == GetAccountAddress(strOldAccount))
491 GetAccountAddress(strOldAccount, true);
494 pwalletMain->SetAddressBookName(address, strAccount);
500 Value getaccount(const Array& params, bool fHelp)
502 if (fHelp || params.size() != 1)
504 "getaccount <bitcoinaddress>\n"
505 "Returns the account associated with the given address.");
507 CBitcoinAddress address(params[0].get_str());
508 if (!address.IsValid())
509 throw JSONRPCError(-5, "Invalid bitcoin address");
512 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
513 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
514 strAccount = (*mi).second;
519 Value getaddressesbyaccount(const Array& params, bool fHelp)
521 if (fHelp || params.size() != 1)
523 "getaddressesbyaccount <account>\n"
524 "Returns the list of addresses for the given account.");
526 string strAccount = AccountFromValue(params[0]);
528 // Find all addresses that have the given account
530 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
532 const CBitcoinAddress& address = item.first;
533 const string& strName = item.second;
534 if (strName == strAccount)
535 ret.push_back(address.ToString());
540 Value settxfee(const Array& params, bool fHelp)
542 if (fHelp || params.size() < 1 || params.size() > 1)
544 "settxfee <amount>\n"
545 "<amount> is a real and is rounded to the nearest 0.00000001");
549 if (params[0].get_real() != 0.0)
550 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
552 nTransactionFee = nAmount;
556 Value sendtoaddress(const Array& params, bool fHelp)
558 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
560 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
561 "<amount> is a real and is rounded to the nearest 0.00000001\n"
562 "requires wallet passphrase to be set with walletpassphrase first");
563 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
565 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
566 "<amount> is a real and is rounded to the nearest 0.00000001");
568 CBitcoinAddress address(params[0].get_str());
569 if (!address.IsValid())
570 throw JSONRPCError(-5, "Invalid bitcoin address");
573 int64 nAmount = AmountFromValue(params[1]);
577 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
578 wtx.mapValue["comment"] = params[2].get_str();
579 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
580 wtx.mapValue["to"] = params[3].get_str();
582 if (pwalletMain->IsLocked())
583 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
585 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
587 throw JSONRPCError(-4, strError);
589 return wtx.GetHash().GetHex();
592 Value signmessage(const Array& params, bool fHelp)
594 if (fHelp || params.size() != 2)
596 "signmessage <bitcoinaddress> <message>\n"
597 "Sign a message with the private key of an address");
599 if (pwalletMain->IsLocked())
600 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
602 string strAddress = params[0].get_str();
603 string strMessage = params[1].get_str();
605 CBitcoinAddress addr(strAddress);
607 throw JSONRPCError(-3, "Invalid address");
610 if (!pwalletMain->GetKey(addr, key))
611 throw JSONRPCError(-4, "Private key not available");
613 CDataStream ss(SER_GETHASH);
614 ss << strMessageMagic;
617 vector<unsigned char> vchSig;
618 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
619 throw JSONRPCError(-5, "Sign failed");
621 return EncodeBase64(&vchSig[0], vchSig.size());
624 Value verifymessage(const Array& params, bool fHelp)
626 if (fHelp || params.size() != 3)
628 "verifymessage <bitcoinaddress> <signature> <message>\n"
629 "Verify a signed message");
631 string strAddress = params[0].get_str();
632 string strSign = params[1].get_str();
633 string strMessage = params[2].get_str();
635 CBitcoinAddress addr(strAddress);
637 throw JSONRPCError(-3, "Invalid address");
639 bool fInvalid = false;
640 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
643 throw JSONRPCError(-5, "Malformed base64 encoding");
645 CDataStream ss(SER_GETHASH);
646 ss << strMessageMagic;
650 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
653 return (CBitcoinAddress(key.GetPubKey()) == addr);
657 Value getreceivedbyaddress(const Array& params, bool fHelp)
659 if (fHelp || params.size() < 1 || params.size() > 2)
661 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
662 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
665 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
666 CScript scriptPubKey;
667 if (!address.IsValid())
668 throw JSONRPCError(-5, "Invalid bitcoin address");
669 scriptPubKey.SetBitcoinAddress(address);
670 if (!IsMine(*pwalletMain,scriptPubKey))
673 // Minimum confirmations
675 if (params.size() > 1)
676 nMinDepth = params[1].get_int();
680 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
682 const CWalletTx& wtx = (*it).second;
683 if (wtx.IsCoinBase() || !wtx.IsFinal())
686 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
687 if (txout.scriptPubKey == scriptPubKey)
688 if (wtx.GetDepthInMainChain() >= nMinDepth)
689 nAmount += txout.nValue;
692 return ValueFromAmount(nAmount);
696 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
698 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
700 const CBitcoinAddress& address = item.first;
701 const string& strName = item.second;
702 if (strName == strAccount)
703 setAddress.insert(address);
708 Value getreceivedbyaccount(const Array& params, bool fHelp)
710 if (fHelp || params.size() < 1 || params.size() > 2)
712 "getreceivedbyaccount <account> [minconf=1]\n"
713 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
715 // Minimum confirmations
717 if (params.size() > 1)
718 nMinDepth = params[1].get_int();
720 // Get the set of pub keys assigned to account
721 string strAccount = AccountFromValue(params[0]);
722 set<CBitcoinAddress> setAddress;
723 GetAccountAddresses(strAccount, setAddress);
727 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
729 const CWalletTx& wtx = (*it).second;
730 if (wtx.IsCoinBase() || !wtx.IsFinal())
733 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
735 CBitcoinAddress address;
736 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
737 if (wtx.GetDepthInMainChain() >= nMinDepth)
738 nAmount += txout.nValue;
742 return (double)nAmount / (double)COIN;
746 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
750 // Tally wallet transactions
751 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
753 const CWalletTx& wtx = (*it).second;
757 int64 nGenerated, nReceived, nSent, nFee;
758 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
760 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
761 nBalance += nReceived;
762 nBalance += nGenerated - nSent - nFee;
765 // Tally internal accounting entries
766 nBalance += walletdb.GetAccountCreditDebit(strAccount);
771 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
773 CWalletDB walletdb(pwalletMain->strWalletFile);
774 return GetAccountBalance(walletdb, strAccount, nMinDepth);
778 Value getbalance(const Array& params, bool fHelp)
780 if (fHelp || params.size() > 2)
782 "getbalance [account] [minconf=1]\n"
783 "If [account] is not specified, returns the server's total available balance.\n"
784 "If [account] is specified, returns the balance in the account.");
786 if (params.size() == 0)
787 return ValueFromAmount(pwalletMain->GetBalance());
790 if (params.size() > 1)
791 nMinDepth = params[1].get_int();
793 if (params[0].get_str() == "*") {
794 // Calculate total balance a different way from GetBalance()
795 // (GetBalance() sums up all unspent TxOuts)
796 // getbalance and getbalance '*' should always return the same number.
798 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
800 const CWalletTx& wtx = (*it).second;
804 int64 allGeneratedImmature, allGeneratedMature, allFee;
805 allGeneratedImmature = allGeneratedMature = allFee = 0;
806 string strSentAccount;
807 list<pair<CBitcoinAddress, int64> > listReceived;
808 list<pair<CBitcoinAddress, int64> > listSent;
809 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
810 if (wtx.GetDepthInMainChain() >= nMinDepth)
811 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
812 nBalance += r.second;
813 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
814 nBalance -= r.second;
816 nBalance += allGeneratedMature;
818 return ValueFromAmount(nBalance);
821 string strAccount = AccountFromValue(params[0]);
823 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
825 return ValueFromAmount(nBalance);
829 Value movecmd(const Array& params, bool fHelp)
831 if (fHelp || params.size() < 3 || params.size() > 5)
833 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
834 "Move from one account in your wallet to another.");
836 string strFrom = AccountFromValue(params[0]);
837 string strTo = AccountFromValue(params[1]);
838 int64 nAmount = AmountFromValue(params[2]);
839 if (params.size() > 3)
840 // unused parameter, used to be nMinDepth, keep type-checking it though
841 (void)params[3].get_int();
843 if (params.size() > 4)
844 strComment = params[4].get_str();
846 CWalletDB walletdb(pwalletMain->strWalletFile);
849 int64 nNow = GetAdjustedTime();
852 CAccountingEntry debit;
853 debit.strAccount = strFrom;
854 debit.nCreditDebit = -nAmount;
856 debit.strOtherAccount = strTo;
857 debit.strComment = strComment;
858 walletdb.WriteAccountingEntry(debit);
861 CAccountingEntry credit;
862 credit.strAccount = strTo;
863 credit.nCreditDebit = nAmount;
865 credit.strOtherAccount = strFrom;
866 credit.strComment = strComment;
867 walletdb.WriteAccountingEntry(credit);
869 walletdb.TxnCommit();
875 Value sendfrom(const Array& params, bool fHelp)
877 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
879 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
880 "<amount> is a real and is rounded to the nearest 0.00000001\n"
881 "requires wallet passphrase to be set with walletpassphrase first");
882 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
884 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
885 "<amount> is a real and is rounded to the nearest 0.00000001");
887 string strAccount = AccountFromValue(params[0]);
888 CBitcoinAddress address(params[1].get_str());
889 if (!address.IsValid())
890 throw JSONRPCError(-5, "Invalid bitcoin address");
891 int64 nAmount = AmountFromValue(params[2]);
893 if (params.size() > 3)
894 nMinDepth = params[3].get_int();
897 wtx.strFromAccount = strAccount;
898 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
899 wtx.mapValue["comment"] = params[4].get_str();
900 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
901 wtx.mapValue["to"] = params[5].get_str();
903 if (pwalletMain->IsLocked())
904 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
907 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
908 if (nAmount > nBalance)
909 throw JSONRPCError(-6, "Account has insufficient funds");
912 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
914 throw JSONRPCError(-4, strError);
916 return wtx.GetHash().GetHex();
920 Value sendmany(const Array& params, bool fHelp)
922 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
924 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
925 "amounts are double-precision floating point numbers\n"
926 "requires wallet passphrase to be set with walletpassphrase first");
927 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
929 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
930 "amounts are double-precision floating point numbers");
932 string strAccount = AccountFromValue(params[0]);
933 Object sendTo = params[1].get_obj();
935 if (params.size() > 2)
936 nMinDepth = params[2].get_int();
939 wtx.strFromAccount = strAccount;
940 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
941 wtx.mapValue["comment"] = params[3].get_str();
943 set<CBitcoinAddress> setAddress;
944 vector<pair<CScript, int64> > vecSend;
946 int64 totalAmount = 0;
947 BOOST_FOREACH(const Pair& s, sendTo)
949 CBitcoinAddress address(s.name_);
950 if (!address.IsValid())
951 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
953 if (setAddress.count(address))
954 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
955 setAddress.insert(address);
957 CScript scriptPubKey;
958 scriptPubKey.SetBitcoinAddress(address);
959 int64 nAmount = AmountFromValue(s.value_);
960 totalAmount += nAmount;
962 vecSend.push_back(make_pair(scriptPubKey, nAmount));
965 if (pwalletMain->IsLocked())
966 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
969 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
970 if (totalAmount > nBalance)
971 throw JSONRPCError(-6, "Account has insufficient funds");
974 CReserveKey keyChange(pwalletMain);
975 int64 nFeeRequired = 0;
976 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
979 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
980 throw JSONRPCError(-6, "Insufficient funds");
981 throw JSONRPCError(-4, "Transaction creation failed");
983 if (!pwalletMain->CommitTransaction(wtx, keyChange))
984 throw JSONRPCError(-4, "Transaction commit failed");
986 return wtx.GetHash().GetHex();
989 Value addmultisigaddress(const Array& params, bool fHelp)
991 if (fHelp || params.size() < 2 || params.size() > 3)
993 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
994 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
995 "each key is a bitcoin address or hex-encoded public key\n"
996 "If [account] is specified, assign address to [account].";
997 throw runtime_error(msg);
1000 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1002 int nRequired = params[0].get_int();
1003 const Array& keys = params[1].get_array();
1005 if (params.size() > 2)
1006 strAccount = AccountFromValue(params[2]);
1008 // Gather public keys
1009 if (nRequired < 1 || keys.size() < nRequired)
1010 throw runtime_error(
1011 strprintf("wrong number of keys"
1012 "(got %d, need at least %d)", keys.size(), nRequired));
1013 std::vector<CKey> pubkeys;
1014 pubkeys.resize(keys.size());
1015 for (int i = 0; i < keys.size(); i++)
1017 const std::string& ks = keys[i].get_str();
1019 // Case 1: bitcoin address and we have full public key:
1020 CBitcoinAddress address(ks);
1021 if (address.IsValid())
1023 if (address.IsScript())
1024 throw runtime_error(
1025 strprintf("%s is a pay-to-script address",ks.c_str()));
1026 std::vector<unsigned char> vchPubKey;
1027 if (!pwalletMain->GetPubKey(address, vchPubKey))
1028 throw runtime_error(
1029 strprintf("no full public key for address %s",ks.c_str()));
1030 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1031 throw runtime_error(" Invalid public key: "+ks);
1034 // Case 2: hex public key
1037 vector<unsigned char> vchPubKey = ParseHex(ks);
1038 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1039 throw runtime_error(" Invalid public key: "+ks);
1043 throw runtime_error(" Invalid public key: "+ks);
1047 // Construct using pay-to-script-hash:
1049 inner.SetMultisig(nRequired, pubkeys);
1051 uint160 scriptHash = Hash160(inner);
1052 CScript scriptPubKey;
1053 scriptPubKey.SetPayToScriptHash(inner);
1054 pwalletMain->AddCScript(inner);
1055 CBitcoinAddress address;
1056 address.SetScriptHash160(scriptHash);
1058 pwalletMain->SetAddressBookName(address, strAccount);
1059 return address.ToString();
1070 nConf = std::numeric_limits<int>::max();
1074 Value ListReceived(const Array& params, bool fByAccounts)
1076 // Minimum confirmations
1078 if (params.size() > 0)
1079 nMinDepth = params[0].get_int();
1081 // Whether to include empty accounts
1082 bool fIncludeEmpty = false;
1083 if (params.size() > 1)
1084 fIncludeEmpty = params[1].get_bool();
1087 map<CBitcoinAddress, tallyitem> mapTally;
1088 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1090 const CWalletTx& wtx = (*it).second;
1092 if (wtx.IsCoinBase() || !wtx.IsFinal())
1095 int nDepth = wtx.GetDepthInMainChain();
1096 if (nDepth < nMinDepth)
1099 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1101 CBitcoinAddress address;
1102 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1105 tallyitem& item = mapTally[address];
1106 item.nAmount += txout.nValue;
1107 item.nConf = min(item.nConf, nDepth);
1113 map<string, tallyitem> mapAccountTally;
1114 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1116 const CBitcoinAddress& address = item.first;
1117 const string& strAccount = item.second;
1118 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1119 if (it == mapTally.end() && !fIncludeEmpty)
1123 int nConf = std::numeric_limits<int>::max();
1124 if (it != mapTally.end())
1126 nAmount = (*it).second.nAmount;
1127 nConf = (*it).second.nConf;
1132 tallyitem& item = mapAccountTally[strAccount];
1133 item.nAmount += nAmount;
1134 item.nConf = min(item.nConf, nConf);
1139 obj.push_back(Pair("address", address.ToString()));
1140 obj.push_back(Pair("account", strAccount));
1141 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1142 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1149 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1151 int64 nAmount = (*it).second.nAmount;
1152 int nConf = (*it).second.nConf;
1154 obj.push_back(Pair("account", (*it).first));
1155 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1156 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1164 Value listreceivedbyaddress(const Array& params, bool fHelp)
1166 if (fHelp || params.size() > 2)
1167 throw runtime_error(
1168 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1169 "[minconf] is the minimum number of confirmations before payments are included.\n"
1170 "[includeempty] whether to include addresses that haven't received any payments.\n"
1171 "Returns an array of objects containing:\n"
1172 " \"address\" : receiving address\n"
1173 " \"account\" : the account of the receiving address\n"
1174 " \"amount\" : total amount received by the address\n"
1175 " \"confirmations\" : number of confirmations of the most recent transaction included");
1177 return ListReceived(params, false);
1180 Value listreceivedbyaccount(const Array& params, bool fHelp)
1182 if (fHelp || params.size() > 2)
1183 throw runtime_error(
1184 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1185 "[minconf] is the minimum number of confirmations before payments are included.\n"
1186 "[includeempty] whether to include accounts that haven't received any payments.\n"
1187 "Returns an array of objects containing:\n"
1188 " \"account\" : the account of the receiving addresses\n"
1189 " \"amount\" : total amount received by addresses with this account\n"
1190 " \"confirmations\" : number of confirmations of the most recent transaction included");
1192 return ListReceived(params, true);
1195 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1197 int64 nGeneratedImmature, nGeneratedMature, nFee;
1198 string strSentAccount;
1199 list<pair<CBitcoinAddress, int64> > listReceived;
1200 list<pair<CBitcoinAddress, int64> > listSent;
1202 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1204 bool fAllAccounts = (strAccount == string("*"));
1206 // Generated blocks assigned to account ""
1207 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1210 entry.push_back(Pair("account", string("")));
1211 if (nGeneratedImmature)
1213 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1214 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1218 entry.push_back(Pair("category", "generate"));
1219 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1222 WalletTxToJSON(wtx, entry);
1223 ret.push_back(entry);
1227 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1229 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1232 entry.push_back(Pair("account", strSentAccount));
1233 entry.push_back(Pair("address", s.first.ToString()));
1234 entry.push_back(Pair("category", "send"));
1235 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1236 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1238 WalletTxToJSON(wtx, entry);
1239 ret.push_back(entry);
1244 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1245 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1248 if (pwalletMain->mapAddressBook.count(r.first))
1249 account = pwalletMain->mapAddressBook[r.first];
1250 if (fAllAccounts || (account == strAccount))
1253 entry.push_back(Pair("account", account));
1254 entry.push_back(Pair("address", r.first.ToString()));
1255 entry.push_back(Pair("category", "receive"));
1256 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1258 WalletTxToJSON(wtx, entry);
1259 ret.push_back(entry);
1264 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1266 bool fAllAccounts = (strAccount == string("*"));
1268 if (fAllAccounts || acentry.strAccount == strAccount)
1271 entry.push_back(Pair("account", acentry.strAccount));
1272 entry.push_back(Pair("category", "move"));
1273 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1274 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1275 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1276 entry.push_back(Pair("comment", acentry.strComment));
1277 ret.push_back(entry);
1281 Value listtransactions(const Array& params, bool fHelp)
1283 if (fHelp || params.size() > 3)
1284 throw runtime_error(
1285 "listtransactions [account] [count=10] [from=0]\n"
1286 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1288 string strAccount = "*";
1289 if (params.size() > 0)
1290 strAccount = params[0].get_str();
1292 if (params.size() > 1)
1293 nCount = params[1].get_int();
1295 if (params.size() > 2)
1296 nFrom = params[2].get_int();
1299 CWalletDB walletdb(pwalletMain->strWalletFile);
1301 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1302 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1303 typedef multimap<int64, TxPair > TxItems;
1306 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1308 CWalletTx* wtx = &((*it).second);
1309 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1311 list<CAccountingEntry> acentries;
1312 walletdb.ListAccountCreditDebit(strAccount, acentries);
1313 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1315 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1318 // Now: iterate backwards until we have nCount items to return:
1319 TxItems::reverse_iterator it = txByTime.rbegin();
1320 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1321 for (; it != txByTime.rend(); ++it)
1323 CWalletTx *const pwtx = (*it).second.first;
1325 ListTransactions(*pwtx, strAccount, 0, true, ret);
1326 CAccountingEntry *const pacentry = (*it).second.second;
1328 AcentryToJSON(*pacentry, strAccount, ret);
1330 if (ret.size() >= nCount) break;
1332 // ret is now newest to oldest
1334 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1335 if (ret.size() > nCount)
1337 Array::iterator last = ret.begin();
1338 std::advance(last, nCount);
1339 ret.erase(last, ret.end());
1341 std::reverse(ret.begin(), ret.end()); // oldest to newest
1346 Value listaccounts(const Array& params, bool fHelp)
1348 if (fHelp || params.size() > 1)
1349 throw runtime_error(
1350 "listaccounts [minconf=1]\n"
1351 "Returns Object that has account names as keys, account balances as values.");
1354 if (params.size() > 0)
1355 nMinDepth = params[0].get_int();
1357 map<string, int64> mapAccountBalances;
1358 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1359 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1360 mapAccountBalances[entry.second] = 0;
1363 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1365 const CWalletTx& wtx = (*it).second;
1366 int64 nGeneratedImmature, nGeneratedMature, nFee;
1367 string strSentAccount;
1368 list<pair<CBitcoinAddress, int64> > listReceived;
1369 list<pair<CBitcoinAddress, int64> > listSent;
1370 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1371 mapAccountBalances[strSentAccount] -= nFee;
1372 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1373 mapAccountBalances[strSentAccount] -= s.second;
1374 if (wtx.GetDepthInMainChain() >= nMinDepth)
1376 mapAccountBalances[""] += nGeneratedMature;
1377 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1378 if (pwalletMain->mapAddressBook.count(r.first))
1379 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1381 mapAccountBalances[""] += r.second;
1385 list<CAccountingEntry> acentries;
1386 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1387 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1388 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1391 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1392 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1397 Value listsinceblock(const Array& params, bool fHelp)
1400 throw runtime_error(
1401 "listsinceblock [blockid] [target-confirmations]\n"
1402 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1404 CBlockIndex *pindex = NULL;
1405 int target_confirms = 1;
1407 if (params.size() > 0)
1409 uint256 blockId = 0;
1411 blockId.SetHex(params[0].get_str());
1412 pindex = CBlockLocator(blockId).GetBlockIndex();
1415 if (params.size() > 1)
1417 target_confirms = params[1].get_int();
1419 if (target_confirms < 1)
1420 throw JSONRPCError(-8, "Invalid parameter");
1423 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1427 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1429 CWalletTx tx = (*it).second;
1431 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1432 ListTransactions(tx, "*", 0, true, transactions);
1437 if (target_confirms == 1)
1440 lastblock = hashBestChain;
1444 int target_height = pindexBest->nHeight + 1 - target_confirms;
1447 for (block = pindexBest;
1448 block && block->nHeight > target_height;
1449 block = block->pprev) { }
1451 lastblock = block ? block->GetBlockHash() : 0;
1455 ret.push_back(Pair("transactions", transactions));
1456 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1461 Value gettransaction(const Array& params, bool fHelp)
1463 if (fHelp || params.size() != 1)
1464 throw runtime_error(
1465 "gettransaction <txid>\n"
1466 "Get detailed information about <txid>");
1469 hash.SetHex(params[0].get_str());
1473 if (!pwalletMain->mapWallet.count(hash))
1474 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1475 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1477 int64 nCredit = wtx.GetCredit();
1478 int64 nDebit = wtx.GetDebit();
1479 int64 nNet = nCredit - nDebit;
1480 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1482 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1484 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1486 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1489 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1490 entry.push_back(Pair("details", details));
1496 Value backupwallet(const Array& params, bool fHelp)
1498 if (fHelp || params.size() != 1)
1499 throw runtime_error(
1500 "backupwallet <destination>\n"
1501 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1503 string strDest = params[0].get_str();
1504 BackupWallet(*pwalletMain, strDest);
1510 Value keypoolrefill(const Array& params, bool fHelp)
1512 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1513 throw runtime_error(
1515 "Fills the keypool, requires wallet passphrase to be set.");
1516 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1517 throw runtime_error(
1519 "Fills the keypool.");
1521 if (pwalletMain->IsLocked())
1522 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1524 pwalletMain->TopUpKeyPool();
1526 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1527 throw JSONRPCError(-4, "Error refreshing keypool.");
1533 void ThreadTopUpKeyPool(void* parg)
1535 pwalletMain->TopUpKeyPool();
1538 void ThreadCleanWalletPassphrase(void* parg)
1540 int64 nMyWakeTime = GetTime() + *((int*)parg);
1542 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1544 if (nWalletUnlockTime == 0)
1546 nWalletUnlockTime = nMyWakeTime;
1548 while (GetTime() < nWalletUnlockTime)
1550 int64 nToSleep = GetTime() - nWalletUnlockTime;
1552 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1554 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1557 nWalletUnlockTime = 0;
1558 pwalletMain->Lock();
1562 if (nWalletUnlockTime < nMyWakeTime)
1563 nWalletUnlockTime = nMyWakeTime;
1566 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1571 Value walletpassphrase(const Array& params, bool fHelp)
1573 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1574 throw runtime_error(
1575 "walletpassphrase <passphrase> <timeout>\n"
1576 "Stores the wallet decryption key in memory for <timeout> seconds.");
1579 if (!pwalletMain->IsCrypted())
1580 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1582 if (!pwalletMain->IsLocked())
1583 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1585 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1586 SecureString strWalletPass;
1587 strWalletPass.reserve(100);
1588 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1589 // Alternately, find a way to make params[0] mlock()'d to begin with.
1590 strWalletPass = params[0].get_str().c_str();
1592 if (strWalletPass.length() > 0)
1594 if (!pwalletMain->Unlock(strWalletPass))
1595 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1598 throw runtime_error(
1599 "walletpassphrase <passphrase> <timeout>\n"
1600 "Stores the wallet decryption key in memory for <timeout> seconds.");
1602 CreateThread(ThreadTopUpKeyPool, NULL);
1603 int* pnSleepTime = new int(params[1].get_int());
1604 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1610 Value walletpassphrasechange(const Array& params, bool fHelp)
1612 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1613 throw runtime_error(
1614 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1615 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1618 if (!pwalletMain->IsCrypted())
1619 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1621 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1622 // Alternately, find a way to make params[0] mlock()'d to begin with.
1623 SecureString strOldWalletPass;
1624 strOldWalletPass.reserve(100);
1625 strOldWalletPass = params[0].get_str().c_str();
1627 SecureString strNewWalletPass;
1628 strNewWalletPass.reserve(100);
1629 strNewWalletPass = params[1].get_str().c_str();
1631 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1632 throw runtime_error(
1633 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1634 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1636 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1637 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1643 Value walletlock(const Array& params, bool fHelp)
1645 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1646 throw runtime_error(
1648 "Removes the wallet encryption key from memory, locking the wallet.\n"
1649 "After calling this method, you will need to call walletpassphrase again\n"
1650 "before being able to call any methods which require the wallet to be unlocked.");
1653 if (!pwalletMain->IsCrypted())
1654 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1656 pwalletMain->Lock();
1657 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1659 nWalletUnlockTime = 0;
1666 Value encryptwallet(const Array& params, bool fHelp)
1668 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1669 throw runtime_error(
1670 "encryptwallet <passphrase>\n"
1671 "Encrypts the wallet with <passphrase>.");
1674 if (pwalletMain->IsCrypted())
1675 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1678 // shutting down via RPC while the GUI is running does not work (yet):
1679 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1682 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1683 // Alternately, find a way to make params[0] mlock()'d to begin with.
1684 SecureString strWalletPass;
1685 strWalletPass.reserve(100);
1686 strWalletPass = params[0].get_str().c_str();
1688 if (strWalletPass.length() < 1)
1689 throw runtime_error(
1690 "encryptwallet <passphrase>\n"
1691 "Encrypts the wallet with <passphrase>.");
1693 if (!pwalletMain->EncryptWallet(strWalletPass))
1694 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1696 // BDB seems to have a bad habit of writing old data into
1697 // slack space in .dat files; that is bad if the old data is
1698 // unencrypted private keys. So:
1699 CreateThread(Shutdown, NULL);
1700 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1704 Value validateaddress(const Array& params, bool fHelp)
1706 if (fHelp || params.size() != 1)
1707 throw runtime_error(
1708 "validateaddress <bitcoinaddress>\n"
1709 "Return information about <bitcoinaddress>.");
1711 CBitcoinAddress address(params[0].get_str());
1712 bool isValid = address.IsValid();
1715 ret.push_back(Pair("isvalid", isValid));
1718 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1719 // version of the address:
1720 string currentAddress = address.ToString();
1721 ret.push_back(Pair("address", currentAddress));
1722 if (pwalletMain->HaveKey(address))
1724 ret.push_back(Pair("ismine", true));
1725 std::vector<unsigned char> vchPubKey;
1726 pwalletMain->GetPubKey(address, vchPubKey);
1727 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1729 key.SetPubKey(vchPubKey);
1730 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1732 else if (pwalletMain->HaveCScript(address.GetHash160()))
1734 ret.push_back(Pair("isscript", true));
1736 pwalletMain->GetCScript(address.GetHash160(), subscript);
1737 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1738 std::vector<CBitcoinAddress> addresses;
1739 txnouttype whichType;
1741 ExtractAddresses(subscript, whichType, addresses, nRequired);
1742 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1744 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1745 a.push_back(addr.ToString());
1746 ret.push_back(Pair("addresses", a));
1747 if (whichType == TX_MULTISIG)
1748 ret.push_back(Pair("sigsrequired", nRequired));
1751 ret.push_back(Pair("ismine", false));
1752 if (pwalletMain->mapAddressBook.count(address))
1753 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1758 Value getwork(const Array& params, bool fHelp)
1760 if (fHelp || params.size() > 1)
1761 throw runtime_error(
1763 "If [data] is not specified, returns formatted hash data to work on:\n"
1764 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1765 " \"data\" : block data\n"
1766 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1767 " \"target\" : little endian hash target\n"
1768 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1771 throw JSONRPCError(-9, "Bitcoin is not connected!");
1773 if (IsInitialBlockDownload())
1774 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1776 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1777 static mapNewBlock_t mapNewBlock;
1778 static vector<CBlock*> vNewBlock;
1779 static CReserveKey reservekey(pwalletMain);
1781 if (params.size() == 0)
1784 static unsigned int nTransactionsUpdatedLast;
1785 static CBlockIndex* pindexPrev;
1786 static int64 nStart;
1787 static CBlock* pblock;
1788 if (pindexPrev != pindexBest ||
1789 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1791 if (pindexPrev != pindexBest)
1793 // Deallocate old blocks since they're obsolete now
1794 mapNewBlock.clear();
1795 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1799 nTransactionsUpdatedLast = nTransactionsUpdated;
1800 pindexPrev = pindexBest;
1804 pblock = CreateNewBlock(reservekey);
1806 throw JSONRPCError(-7, "Out of memory");
1807 vNewBlock.push_back(pblock);
1811 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1814 // Update nExtraNonce
1815 static unsigned int nExtraNonce = 0;
1816 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1819 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1821 // Prebuild hash buffers
1825 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1827 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1830 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1831 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1832 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1833 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1839 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1840 if (vchData.size() != 128)
1841 throw JSONRPCError(-8, "Invalid parameter");
1842 CBlock* pdata = (CBlock*)&vchData[0];
1845 for (int i = 0; i < 128/4; i++)
1846 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1849 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1851 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1853 pblock->nTime = pdata->nTime;
1854 pblock->nNonce = pdata->nNonce;
1855 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1856 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1858 return CheckWork(pblock, *pwalletMain, reservekey);
1863 Value getmemorypool(const Array& params, bool fHelp)
1865 if (fHelp || params.size() > 1)
1866 throw runtime_error(
1867 "getmemorypool [data]\n"
1868 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1869 " \"version\" : block version\n"
1870 " \"previousblockhash\" : hash of current highest block\n"
1871 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1872 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1873 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1874 " \"time\" : timestamp appropriate for next block\n"
1875 " \"mintime\" : minimum timestamp appropriate for next block\n"
1876 " \"curtime\" : current timestamp\n"
1877 " \"bits\" : compressed target of next block\n"
1878 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1880 if (params.size() == 0)
1883 throw JSONRPCError(-9, "Bitcoin is not connected!");
1885 if (IsInitialBlockDownload())
1886 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1888 static CReserveKey reservekey(pwalletMain);
1891 static unsigned int nTransactionsUpdatedLast;
1892 static CBlockIndex* pindexPrev;
1893 static int64 nStart;
1894 static CBlock* pblock;
1895 if (pindexPrev != pindexBest ||
1896 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1898 nTransactionsUpdatedLast = nTransactionsUpdated;
1899 pindexPrev = pindexBest;
1905 pblock = CreateNewBlock(reservekey);
1907 throw JSONRPCError(-7, "Out of memory");
1911 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1915 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1922 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1926 result.push_back(Pair("version", pblock->nVersion));
1927 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1928 result.push_back(Pair("transactions", transactions));
1929 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1930 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1931 result.push_back(Pair("time", (int64_t)pblock->nTime));
1932 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1933 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1939 uBits.nBits = htonl((int32_t)pblock->nBits);
1940 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1947 CDataStream ssBlock(ParseHex(params[0].get_str()));
1951 return ProcessBlock(NULL, &pblock);
1955 Value getblockhash(const Array& params, bool fHelp)
1957 if (fHelp || params.size() != 1)
1958 throw runtime_error(
1959 "getblockhash <index>\n"
1960 "Returns hash of block in best-block-chain at <index>.");
1962 int nHeight = params[0].get_int();
1963 if (nHeight < 0 || nHeight > nBestHeight)
1964 throw runtime_error("Block number out of range.");
1967 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1968 while (pblockindex->nHeight > nHeight)
1969 pblockindex = pblockindex->pprev;
1970 return pblockindex->phashBlock->GetHex();
1973 Value getblock(const Array& params, bool fHelp)
1975 if (fHelp || params.size() != 1)
1976 throw runtime_error(
1978 "Returns details of a block with given block-hash.");
1980 std::string strHash = params[0].get_str();
1981 uint256 hash(strHash);
1983 if (mapBlockIndex.count(hash) == 0)
1984 throw JSONRPCError(-5, "Block not found");
1987 CBlockIndex* pblockindex = mapBlockIndex[hash];
1988 block.ReadFromDisk(pblockindex, true);
1990 return blockToJSON(block, pblockindex);
2007 pair<string, rpcfn_type> pCallTable[] =
2009 make_pair("help", &help),
2010 make_pair("stop", &stop),
2011 make_pair("getblockcount", &getblockcount),
2012 make_pair("getblocknumber", &getblocknumber),
2013 make_pair("getconnectioncount", &getconnectioncount),
2014 make_pair("getdifficulty", &getdifficulty),
2015 make_pair("getgenerate", &getgenerate),
2016 make_pair("setgenerate", &setgenerate),
2017 make_pair("gethashespersec", &gethashespersec),
2018 make_pair("getinfo", &getinfo),
2019 make_pair("getmininginfo", &getmininginfo),
2020 make_pair("getnewaddress", &getnewaddress),
2021 make_pair("getaccountaddress", &getaccountaddress),
2022 make_pair("setaccount", &setaccount),
2023 make_pair("getaccount", &getaccount),
2024 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2025 make_pair("sendtoaddress", &sendtoaddress),
2026 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2027 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2028 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2029 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2030 make_pair("backupwallet", &backupwallet),
2031 make_pair("keypoolrefill", &keypoolrefill),
2032 make_pair("walletpassphrase", &walletpassphrase),
2033 make_pair("walletpassphrasechange", &walletpassphrasechange),
2034 make_pair("walletlock", &walletlock),
2035 make_pair("encryptwallet", &encryptwallet),
2036 make_pair("validateaddress", &validateaddress),
2037 make_pair("getbalance", &getbalance),
2038 make_pair("move", &movecmd),
2039 make_pair("sendfrom", &sendfrom),
2040 make_pair("sendmany", &sendmany),
2041 make_pair("addmultisigaddress", &addmultisigaddress),
2042 make_pair("getblock", &getblock),
2043 make_pair("getblockhash", &getblockhash),
2044 make_pair("gettransaction", &gettransaction),
2045 make_pair("listtransactions", &listtransactions),
2046 make_pair("signmessage", &signmessage),
2047 make_pair("verifymessage", &verifymessage),
2048 make_pair("getwork", &getwork),
2049 make_pair("listaccounts", &listaccounts),
2050 make_pair("settxfee", &settxfee),
2051 make_pair("getmemorypool", &getmemorypool),
2052 make_pair("listsinceblock", &listsinceblock),
2053 make_pair("dumpprivkey", &dumpprivkey),
2054 make_pair("importprivkey", &importprivkey)
2056 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2058 string pAllowInSafeMode[] =
2063 "getblocknumber", // deprecated
2064 "getconnectioncount",
2072 "getaccountaddress",
2074 "getaddressesbyaccount",
2083 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2091 // This ain't Apache. We're just using HTTP header for the length field
2092 // and to be compatible with other JSON-RPC implementations.
2095 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2098 s << "POST / HTTP/1.1\r\n"
2099 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2100 << "Host: 127.0.0.1\r\n"
2101 << "Content-Type: application/json\r\n"
2102 << "Content-Length: " << strMsg.size() << "\r\n"
2103 << "Connection: close\r\n"
2104 << "Accept: application/json\r\n";
2105 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2106 s << item.first << ": " << item.second << "\r\n";
2107 s << "\r\n" << strMsg;
2112 string rfc1123Time()
2117 struct tm* now_gmt = gmtime(&now);
2118 string locale(setlocale(LC_TIME, NULL));
2119 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2120 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2121 setlocale(LC_TIME, locale.c_str());
2122 return string(buffer);
2125 static string HTTPReply(int nStatus, const string& strMsg)
2128 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2130 "Server: bitcoin-json-rpc/%s\r\n"
2131 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2132 "Content-Type: text/html\r\n"
2133 "Content-Length: 296\r\n"
2135 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2136 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2139 "<TITLE>Error</TITLE>\r\n"
2140 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2142 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2143 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2144 const char *cStatus;
2145 if (nStatus == 200) cStatus = "OK";
2146 else if (nStatus == 400) cStatus = "Bad Request";
2147 else if (nStatus == 403) cStatus = "Forbidden";
2148 else if (nStatus == 404) cStatus = "Not Found";
2149 else if (nStatus == 500) cStatus = "Internal Server Error";
2152 "HTTP/1.1 %d %s\r\n"
2154 "Connection: close\r\n"
2155 "Content-Length: %d\r\n"
2156 "Content-Type: application/json\r\n"
2157 "Server: bitcoin-json-rpc/%s\r\n"
2162 rfc1123Time().c_str(),
2164 FormatFullVersion().c_str(),
2168 int ReadHTTPStatus(std::basic_istream<char>& stream)
2171 getline(stream, str);
2172 vector<string> vWords;
2173 boost::split(vWords, str, boost::is_any_of(" "));
2174 if (vWords.size() < 2)
2176 return atoi(vWords[1].c_str());
2179 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2185 std::getline(stream, str);
2186 if (str.empty() || str == "\r")
2188 string::size_type nColon = str.find(":");
2189 if (nColon != string::npos)
2191 string strHeader = str.substr(0, nColon);
2192 boost::trim(strHeader);
2193 boost::to_lower(strHeader);
2194 string strValue = str.substr(nColon+1);
2195 boost::trim(strValue);
2196 mapHeadersRet[strHeader] = strValue;
2197 if (strHeader == "content-length")
2198 nLen = atoi(strValue.c_str());
2204 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2206 mapHeadersRet.clear();
2210 int nStatus = ReadHTTPStatus(stream);
2213 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2214 if (nLen < 0 || nLen > MAX_SIZE)
2220 vector<char> vch(nLen);
2221 stream.read(&vch[0], nLen);
2222 strMessageRet = string(vch.begin(), vch.end());
2228 bool HTTPAuthorized(map<string, string>& mapHeaders)
2230 string strAuth = mapHeaders["authorization"];
2231 if (strAuth.substr(0,6) != "Basic ")
2233 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2234 string strUserPass = DecodeBase64(strUserPass64);
2235 return strUserPass == strRPCUserColonPass;
2239 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2240 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2241 // unspecified (HTTP errors and contents of 'error').
2243 // 1.0 spec: http://json-rpc.org/wiki/specification
2244 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2245 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2248 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2251 request.push_back(Pair("method", strMethod));
2252 request.push_back(Pair("params", params));
2253 request.push_back(Pair("id", id));
2254 return write_string(Value(request), false) + "\n";
2257 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2260 if (error.type() != null_type)
2261 reply.push_back(Pair("result", Value::null));
2263 reply.push_back(Pair("result", result));
2264 reply.push_back(Pair("error", error));
2265 reply.push_back(Pair("id", id));
2266 return write_string(Value(reply), false) + "\n";
2269 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2271 // Send error reply from json-rpc error object
2273 int code = find_value(objError, "code").get_int();
2274 if (code == -32600) nStatus = 400;
2275 else if (code == -32601) nStatus = 404;
2276 string strReply = JSONRPCReply(Value::null, objError, id);
2277 stream << HTTPReply(nStatus, strReply) << std::flush;
2280 bool ClientAllowed(const string& strAddress)
2282 if (strAddress == asio::ip::address_v4::loopback().to_string())
2284 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2285 BOOST_FOREACH(string strAllow, vAllow)
2286 if (WildcardMatch(strAddress, strAllow))
2293 // IOStream device that speaks SSL but can also speak non-SSL
2295 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2297 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2299 fUseSSL = fUseSSLIn;
2300 fNeedHandshake = fUseSSLIn;
2303 void handshake(ssl::stream_base::handshake_type role)
2305 if (!fNeedHandshake) return;
2306 fNeedHandshake = false;
2307 stream.handshake(role);
2309 std::streamsize read(char* s, std::streamsize n)
2311 handshake(ssl::stream_base::server); // HTTPS servers read first
2312 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2313 return stream.next_layer().read_some(asio::buffer(s, n));
2315 std::streamsize write(const char* s, std::streamsize n)
2317 handshake(ssl::stream_base::client); // HTTPS clients write first
2318 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2319 return asio::write(stream.next_layer(), asio::buffer(s, n));
2321 bool connect(const std::string& server, const std::string& port)
2323 ip::tcp::resolver resolver(stream.get_io_service());
2324 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2325 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2326 ip::tcp::resolver::iterator end;
2327 boost::system::error_code error = asio::error::host_not_found;
2328 while (error && endpoint_iterator != end)
2330 stream.lowest_layer().close();
2331 stream.lowest_layer().connect(*endpoint_iterator++, error);
2339 bool fNeedHandshake;
2345 void ThreadRPCServer(void* parg)
2347 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2350 vnThreadsRunning[4]++;
2351 ThreadRPCServer2(parg);
2352 vnThreadsRunning[4]--;
2354 catch (std::exception& e) {
2355 vnThreadsRunning[4]--;
2356 PrintException(&e, "ThreadRPCServer()");
2358 vnThreadsRunning[4]--;
2359 PrintException(NULL, "ThreadRPCServer()");
2361 printf("ThreadRPCServer exiting\n");
2364 void ThreadRPCServer2(void* parg)
2366 printf("ThreadRPCServer started\n");
2368 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2369 if (mapArgs["-rpcpassword"] == "")
2371 unsigned char rand_pwd[32];
2372 RAND_bytes(rand_pwd, 32);
2373 string strWhatAmI = "To use bitcoind";
2374 if (mapArgs.count("-server"))
2375 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2376 else if (mapArgs.count("-daemon"))
2377 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2379 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2380 "It is recommended you use the following random password:\n"
2381 "rpcuser=bitcoinrpc\n"
2383 "(you do not need to remember this password)\n"
2384 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2386 GetConfigFile().c_str(),
2387 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2389 CreateThread(Shutdown, NULL);
2394 bool fUseSSL = GetBoolArg("-rpcssl");
2395 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2397 asio::io_service io_service;
2398 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2399 ip::tcp::acceptor acceptor(io_service, endpoint);
2401 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2404 ssl::context context(io_service, ssl::context::sslv23);
2407 context.set_options(ssl::context::no_sslv2);
2408 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2409 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2410 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2411 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2412 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2413 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2414 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2415 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2417 string ciphers = GetArg("-rpcsslciphers",
2418 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2419 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2423 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2428 // Accept connection
2430 SSLStream sslStream(io_service, context);
2431 SSLIOStreamDevice d(sslStream, fUseSSL);
2432 iostreams::stream<SSLIOStreamDevice> stream(d);
2434 ip::tcp::iostream stream;
2437 ip::tcp::endpoint peer;
2438 vnThreadsRunning[4]--;
2440 acceptor.accept(sslStream.lowest_layer(), peer);
2442 acceptor.accept(*stream.rdbuf(), peer);
2444 vnThreadsRunning[4]++;
2448 // Restrict callers by IP
2449 if (!ClientAllowed(peer.address().to_string()))
2451 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2453 stream << HTTPReply(403, "") << std::flush;
2457 map<string, string> mapHeaders;
2460 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2461 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2464 printf("ThreadRPCServer ReadHTTP timeout\n");
2468 // Check authorization
2469 if (mapHeaders.count("authorization") == 0)
2471 stream << HTTPReply(401, "") << std::flush;
2474 if (!HTTPAuthorized(mapHeaders))
2476 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2477 /* Deter brute-forcing short passwords.
2478 If this results in a DOS the user really
2479 shouldn't have their RPC port exposed.*/
2480 if (mapArgs["-rpcpassword"].size() < 20)
2483 stream << HTTPReply(401, "") << std::flush;
2487 Value id = Value::null;
2492 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2493 throw JSONRPCError(-32700, "Parse error");
2494 const Object& request = valRequest.get_obj();
2496 // Parse id now so errors from here on will have the id
2497 id = find_value(request, "id");
2500 Value valMethod = find_value(request, "method");
2501 if (valMethod.type() == null_type)
2502 throw JSONRPCError(-32600, "Missing method");
2503 if (valMethod.type() != str_type)
2504 throw JSONRPCError(-32600, "Method must be a string");
2505 string strMethod = valMethod.get_str();
2506 if (strMethod != "getwork" && strMethod != "getmemorypool")
2507 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2510 Value valParams = find_value(request, "params");
2512 if (valParams.type() == array_type)
2513 params = valParams.get_array();
2514 else if (valParams.type() == null_type)
2517 throw JSONRPCError(-32600, "Params must be an array");
2520 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2521 if (mi == mapCallTable.end())
2522 throw JSONRPCError(-32601, "Method not found");
2524 // Observe safe mode
2525 string strWarning = GetWarnings("rpc");
2526 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2527 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2533 CRITICAL_BLOCK(cs_main)
2534 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2535 result = (*(*mi).second)(params, false);
2538 string strReply = JSONRPCReply(result, Value::null, id);
2539 stream << HTTPReply(200, strReply) << std::flush;
2541 catch (std::exception& e)
2543 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2546 catch (Object& objError)
2548 ErrorReply(stream, objError, id);
2550 catch (std::exception& e)
2552 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2560 Object CallRPC(const string& strMethod, const Array& params)
2562 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2563 throw runtime_error(strprintf(
2564 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2565 "If the file does not exist, create it with owner-readable-only file permissions."),
2566 GetConfigFile().c_str()));
2568 // Connect to localhost
2569 bool fUseSSL = GetBoolArg("-rpcssl");
2571 asio::io_service io_service;
2572 ssl::context context(io_service, ssl::context::sslv23);
2573 context.set_options(ssl::context::no_sslv2);
2574 SSLStream sslStream(io_service, context);
2575 SSLIOStreamDevice d(sslStream, fUseSSL);
2576 iostreams::stream<SSLIOStreamDevice> stream(d);
2577 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2578 throw runtime_error("couldn't connect to server");
2581 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2583 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2585 throw runtime_error("couldn't connect to server");
2589 // HTTP basic authentication
2590 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2591 map<string, string> mapRequestHeaders;
2592 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2595 string strRequest = JSONRPCRequest(strMethod, params, 1);
2596 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2597 stream << strPost << std::flush;
2600 map<string, string> mapHeaders;
2602 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2604 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2605 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2606 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2607 else if (strReply.empty())
2608 throw runtime_error("no response from server");
2612 if (!read_string(strReply, valReply))
2613 throw runtime_error("couldn't parse reply from server");
2614 const Object& reply = valReply.get_obj();
2616 throw runtime_error("expected reply to have result, error and id properties");
2624 template<typename T>
2625 void ConvertTo(Value& value)
2627 if (value.type() == str_type)
2629 // reinterpret string as unquoted json value
2631 if (!read_string(value.get_str(), value2))
2632 throw runtime_error("type mismatch");
2633 value = value2.get_value<T>();
2637 value = value.get_value<T>();
2641 int CommandLineRPC(int argc, char *argv[])
2648 while (argc > 1 && IsSwitchChar(argv[1][0]))
2656 throw runtime_error("too few parameters");
2657 string strMethod = argv[1];
2659 // Parameters default to strings
2661 for (int i = 2; i < argc; i++)
2662 params.push_back(argv[i]);
2663 int n = params.size();
2666 // Special case non-string parameter types
2668 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2669 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2670 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2671 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2672 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2673 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2675 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2676 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2677 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2678 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2679 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2680 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2681 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2682 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2683 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2684 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2685 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2686 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2687 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2688 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2689 if (strMethod == "sendmany" && n > 1)
2691 string s = params[1].get_str();
2693 if (!read_string(s, v) || v.type() != obj_type)
2694 throw runtime_error("type mismatch");
2695 params[1] = v.get_obj();
2697 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2698 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2699 if (strMethod == "addmultisigaddress" && n > 1)
2701 string s = params[1].get_str();
2703 if (!read_string(s, v) || v.type() != array_type)
2704 throw runtime_error("type mismatch "+s);
2705 params[1] = v.get_array();
2709 Object reply = CallRPC(strMethod, params);
2712 const Value& result = find_value(reply, "result");
2713 const Value& error = find_value(reply, "error");
2715 if (error.type() != null_type)
2718 strPrint = "error: " + write_string(error, false);
2719 int code = find_value(error.get_obj(), "code").get_int();
2725 if (result.type() == null_type)
2727 else if (result.type() == str_type)
2728 strPrint = result.get_str();
2730 strPrint = write_string(result, true);
2733 catch (std::exception& e)
2735 strPrint = string("error: ") + e.what();
2740 PrintException(NULL, "CommandLineRPC()");
2745 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2754 int main(int argc, char *argv[])
2757 // Turn off microsoft heap dump noise
2758 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2759 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2761 setbuf(stdin, NULL);
2762 setbuf(stdout, NULL);
2763 setbuf(stderr, NULL);
2767 if (argc >= 2 && string(argv[1]) == "-server")
2769 printf("server ready\n");
2770 ThreadRPCServer(NULL);
2774 return CommandLineRPC(argc, argv);
2777 catch (std::exception& e) {
2778 PrintException(&e, "main()");
2780 PrintException(NULL, "main()");