1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
58 void PrintConsole(const std::string &format, ...)
61 int limit = sizeof(buffer);
63 va_start(arg_ptr, format);
64 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
66 if (ret < 0 || ret >= limit)
72 fprintf(stdout, "%s", buffer);
75 double GetDifficulty(const CBlockIndex* blockindex = NULL)
77 // Floating point number that is a multiple of the minimum difficulty,
78 // minimum difficulty = 1.0.
79 if (blockindex == NULL)
81 if (pindexBest == NULL)
84 blockindex = pindexBest;
87 int nShift = (blockindex->nBits >> 24) & 0xff;
90 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
107 int64 AmountFromValue(const Value& value)
109 double dAmount = value.get_real();
110 if (dAmount <= 0.0 || dAmount > 21000000.0)
111 throw JSONRPCError(-3, "Invalid amount");
112 int64 nAmount = roundint64(dAmount * COIN);
113 if (!MoneyRange(nAmount))
114 throw JSONRPCError(-3, "Invalid amount");
118 Value ValueFromAmount(int64 amount)
120 return (double)amount / (double)COIN;
123 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
125 int confirms = wtx.GetDepthInMainChain();
126 entry.push_back(Pair("confirmations", confirms));
129 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
130 entry.push_back(Pair("blockindex", wtx.nIndex));
132 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
133 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
134 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
135 entry.push_back(Pair(item.first, item.second));
138 string AccountFromValue(const Value& value)
140 string strAccount = value.get_str();
141 if (strAccount == "*")
142 throw JSONRPCError(-11, "Invalid account name");
146 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
149 result.push_back(Pair("hash", block.GetHash().GetHex()));
150 result.push_back(Pair("blockcount", blockindex->nHeight));
151 result.push_back(Pair("version", block.nVersion));
152 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
153 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
154 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
155 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
157 BOOST_FOREACH (const CTransaction&tx, block.vtx)
158 txhashes.push_back(tx.GetHash().GetHex());
159 result.push_back(Pair("tx", txhashes));
161 if (blockindex->pprev)
162 result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex()));
163 if (blockindex->pnext)
164 result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex()));
171 /// Note: This interface may still be subject to change.
175 Value help(const Array& params, bool fHelp)
177 if (fHelp || params.size() > 1)
180 "List commands, or get help for a command.");
183 if (params.size() > 0)
184 strCommand = params[0].get_str();
187 set<rpcfn_type> setDone;
188 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
190 string strMethod = (*mi).first;
191 // We already filter duplicates, but these deprecated screw up the sort order
192 if (strMethod == "getamountreceived" ||
193 strMethod == "getallreceived" ||
194 strMethod == "getblocknumber" || // deprecated
195 (strMethod.find("label") != string::npos))
197 if (strCommand != "" && strMethod != strCommand)
202 rpcfn_type pfn = (*mi).second;
203 if (setDone.insert(pfn).second)
204 (*pfn)(params, true);
206 catch (std::exception& e)
208 // Help text is returned in an exception
209 string strHelp = string(e.what());
210 if (strCommand == "")
211 if (strHelp.find('\n') != -1)
212 strHelp = strHelp.substr(0, strHelp.find('\n'));
213 strRet += strHelp + "\n";
217 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
218 strRet = strRet.substr(0,strRet.size()-1);
223 Value stop(const Array& params, bool fHelp)
225 if (fHelp || params.size() != 0)
228 "Stop bitcoin server.");
230 // Shutdown will take long enough that the response should get back
231 CreateThread(Shutdown, NULL);
232 return "bitcoin server stopping";
234 throw runtime_error("NYI: cannot shut down GUI with RPC command");
239 Value getblockcount(const Array& params, bool fHelp)
241 if (fHelp || params.size() != 0)
244 "Returns the number of blocks in the longest block chain.");
251 Value getblocknumber(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
256 "Deprecated. Use getblockcount.");
262 Value getconnectioncount(const Array& params, bool fHelp)
264 if (fHelp || params.size() != 0)
266 "getconnectioncount\n"
267 "Returns the number of connections to other nodes.");
269 return (int)vNodes.size();
273 Value getdifficulty(const Array& params, bool fHelp)
275 if (fHelp || params.size() != 0)
278 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
280 return GetDifficulty();
284 Value getgenerate(const Array& params, bool fHelp)
286 if (fHelp || params.size() != 0)
289 "Returns true or false.");
291 return (bool)fGenerateBitcoins;
295 Value setgenerate(const Array& params, bool fHelp)
297 if (fHelp || params.size() < 1 || params.size() > 2)
299 "setgenerate <generate> [genproclimit]\n"
300 "<generate> is true or false to turn generation on or off.\n"
301 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
303 bool fGenerate = true;
304 if (params.size() > 0)
305 fGenerate = params[0].get_bool();
307 if (params.size() > 1)
309 int nGenProcLimit = params[1].get_int();
310 fLimitProcessors = (nGenProcLimit != -1);
311 WriteSetting("fLimitProcessors", fLimitProcessors);
312 if (nGenProcLimit != -1)
313 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
314 if (nGenProcLimit == 0)
318 GenerateBitcoins(fGenerate, pwalletMain);
323 Value gethashespersec(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 0)
328 "Returns a recent hashes per second performance measurement while generating.");
330 if (GetTimeMillis() - nHPSTimerStart > 8000)
331 return (boost::int64_t)0;
332 return (boost::int64_t)dHashesPerSec;
336 Value getinfo(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 0)
341 "Returns an object containing various state info.");
344 obj.push_back(Pair("version", (int)CLIENT_VERSION));
345 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
346 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
347 obj.push_back(Pair("blocks", (int)nBestHeight));
348 obj.push_back(Pair("connections", (int)vNodes.size()));
349 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
350 obj.push_back(Pair("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 static const string strMessageMagic = "Bitcoin Signed Message:\n";
594 Value signmessage(const Array& params, bool fHelp)
596 if (fHelp || params.size() != 2)
598 "signmessage <bitcoinaddress> <message>\n"
599 "Sign a message with the private key of an address");
601 if (pwalletMain->IsLocked())
602 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
604 string strAddress = params[0].get_str();
605 string strMessage = params[1].get_str();
607 CBitcoinAddress addr(strAddress);
609 throw JSONRPCError(-3, "Invalid address");
612 if (!pwalletMain->GetKey(addr, key))
613 throw JSONRPCError(-4, "Private key not available");
615 CDataStream ss(SER_GETHASH);
616 ss << strMessageMagic;
619 vector<unsigned char> vchSig;
620 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
621 throw JSONRPCError(-5, "Sign failed");
623 return EncodeBase64(&vchSig[0], vchSig.size());
626 Value verifymessage(const Array& params, bool fHelp)
628 if (fHelp || params.size() != 3)
630 "verifymessage <bitcoinaddress> <signature> <message>\n"
631 "Verify a signed message");
633 string strAddress = params[0].get_str();
634 string strSign = params[1].get_str();
635 string strMessage = params[2].get_str();
637 CBitcoinAddress addr(strAddress);
639 throw JSONRPCError(-3, "Invalid address");
641 bool fInvalid = false;
642 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
645 throw JSONRPCError(-5, "Malformed base64 encoding");
647 CDataStream ss(SER_GETHASH);
648 ss << strMessageMagic;
652 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
655 return (CBitcoinAddress(key.GetPubKey()) == addr);
659 Value getreceivedbyaddress(const Array& params, bool fHelp)
661 if (fHelp || params.size() < 1 || params.size() > 2)
663 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
664 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
667 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
668 CScript scriptPubKey;
669 if (!address.IsValid())
670 throw JSONRPCError(-5, "Invalid bitcoin address");
671 scriptPubKey.SetBitcoinAddress(address);
672 if (!IsMine(*pwalletMain,scriptPubKey))
675 // Minimum confirmations
677 if (params.size() > 1)
678 nMinDepth = params[1].get_int();
682 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
684 const CWalletTx& wtx = (*it).second;
685 if (wtx.IsCoinBase() || !wtx.IsFinal())
688 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
689 if (txout.scriptPubKey == scriptPubKey)
690 if (wtx.GetDepthInMainChain() >= nMinDepth)
691 nAmount += txout.nValue;
694 return ValueFromAmount(nAmount);
698 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
700 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
702 const CBitcoinAddress& address = item.first;
703 const string& strName = item.second;
704 if (strName == strAccount)
705 setAddress.insert(address);
710 Value getreceivedbyaccount(const Array& params, bool fHelp)
712 if (fHelp || params.size() < 1 || params.size() > 2)
714 "getreceivedbyaccount <account> [minconf=1]\n"
715 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
717 // Minimum confirmations
719 if (params.size() > 1)
720 nMinDepth = params[1].get_int();
722 // Get the set of pub keys assigned to account
723 string strAccount = AccountFromValue(params[0]);
724 set<CBitcoinAddress> setAddress;
725 GetAccountAddresses(strAccount, setAddress);
729 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
731 const CWalletTx& wtx = (*it).second;
732 if (wtx.IsCoinBase() || !wtx.IsFinal())
735 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
737 CBitcoinAddress address;
738 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
739 if (wtx.GetDepthInMainChain() >= nMinDepth)
740 nAmount += txout.nValue;
744 return (double)nAmount / (double)COIN;
748 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
752 // Tally wallet transactions
753 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
755 const CWalletTx& wtx = (*it).second;
759 int64 nGenerated, nReceived, nSent, nFee;
760 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
762 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
763 nBalance += nReceived;
764 nBalance += nGenerated - nSent - nFee;
767 // Tally internal accounting entries
768 nBalance += walletdb.GetAccountCreditDebit(strAccount);
773 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
775 CWalletDB walletdb(pwalletMain->strWalletFile);
776 return GetAccountBalance(walletdb, strAccount, nMinDepth);
780 Value getbalance(const Array& params, bool fHelp)
782 if (fHelp || params.size() > 2)
784 "getbalance [account] [minconf=1]\n"
785 "If [account] is not specified, returns the server's total available balance.\n"
786 "If [account] is specified, returns the balance in the account.");
788 if (params.size() == 0)
789 return ValueFromAmount(pwalletMain->GetBalance());
792 if (params.size() > 1)
793 nMinDepth = params[1].get_int();
795 if (params[0].get_str() == "*") {
796 // Calculate total balance a different way from GetBalance()
797 // (GetBalance() sums up all unspent TxOuts)
798 // getbalance and getbalance '*' should always return the same number.
800 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
802 const CWalletTx& wtx = (*it).second;
806 int64 allGeneratedImmature, allGeneratedMature, allFee;
807 allGeneratedImmature = allGeneratedMature = allFee = 0;
808 string strSentAccount;
809 list<pair<CBitcoinAddress, int64> > listReceived;
810 list<pair<CBitcoinAddress, int64> > listSent;
811 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
812 if (wtx.GetDepthInMainChain() >= nMinDepth)
813 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
814 nBalance += r.second;
815 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
816 nBalance -= r.second;
818 nBalance += allGeneratedMature;
820 return ValueFromAmount(nBalance);
823 string strAccount = AccountFromValue(params[0]);
825 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
827 return ValueFromAmount(nBalance);
831 Value movecmd(const Array& params, bool fHelp)
833 if (fHelp || params.size() < 3 || params.size() > 5)
835 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
836 "Move from one account in your wallet to another.");
838 string strFrom = AccountFromValue(params[0]);
839 string strTo = AccountFromValue(params[1]);
840 int64 nAmount = AmountFromValue(params[2]);
841 if (params.size() > 3)
842 // unused parameter, used to be nMinDepth, keep type-checking it though
843 (void)params[3].get_int();
845 if (params.size() > 4)
846 strComment = params[4].get_str();
848 CWalletDB walletdb(pwalletMain->strWalletFile);
851 int64 nNow = GetAdjustedTime();
854 CAccountingEntry debit;
855 debit.strAccount = strFrom;
856 debit.nCreditDebit = -nAmount;
858 debit.strOtherAccount = strTo;
859 debit.strComment = strComment;
860 walletdb.WriteAccountingEntry(debit);
863 CAccountingEntry credit;
864 credit.strAccount = strTo;
865 credit.nCreditDebit = nAmount;
867 credit.strOtherAccount = strFrom;
868 credit.strComment = strComment;
869 walletdb.WriteAccountingEntry(credit);
871 walletdb.TxnCommit();
877 Value sendfrom(const Array& params, bool fHelp)
879 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
881 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
882 "<amount> is a real and is rounded to the nearest 0.00000001\n"
883 "requires wallet passphrase to be set with walletpassphrase first");
884 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
886 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
887 "<amount> is a real and is rounded to the nearest 0.00000001");
889 string strAccount = AccountFromValue(params[0]);
890 CBitcoinAddress address(params[1].get_str());
891 if (!address.IsValid())
892 throw JSONRPCError(-5, "Invalid bitcoin address");
893 int64 nAmount = AmountFromValue(params[2]);
895 if (params.size() > 3)
896 nMinDepth = params[3].get_int();
899 wtx.strFromAccount = strAccount;
900 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
901 wtx.mapValue["comment"] = params[4].get_str();
902 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
903 wtx.mapValue["to"] = params[5].get_str();
905 if (pwalletMain->IsLocked())
906 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
909 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
910 if (nAmount > nBalance)
911 throw JSONRPCError(-6, "Account has insufficient funds");
914 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
916 throw JSONRPCError(-4, strError);
918 return wtx.GetHash().GetHex();
922 Value sendmany(const Array& params, bool fHelp)
924 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
926 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
927 "amounts are double-precision floating point numbers\n"
928 "requires wallet passphrase to be set with walletpassphrase first");
929 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
931 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
932 "amounts are double-precision floating point numbers");
934 string strAccount = AccountFromValue(params[0]);
935 Object sendTo = params[1].get_obj();
937 if (params.size() > 2)
938 nMinDepth = params[2].get_int();
941 wtx.strFromAccount = strAccount;
942 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
943 wtx.mapValue["comment"] = params[3].get_str();
945 set<CBitcoinAddress> setAddress;
946 vector<pair<CScript, int64> > vecSend;
948 int64 totalAmount = 0;
949 BOOST_FOREACH(const Pair& s, sendTo)
951 CBitcoinAddress address(s.name_);
952 if (!address.IsValid())
953 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
955 if (setAddress.count(address))
956 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
957 setAddress.insert(address);
959 CScript scriptPubKey;
960 scriptPubKey.SetBitcoinAddress(address);
961 int64 nAmount = AmountFromValue(s.value_);
962 totalAmount += nAmount;
964 vecSend.push_back(make_pair(scriptPubKey, nAmount));
967 if (pwalletMain->IsLocked())
968 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
971 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
972 if (totalAmount > nBalance)
973 throw JSONRPCError(-6, "Account has insufficient funds");
976 CReserveKey keyChange(pwalletMain);
977 int64 nFeeRequired = 0;
978 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
981 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
982 throw JSONRPCError(-6, "Insufficient funds");
983 throw JSONRPCError(-4, "Transaction creation failed");
985 if (!pwalletMain->CommitTransaction(wtx, keyChange))
986 throw JSONRPCError(-4, "Transaction commit failed");
988 return wtx.GetHash().GetHex();
991 Value addmultisigaddress(const Array& params, bool fHelp)
993 if (fHelp || params.size() < 2 || params.size() > 3)
995 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
996 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
997 "each key is a bitcoin address, hex or base58 public key\n"
998 "If [account] is specified, assign address to [account].";
999 throw runtime_error(msg);
1002 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1004 int nRequired = params[0].get_int();
1005 const Array& keys = params[1].get_array();
1007 if (params.size() > 2)
1008 strAccount = AccountFromValue(params[2]);
1010 // Gather public keys
1011 if (nRequired < 1 || keys.size() < nRequired)
1012 throw runtime_error(
1013 strprintf("wrong number of keys"
1014 "(got %d, need at least %d)", keys.size(), nRequired));
1015 std::vector<CKey> pubkeys;
1016 pubkeys.resize(keys.size());
1017 for (int i = 0; i < keys.size(); i++)
1019 const std::string& ks = keys[i].get_str();
1021 // Case 1: bitcoin address and we have full public key:
1022 CBitcoinAddress address(ks);
1023 if (address.IsValid())
1025 if (address.IsScript())
1026 throw runtime_error(
1027 strprintf("%s is a pay-to-script address",ks.c_str()));
1028 if (!pwalletMain->GetKey(address, pubkeys[i]))
1029 throw runtime_error(
1030 strprintf("no full public key for address %s",ks.c_str()));
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);
1040 // There is approximately a zero percent chance a random
1041 // public key encoded as base58 will consist entirely
1042 // of hex characters.
1045 // Case 3: base58-encoded public key
1047 vector<unsigned char> vchPubKey;
1048 if (!DecodeBase58(ks, vchPubKey))
1049 throw runtime_error("base58 decoding failed: "+ks);
1050 if (vchPubKey.size() < 33) // 33 is size of a compressed public key
1051 throw runtime_error("decoded public key too short: "+ks);
1052 if (pubkeys[i].SetPubKey(vchPubKey))
1056 throw runtime_error(" Invalid public key: "+ks);
1059 // Construct using pay-to-script-hash:
1061 inner.SetMultisig(nRequired, pubkeys);
1063 uint160 scriptHash = Hash160(inner);
1064 CScript scriptPubKey;
1065 scriptPubKey.SetPayToScriptHash(inner);
1066 pwalletMain->AddCScript(inner);
1067 CBitcoinAddress address;
1068 address.SetScriptHash160(scriptHash);
1070 pwalletMain->SetAddressBookName(address, strAccount);
1071 return address.ToString();
1082 nConf = std::numeric_limits<int>::max();
1086 Value ListReceived(const Array& params, bool fByAccounts)
1088 // Minimum confirmations
1090 if (params.size() > 0)
1091 nMinDepth = params[0].get_int();
1093 // Whether to include empty accounts
1094 bool fIncludeEmpty = false;
1095 if (params.size() > 1)
1096 fIncludeEmpty = params[1].get_bool();
1099 map<CBitcoinAddress, tallyitem> mapTally;
1100 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1102 const CWalletTx& wtx = (*it).second;
1104 if (wtx.IsCoinBase() || !wtx.IsFinal())
1107 int nDepth = wtx.GetDepthInMainChain();
1108 if (nDepth < nMinDepth)
1111 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1113 CBitcoinAddress address;
1114 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1117 tallyitem& item = mapTally[address];
1118 item.nAmount += txout.nValue;
1119 item.nConf = min(item.nConf, nDepth);
1125 map<string, tallyitem> mapAccountTally;
1126 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1128 const CBitcoinAddress& address = item.first;
1129 const string& strAccount = item.second;
1130 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1131 if (it == mapTally.end() && !fIncludeEmpty)
1135 int nConf = std::numeric_limits<int>::max();
1136 if (it != mapTally.end())
1138 nAmount = (*it).second.nAmount;
1139 nConf = (*it).second.nConf;
1144 tallyitem& item = mapAccountTally[strAccount];
1145 item.nAmount += nAmount;
1146 item.nConf = min(item.nConf, nConf);
1151 obj.push_back(Pair("address", address.ToString()));
1152 obj.push_back(Pair("account", strAccount));
1153 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1154 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1161 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1163 int64 nAmount = (*it).second.nAmount;
1164 int nConf = (*it).second.nConf;
1166 obj.push_back(Pair("account", (*it).first));
1167 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1168 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1176 Value listreceivedbyaddress(const Array& params, bool fHelp)
1178 if (fHelp || params.size() > 2)
1179 throw runtime_error(
1180 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1181 "[minconf] is the minimum number of confirmations before payments are included.\n"
1182 "[includeempty] whether to include addresses that haven't received any payments.\n"
1183 "Returns an array of objects containing:\n"
1184 " \"address\" : receiving address\n"
1185 " \"account\" : the account of the receiving address\n"
1186 " \"amount\" : total amount received by the address\n"
1187 " \"confirmations\" : number of confirmations of the most recent transaction included");
1189 return ListReceived(params, false);
1192 Value listreceivedbyaccount(const Array& params, bool fHelp)
1194 if (fHelp || params.size() > 2)
1195 throw runtime_error(
1196 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1197 "[minconf] is the minimum number of confirmations before payments are included.\n"
1198 "[includeempty] whether to include accounts that haven't received any payments.\n"
1199 "Returns an array of objects containing:\n"
1200 " \"account\" : the account of the receiving addresses\n"
1201 " \"amount\" : total amount received by addresses with this account\n"
1202 " \"confirmations\" : number of confirmations of the most recent transaction included");
1204 return ListReceived(params, true);
1207 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1209 int64 nGeneratedImmature, nGeneratedMature, nFee;
1210 string strSentAccount;
1211 list<pair<CBitcoinAddress, int64> > listReceived;
1212 list<pair<CBitcoinAddress, int64> > listSent;
1214 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1216 bool fAllAccounts = (strAccount == string("*"));
1218 // Generated blocks assigned to account ""
1219 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1222 entry.push_back(Pair("account", string("")));
1223 if (nGeneratedImmature)
1225 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1226 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1230 entry.push_back(Pair("category", "generate"));
1231 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1234 WalletTxToJSON(wtx, entry);
1235 ret.push_back(entry);
1239 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1241 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1244 entry.push_back(Pair("account", strSentAccount));
1245 entry.push_back(Pair("address", s.first.ToString()));
1246 entry.push_back(Pair("category", "send"));
1247 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1248 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1250 WalletTxToJSON(wtx, entry);
1251 ret.push_back(entry);
1256 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1257 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1260 if (pwalletMain->mapAddressBook.count(r.first))
1261 account = pwalletMain->mapAddressBook[r.first];
1262 if (fAllAccounts || (account == strAccount))
1265 entry.push_back(Pair("account", account));
1266 entry.push_back(Pair("address", r.first.ToString()));
1267 entry.push_back(Pair("category", "receive"));
1268 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1270 WalletTxToJSON(wtx, entry);
1271 ret.push_back(entry);
1276 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1278 bool fAllAccounts = (strAccount == string("*"));
1280 if (fAllAccounts || acentry.strAccount == strAccount)
1283 entry.push_back(Pair("account", acentry.strAccount));
1284 entry.push_back(Pair("category", "move"));
1285 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1286 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1287 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1288 entry.push_back(Pair("comment", acentry.strComment));
1289 ret.push_back(entry);
1293 Value listtransactions(const Array& params, bool fHelp)
1295 if (fHelp || params.size() > 3)
1296 throw runtime_error(
1297 "listtransactions [account] [count=10] [from=0]\n"
1298 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1300 string strAccount = "*";
1301 if (params.size() > 0)
1302 strAccount = params[0].get_str();
1304 if (params.size() > 1)
1305 nCount = params[1].get_int();
1307 if (params.size() > 2)
1308 nFrom = params[2].get_int();
1311 CWalletDB walletdb(pwalletMain->strWalletFile);
1313 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1314 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1315 typedef multimap<int64, TxPair > TxItems;
1318 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1320 CWalletTx* wtx = &((*it).second);
1321 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1323 list<CAccountingEntry> acentries;
1324 walletdb.ListAccountCreditDebit(strAccount, acentries);
1325 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1327 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1330 // Now: iterate backwards until we have nCount items to return:
1331 TxItems::reverse_iterator it = txByTime.rbegin();
1332 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1333 for (; it != txByTime.rend(); ++it)
1335 CWalletTx *const pwtx = (*it).second.first;
1337 ListTransactions(*pwtx, strAccount, 0, true, ret);
1338 CAccountingEntry *const pacentry = (*it).second.second;
1340 AcentryToJSON(*pacentry, strAccount, ret);
1342 if (ret.size() >= nCount) break;
1344 // ret is now newest to oldest
1346 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1347 if (ret.size() > nCount)
1349 Array::iterator last = ret.begin();
1350 std::advance(last, nCount);
1351 ret.erase(last, ret.end());
1353 std::reverse(ret.begin(), ret.end()); // oldest to newest
1358 Value listaccounts(const Array& params, bool fHelp)
1360 if (fHelp || params.size() > 1)
1361 throw runtime_error(
1362 "listaccounts [minconf=1]\n"
1363 "Returns Object that has account names as keys, account balances as values.");
1366 if (params.size() > 0)
1367 nMinDepth = params[0].get_int();
1369 map<string, int64> mapAccountBalances;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1371 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1372 mapAccountBalances[entry.second] = 0;
1375 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1377 const CWalletTx& wtx = (*it).second;
1378 int64 nGeneratedImmature, nGeneratedMature, nFee;
1379 string strSentAccount;
1380 list<pair<CBitcoinAddress, int64> > listReceived;
1381 list<pair<CBitcoinAddress, int64> > listSent;
1382 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1383 mapAccountBalances[strSentAccount] -= nFee;
1384 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1385 mapAccountBalances[strSentAccount] -= s.second;
1386 if (wtx.GetDepthInMainChain() >= nMinDepth)
1388 mapAccountBalances[""] += nGeneratedMature;
1389 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1390 if (pwalletMain->mapAddressBook.count(r.first))
1391 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1393 mapAccountBalances[""] += r.second;
1397 list<CAccountingEntry> acentries;
1398 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1399 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1400 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1403 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1404 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1409 Value listsinceblock(const Array& params, bool fHelp)
1412 throw runtime_error(
1413 "listsinceblock [blockid] [target-confirmations]\n"
1414 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1416 CBlockIndex *pindex = NULL;
1417 int target_confirms = 1;
1419 if (params.size() > 0)
1421 uint256 blockId = 0;
1423 blockId.SetHex(params[0].get_str());
1424 pindex = CBlockLocator(blockId).GetBlockIndex();
1427 if (params.size() > 1)
1429 target_confirms = params[1].get_int();
1431 if (target_confirms < 1)
1432 throw JSONRPCError(-8, "Invalid parameter");
1435 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1439 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1441 CWalletTx tx = (*it).second;
1443 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1444 ListTransactions(tx, "*", 0, true, transactions);
1449 if (target_confirms == 1)
1452 lastblock = hashBestChain;
1456 int target_height = pindexBest->nHeight + 1 - target_confirms;
1459 for (block = pindexBest;
1460 block && block->nHeight > target_height;
1461 block = block->pprev) { }
1463 lastblock = block ? block->GetBlockHash() : 0;
1467 ret.push_back(Pair("transactions", transactions));
1468 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1473 Value gettransaction(const Array& params, bool fHelp)
1475 if (fHelp || params.size() != 1)
1476 throw runtime_error(
1477 "gettransaction <txid>\n"
1478 "Get detailed information about <txid>");
1481 hash.SetHex(params[0].get_str());
1485 if (!pwalletMain->mapWallet.count(hash))
1486 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1487 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1489 int64 nCredit = wtx.GetCredit();
1490 int64 nDebit = wtx.GetDebit();
1491 int64 nNet = nCredit - nDebit;
1492 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1494 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1496 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1498 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1501 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1502 entry.push_back(Pair("details", details));
1508 Value backupwallet(const Array& params, bool fHelp)
1510 if (fHelp || params.size() != 1)
1511 throw runtime_error(
1512 "backupwallet <destination>\n"
1513 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1515 string strDest = params[0].get_str();
1516 BackupWallet(*pwalletMain, strDest);
1522 Value keypoolrefill(const Array& params, bool fHelp)
1524 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1525 throw runtime_error(
1527 "Fills the keypool, requires wallet passphrase to be set.");
1528 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1529 throw runtime_error(
1531 "Fills the keypool.");
1533 if (pwalletMain->IsLocked())
1534 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1536 pwalletMain->TopUpKeyPool();
1538 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1539 throw JSONRPCError(-4, "Error refreshing keypool.");
1545 void ThreadTopUpKeyPool(void* parg)
1547 pwalletMain->TopUpKeyPool();
1550 void ThreadCleanWalletPassphrase(void* parg)
1552 int64 nMyWakeTime = GetTime() + *((int*)parg);
1554 if (nWalletUnlockTime == 0)
1556 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1558 nWalletUnlockTime = nMyWakeTime;
1561 while (GetTime() < nWalletUnlockTime)
1562 Sleep(GetTime() - nWalletUnlockTime);
1564 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1566 nWalletUnlockTime = 0;
1571 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1573 if (nWalletUnlockTime < nMyWakeTime)
1574 nWalletUnlockTime = nMyWakeTime;
1580 pwalletMain->Lock();
1585 Value walletpassphrase(const Array& params, bool fHelp)
1587 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1588 throw runtime_error(
1589 "walletpassphrase <passphrase> <timeout>\n"
1590 "Stores the wallet decryption key in memory for <timeout> seconds.");
1593 if (!pwalletMain->IsCrypted())
1594 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1596 if (!pwalletMain->IsLocked())
1597 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1599 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1600 SecureString strWalletPass;
1601 strWalletPass.reserve(100);
1602 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1603 // Alternately, find a way to make params[0] mlock()'d to begin with.
1604 strWalletPass = params[0].get_str().c_str();
1606 if (strWalletPass.length() > 0)
1608 if (!pwalletMain->Unlock(strWalletPass))
1609 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1612 throw runtime_error(
1613 "walletpassphrase <passphrase> <timeout>\n"
1614 "Stores the wallet decryption key in memory for <timeout> seconds.");
1616 CreateThread(ThreadTopUpKeyPool, NULL);
1617 int* pnSleepTime = new int(params[1].get_int());
1618 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1624 Value walletpassphrasechange(const Array& params, bool fHelp)
1626 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1627 throw runtime_error(
1628 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1629 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1632 if (!pwalletMain->IsCrypted())
1633 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1635 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1636 // Alternately, find a way to make params[0] mlock()'d to begin with.
1637 SecureString strOldWalletPass;
1638 strOldWalletPass.reserve(100);
1639 strOldWalletPass = params[0].get_str().c_str();
1641 SecureString strNewWalletPass;
1642 strNewWalletPass.reserve(100);
1643 strNewWalletPass = params[1].get_str().c_str();
1645 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1646 throw runtime_error(
1647 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1648 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1650 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1651 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1657 Value walletlock(const Array& params, bool fHelp)
1659 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1660 throw runtime_error(
1662 "Removes the wallet encryption key from memory, locking the wallet.\n"
1663 "After calling this method, you will need to call walletpassphrase again\n"
1664 "before being able to call any methods which require the wallet to be unlocked.");
1667 if (!pwalletMain->IsCrypted())
1668 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1670 pwalletMain->Lock();
1671 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1673 nWalletUnlockTime = 0;
1680 Value encryptwallet(const Array& params, bool fHelp)
1682 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1683 throw runtime_error(
1684 "encryptwallet <passphrase>\n"
1685 "Encrypts the wallet with <passphrase>.");
1688 if (pwalletMain->IsCrypted())
1689 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1692 // shutting down via RPC while the GUI is running does not work (yet):
1693 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1696 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1697 // Alternately, find a way to make params[0] mlock()'d to begin with.
1698 SecureString strWalletPass;
1699 strWalletPass.reserve(100);
1700 strWalletPass = params[0].get_str().c_str();
1702 if (strWalletPass.length() < 1)
1703 throw runtime_error(
1704 "encryptwallet <passphrase>\n"
1705 "Encrypts the wallet with <passphrase>.");
1707 if (!pwalletMain->EncryptWallet(strWalletPass))
1708 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1710 // BDB seems to have a bad habit of writing old data into
1711 // slack space in .dat files; that is bad if the old data is
1712 // unencrypted private keys. So:
1713 CreateThread(Shutdown, NULL);
1714 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1718 Value validateaddress(const Array& params, bool fHelp)
1720 if (fHelp || params.size() != 1)
1721 throw runtime_error(
1722 "validateaddress <bitcoinaddress>\n"
1723 "Return information about <bitcoinaddress>.");
1725 CBitcoinAddress address(params[0].get_str());
1726 bool isValid = address.IsValid();
1729 ret.push_back(Pair("isvalid", isValid));
1732 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1733 // version of the address:
1734 string currentAddress = address.ToString();
1735 ret.push_back(Pair("address", currentAddress));
1736 if (pwalletMain->HaveKey(address))
1738 ret.push_back(Pair("ismine", true));
1739 std::vector<unsigned char> vchPubKey;
1740 pwalletMain->GetPubKey(address, vchPubKey);
1741 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1742 std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
1743 ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
1745 key.SetPubKey(vchPubKey);
1746 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1748 else if (pwalletMain->HaveCScript(address.GetHash160()))
1750 ret.push_back(Pair("isscript", true));
1752 pwalletMain->GetCScript(address.GetHash160(), subscript);
1753 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1754 std::vector<CBitcoinAddress> addresses;
1755 txnouttype whichType;
1757 ExtractAddresses(subscript, whichType, addresses, nRequired);
1758 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1760 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1761 a.push_back(addr.ToString());
1762 ret.push_back(Pair("addresses", a));
1763 if (whichType == TX_MULTISIG)
1764 ret.push_back(Pair("sigsrequired", nRequired));
1767 ret.push_back(Pair("ismine", false));
1768 if (pwalletMain->mapAddressBook.count(address))
1769 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1774 Value getwork(const Array& params, bool fHelp)
1776 if (fHelp || params.size() > 1)
1777 throw runtime_error(
1779 "If [data] is not specified, returns formatted hash data to work on:\n"
1780 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1781 " \"data\" : block data\n"
1782 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1783 " \"target\" : little endian hash target\n"
1784 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1787 throw JSONRPCError(-9, "Bitcoin is not connected!");
1789 if (IsInitialBlockDownload())
1790 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1792 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1793 static mapNewBlock_t mapNewBlock;
1794 static vector<CBlock*> vNewBlock;
1795 static CReserveKey reservekey(pwalletMain);
1797 if (params.size() == 0)
1800 static unsigned int nTransactionsUpdatedLast;
1801 static CBlockIndex* pindexPrev;
1802 static int64 nStart;
1803 static CBlock* pblock;
1804 if (pindexPrev != pindexBest ||
1805 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1807 if (pindexPrev != pindexBest)
1809 // Deallocate old blocks since they're obsolete now
1810 mapNewBlock.clear();
1811 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1815 nTransactionsUpdatedLast = nTransactionsUpdated;
1816 pindexPrev = pindexBest;
1820 pblock = CreateNewBlock(reservekey);
1822 throw JSONRPCError(-7, "Out of memory");
1823 vNewBlock.push_back(pblock);
1827 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1830 // Update nExtraNonce
1831 static unsigned int nExtraNonce = 0;
1832 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1835 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1837 // Prebuild hash buffers
1841 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1843 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1846 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1847 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1848 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1849 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1855 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1856 if (vchData.size() != 128)
1857 throw JSONRPCError(-8, "Invalid parameter");
1858 CBlock* pdata = (CBlock*)&vchData[0];
1861 for (int i = 0; i < 128/4; i++)
1862 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1865 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1867 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1869 pblock->nTime = pdata->nTime;
1870 pblock->nNonce = pdata->nNonce;
1871 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1872 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1874 return CheckWork(pblock, *pwalletMain, reservekey);
1879 Value getmemorypool(const Array& params, bool fHelp)
1881 if (fHelp || params.size() > 1)
1882 throw runtime_error(
1883 "getmemorypool [data]\n"
1884 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1885 " \"version\" : block version\n"
1886 " \"previousblockhash\" : hash of current highest block\n"
1887 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1888 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1889 " \"time\" : timestamp appropriate for next block\n"
1890 " \"bits\" : compressed target of next block\n"
1891 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1893 if (params.size() == 0)
1896 throw JSONRPCError(-9, "Bitcoin is not connected!");
1898 if (IsInitialBlockDownload())
1899 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1901 static CReserveKey reservekey(pwalletMain);
1904 static unsigned int nTransactionsUpdatedLast;
1905 static CBlockIndex* pindexPrev;
1906 static int64 nStart;
1907 static CBlock* pblock;
1908 if (pindexPrev != pindexBest ||
1909 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1911 nTransactionsUpdatedLast = nTransactionsUpdated;
1912 pindexPrev = pindexBest;
1918 pblock = CreateNewBlock(reservekey);
1920 throw JSONRPCError(-7, "Out of memory");
1924 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1928 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1935 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1939 result.push_back(Pair("version", pblock->nVersion));
1940 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1941 result.push_back(Pair("transactions", transactions));
1942 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1943 result.push_back(Pair("time", (int64_t)pblock->nTime));
1949 uBits.nBits = htonl((int32_t)pblock->nBits);
1950 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1957 CDataStream ssBlock(ParseHex(params[0].get_str()));
1961 return ProcessBlock(NULL, &pblock);
1965 Value getblockhash(const Array& params, bool fHelp)
1967 if (fHelp || params.size() != 1)
1968 throw runtime_error(
1969 "getblockhash <index>\n"
1970 "Returns hash of block in best-block-chain at <index>.");
1972 int nHeight = params[0].get_int();
1973 if (nHeight < 0 || nHeight > nBestHeight)
1974 throw runtime_error("Block number out of range.");
1977 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1978 while (pblockindex->nHeight > nHeight)
1979 pblockindex = pblockindex->pprev;
1980 return pblockindex->phashBlock->GetHex();
1983 Value getblock(const Array& params, bool fHelp)
1985 if (fHelp || params.size() != 1)
1986 throw runtime_error(
1988 "Returns details of a block with given block-hash.");
1990 std::string strHash = params[0].get_str();
1991 uint256 hash(strHash);
1993 if (mapBlockIndex.count(hash) == 0)
1994 throw JSONRPCError(-5, "Block not found");
1997 CBlockIndex* pblockindex = mapBlockIndex[hash];
1998 block.ReadFromDisk(pblockindex, true);
2000 return blockToJSON(block, pblockindex);
2017 pair<string, rpcfn_type> pCallTable[] =
2019 make_pair("help", &help),
2020 make_pair("stop", &stop),
2021 make_pair("getblockcount", &getblockcount),
2022 make_pair("getblocknumber", &getblocknumber),
2023 make_pair("getconnectioncount", &getconnectioncount),
2024 make_pair("getdifficulty", &getdifficulty),
2025 make_pair("getgenerate", &getgenerate),
2026 make_pair("setgenerate", &setgenerate),
2027 make_pair("gethashespersec", &gethashespersec),
2028 make_pair("getinfo", &getinfo),
2029 make_pair("getmininginfo", &getmininginfo),
2030 make_pair("getnewaddress", &getnewaddress),
2031 make_pair("getaccountaddress", &getaccountaddress),
2032 make_pair("setaccount", &setaccount),
2033 make_pair("getaccount", &getaccount),
2034 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2035 make_pair("sendtoaddress", &sendtoaddress),
2036 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2037 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2038 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2039 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2040 make_pair("backupwallet", &backupwallet),
2041 make_pair("keypoolrefill", &keypoolrefill),
2042 make_pair("walletpassphrase", &walletpassphrase),
2043 make_pair("walletpassphrasechange", &walletpassphrasechange),
2044 make_pair("walletlock", &walletlock),
2045 make_pair("encryptwallet", &encryptwallet),
2046 make_pair("validateaddress", &validateaddress),
2047 make_pair("getbalance", &getbalance),
2048 make_pair("move", &movecmd),
2049 make_pair("sendfrom", &sendfrom),
2050 make_pair("sendmany", &sendmany),
2051 make_pair("addmultisigaddress", &addmultisigaddress),
2052 make_pair("getblock", &getblock),
2053 make_pair("getblockhash", &getblockhash),
2054 make_pair("gettransaction", &gettransaction),
2055 make_pair("listtransactions", &listtransactions),
2056 make_pair("signmessage", &signmessage),
2057 make_pair("verifymessage", &verifymessage),
2058 make_pair("getwork", &getwork),
2059 make_pair("listaccounts", &listaccounts),
2060 make_pair("settxfee", &settxfee),
2061 make_pair("getmemorypool", &getmemorypool),
2062 make_pair("listsinceblock", &listsinceblock),
2063 make_pair("dumpprivkey", &dumpprivkey),
2064 make_pair("importprivkey", &importprivkey)
2066 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2068 string pAllowInSafeMode[] =
2073 "getblocknumber", // deprecated
2074 "getconnectioncount",
2082 "getaccountaddress",
2084 "getaddressesbyaccount",
2093 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2101 // This ain't Apache. We're just using HTTP header for the length field
2102 // and to be compatible with other JSON-RPC implementations.
2105 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2108 s << "POST / HTTP/1.1\r\n"
2109 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2110 << "Host: 127.0.0.1\r\n"
2111 << "Content-Type: application/json\r\n"
2112 << "Content-Length: " << strMsg.size() << "\r\n"
2113 << "Connection: close\r\n"
2114 << "Accept: application/json\r\n";
2115 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2116 s << item.first << ": " << item.second << "\r\n";
2117 s << "\r\n" << strMsg;
2122 string rfc1123Time()
2127 struct tm* now_gmt = gmtime(&now);
2128 string locale(setlocale(LC_TIME, NULL));
2129 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2130 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2131 setlocale(LC_TIME, locale.c_str());
2132 return string(buffer);
2135 static string HTTPReply(int nStatus, const string& strMsg)
2138 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2140 "Server: bitcoin-json-rpc/%s\r\n"
2141 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2142 "Content-Type: text/html\r\n"
2143 "Content-Length: 296\r\n"
2145 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2146 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2149 "<TITLE>Error</TITLE>\r\n"
2150 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2152 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2153 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2154 const char *cStatus;
2155 if (nStatus == 200) cStatus = "OK";
2156 else if (nStatus == 400) cStatus = "Bad Request";
2157 else if (nStatus == 403) cStatus = "Forbidden";
2158 else if (nStatus == 404) cStatus = "Not Found";
2159 else if (nStatus == 500) cStatus = "Internal Server Error";
2162 "HTTP/1.1 %d %s\r\n"
2164 "Connection: close\r\n"
2165 "Content-Length: %d\r\n"
2166 "Content-Type: application/json\r\n"
2167 "Server: bitcoin-json-rpc/%s\r\n"
2172 rfc1123Time().c_str(),
2174 FormatFullVersion().c_str(),
2178 int ReadHTTPStatus(std::basic_istream<char>& stream)
2181 getline(stream, str);
2182 vector<string> vWords;
2183 boost::split(vWords, str, boost::is_any_of(" "));
2184 if (vWords.size() < 2)
2186 return atoi(vWords[1].c_str());
2189 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2195 std::getline(stream, str);
2196 if (str.empty() || str == "\r")
2198 string::size_type nColon = str.find(":");
2199 if (nColon != string::npos)
2201 string strHeader = str.substr(0, nColon);
2202 boost::trim(strHeader);
2203 boost::to_lower(strHeader);
2204 string strValue = str.substr(nColon+1);
2205 boost::trim(strValue);
2206 mapHeadersRet[strHeader] = strValue;
2207 if (strHeader == "content-length")
2208 nLen = atoi(strValue.c_str());
2214 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2216 mapHeadersRet.clear();
2220 int nStatus = ReadHTTPStatus(stream);
2223 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2224 if (nLen < 0 || nLen > MAX_SIZE)
2230 vector<char> vch(nLen);
2231 stream.read(&vch[0], nLen);
2232 strMessageRet = string(vch.begin(), vch.end());
2238 bool HTTPAuthorized(map<string, string>& mapHeaders)
2240 string strAuth = mapHeaders["authorization"];
2241 if (strAuth.substr(0,6) != "Basic ")
2243 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2244 string strUserPass = DecodeBase64(strUserPass64);
2245 return strUserPass == strRPCUserColonPass;
2249 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2250 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2251 // unspecified (HTTP errors and contents of 'error').
2253 // 1.0 spec: http://json-rpc.org/wiki/specification
2254 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2255 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2258 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2261 request.push_back(Pair("method", strMethod));
2262 request.push_back(Pair("params", params));
2263 request.push_back(Pair("id", id));
2264 return write_string(Value(request), false) + "\n";
2267 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2270 if (error.type() != null_type)
2271 reply.push_back(Pair("result", Value::null));
2273 reply.push_back(Pair("result", result));
2274 reply.push_back(Pair("error", error));
2275 reply.push_back(Pair("id", id));
2276 return write_string(Value(reply), false) + "\n";
2279 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2281 // Send error reply from json-rpc error object
2283 int code = find_value(objError, "code").get_int();
2284 if (code == -32600) nStatus = 400;
2285 else if (code == -32601) nStatus = 404;
2286 string strReply = JSONRPCReply(Value::null, objError, id);
2287 stream << HTTPReply(nStatus, strReply) << std::flush;
2290 bool ClientAllowed(const string& strAddress)
2292 if (strAddress == asio::ip::address_v4::loopback().to_string())
2294 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2295 BOOST_FOREACH(string strAllow, vAllow)
2296 if (WildcardMatch(strAddress, strAllow))
2303 // IOStream device that speaks SSL but can also speak non-SSL
2305 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2307 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2309 fUseSSL = fUseSSLIn;
2310 fNeedHandshake = fUseSSLIn;
2313 void handshake(ssl::stream_base::handshake_type role)
2315 if (!fNeedHandshake) return;
2316 fNeedHandshake = false;
2317 stream.handshake(role);
2319 std::streamsize read(char* s, std::streamsize n)
2321 handshake(ssl::stream_base::server); // HTTPS servers read first
2322 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2323 return stream.next_layer().read_some(asio::buffer(s, n));
2325 std::streamsize write(const char* s, std::streamsize n)
2327 handshake(ssl::stream_base::client); // HTTPS clients write first
2328 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2329 return asio::write(stream.next_layer(), asio::buffer(s, n));
2331 bool connect(const std::string& server, const std::string& port)
2333 ip::tcp::resolver resolver(stream.get_io_service());
2334 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2335 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2336 ip::tcp::resolver::iterator end;
2337 boost::system::error_code error = asio::error::host_not_found;
2338 while (error && endpoint_iterator != end)
2340 stream.lowest_layer().close();
2341 stream.lowest_layer().connect(*endpoint_iterator++, error);
2349 bool fNeedHandshake;
2355 void ThreadRPCServer(void* parg)
2357 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2360 vnThreadsRunning[4]++;
2361 ThreadRPCServer2(parg);
2362 vnThreadsRunning[4]--;
2364 catch (std::exception& e) {
2365 vnThreadsRunning[4]--;
2366 PrintException(&e, "ThreadRPCServer()");
2368 vnThreadsRunning[4]--;
2369 PrintException(NULL, "ThreadRPCServer()");
2371 printf("ThreadRPCServer exiting\n");
2374 void ThreadRPCServer2(void* parg)
2376 printf("ThreadRPCServer started\n");
2378 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2379 if (strRPCUserColonPass == ":")
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 rpcpassword=<password>\nin the configuration file: %s\n"
2388 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2390 GetConfigFile().c_str());
2392 CreateThread(Shutdown, NULL);
2397 bool fUseSSL = GetBoolArg("-rpcssl");
2398 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2400 asio::io_service io_service;
2401 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2402 ip::tcp::acceptor acceptor(io_service, endpoint);
2404 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2407 ssl::context context(io_service, ssl::context::sslv23);
2410 context.set_options(ssl::context::no_sslv2);
2411 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2412 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2413 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2414 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2415 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2416 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2417 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2418 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2420 string ciphers = GetArg("-rpcsslciphers",
2421 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2422 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2426 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2431 // Accept connection
2433 SSLStream sslStream(io_service, context);
2434 SSLIOStreamDevice d(sslStream, fUseSSL);
2435 iostreams::stream<SSLIOStreamDevice> stream(d);
2437 ip::tcp::iostream stream;
2440 ip::tcp::endpoint peer;
2441 vnThreadsRunning[4]--;
2443 acceptor.accept(sslStream.lowest_layer(), peer);
2445 acceptor.accept(*stream.rdbuf(), peer);
2447 vnThreadsRunning[4]++;
2451 // Restrict callers by IP
2452 if (!ClientAllowed(peer.address().to_string()))
2454 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2456 stream << HTTPReply(403, "") << std::flush;
2460 map<string, string> mapHeaders;
2463 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2464 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2467 printf("ThreadRPCServer ReadHTTP timeout\n");
2471 // Check authorization
2472 if (mapHeaders.count("authorization") == 0)
2474 stream << HTTPReply(401, "") << std::flush;
2477 if (!HTTPAuthorized(mapHeaders))
2479 // Deter brute-forcing short passwords
2480 if (mapArgs["-rpcpassword"].size() < 15)
2483 stream << HTTPReply(401, "") << std::flush;
2484 printf("ThreadRPCServer incorrect password attempt\n");
2488 Value id = Value::null;
2493 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2494 throw JSONRPCError(-32700, "Parse error");
2495 const Object& request = valRequest.get_obj();
2497 // Parse id now so errors from here on will have the id
2498 id = find_value(request, "id");
2501 Value valMethod = find_value(request, "method");
2502 if (valMethod.type() == null_type)
2503 throw JSONRPCError(-32600, "Missing method");
2504 if (valMethod.type() != str_type)
2505 throw JSONRPCError(-32600, "Method must be a string");
2506 string strMethod = valMethod.get_str();
2507 if (strMethod != "getwork" && strMethod != "getmemorypool")
2508 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2511 Value valParams = find_value(request, "params");
2513 if (valParams.type() == array_type)
2514 params = valParams.get_array();
2515 else if (valParams.type() == null_type)
2518 throw JSONRPCError(-32600, "Params must be an array");
2521 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2522 if (mi == mapCallTable.end())
2523 throw JSONRPCError(-32601, "Method not found");
2525 // Observe safe mode
2526 string strWarning = GetWarnings("rpc");
2527 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2528 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2534 CRITICAL_BLOCK(cs_main)
2535 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2536 result = (*(*mi).second)(params, false);
2539 string strReply = JSONRPCReply(result, Value::null, id);
2540 stream << HTTPReply(200, strReply) << std::flush;
2542 catch (std::exception& e)
2544 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2547 catch (Object& objError)
2549 ErrorReply(stream, objError, id);
2551 catch (std::exception& e)
2553 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2561 Object CallRPC(const string& strMethod, const Array& params)
2563 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2564 throw runtime_error(strprintf(
2565 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2566 "If the file does not exist, create it with owner-readable-only file permissions."),
2567 GetConfigFile().c_str()));
2569 // Connect to localhost
2570 bool fUseSSL = GetBoolArg("-rpcssl");
2572 asio::io_service io_service;
2573 ssl::context context(io_service, ssl::context::sslv23);
2574 context.set_options(ssl::context::no_sslv2);
2575 SSLStream sslStream(io_service, context);
2576 SSLIOStreamDevice d(sslStream, fUseSSL);
2577 iostreams::stream<SSLIOStreamDevice> stream(d);
2578 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2579 throw runtime_error("couldn't connect to server");
2582 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2584 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2586 throw runtime_error("couldn't connect to server");
2590 // HTTP basic authentication
2591 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2592 map<string, string> mapRequestHeaders;
2593 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2596 string strRequest = JSONRPCRequest(strMethod, params, 1);
2597 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2598 stream << strPost << std::flush;
2601 map<string, string> mapHeaders;
2603 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2605 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2606 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2607 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2608 else if (strReply.empty())
2609 throw runtime_error("no response from server");
2613 if (!read_string(strReply, valReply))
2614 throw runtime_error("couldn't parse reply from server");
2615 const Object& reply = valReply.get_obj();
2617 throw runtime_error("expected reply to have result, error and id properties");
2625 template<typename T>
2626 void ConvertTo(Value& value)
2628 if (value.type() == str_type)
2630 // reinterpret string as unquoted json value
2632 if (!read_string(value.get_str(), value2))
2633 throw runtime_error("type mismatch");
2634 value = value2.get_value<T>();
2638 value = value.get_value<T>();
2642 int CommandLineRPC(int argc, char *argv[])
2649 while (argc > 1 && IsSwitchChar(argv[1][0]))
2657 throw runtime_error("too few parameters");
2658 string strMethod = argv[1];
2660 // Parameters default to strings
2662 for (int i = 2; i < argc; i++)
2663 params.push_back(argv[i]);
2664 int n = params.size();
2667 // Special case non-string parameter types
2669 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2670 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2672 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2673 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2676 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2677 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2678 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2679 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2680 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2681 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2682 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2683 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2684 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2685 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2686 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2687 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2688 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2689 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2690 if (strMethod == "sendmany" && n > 1)
2692 string s = params[1].get_str();
2694 if (!read_string(s, v) || v.type() != obj_type)
2695 throw runtime_error("type mismatch");
2696 params[1] = v.get_obj();
2698 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2699 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2700 if (strMethod == "addmultisigaddress" && n > 1)
2702 string s = params[1].get_str();
2704 if (!read_string(s, v) || v.type() != array_type)
2705 throw runtime_error("type mismatch "+s);
2706 params[1] = v.get_array();
2710 Object reply = CallRPC(strMethod, params);
2713 const Value& result = find_value(reply, "result");
2714 const Value& error = find_value(reply, "error");
2716 if (error.type() != null_type)
2719 strPrint = "error: " + write_string(error, false);
2720 int code = find_value(error.get_obj(), "code").get_int();
2726 if (result.type() == null_type)
2728 else if (result.type() == str_type)
2729 strPrint = result.get_str();
2731 strPrint = write_string(result, true);
2734 catch (std::exception& e)
2736 strPrint = string("error: ") + e.what();
2741 PrintException(NULL, "CommandLineRPC()");
2746 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2755 int main(int argc, char *argv[])
2758 // Turn off microsoft heap dump noise
2759 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2760 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2762 setbuf(stdin, NULL);
2763 setbuf(stdout, NULL);
2764 setbuf(stderr, NULL);
2768 if (argc >= 2 && string(argv[1]) == "-server")
2770 printf("server ready\n");
2771 ThreadRPCServer(NULL);
2775 return CommandLineRPC(argc, argv);
2778 catch (std::exception& e) {
2779 PrintException(&e, "main()");
2781 PrintException(NULL, "main()");