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 or hex-encoded 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()));
1033 // Case 2: hex public key
1036 vector<unsigned char> vchPubKey = ParseHex(ks);
1037 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1038 throw runtime_error(" Invalid public key: "+ks);
1042 throw runtime_error(" Invalid public key: "+ks);
1046 // Construct using pay-to-script-hash:
1048 inner.SetMultisig(nRequired, pubkeys);
1050 uint160 scriptHash = Hash160(inner);
1051 CScript scriptPubKey;
1052 scriptPubKey.SetPayToScriptHash(inner);
1053 pwalletMain->AddCScript(inner);
1054 CBitcoinAddress address;
1055 address.SetScriptHash160(scriptHash);
1057 pwalletMain->SetAddressBookName(address, strAccount);
1058 return address.ToString();
1069 nConf = std::numeric_limits<int>::max();
1073 Value ListReceived(const Array& params, bool fByAccounts)
1075 // Minimum confirmations
1077 if (params.size() > 0)
1078 nMinDepth = params[0].get_int();
1080 // Whether to include empty accounts
1081 bool fIncludeEmpty = false;
1082 if (params.size() > 1)
1083 fIncludeEmpty = params[1].get_bool();
1086 map<CBitcoinAddress, tallyitem> mapTally;
1087 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1089 const CWalletTx& wtx = (*it).second;
1091 if (wtx.IsCoinBase() || !wtx.IsFinal())
1094 int nDepth = wtx.GetDepthInMainChain();
1095 if (nDepth < nMinDepth)
1098 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1100 CBitcoinAddress address;
1101 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1104 tallyitem& item = mapTally[address];
1105 item.nAmount += txout.nValue;
1106 item.nConf = min(item.nConf, nDepth);
1112 map<string, tallyitem> mapAccountTally;
1113 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1115 const CBitcoinAddress& address = item.first;
1116 const string& strAccount = item.second;
1117 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1118 if (it == mapTally.end() && !fIncludeEmpty)
1122 int nConf = std::numeric_limits<int>::max();
1123 if (it != mapTally.end())
1125 nAmount = (*it).second.nAmount;
1126 nConf = (*it).second.nConf;
1131 tallyitem& item = mapAccountTally[strAccount];
1132 item.nAmount += nAmount;
1133 item.nConf = min(item.nConf, nConf);
1138 obj.push_back(Pair("address", address.ToString()));
1139 obj.push_back(Pair("account", strAccount));
1140 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1141 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1148 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1150 int64 nAmount = (*it).second.nAmount;
1151 int nConf = (*it).second.nConf;
1153 obj.push_back(Pair("account", (*it).first));
1154 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1155 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1163 Value listreceivedbyaddress(const Array& params, bool fHelp)
1165 if (fHelp || params.size() > 2)
1166 throw runtime_error(
1167 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1168 "[minconf] is the minimum number of confirmations before payments are included.\n"
1169 "[includeempty] whether to include addresses that haven't received any payments.\n"
1170 "Returns an array of objects containing:\n"
1171 " \"address\" : receiving address\n"
1172 " \"account\" : the account of the receiving address\n"
1173 " \"amount\" : total amount received by the address\n"
1174 " \"confirmations\" : number of confirmations of the most recent transaction included");
1176 return ListReceived(params, false);
1179 Value listreceivedbyaccount(const Array& params, bool fHelp)
1181 if (fHelp || params.size() > 2)
1182 throw runtime_error(
1183 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1184 "[minconf] is the minimum number of confirmations before payments are included.\n"
1185 "[includeempty] whether to include accounts that haven't received any payments.\n"
1186 "Returns an array of objects containing:\n"
1187 " \"account\" : the account of the receiving addresses\n"
1188 " \"amount\" : total amount received by addresses with this account\n"
1189 " \"confirmations\" : number of confirmations of the most recent transaction included");
1191 return ListReceived(params, true);
1194 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1196 int64 nGeneratedImmature, nGeneratedMature, nFee;
1197 string strSentAccount;
1198 list<pair<CBitcoinAddress, int64> > listReceived;
1199 list<pair<CBitcoinAddress, int64> > listSent;
1201 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1203 bool fAllAccounts = (strAccount == string("*"));
1205 // Generated blocks assigned to account ""
1206 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1209 entry.push_back(Pair("account", string("")));
1210 if (nGeneratedImmature)
1212 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1213 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1217 entry.push_back(Pair("category", "generate"));
1218 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1221 WalletTxToJSON(wtx, entry);
1222 ret.push_back(entry);
1226 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1228 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1231 entry.push_back(Pair("account", strSentAccount));
1232 entry.push_back(Pair("address", s.first.ToString()));
1233 entry.push_back(Pair("category", "send"));
1234 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1235 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1237 WalletTxToJSON(wtx, entry);
1238 ret.push_back(entry);
1243 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1244 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1247 if (pwalletMain->mapAddressBook.count(r.first))
1248 account = pwalletMain->mapAddressBook[r.first];
1249 if (fAllAccounts || (account == strAccount))
1252 entry.push_back(Pair("account", account));
1253 entry.push_back(Pair("address", r.first.ToString()));
1254 entry.push_back(Pair("category", "receive"));
1255 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1257 WalletTxToJSON(wtx, entry);
1258 ret.push_back(entry);
1263 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1265 bool fAllAccounts = (strAccount == string("*"));
1267 if (fAllAccounts || acentry.strAccount == strAccount)
1270 entry.push_back(Pair("account", acentry.strAccount));
1271 entry.push_back(Pair("category", "move"));
1272 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1273 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1274 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1275 entry.push_back(Pair("comment", acentry.strComment));
1276 ret.push_back(entry);
1280 Value listtransactions(const Array& params, bool fHelp)
1282 if (fHelp || params.size() > 3)
1283 throw runtime_error(
1284 "listtransactions [account] [count=10] [from=0]\n"
1285 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1287 string strAccount = "*";
1288 if (params.size() > 0)
1289 strAccount = params[0].get_str();
1291 if (params.size() > 1)
1292 nCount = params[1].get_int();
1294 if (params.size() > 2)
1295 nFrom = params[2].get_int();
1298 CWalletDB walletdb(pwalletMain->strWalletFile);
1300 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1301 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1302 typedef multimap<int64, TxPair > TxItems;
1305 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1307 CWalletTx* wtx = &((*it).second);
1308 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1310 list<CAccountingEntry> acentries;
1311 walletdb.ListAccountCreditDebit(strAccount, acentries);
1312 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1314 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1317 // Now: iterate backwards until we have nCount items to return:
1318 TxItems::reverse_iterator it = txByTime.rbegin();
1319 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1320 for (; it != txByTime.rend(); ++it)
1322 CWalletTx *const pwtx = (*it).second.first;
1324 ListTransactions(*pwtx, strAccount, 0, true, ret);
1325 CAccountingEntry *const pacentry = (*it).second.second;
1327 AcentryToJSON(*pacentry, strAccount, ret);
1329 if (ret.size() >= nCount) break;
1331 // ret is now newest to oldest
1333 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1334 if (ret.size() > nCount)
1336 Array::iterator last = ret.begin();
1337 std::advance(last, nCount);
1338 ret.erase(last, ret.end());
1340 std::reverse(ret.begin(), ret.end()); // oldest to newest
1345 Value listaccounts(const Array& params, bool fHelp)
1347 if (fHelp || params.size() > 1)
1348 throw runtime_error(
1349 "listaccounts [minconf=1]\n"
1350 "Returns Object that has account names as keys, account balances as values.");
1353 if (params.size() > 0)
1354 nMinDepth = params[0].get_int();
1356 map<string, int64> mapAccountBalances;
1357 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1358 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1359 mapAccountBalances[entry.second] = 0;
1362 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1364 const CWalletTx& wtx = (*it).second;
1365 int64 nGeneratedImmature, nGeneratedMature, nFee;
1366 string strSentAccount;
1367 list<pair<CBitcoinAddress, int64> > listReceived;
1368 list<pair<CBitcoinAddress, int64> > listSent;
1369 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1370 mapAccountBalances[strSentAccount] -= nFee;
1371 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1372 mapAccountBalances[strSentAccount] -= s.second;
1373 if (wtx.GetDepthInMainChain() >= nMinDepth)
1375 mapAccountBalances[""] += nGeneratedMature;
1376 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1377 if (pwalletMain->mapAddressBook.count(r.first))
1378 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1380 mapAccountBalances[""] += r.second;
1384 list<CAccountingEntry> acentries;
1385 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1386 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1387 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1390 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1391 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1396 Value listsinceblock(const Array& params, bool fHelp)
1399 throw runtime_error(
1400 "listsinceblock [blockid] [target-confirmations]\n"
1401 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1403 CBlockIndex *pindex = NULL;
1404 int target_confirms = 1;
1406 if (params.size() > 0)
1408 uint256 blockId = 0;
1410 blockId.SetHex(params[0].get_str());
1411 pindex = CBlockLocator(blockId).GetBlockIndex();
1414 if (params.size() > 1)
1416 target_confirms = params[1].get_int();
1418 if (target_confirms < 1)
1419 throw JSONRPCError(-8, "Invalid parameter");
1422 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1426 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1428 CWalletTx tx = (*it).second;
1430 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1431 ListTransactions(tx, "*", 0, true, transactions);
1436 if (target_confirms == 1)
1439 lastblock = hashBestChain;
1443 int target_height = pindexBest->nHeight + 1 - target_confirms;
1446 for (block = pindexBest;
1447 block && block->nHeight > target_height;
1448 block = block->pprev) { }
1450 lastblock = block ? block->GetBlockHash() : 0;
1454 ret.push_back(Pair("transactions", transactions));
1455 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1460 Value gettransaction(const Array& params, bool fHelp)
1462 if (fHelp || params.size() != 1)
1463 throw runtime_error(
1464 "gettransaction <txid>\n"
1465 "Get detailed information about <txid>");
1468 hash.SetHex(params[0].get_str());
1472 if (!pwalletMain->mapWallet.count(hash))
1473 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1474 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1476 int64 nCredit = wtx.GetCredit();
1477 int64 nDebit = wtx.GetDebit();
1478 int64 nNet = nCredit - nDebit;
1479 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1481 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1483 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1485 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1488 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1489 entry.push_back(Pair("details", details));
1495 Value backupwallet(const Array& params, bool fHelp)
1497 if (fHelp || params.size() != 1)
1498 throw runtime_error(
1499 "backupwallet <destination>\n"
1500 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1502 string strDest = params[0].get_str();
1503 BackupWallet(*pwalletMain, strDest);
1509 Value keypoolrefill(const Array& params, bool fHelp)
1511 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1512 throw runtime_error(
1514 "Fills the keypool, requires wallet passphrase to be set.");
1515 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1516 throw runtime_error(
1518 "Fills the keypool.");
1520 if (pwalletMain->IsLocked())
1521 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1523 pwalletMain->TopUpKeyPool();
1525 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1526 throw JSONRPCError(-4, "Error refreshing keypool.");
1532 void ThreadTopUpKeyPool(void* parg)
1534 pwalletMain->TopUpKeyPool();
1537 void ThreadCleanWalletPassphrase(void* parg)
1539 int64 nMyWakeTime = GetTime() + *((int*)parg);
1541 if (nWalletUnlockTime == 0)
1543 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1545 nWalletUnlockTime = nMyWakeTime;
1548 while (GetTime() < nWalletUnlockTime)
1549 Sleep(GetTime() - nWalletUnlockTime);
1551 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1553 nWalletUnlockTime = 0;
1558 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1560 if (nWalletUnlockTime < nMyWakeTime)
1561 nWalletUnlockTime = nMyWakeTime;
1567 pwalletMain->Lock();
1572 Value walletpassphrase(const Array& params, bool fHelp)
1574 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1575 throw runtime_error(
1576 "walletpassphrase <passphrase> <timeout>\n"
1577 "Stores the wallet decryption key in memory for <timeout> seconds.");
1580 if (!pwalletMain->IsCrypted())
1581 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1583 if (!pwalletMain->IsLocked())
1584 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1586 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1587 SecureString strWalletPass;
1588 strWalletPass.reserve(100);
1589 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1590 // Alternately, find a way to make params[0] mlock()'d to begin with.
1591 strWalletPass = params[0].get_str().c_str();
1593 if (strWalletPass.length() > 0)
1595 if (!pwalletMain->Unlock(strWalletPass))
1596 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1599 throw runtime_error(
1600 "walletpassphrase <passphrase> <timeout>\n"
1601 "Stores the wallet decryption key in memory for <timeout> seconds.");
1603 CreateThread(ThreadTopUpKeyPool, NULL);
1604 int* pnSleepTime = new int(params[1].get_int());
1605 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1611 Value walletpassphrasechange(const Array& params, bool fHelp)
1613 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1614 throw runtime_error(
1615 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1616 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1619 if (!pwalletMain->IsCrypted())
1620 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1622 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1623 // Alternately, find a way to make params[0] mlock()'d to begin with.
1624 SecureString strOldWalletPass;
1625 strOldWalletPass.reserve(100);
1626 strOldWalletPass = params[0].get_str().c_str();
1628 SecureString strNewWalletPass;
1629 strNewWalletPass.reserve(100);
1630 strNewWalletPass = params[1].get_str().c_str();
1632 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1633 throw runtime_error(
1634 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1635 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1637 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1638 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1644 Value walletlock(const Array& params, bool fHelp)
1646 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1647 throw runtime_error(
1649 "Removes the wallet encryption key from memory, locking the wallet.\n"
1650 "After calling this method, you will need to call walletpassphrase again\n"
1651 "before being able to call any methods which require the wallet to be unlocked.");
1654 if (!pwalletMain->IsCrypted())
1655 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1657 pwalletMain->Lock();
1658 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1660 nWalletUnlockTime = 0;
1667 Value encryptwallet(const Array& params, bool fHelp)
1669 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1670 throw runtime_error(
1671 "encryptwallet <passphrase>\n"
1672 "Encrypts the wallet with <passphrase>.");
1675 if (pwalletMain->IsCrypted())
1676 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1679 // shutting down via RPC while the GUI is running does not work (yet):
1680 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1683 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1684 // Alternately, find a way to make params[0] mlock()'d to begin with.
1685 SecureString strWalletPass;
1686 strWalletPass.reserve(100);
1687 strWalletPass = params[0].get_str().c_str();
1689 if (strWalletPass.length() < 1)
1690 throw runtime_error(
1691 "encryptwallet <passphrase>\n"
1692 "Encrypts the wallet with <passphrase>.");
1694 if (!pwalletMain->EncryptWallet(strWalletPass))
1695 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1697 // BDB seems to have a bad habit of writing old data into
1698 // slack space in .dat files; that is bad if the old data is
1699 // unencrypted private keys. So:
1700 CreateThread(Shutdown, NULL);
1701 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1705 Value validateaddress(const Array& params, bool fHelp)
1707 if (fHelp || params.size() != 1)
1708 throw runtime_error(
1709 "validateaddress <bitcoinaddress>\n"
1710 "Return information about <bitcoinaddress>.");
1712 CBitcoinAddress address(params[0].get_str());
1713 bool isValid = address.IsValid();
1716 ret.push_back(Pair("isvalid", isValid));
1719 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1720 // version of the address:
1721 string currentAddress = address.ToString();
1722 ret.push_back(Pair("address", currentAddress));
1723 if (pwalletMain->HaveKey(address))
1725 ret.push_back(Pair("ismine", true));
1726 std::vector<unsigned char> vchPubKey;
1727 pwalletMain->GetPubKey(address, vchPubKey);
1728 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1730 key.SetPubKey(vchPubKey);
1731 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1733 else if (pwalletMain->HaveCScript(address.GetHash160()))
1735 ret.push_back(Pair("isscript", true));
1737 pwalletMain->GetCScript(address.GetHash160(), subscript);
1738 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1739 std::vector<CBitcoinAddress> addresses;
1740 txnouttype whichType;
1742 ExtractAddresses(subscript, whichType, addresses, nRequired);
1743 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1745 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1746 a.push_back(addr.ToString());
1747 ret.push_back(Pair("addresses", a));
1748 if (whichType == TX_MULTISIG)
1749 ret.push_back(Pair("sigsrequired", nRequired));
1752 ret.push_back(Pair("ismine", false));
1753 if (pwalletMain->mapAddressBook.count(address))
1754 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1759 Value getwork(const Array& params, bool fHelp)
1761 if (fHelp || params.size() > 1)
1762 throw runtime_error(
1764 "If [data] is not specified, returns formatted hash data to work on:\n"
1765 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1766 " \"data\" : block data\n"
1767 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1768 " \"target\" : little endian hash target\n"
1769 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1772 throw JSONRPCError(-9, "Bitcoin is not connected!");
1774 if (IsInitialBlockDownload())
1775 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1777 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1778 static mapNewBlock_t mapNewBlock;
1779 static vector<CBlock*> vNewBlock;
1780 static CReserveKey reservekey(pwalletMain);
1782 if (params.size() == 0)
1785 static unsigned int nTransactionsUpdatedLast;
1786 static CBlockIndex* pindexPrev;
1787 static int64 nStart;
1788 static CBlock* pblock;
1789 if (pindexPrev != pindexBest ||
1790 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1792 if (pindexPrev != pindexBest)
1794 // Deallocate old blocks since they're obsolete now
1795 mapNewBlock.clear();
1796 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1800 nTransactionsUpdatedLast = nTransactionsUpdated;
1801 pindexPrev = pindexBest;
1805 pblock = CreateNewBlock(reservekey);
1807 throw JSONRPCError(-7, "Out of memory");
1808 vNewBlock.push_back(pblock);
1812 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1815 // Update nExtraNonce
1816 static unsigned int nExtraNonce = 0;
1817 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1820 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1822 // Prebuild hash buffers
1826 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1828 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1831 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1832 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1833 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1834 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1840 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1841 if (vchData.size() != 128)
1842 throw JSONRPCError(-8, "Invalid parameter");
1843 CBlock* pdata = (CBlock*)&vchData[0];
1846 for (int i = 0; i < 128/4; i++)
1847 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1850 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1852 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1854 pblock->nTime = pdata->nTime;
1855 pblock->nNonce = pdata->nNonce;
1856 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1857 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1859 return CheckWork(pblock, *pwalletMain, reservekey);
1864 Value getmemorypool(const Array& params, bool fHelp)
1866 if (fHelp || params.size() > 1)
1867 throw runtime_error(
1868 "getmemorypool [data]\n"
1869 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1870 " \"version\" : block version\n"
1871 " \"previousblockhash\" : hash of current highest block\n"
1872 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1873 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1874 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1875 " \"time\" : timestamp appropriate for next block\n"
1876 " \"mintime\" : minimum timestamp appropriate for next block\n"
1877 " \"curtime\" : current timestamp\n"
1878 " \"bits\" : compressed target of next block\n"
1879 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1881 if (params.size() == 0)
1884 throw JSONRPCError(-9, "Bitcoin is not connected!");
1886 if (IsInitialBlockDownload())
1887 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1889 static CReserveKey reservekey(pwalletMain);
1892 static unsigned int nTransactionsUpdatedLast;
1893 static CBlockIndex* pindexPrev;
1894 static int64 nStart;
1895 static CBlock* pblock;
1896 if (pindexPrev != pindexBest ||
1897 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1899 nTransactionsUpdatedLast = nTransactionsUpdated;
1900 pindexPrev = pindexBest;
1906 pblock = CreateNewBlock(reservekey);
1908 throw JSONRPCError(-7, "Out of memory");
1912 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1916 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1923 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1927 result.push_back(Pair("version", pblock->nVersion));
1928 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1929 result.push_back(Pair("transactions", transactions));
1930 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1931 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1932 result.push_back(Pair("time", (int64_t)pblock->nTime));
1933 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1934 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1940 uBits.nBits = htonl((int32_t)pblock->nBits);
1941 result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1948 CDataStream ssBlock(ParseHex(params[0].get_str()));
1952 return ProcessBlock(NULL, &pblock);
1956 Value getblockhash(const Array& params, bool fHelp)
1958 if (fHelp || params.size() != 1)
1959 throw runtime_error(
1960 "getblockhash <index>\n"
1961 "Returns hash of block in best-block-chain at <index>.");
1963 int nHeight = params[0].get_int();
1964 if (nHeight < 0 || nHeight > nBestHeight)
1965 throw runtime_error("Block number out of range.");
1968 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1969 while (pblockindex->nHeight > nHeight)
1970 pblockindex = pblockindex->pprev;
1971 return pblockindex->phashBlock->GetHex();
1974 Value getblock(const Array& params, bool fHelp)
1976 if (fHelp || params.size() != 1)
1977 throw runtime_error(
1979 "Returns details of a block with given block-hash.");
1981 std::string strHash = params[0].get_str();
1982 uint256 hash(strHash);
1984 if (mapBlockIndex.count(hash) == 0)
1985 throw JSONRPCError(-5, "Block not found");
1988 CBlockIndex* pblockindex = mapBlockIndex[hash];
1989 block.ReadFromDisk(pblockindex, true);
1991 return blockToJSON(block, pblockindex);
2008 pair<string, rpcfn_type> pCallTable[] =
2010 make_pair("help", &help),
2011 make_pair("stop", &stop),
2012 make_pair("getblockcount", &getblockcount),
2013 make_pair("getblocknumber", &getblocknumber),
2014 make_pair("getconnectioncount", &getconnectioncount),
2015 make_pair("getdifficulty", &getdifficulty),
2016 make_pair("getgenerate", &getgenerate),
2017 make_pair("setgenerate", &setgenerate),
2018 make_pair("gethashespersec", &gethashespersec),
2019 make_pair("getinfo", &getinfo),
2020 make_pair("getmininginfo", &getmininginfo),
2021 make_pair("getnewaddress", &getnewaddress),
2022 make_pair("getaccountaddress", &getaccountaddress),
2023 make_pair("setaccount", &setaccount),
2024 make_pair("getaccount", &getaccount),
2025 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2026 make_pair("sendtoaddress", &sendtoaddress),
2027 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2028 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2029 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2030 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2031 make_pair("backupwallet", &backupwallet),
2032 make_pair("keypoolrefill", &keypoolrefill),
2033 make_pair("walletpassphrase", &walletpassphrase),
2034 make_pair("walletpassphrasechange", &walletpassphrasechange),
2035 make_pair("walletlock", &walletlock),
2036 make_pair("encryptwallet", &encryptwallet),
2037 make_pair("validateaddress", &validateaddress),
2038 make_pair("getbalance", &getbalance),
2039 make_pair("move", &movecmd),
2040 make_pair("sendfrom", &sendfrom),
2041 make_pair("sendmany", &sendmany),
2042 make_pair("addmultisigaddress", &addmultisigaddress),
2043 make_pair("getblock", &getblock),
2044 make_pair("getblockhash", &getblockhash),
2045 make_pair("gettransaction", &gettransaction),
2046 make_pair("listtransactions", &listtransactions),
2047 make_pair("signmessage", &signmessage),
2048 make_pair("verifymessage", &verifymessage),
2049 make_pair("getwork", &getwork),
2050 make_pair("listaccounts", &listaccounts),
2051 make_pair("settxfee", &settxfee),
2052 make_pair("getmemorypool", &getmemorypool),
2053 make_pair("listsinceblock", &listsinceblock),
2054 make_pair("dumpprivkey", &dumpprivkey),
2055 make_pair("importprivkey", &importprivkey)
2057 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2059 string pAllowInSafeMode[] =
2064 "getblocknumber", // deprecated
2065 "getconnectioncount",
2073 "getaccountaddress",
2075 "getaddressesbyaccount",
2084 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2092 // This ain't Apache. We're just using HTTP header for the length field
2093 // and to be compatible with other JSON-RPC implementations.
2096 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2099 s << "POST / HTTP/1.1\r\n"
2100 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2101 << "Host: 127.0.0.1\r\n"
2102 << "Content-Type: application/json\r\n"
2103 << "Content-Length: " << strMsg.size() << "\r\n"
2104 << "Connection: close\r\n"
2105 << "Accept: application/json\r\n";
2106 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2107 s << item.first << ": " << item.second << "\r\n";
2108 s << "\r\n" << strMsg;
2113 string rfc1123Time()
2118 struct tm* now_gmt = gmtime(&now);
2119 string locale(setlocale(LC_TIME, NULL));
2120 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2121 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2122 setlocale(LC_TIME, locale.c_str());
2123 return string(buffer);
2126 static string HTTPReply(int nStatus, const string& strMsg)
2129 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2131 "Server: bitcoin-json-rpc/%s\r\n"
2132 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2133 "Content-Type: text/html\r\n"
2134 "Content-Length: 296\r\n"
2136 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2137 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2140 "<TITLE>Error</TITLE>\r\n"
2141 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2143 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2144 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2145 const char *cStatus;
2146 if (nStatus == 200) cStatus = "OK";
2147 else if (nStatus == 400) cStatus = "Bad Request";
2148 else if (nStatus == 403) cStatus = "Forbidden";
2149 else if (nStatus == 404) cStatus = "Not Found";
2150 else if (nStatus == 500) cStatus = "Internal Server Error";
2153 "HTTP/1.1 %d %s\r\n"
2155 "Connection: close\r\n"
2156 "Content-Length: %d\r\n"
2157 "Content-Type: application/json\r\n"
2158 "Server: bitcoin-json-rpc/%s\r\n"
2163 rfc1123Time().c_str(),
2165 FormatFullVersion().c_str(),
2169 int ReadHTTPStatus(std::basic_istream<char>& stream)
2172 getline(stream, str);
2173 vector<string> vWords;
2174 boost::split(vWords, str, boost::is_any_of(" "));
2175 if (vWords.size() < 2)
2177 return atoi(vWords[1].c_str());
2180 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2186 std::getline(stream, str);
2187 if (str.empty() || str == "\r")
2189 string::size_type nColon = str.find(":");
2190 if (nColon != string::npos)
2192 string strHeader = str.substr(0, nColon);
2193 boost::trim(strHeader);
2194 boost::to_lower(strHeader);
2195 string strValue = str.substr(nColon+1);
2196 boost::trim(strValue);
2197 mapHeadersRet[strHeader] = strValue;
2198 if (strHeader == "content-length")
2199 nLen = atoi(strValue.c_str());
2205 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2207 mapHeadersRet.clear();
2211 int nStatus = ReadHTTPStatus(stream);
2214 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2215 if (nLen < 0 || nLen > MAX_SIZE)
2221 vector<char> vch(nLen);
2222 stream.read(&vch[0], nLen);
2223 strMessageRet = string(vch.begin(), vch.end());
2229 bool HTTPAuthorized(map<string, string>& mapHeaders)
2231 string strAuth = mapHeaders["authorization"];
2232 if (strAuth.substr(0,6) != "Basic ")
2234 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2235 string strUserPass = DecodeBase64(strUserPass64);
2236 return strUserPass == strRPCUserColonPass;
2240 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2241 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2242 // unspecified (HTTP errors and contents of 'error').
2244 // 1.0 spec: http://json-rpc.org/wiki/specification
2245 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2246 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2249 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2252 request.push_back(Pair("method", strMethod));
2253 request.push_back(Pair("params", params));
2254 request.push_back(Pair("id", id));
2255 return write_string(Value(request), false) + "\n";
2258 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2261 if (error.type() != null_type)
2262 reply.push_back(Pair("result", Value::null));
2264 reply.push_back(Pair("result", result));
2265 reply.push_back(Pair("error", error));
2266 reply.push_back(Pair("id", id));
2267 return write_string(Value(reply), false) + "\n";
2270 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2272 // Send error reply from json-rpc error object
2274 int code = find_value(objError, "code").get_int();
2275 if (code == -32600) nStatus = 400;
2276 else if (code == -32601) nStatus = 404;
2277 string strReply = JSONRPCReply(Value::null, objError, id);
2278 stream << HTTPReply(nStatus, strReply) << std::flush;
2281 bool ClientAllowed(const string& strAddress)
2283 if (strAddress == asio::ip::address_v4::loopback().to_string())
2285 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2286 BOOST_FOREACH(string strAllow, vAllow)
2287 if (WildcardMatch(strAddress, strAllow))
2294 // IOStream device that speaks SSL but can also speak non-SSL
2296 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2298 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2300 fUseSSL = fUseSSLIn;
2301 fNeedHandshake = fUseSSLIn;
2304 void handshake(ssl::stream_base::handshake_type role)
2306 if (!fNeedHandshake) return;
2307 fNeedHandshake = false;
2308 stream.handshake(role);
2310 std::streamsize read(char* s, std::streamsize n)
2312 handshake(ssl::stream_base::server); // HTTPS servers read first
2313 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2314 return stream.next_layer().read_some(asio::buffer(s, n));
2316 std::streamsize write(const char* s, std::streamsize n)
2318 handshake(ssl::stream_base::client); // HTTPS clients write first
2319 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2320 return asio::write(stream.next_layer(), asio::buffer(s, n));
2322 bool connect(const std::string& server, const std::string& port)
2324 ip::tcp::resolver resolver(stream.get_io_service());
2325 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2326 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2327 ip::tcp::resolver::iterator end;
2328 boost::system::error_code error = asio::error::host_not_found;
2329 while (error && endpoint_iterator != end)
2331 stream.lowest_layer().close();
2332 stream.lowest_layer().connect(*endpoint_iterator++, error);
2340 bool fNeedHandshake;
2346 void ThreadRPCServer(void* parg)
2348 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2351 vnThreadsRunning[4]++;
2352 ThreadRPCServer2(parg);
2353 vnThreadsRunning[4]--;
2355 catch (std::exception& e) {
2356 vnThreadsRunning[4]--;
2357 PrintException(&e, "ThreadRPCServer()");
2359 vnThreadsRunning[4]--;
2360 PrintException(NULL, "ThreadRPCServer()");
2362 printf("ThreadRPCServer exiting\n");
2365 void ThreadRPCServer2(void* parg)
2367 printf("ThreadRPCServer started\n");
2369 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2370 if (strRPCUserColonPass == ":")
2372 string strWhatAmI = "To use bitcoind";
2373 if (mapArgs.count("-server"))
2374 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2375 else if (mapArgs.count("-daemon"))
2376 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2378 _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2379 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2381 GetConfigFile().c_str());
2383 CreateThread(Shutdown, NULL);
2388 bool fUseSSL = GetBoolArg("-rpcssl");
2389 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2391 asio::io_service io_service;
2392 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2393 ip::tcp::acceptor acceptor(io_service, endpoint);
2395 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2398 ssl::context context(io_service, ssl::context::sslv23);
2401 context.set_options(ssl::context::no_sslv2);
2402 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2403 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2404 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2405 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2406 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2407 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2408 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2409 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2411 string ciphers = GetArg("-rpcsslciphers",
2412 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2413 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2417 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2422 // Accept connection
2424 SSLStream sslStream(io_service, context);
2425 SSLIOStreamDevice d(sslStream, fUseSSL);
2426 iostreams::stream<SSLIOStreamDevice> stream(d);
2428 ip::tcp::iostream stream;
2431 ip::tcp::endpoint peer;
2432 vnThreadsRunning[4]--;
2434 acceptor.accept(sslStream.lowest_layer(), peer);
2436 acceptor.accept(*stream.rdbuf(), peer);
2438 vnThreadsRunning[4]++;
2442 // Restrict callers by IP
2443 if (!ClientAllowed(peer.address().to_string()))
2445 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2447 stream << HTTPReply(403, "") << std::flush;
2451 map<string, string> mapHeaders;
2454 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2455 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2458 printf("ThreadRPCServer ReadHTTP timeout\n");
2462 // Check authorization
2463 if (mapHeaders.count("authorization") == 0)
2465 stream << HTTPReply(401, "") << std::flush;
2468 if (!HTTPAuthorized(mapHeaders))
2470 // Deter brute-forcing short passwords
2471 if (mapArgs["-rpcpassword"].size() < 15)
2474 stream << HTTPReply(401, "") << std::flush;
2475 printf("ThreadRPCServer incorrect password attempt\n");
2479 Value id = Value::null;
2484 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2485 throw JSONRPCError(-32700, "Parse error");
2486 const Object& request = valRequest.get_obj();
2488 // Parse id now so errors from here on will have the id
2489 id = find_value(request, "id");
2492 Value valMethod = find_value(request, "method");
2493 if (valMethod.type() == null_type)
2494 throw JSONRPCError(-32600, "Missing method");
2495 if (valMethod.type() != str_type)
2496 throw JSONRPCError(-32600, "Method must be a string");
2497 string strMethod = valMethod.get_str();
2498 if (strMethod != "getwork" && strMethod != "getmemorypool")
2499 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2502 Value valParams = find_value(request, "params");
2504 if (valParams.type() == array_type)
2505 params = valParams.get_array();
2506 else if (valParams.type() == null_type)
2509 throw JSONRPCError(-32600, "Params must be an array");
2512 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2513 if (mi == mapCallTable.end())
2514 throw JSONRPCError(-32601, "Method not found");
2516 // Observe safe mode
2517 string strWarning = GetWarnings("rpc");
2518 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2519 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2525 CRITICAL_BLOCK(cs_main)
2526 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2527 result = (*(*mi).second)(params, false);
2530 string strReply = JSONRPCReply(result, Value::null, id);
2531 stream << HTTPReply(200, strReply) << std::flush;
2533 catch (std::exception& e)
2535 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2538 catch (Object& objError)
2540 ErrorReply(stream, objError, id);
2542 catch (std::exception& e)
2544 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2552 Object CallRPC(const string& strMethod, const Array& params)
2554 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2555 throw runtime_error(strprintf(
2556 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2557 "If the file does not exist, create it with owner-readable-only file permissions."),
2558 GetConfigFile().c_str()));
2560 // Connect to localhost
2561 bool fUseSSL = GetBoolArg("-rpcssl");
2563 asio::io_service io_service;
2564 ssl::context context(io_service, ssl::context::sslv23);
2565 context.set_options(ssl::context::no_sslv2);
2566 SSLStream sslStream(io_service, context);
2567 SSLIOStreamDevice d(sslStream, fUseSSL);
2568 iostreams::stream<SSLIOStreamDevice> stream(d);
2569 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2570 throw runtime_error("couldn't connect to server");
2573 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2575 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2577 throw runtime_error("couldn't connect to server");
2581 // HTTP basic authentication
2582 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2583 map<string, string> mapRequestHeaders;
2584 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2587 string strRequest = JSONRPCRequest(strMethod, params, 1);
2588 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2589 stream << strPost << std::flush;
2592 map<string, string> mapHeaders;
2594 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2596 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2597 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2598 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2599 else if (strReply.empty())
2600 throw runtime_error("no response from server");
2604 if (!read_string(strReply, valReply))
2605 throw runtime_error("couldn't parse reply from server");
2606 const Object& reply = valReply.get_obj();
2608 throw runtime_error("expected reply to have result, error and id properties");
2616 template<typename T>
2617 void ConvertTo(Value& value)
2619 if (value.type() == str_type)
2621 // reinterpret string as unquoted json value
2623 if (!read_string(value.get_str(), value2))
2624 throw runtime_error("type mismatch");
2625 value = value2.get_value<T>();
2629 value = value.get_value<T>();
2633 int CommandLineRPC(int argc, char *argv[])
2640 while (argc > 1 && IsSwitchChar(argv[1][0]))
2648 throw runtime_error("too few parameters");
2649 string strMethod = argv[1];
2651 // Parameters default to strings
2653 for (int i = 2; i < argc; i++)
2654 params.push_back(argv[i]);
2655 int n = params.size();
2658 // Special case non-string parameter types
2660 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2661 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2662 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2663 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2664 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2666 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2668 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2669 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2670 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2672 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2673 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2674 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2675 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2676 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2677 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2678 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2680 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2681 if (strMethod == "sendmany" && n > 1)
2683 string s = params[1].get_str();
2685 if (!read_string(s, v) || v.type() != obj_type)
2686 throw runtime_error("type mismatch");
2687 params[1] = v.get_obj();
2689 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2690 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2691 if (strMethod == "addmultisigaddress" && n > 1)
2693 string s = params[1].get_str();
2695 if (!read_string(s, v) || v.type() != array_type)
2696 throw runtime_error("type mismatch "+s);
2697 params[1] = v.get_array();
2701 Object reply = CallRPC(strMethod, params);
2704 const Value& result = find_value(reply, "result");
2705 const Value& error = find_value(reply, "error");
2707 if (error.type() != null_type)
2710 strPrint = "error: " + write_string(error, false);
2711 int code = find_value(error.get_obj(), "code").get_int();
2717 if (result.type() == null_type)
2719 else if (result.type() == str_type)
2720 strPrint = result.get_str();
2722 strPrint = write_string(result, true);
2725 catch (std::exception& e)
2727 strPrint = string("error: ") + e.what();
2732 PrintException(NULL, "CommandLineRPC()");
2737 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2746 int main(int argc, char *argv[])
2749 // Turn off microsoft heap dump noise
2750 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2751 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2753 setbuf(stdin, NULL);
2754 setbuf(stdout, NULL);
2755 setbuf(stderr, NULL);
2759 if (argc >= 2 && string(argv[1]) == "-server")
2761 printf("server ready\n");
2762 ThreadRPCServer(NULL);
2766 return CommandLineRPC(argc, argv);
2769 catch (std::exception& e) {
2770 PrintException(&e, "main()");
2772 PrintException(NULL, "main()");