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 / 1000));
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 = GetTimeMillis() + *((int*)parg) * 1000;
1542 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1544 if (nWalletUnlockTime == 0)
1546 nWalletUnlockTime = nMyWakeTime;
1550 if (nWalletUnlockTime==0)
1552 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1556 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1558 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1562 if (nWalletUnlockTime)
1564 nWalletUnlockTime = 0;
1565 pwalletMain->Lock();
1570 if (nWalletUnlockTime < nMyWakeTime)
1571 nWalletUnlockTime = nMyWakeTime;
1574 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1579 Value walletpassphrase(const Array& params, bool fHelp)
1581 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1582 throw runtime_error(
1583 "walletpassphrase <passphrase> <timeout>\n"
1584 "Stores the wallet decryption key in memory for <timeout> seconds.");
1587 if (!pwalletMain->IsCrypted())
1588 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1590 if (!pwalletMain->IsLocked())
1591 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1593 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1594 SecureString strWalletPass;
1595 strWalletPass.reserve(100);
1596 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1597 // Alternately, find a way to make params[0] mlock()'d to begin with.
1598 strWalletPass = params[0].get_str().c_str();
1600 if (strWalletPass.length() > 0)
1602 if (!pwalletMain->Unlock(strWalletPass))
1603 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1606 throw runtime_error(
1607 "walletpassphrase <passphrase> <timeout>\n"
1608 "Stores the wallet decryption key in memory for <timeout> seconds.");
1610 CreateThread(ThreadTopUpKeyPool, NULL);
1611 int* pnSleepTime = new int(params[1].get_int());
1612 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1618 Value walletpassphrasechange(const Array& params, bool fHelp)
1620 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1621 throw runtime_error(
1622 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1623 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1626 if (!pwalletMain->IsCrypted())
1627 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1629 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1630 // Alternately, find a way to make params[0] mlock()'d to begin with.
1631 SecureString strOldWalletPass;
1632 strOldWalletPass.reserve(100);
1633 strOldWalletPass = params[0].get_str().c_str();
1635 SecureString strNewWalletPass;
1636 strNewWalletPass.reserve(100);
1637 strNewWalletPass = params[1].get_str().c_str();
1639 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1640 throw runtime_error(
1641 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1642 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1644 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1645 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1651 Value walletlock(const Array& params, bool fHelp)
1653 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1654 throw runtime_error(
1656 "Removes the wallet encryption key from memory, locking the wallet.\n"
1657 "After calling this method, you will need to call walletpassphrase again\n"
1658 "before being able to call any methods which require the wallet to be unlocked.");
1661 if (!pwalletMain->IsCrypted())
1662 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1664 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1666 pwalletMain->Lock();
1667 nWalletUnlockTime = 0;
1674 Value encryptwallet(const Array& params, bool fHelp)
1676 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1677 throw runtime_error(
1678 "encryptwallet <passphrase>\n"
1679 "Encrypts the wallet with <passphrase>.");
1682 if (pwalletMain->IsCrypted())
1683 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1686 // shutting down via RPC while the GUI is running does not work (yet):
1687 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1690 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1691 // Alternately, find a way to make params[0] mlock()'d to begin with.
1692 SecureString strWalletPass;
1693 strWalletPass.reserve(100);
1694 strWalletPass = params[0].get_str().c_str();
1696 if (strWalletPass.length() < 1)
1697 throw runtime_error(
1698 "encryptwallet <passphrase>\n"
1699 "Encrypts the wallet with <passphrase>.");
1701 if (!pwalletMain->EncryptWallet(strWalletPass))
1702 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1704 // BDB seems to have a bad habit of writing old data into
1705 // slack space in .dat files; that is bad if the old data is
1706 // unencrypted private keys. So:
1707 CreateThread(Shutdown, NULL);
1708 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1712 Value validateaddress(const Array& params, bool fHelp)
1714 if (fHelp || params.size() != 1)
1715 throw runtime_error(
1716 "validateaddress <bitcoinaddress>\n"
1717 "Return information about <bitcoinaddress>.");
1719 CBitcoinAddress address(params[0].get_str());
1720 bool isValid = address.IsValid();
1723 ret.push_back(Pair("isvalid", isValid));
1726 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1727 // version of the address:
1728 string currentAddress = address.ToString();
1729 ret.push_back(Pair("address", currentAddress));
1730 if (pwalletMain->HaveKey(address))
1732 ret.push_back(Pair("ismine", true));
1733 std::vector<unsigned char> vchPubKey;
1734 pwalletMain->GetPubKey(address, vchPubKey);
1735 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1737 key.SetPubKey(vchPubKey);
1738 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1740 else if (pwalletMain->HaveCScript(address.GetHash160()))
1742 ret.push_back(Pair("isscript", true));
1744 pwalletMain->GetCScript(address.GetHash160(), subscript);
1745 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1746 std::vector<CBitcoinAddress> addresses;
1747 txnouttype whichType;
1749 ExtractAddresses(subscript, whichType, addresses, nRequired);
1750 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1752 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1753 a.push_back(addr.ToString());
1754 ret.push_back(Pair("addresses", a));
1755 if (whichType == TX_MULTISIG)
1756 ret.push_back(Pair("sigsrequired", nRequired));
1759 ret.push_back(Pair("ismine", false));
1760 if (pwalletMain->mapAddressBook.count(address))
1761 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1766 Value getwork(const Array& params, bool fHelp)
1768 if (fHelp || params.size() > 1)
1769 throw runtime_error(
1771 "If [data] is not specified, returns formatted hash data to work on:\n"
1772 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1773 " \"data\" : block data\n"
1774 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1775 " \"target\" : little endian hash target\n"
1776 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1779 throw JSONRPCError(-9, "Bitcoin is not connected!");
1781 if (IsInitialBlockDownload())
1782 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1784 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1785 static mapNewBlock_t mapNewBlock;
1786 static vector<CBlock*> vNewBlock;
1787 static CReserveKey reservekey(pwalletMain);
1789 if (params.size() == 0)
1792 static unsigned int nTransactionsUpdatedLast;
1793 static CBlockIndex* pindexPrev;
1794 static int64 nStart;
1795 static CBlock* pblock;
1796 if (pindexPrev != pindexBest ||
1797 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1799 if (pindexPrev != pindexBest)
1801 // Deallocate old blocks since they're obsolete now
1802 mapNewBlock.clear();
1803 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1807 nTransactionsUpdatedLast = nTransactionsUpdated;
1808 pindexPrev = pindexBest;
1812 pblock = CreateNewBlock(reservekey);
1814 throw JSONRPCError(-7, "Out of memory");
1815 vNewBlock.push_back(pblock);
1819 pblock->UpdateTime(pindexPrev);
1822 // Update nExtraNonce
1823 static unsigned int nExtraNonce = 0;
1824 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1827 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1829 // Prebuild hash buffers
1833 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1835 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1838 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1839 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1840 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1841 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1847 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1848 if (vchData.size() != 128)
1849 throw JSONRPCError(-8, "Invalid parameter");
1850 CBlock* pdata = (CBlock*)&vchData[0];
1853 for (int i = 0; i < 128/4; i++)
1854 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1857 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1859 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1861 pblock->nTime = pdata->nTime;
1862 pblock->nNonce = pdata->nNonce;
1863 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1864 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1866 return CheckWork(pblock, *pwalletMain, reservekey);
1871 Value getmemorypool(const Array& params, bool fHelp)
1873 if (fHelp || params.size() > 1)
1874 throw runtime_error(
1875 "getmemorypool [data]\n"
1876 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1877 " \"version\" : block version\n"
1878 " \"previousblockhash\" : hash of current highest block\n"
1879 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1880 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1881 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1882 " \"time\" : timestamp appropriate for next block\n"
1883 " \"mintime\" : minimum timestamp appropriate for next block\n"
1884 " \"curtime\" : current timestamp\n"
1885 " \"bits\" : compressed target of next block\n"
1886 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1888 if (params.size() == 0)
1891 throw JSONRPCError(-9, "Bitcoin is not connected!");
1893 if (IsInitialBlockDownload())
1894 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1896 static CReserveKey reservekey(pwalletMain);
1899 static unsigned int nTransactionsUpdatedLast;
1900 static CBlockIndex* pindexPrev;
1901 static int64 nStart;
1902 static CBlock* pblock;
1903 if (pindexPrev != pindexBest ||
1904 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1906 nTransactionsUpdatedLast = nTransactionsUpdated;
1907 pindexPrev = pindexBest;
1913 pblock = CreateNewBlock(reservekey);
1915 throw JSONRPCError(-7, "Out of memory");
1919 pblock->UpdateTime(pindexPrev);
1923 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1930 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1934 result.push_back(Pair("version", pblock->nVersion));
1935 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1936 result.push_back(Pair("transactions", transactions));
1937 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1938 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1939 result.push_back(Pair("time", (int64_t)pblock->nTime));
1940 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1941 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1947 uBits.nBits = htonl((int32_t)pblock->nBits);
1948 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1955 CDataStream ssBlock(ParseHex(params[0].get_str()));
1959 return ProcessBlock(NULL, &pblock);
1963 Value getblockhash(const Array& params, bool fHelp)
1965 if (fHelp || params.size() != 1)
1966 throw runtime_error(
1967 "getblockhash <index>\n"
1968 "Returns hash of block in best-block-chain at <index>.");
1970 int nHeight = params[0].get_int();
1971 if (nHeight < 0 || nHeight > nBestHeight)
1972 throw runtime_error("Block number out of range.");
1975 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1976 while (pblockindex->nHeight > nHeight)
1977 pblockindex = pblockindex->pprev;
1978 return pblockindex->phashBlock->GetHex();
1981 Value getblock(const Array& params, bool fHelp)
1983 if (fHelp || params.size() != 1)
1984 throw runtime_error(
1986 "Returns details of a block with given block-hash.");
1988 std::string strHash = params[0].get_str();
1989 uint256 hash(strHash);
1991 if (mapBlockIndex.count(hash) == 0)
1992 throw JSONRPCError(-5, "Block not found");
1995 CBlockIndex* pblockindex = mapBlockIndex[hash];
1996 block.ReadFromDisk(pblockindex, true);
1998 return blockToJSON(block, pblockindex);
2015 pair<string, rpcfn_type> pCallTable[] =
2017 make_pair("help", &help),
2018 make_pair("stop", &stop),
2019 make_pair("getblockcount", &getblockcount),
2020 make_pair("getblocknumber", &getblocknumber),
2021 make_pair("getconnectioncount", &getconnectioncount),
2022 make_pair("getdifficulty", &getdifficulty),
2023 make_pair("getgenerate", &getgenerate),
2024 make_pair("setgenerate", &setgenerate),
2025 make_pair("gethashespersec", &gethashespersec),
2026 make_pair("getinfo", &getinfo),
2027 make_pair("getmininginfo", &getmininginfo),
2028 make_pair("getnewaddress", &getnewaddress),
2029 make_pair("getaccountaddress", &getaccountaddress),
2030 make_pair("setaccount", &setaccount),
2031 make_pair("getaccount", &getaccount),
2032 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2033 make_pair("sendtoaddress", &sendtoaddress),
2034 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2035 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2036 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2037 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2038 make_pair("backupwallet", &backupwallet),
2039 make_pair("keypoolrefill", &keypoolrefill),
2040 make_pair("walletpassphrase", &walletpassphrase),
2041 make_pair("walletpassphrasechange", &walletpassphrasechange),
2042 make_pair("walletlock", &walletlock),
2043 make_pair("encryptwallet", &encryptwallet),
2044 make_pair("validateaddress", &validateaddress),
2045 make_pair("getbalance", &getbalance),
2046 make_pair("move", &movecmd),
2047 make_pair("sendfrom", &sendfrom),
2048 make_pair("sendmany", &sendmany),
2049 make_pair("addmultisigaddress", &addmultisigaddress),
2050 make_pair("getblock", &getblock),
2051 make_pair("getblockhash", &getblockhash),
2052 make_pair("gettransaction", &gettransaction),
2053 make_pair("listtransactions", &listtransactions),
2054 make_pair("signmessage", &signmessage),
2055 make_pair("verifymessage", &verifymessage),
2056 make_pair("getwork", &getwork),
2057 make_pair("listaccounts", &listaccounts),
2058 make_pair("settxfee", &settxfee),
2059 make_pair("getmemorypool", &getmemorypool),
2060 make_pair("listsinceblock", &listsinceblock),
2061 make_pair("dumpprivkey", &dumpprivkey),
2062 make_pair("importprivkey", &importprivkey)
2064 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2066 string pAllowInSafeMode[] =
2071 "getblocknumber", // deprecated
2072 "getconnectioncount",
2080 "getaccountaddress",
2082 "getaddressesbyaccount",
2091 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2099 // This ain't Apache. We're just using HTTP header for the length field
2100 // and to be compatible with other JSON-RPC implementations.
2103 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2106 s << "POST / HTTP/1.1\r\n"
2107 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2108 << "Host: 127.0.0.1\r\n"
2109 << "Content-Type: application/json\r\n"
2110 << "Content-Length: " << strMsg.size() << "\r\n"
2111 << "Connection: close\r\n"
2112 << "Accept: application/json\r\n";
2113 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2114 s << item.first << ": " << item.second << "\r\n";
2115 s << "\r\n" << strMsg;
2120 string rfc1123Time()
2125 struct tm* now_gmt = gmtime(&now);
2126 string locale(setlocale(LC_TIME, NULL));
2127 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2128 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2129 setlocale(LC_TIME, locale.c_str());
2130 return string(buffer);
2133 static string HTTPReply(int nStatus, const string& strMsg)
2136 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2138 "Server: bitcoin-json-rpc/%s\r\n"
2139 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2140 "Content-Type: text/html\r\n"
2141 "Content-Length: 296\r\n"
2143 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2144 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2147 "<TITLE>Error</TITLE>\r\n"
2148 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2150 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2151 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2152 const char *cStatus;
2153 if (nStatus == 200) cStatus = "OK";
2154 else if (nStatus == 400) cStatus = "Bad Request";
2155 else if (nStatus == 403) cStatus = "Forbidden";
2156 else if (nStatus == 404) cStatus = "Not Found";
2157 else if (nStatus == 500) cStatus = "Internal Server Error";
2160 "HTTP/1.1 %d %s\r\n"
2162 "Connection: close\r\n"
2163 "Content-Length: %d\r\n"
2164 "Content-Type: application/json\r\n"
2165 "Server: bitcoin-json-rpc/%s\r\n"
2170 rfc1123Time().c_str(),
2172 FormatFullVersion().c_str(),
2176 int ReadHTTPStatus(std::basic_istream<char>& stream)
2179 getline(stream, str);
2180 vector<string> vWords;
2181 boost::split(vWords, str, boost::is_any_of(" "));
2182 if (vWords.size() < 2)
2184 return atoi(vWords[1].c_str());
2187 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2193 std::getline(stream, str);
2194 if (str.empty() || str == "\r")
2196 string::size_type nColon = str.find(":");
2197 if (nColon != string::npos)
2199 string strHeader = str.substr(0, nColon);
2200 boost::trim(strHeader);
2201 boost::to_lower(strHeader);
2202 string strValue = str.substr(nColon+1);
2203 boost::trim(strValue);
2204 mapHeadersRet[strHeader] = strValue;
2205 if (strHeader == "content-length")
2206 nLen = atoi(strValue.c_str());
2212 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2214 mapHeadersRet.clear();
2218 int nStatus = ReadHTTPStatus(stream);
2221 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2222 if (nLen < 0 || nLen > MAX_SIZE)
2228 vector<char> vch(nLen);
2229 stream.read(&vch[0], nLen);
2230 strMessageRet = string(vch.begin(), vch.end());
2236 bool HTTPAuthorized(map<string, string>& mapHeaders)
2238 string strAuth = mapHeaders["authorization"];
2239 if (strAuth.substr(0,6) != "Basic ")
2241 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2242 string strUserPass = DecodeBase64(strUserPass64);
2243 return strUserPass == strRPCUserColonPass;
2247 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2248 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2249 // unspecified (HTTP errors and contents of 'error').
2251 // 1.0 spec: http://json-rpc.org/wiki/specification
2252 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2253 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2256 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2259 request.push_back(Pair("method", strMethod));
2260 request.push_back(Pair("params", params));
2261 request.push_back(Pair("id", id));
2262 return write_string(Value(request), false) + "\n";
2265 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2268 if (error.type() != null_type)
2269 reply.push_back(Pair("result", Value::null));
2271 reply.push_back(Pair("result", result));
2272 reply.push_back(Pair("error", error));
2273 reply.push_back(Pair("id", id));
2274 return write_string(Value(reply), false) + "\n";
2277 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2279 // Send error reply from json-rpc error object
2281 int code = find_value(objError, "code").get_int();
2282 if (code == -32600) nStatus = 400;
2283 else if (code == -32601) nStatus = 404;
2284 string strReply = JSONRPCReply(Value::null, objError, id);
2285 stream << HTTPReply(nStatus, strReply) << std::flush;
2288 bool ClientAllowed(const string& strAddress)
2290 if (strAddress == asio::ip::address_v4::loopback().to_string())
2292 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2293 BOOST_FOREACH(string strAllow, vAllow)
2294 if (WildcardMatch(strAddress, strAllow))
2301 // IOStream device that speaks SSL but can also speak non-SSL
2303 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2305 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2307 fUseSSL = fUseSSLIn;
2308 fNeedHandshake = fUseSSLIn;
2311 void handshake(ssl::stream_base::handshake_type role)
2313 if (!fNeedHandshake) return;
2314 fNeedHandshake = false;
2315 stream.handshake(role);
2317 std::streamsize read(char* s, std::streamsize n)
2319 handshake(ssl::stream_base::server); // HTTPS servers read first
2320 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2321 return stream.next_layer().read_some(asio::buffer(s, n));
2323 std::streamsize write(const char* s, std::streamsize n)
2325 handshake(ssl::stream_base::client); // HTTPS clients write first
2326 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2327 return asio::write(stream.next_layer(), asio::buffer(s, n));
2329 bool connect(const std::string& server, const std::string& port)
2331 ip::tcp::resolver resolver(stream.get_io_service());
2332 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2333 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2334 ip::tcp::resolver::iterator end;
2335 boost::system::error_code error = asio::error::host_not_found;
2336 while (error && endpoint_iterator != end)
2338 stream.lowest_layer().close();
2339 stream.lowest_layer().connect(*endpoint_iterator++, error);
2347 bool fNeedHandshake;
2353 void ThreadRPCServer(void* parg)
2355 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2358 vnThreadsRunning[THREAD_RPCSERVER]++;
2359 ThreadRPCServer2(parg);
2360 vnThreadsRunning[THREAD_RPCSERVER]--;
2362 catch (std::exception& e) {
2363 vnThreadsRunning[THREAD_RPCSERVER]--;
2364 PrintException(&e, "ThreadRPCServer()");
2366 vnThreadsRunning[THREAD_RPCSERVER]--;
2367 PrintException(NULL, "ThreadRPCServer()");
2369 printf("ThreadRPCServer exiting\n");
2372 void ThreadRPCServer2(void* parg)
2374 printf("ThreadRPCServer started\n");
2376 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2377 if (mapArgs["-rpcpassword"] == "")
2379 unsigned char rand_pwd[32];
2380 RAND_bytes(rand_pwd, 32);
2381 string strWhatAmI = "To use bitcoind";
2382 if (mapArgs.count("-server"))
2383 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2384 else if (mapArgs.count("-daemon"))
2385 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2387 _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2388 "It is recommended you use the following random password:\n"
2389 "rpcuser=bitcoinrpc\n"
2391 "(you do not need to remember this password)\n"
2392 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2394 GetConfigFile().c_str(),
2395 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2397 CreateThread(Shutdown, NULL);
2402 bool fUseSSL = GetBoolArg("-rpcssl");
2403 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2405 asio::io_service io_service;
2406 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2407 ip::tcp::acceptor acceptor(io_service, endpoint);
2409 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2412 ssl::context context(io_service, ssl::context::sslv23);
2415 context.set_options(ssl::context::no_sslv2);
2416 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2417 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2418 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2419 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2420 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2421 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2422 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2423 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2425 string ciphers = GetArg("-rpcsslciphers",
2426 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2427 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2431 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2436 // Accept connection
2438 SSLStream sslStream(io_service, context);
2439 SSLIOStreamDevice d(sslStream, fUseSSL);
2440 iostreams::stream<SSLIOStreamDevice> stream(d);
2442 ip::tcp::iostream stream;
2445 ip::tcp::endpoint peer;
2446 vnThreadsRunning[THREAD_RPCSERVER]--;
2448 acceptor.accept(sslStream.lowest_layer(), peer);
2450 acceptor.accept(*stream.rdbuf(), peer);
2452 vnThreadsRunning[4]++;
2456 // Restrict callers by IP
2457 if (!ClientAllowed(peer.address().to_string()))
2459 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2461 stream << HTTPReply(403, "") << std::flush;
2465 map<string, string> mapHeaders;
2468 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2469 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2472 printf("ThreadRPCServer ReadHTTP timeout\n");
2476 // Check authorization
2477 if (mapHeaders.count("authorization") == 0)
2479 stream << HTTPReply(401, "") << std::flush;
2482 if (!HTTPAuthorized(mapHeaders))
2484 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2485 /* Deter brute-forcing short passwords.
2486 If this results in a DOS the user really
2487 shouldn't have their RPC port exposed.*/
2488 if (mapArgs["-rpcpassword"].size() < 20)
2491 stream << HTTPReply(401, "") << std::flush;
2495 Value id = Value::null;
2500 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2501 throw JSONRPCError(-32700, "Parse error");
2502 const Object& request = valRequest.get_obj();
2504 // Parse id now so errors from here on will have the id
2505 id = find_value(request, "id");
2508 Value valMethod = find_value(request, "method");
2509 if (valMethod.type() == null_type)
2510 throw JSONRPCError(-32600, "Missing method");
2511 if (valMethod.type() != str_type)
2512 throw JSONRPCError(-32600, "Method must be a string");
2513 string strMethod = valMethod.get_str();
2514 if (strMethod != "getwork" && strMethod != "getmemorypool")
2515 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2518 Value valParams = find_value(request, "params");
2520 if (valParams.type() == array_type)
2521 params = valParams.get_array();
2522 else if (valParams.type() == null_type)
2525 throw JSONRPCError(-32600, "Params must be an array");
2528 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2529 if (mi == mapCallTable.end())
2530 throw JSONRPCError(-32601, "Method not found");
2532 // Observe safe mode
2533 string strWarning = GetWarnings("rpc");
2534 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2535 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2541 CRITICAL_BLOCK(cs_main)
2542 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2543 result = (*(*mi).second)(params, false);
2546 string strReply = JSONRPCReply(result, Value::null, id);
2547 stream << HTTPReply(200, strReply) << std::flush;
2549 catch (std::exception& e)
2551 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2554 catch (Object& objError)
2556 ErrorReply(stream, objError, id);
2558 catch (std::exception& e)
2560 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2568 Object CallRPC(const string& strMethod, const Array& params)
2570 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2571 throw runtime_error(strprintf(
2572 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2573 "If the file does not exist, create it with owner-readable-only file permissions."),
2574 GetConfigFile().c_str()));
2576 // Connect to localhost
2577 bool fUseSSL = GetBoolArg("-rpcssl");
2579 asio::io_service io_service;
2580 ssl::context context(io_service, ssl::context::sslv23);
2581 context.set_options(ssl::context::no_sslv2);
2582 SSLStream sslStream(io_service, context);
2583 SSLIOStreamDevice d(sslStream, fUseSSL);
2584 iostreams::stream<SSLIOStreamDevice> stream(d);
2585 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2586 throw runtime_error("couldn't connect to server");
2589 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2591 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2593 throw runtime_error("couldn't connect to server");
2597 // HTTP basic authentication
2598 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2599 map<string, string> mapRequestHeaders;
2600 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2603 string strRequest = JSONRPCRequest(strMethod, params, 1);
2604 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2605 stream << strPost << std::flush;
2608 map<string, string> mapHeaders;
2610 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2612 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2613 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2614 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2615 else if (strReply.empty())
2616 throw runtime_error("no response from server");
2620 if (!read_string(strReply, valReply))
2621 throw runtime_error("couldn't parse reply from server");
2622 const Object& reply = valReply.get_obj();
2624 throw runtime_error("expected reply to have result, error and id properties");
2632 template<typename T>
2633 void ConvertTo(Value& value)
2635 if (value.type() == str_type)
2637 // reinterpret string as unquoted json value
2639 if (!read_string(value.get_str(), value2))
2640 throw runtime_error("type mismatch");
2641 value = value2.get_value<T>();
2645 value = value.get_value<T>();
2649 int CommandLineRPC(int argc, char *argv[])
2656 while (argc > 1 && IsSwitchChar(argv[1][0]))
2664 throw runtime_error("too few parameters");
2665 string strMethod = argv[1];
2667 // Parameters default to strings
2669 for (int i = 2; i < argc; i++)
2670 params.push_back(argv[i]);
2671 int n = params.size();
2674 // Special case non-string parameter types
2676 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2677 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2678 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2679 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2680 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2681 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2682 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2683 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2684 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2685 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2686 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2687 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2688 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2689 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2690 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2691 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2692 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2693 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2694 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2695 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2696 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2697 if (strMethod == "sendmany" && n > 1)
2699 string s = params[1].get_str();
2701 if (!read_string(s, v) || v.type() != obj_type)
2702 throw runtime_error("type mismatch");
2703 params[1] = v.get_obj();
2705 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2706 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2707 if (strMethod == "addmultisigaddress" && n > 1)
2709 string s = params[1].get_str();
2711 if (!read_string(s, v) || v.type() != array_type)
2712 throw runtime_error("type mismatch "+s);
2713 params[1] = v.get_array();
2717 Object reply = CallRPC(strMethod, params);
2720 const Value& result = find_value(reply, "result");
2721 const Value& error = find_value(reply, "error");
2723 if (error.type() != null_type)
2726 strPrint = "error: " + write_string(error, false);
2727 int code = find_value(error.get_obj(), "code").get_int();
2733 if (result.type() == null_type)
2735 else if (result.type() == str_type)
2736 strPrint = result.get_str();
2738 strPrint = write_string(result, true);
2741 catch (std::exception& e)
2743 strPrint = string("error: ") + e.what();
2748 PrintException(NULL, "CommandLineRPC()");
2753 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2762 int main(int argc, char *argv[])
2765 // Turn off microsoft heap dump noise
2766 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2767 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2769 setbuf(stdin, NULL);
2770 setbuf(stdout, NULL);
2771 setbuf(stderr, NULL);
2775 if (argc >= 2 && string(argv[1]) == "-server")
2777 printf("server ready\n");
2778 ThreadRPCServer(NULL);
2782 return CommandLineRPC(argc, argv);
2785 catch (std::exception& e) {
2786 PrintException(&e, "main()");
2788 PrintException(NULL, "main()");