1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
57 double GetDifficulty(const CBlockIndex* blockindex = NULL)
59 // Floating point number that is a multiple of the minimum difficulty,
60 // minimum difficulty = 1.0.
61 if (blockindex == NULL)
63 if (pindexBest == NULL)
66 blockindex = pindexBest;
69 int nShift = (blockindex->nBits >> 24) & 0xff;
72 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
89 int64 AmountFromValue(const Value& value)
91 double dAmount = value.get_real();
92 if (dAmount <= 0.0 || dAmount > 21000000.0)
93 throw JSONRPCError(-3, "Invalid amount");
94 int64 nAmount = roundint64(dAmount * COIN);
95 if (!MoneyRange(nAmount))
96 throw JSONRPCError(-3, "Invalid amount");
100 Value ValueFromAmount(int64 amount)
102 return (double)amount / (double)COIN;
106 HexBits(unsigned int nBits)
112 uBits.nBits = htonl((int32_t)nBits);
113 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
116 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
118 int confirms = wtx.GetDepthInMainChain();
119 entry.push_back(Pair("confirmations", confirms));
122 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
123 entry.push_back(Pair("blockindex", wtx.nIndex));
125 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
126 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
127 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
128 entry.push_back(Pair(item.first, item.second));
131 string AccountFromValue(const Value& value)
133 string strAccount = value.get_str();
134 if (strAccount == "*")
135 throw JSONRPCError(-11, "Invalid account name");
139 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
142 result.push_back(Pair("hash", block.GetHash().GetHex()));
143 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
144 result.push_back(Pair("height", blockindex->nHeight));
145 result.push_back(Pair("version", block.nVersion));
146 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
147 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
148 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
149 result.push_back(Pair("bits", HexBits(block.nBits)));
150 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
152 BOOST_FOREACH (const CTransaction&tx, block.vtx)
153 txhashes.push_back(tx.GetHash().GetHex());
154 result.push_back(Pair("tx", txhashes));
156 if (blockindex->pprev)
157 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
158 if (blockindex->pnext)
159 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
166 /// Note: This interface may still be subject to change.
170 Value help(const Array& params, bool fHelp)
172 if (fHelp || params.size() > 1)
175 "List commands, or get help for a command.");
178 if (params.size() > 0)
179 strCommand = params[0].get_str();
182 set<rpcfn_type> setDone;
183 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
185 string strMethod = (*mi).first;
186 // We already filter duplicates, but these deprecated screw up the sort order
187 if (strMethod == "getamountreceived" ||
188 strMethod == "getallreceived" ||
189 strMethod == "getblocknumber" || // deprecated
190 (strMethod.find("label") != string::npos))
192 if (strCommand != "" && strMethod != strCommand)
197 rpcfn_type pfn = (*mi).second;
198 if (setDone.insert(pfn).second)
199 (*pfn)(params, true);
201 catch (std::exception& e)
203 // Help text is returned in an exception
204 string strHelp = string(e.what());
205 if (strCommand == "")
206 if (strHelp.find('\n') != -1)
207 strHelp = strHelp.substr(0, strHelp.find('\n'));
208 strRet += strHelp + "\n";
212 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
213 strRet = strRet.substr(0,strRet.size()-1);
218 Value stop(const Array& params, bool fHelp)
220 if (fHelp || params.size() != 0)
223 "Stop bitcoin server.");
225 // Shutdown will take long enough that the response should get back
226 CreateThread(Shutdown, NULL);
227 return "bitcoin server stopping";
229 throw runtime_error("NYI: cannot shut down GUI with RPC command");
234 Value getblockcount(const Array& params, bool fHelp)
236 if (fHelp || params.size() != 0)
239 "Returns the number of blocks in the longest block chain.");
246 Value getblocknumber(const Array& params, bool fHelp)
248 if (fHelp || params.size() != 0)
251 "Deprecated. Use getblockcount.");
257 Value getconnectioncount(const Array& params, bool fHelp)
259 if (fHelp || params.size() != 0)
261 "getconnectioncount\n"
262 "Returns the number of connections to other nodes.");
264 return (int)vNodes.size();
268 Value getdifficulty(const Array& params, bool fHelp)
270 if (fHelp || params.size() != 0)
273 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
275 return GetDifficulty();
279 Value getgenerate(const Array& params, bool fHelp)
281 if (fHelp || params.size() != 0)
284 "Returns true or false.");
286 return GetBoolArg("-gen");
290 Value setgenerate(const Array& params, bool fHelp)
292 if (fHelp || params.size() < 1 || params.size() > 2)
294 "setgenerate <generate> [genproclimit]\n"
295 "<generate> is true or false to turn generation on or off.\n"
296 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
298 bool fGenerate = true;
299 if (params.size() > 0)
300 fGenerate = params[0].get_bool();
302 if (params.size() > 1)
304 int nGenProcLimit = params[1].get_int();
305 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
306 if (nGenProcLimit == 0)
309 mapArgs["-gen"] = (fGenerate ? "1" : "0");
311 GenerateBitcoins(fGenerate, pwalletMain);
316 Value gethashespersec(const Array& params, bool fHelp)
318 if (fHelp || params.size() != 0)
321 "Returns a recent hashes per second performance measurement while generating.");
323 if (GetTimeMillis() - nHPSTimerStart > 8000)
324 return (boost::int64_t)0;
325 return (boost::int64_t)dHashesPerSec;
329 Value getinfo(const Array& params, bool fHelp)
331 if (fHelp || params.size() != 0)
334 "Returns an object containing various state info.");
337 obj.push_back(Pair("version", (int)CLIENT_VERSION));
338 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
339 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
340 obj.push_back(Pair("blocks", (int)nBestHeight));
341 obj.push_back(Pair("connections", (int)vNodes.size()));
342 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
343 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
344 obj.push_back(Pair("testnet", fTestNet));
345 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
346 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
347 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
348 if (pwalletMain->IsCrypted())
349 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
350 obj.push_back(Pair("errors", GetWarnings("statusbar")));
355 Value getmininginfo(const Array& params, bool fHelp)
357 if (fHelp || params.size() != 0)
360 "Returns an object containing mining-related information.");
363 obj.push_back(Pair("blocks", (int)nBestHeight));
364 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
365 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
366 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
367 obj.push_back(Pair("errors", GetWarnings("statusbar")));
368 obj.push_back(Pair("generate", GetBoolArg("-gen")));
369 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
370 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
371 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
372 obj.push_back(Pair("testnet", fTestNet));
377 Value getnewaddress(const Array& params, bool fHelp)
379 if (fHelp || params.size() > 1)
381 "getnewaddress [account]\n"
382 "Returns a new bitcoin address for receiving payments. "
383 "If [account] is specified (recommended), it is added to the address book "
384 "so payments received with the address will be credited to [account].");
386 // Parse the account first so we don't generate a key if there's an error
388 if (params.size() > 0)
389 strAccount = AccountFromValue(params[0]);
391 if (!pwalletMain->IsLocked())
392 pwalletMain->TopUpKeyPool();
394 // Generate a new key that is added to wallet
395 std::vector<unsigned char> newKey;
396 if (!pwalletMain->GetKeyFromPool(newKey, false))
397 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
398 CBitcoinAddress address(newKey);
400 pwalletMain->SetAddressBookName(address, strAccount);
402 return address.ToString();
406 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
408 CWalletDB walletdb(pwalletMain->strWalletFile);
411 walletdb.ReadAccount(strAccount, account);
413 bool bKeyUsed = false;
415 // Check if the current key has been used
416 if (!account.vchPubKey.empty())
418 CScript scriptPubKey;
419 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
420 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
421 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
424 const CWalletTx& wtx = (*it).second;
425 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
426 if (txout.scriptPubKey == scriptPubKey)
431 // Generate a new key
432 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
434 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
435 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
437 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
438 walletdb.WriteAccount(strAccount, account);
441 return CBitcoinAddress(account.vchPubKey);
444 Value getaccountaddress(const Array& params, bool fHelp)
446 if (fHelp || params.size() != 1)
448 "getaccountaddress <account>\n"
449 "Returns the current bitcoin address for receiving payments to this account.");
451 // Parse the account first so we don't generate a key if there's an error
452 string strAccount = AccountFromValue(params[0]);
456 ret = GetAccountAddress(strAccount).ToString();
463 Value setaccount(const Array& params, bool fHelp)
465 if (fHelp || params.size() < 1 || params.size() > 2)
467 "setaccount <bitcoinaddress> <account>\n"
468 "Sets the account associated with the given address.");
470 CBitcoinAddress address(params[0].get_str());
471 if (!address.IsValid())
472 throw JSONRPCError(-5, "Invalid bitcoin address");
476 if (params.size() > 1)
477 strAccount = AccountFromValue(params[1]);
479 // Detect when changing the account of an address that is the 'unused current key' of another account:
480 if (pwalletMain->mapAddressBook.count(address))
482 string strOldAccount = pwalletMain->mapAddressBook[address];
483 if (address == GetAccountAddress(strOldAccount))
484 GetAccountAddress(strOldAccount, true);
487 pwalletMain->SetAddressBookName(address, strAccount);
493 Value getaccount(const Array& params, bool fHelp)
495 if (fHelp || params.size() != 1)
497 "getaccount <bitcoinaddress>\n"
498 "Returns the account associated with the given address.");
500 CBitcoinAddress address(params[0].get_str());
501 if (!address.IsValid())
502 throw JSONRPCError(-5, "Invalid bitcoin address");
505 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
506 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
507 strAccount = (*mi).second;
512 Value getaddressesbyaccount(const Array& params, bool fHelp)
514 if (fHelp || params.size() != 1)
516 "getaddressesbyaccount <account>\n"
517 "Returns the list of addresses for the given account.");
519 string strAccount = AccountFromValue(params[0]);
521 // Find all addresses that have the given account
523 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
525 const CBitcoinAddress& address = item.first;
526 const string& strName = item.second;
527 if (strName == strAccount)
528 ret.push_back(address.ToString());
533 Value settxfee(const Array& params, bool fHelp)
535 if (fHelp || params.size() < 1 || params.size() > 1)
537 "settxfee <amount>\n"
538 "<amount> is a real and is rounded to the nearest 0.00000001");
542 if (params[0].get_real() != 0.0)
543 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
545 nTransactionFee = nAmount;
549 Value sendtoaddress(const Array& params, bool fHelp)
551 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
553 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
554 "<amount> is a real and is rounded to the nearest 0.00000001\n"
555 "requires wallet passphrase to be set with walletpassphrase first");
556 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
558 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
559 "<amount> is a real and is rounded to the nearest 0.00000001");
561 CBitcoinAddress address(params[0].get_str());
562 if (!address.IsValid())
563 throw JSONRPCError(-5, "Invalid bitcoin address");
566 int64 nAmount = AmountFromValue(params[1]);
570 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
571 wtx.mapValue["comment"] = params[2].get_str();
572 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
573 wtx.mapValue["to"] = params[3].get_str();
575 if (pwalletMain->IsLocked())
576 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
578 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
580 throw JSONRPCError(-4, strError);
582 return wtx.GetHash().GetHex();
585 Value signmessage(const Array& params, bool fHelp)
587 if (fHelp || params.size() != 2)
589 "signmessage <bitcoinaddress> <message>\n"
590 "Sign a message with the private key of an address");
592 if (pwalletMain->IsLocked())
593 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
595 string strAddress = params[0].get_str();
596 string strMessage = params[1].get_str();
598 CBitcoinAddress addr(strAddress);
600 throw JSONRPCError(-3, "Invalid address");
603 if (!pwalletMain->GetKey(addr, key))
604 throw JSONRPCError(-4, "Private key not available");
606 CDataStream ss(SER_GETHASH);
607 ss << strMessageMagic;
610 vector<unsigned char> vchSig;
611 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
612 throw JSONRPCError(-5, "Sign failed");
614 return EncodeBase64(&vchSig[0], vchSig.size());
617 Value verifymessage(const Array& params, bool fHelp)
619 if (fHelp || params.size() != 3)
621 "verifymessage <bitcoinaddress> <signature> <message>\n"
622 "Verify a signed message");
624 string strAddress = params[0].get_str();
625 string strSign = params[1].get_str();
626 string strMessage = params[2].get_str();
628 CBitcoinAddress addr(strAddress);
630 throw JSONRPCError(-3, "Invalid address");
632 bool fInvalid = false;
633 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
636 throw JSONRPCError(-5, "Malformed base64 encoding");
638 CDataStream ss(SER_GETHASH);
639 ss << strMessageMagic;
643 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
646 return (CBitcoinAddress(key.GetPubKey()) == addr);
650 Value getreceivedbyaddress(const Array& params, bool fHelp)
652 if (fHelp || params.size() < 1 || params.size() > 2)
654 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
655 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
658 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
659 CScript scriptPubKey;
660 if (!address.IsValid())
661 throw JSONRPCError(-5, "Invalid bitcoin address");
662 scriptPubKey.SetBitcoinAddress(address);
663 if (!IsMine(*pwalletMain,scriptPubKey))
666 // Minimum confirmations
668 if (params.size() > 1)
669 nMinDepth = params[1].get_int();
673 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
675 const CWalletTx& wtx = (*it).second;
676 if (wtx.IsCoinBase() || !wtx.IsFinal())
679 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
680 if (txout.scriptPubKey == scriptPubKey)
681 if (wtx.GetDepthInMainChain() >= nMinDepth)
682 nAmount += txout.nValue;
685 return ValueFromAmount(nAmount);
689 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
691 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
693 const CBitcoinAddress& address = item.first;
694 const string& strName = item.second;
695 if (strName == strAccount)
696 setAddress.insert(address);
701 Value getreceivedbyaccount(const Array& params, bool fHelp)
703 if (fHelp || params.size() < 1 || params.size() > 2)
705 "getreceivedbyaccount <account> [minconf=1]\n"
706 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
708 // Minimum confirmations
710 if (params.size() > 1)
711 nMinDepth = params[1].get_int();
713 // Get the set of pub keys assigned to account
714 string strAccount = AccountFromValue(params[0]);
715 set<CBitcoinAddress> setAddress;
716 GetAccountAddresses(strAccount, setAddress);
720 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
722 const CWalletTx& wtx = (*it).second;
723 if (wtx.IsCoinBase() || !wtx.IsFinal())
726 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
728 CBitcoinAddress address;
729 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
730 if (wtx.GetDepthInMainChain() >= nMinDepth)
731 nAmount += txout.nValue;
735 return (double)nAmount / (double)COIN;
739 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
743 // Tally wallet transactions
744 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
746 const CWalletTx& wtx = (*it).second;
750 int64 nGenerated, nReceived, nSent, nFee;
751 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
753 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
754 nBalance += nReceived;
755 nBalance += nGenerated - nSent - nFee;
758 // Tally internal accounting entries
759 nBalance += walletdb.GetAccountCreditDebit(strAccount);
764 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
766 CWalletDB walletdb(pwalletMain->strWalletFile);
767 return GetAccountBalance(walletdb, strAccount, nMinDepth);
771 Value getbalance(const Array& params, bool fHelp)
773 if (fHelp || params.size() > 2)
775 "getbalance [account] [minconf=1]\n"
776 "If [account] is not specified, returns the server's total available balance.\n"
777 "If [account] is specified, returns the balance in the account.");
779 if (params.size() == 0)
780 return ValueFromAmount(pwalletMain->GetBalance());
783 if (params.size() > 1)
784 nMinDepth = params[1].get_int();
786 if (params[0].get_str() == "*") {
787 // Calculate total balance a different way from GetBalance()
788 // (GetBalance() sums up all unspent TxOuts)
789 // getbalance and getbalance '*' should always return the same number.
791 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
793 const CWalletTx& wtx = (*it).second;
797 int64 allGeneratedImmature, allGeneratedMature, allFee;
798 allGeneratedImmature = allGeneratedMature = allFee = 0;
799 string strSentAccount;
800 list<pair<CBitcoinAddress, int64> > listReceived;
801 list<pair<CBitcoinAddress, int64> > listSent;
802 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
803 if (wtx.GetDepthInMainChain() >= nMinDepth)
804 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
805 nBalance += r.second;
806 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
807 nBalance -= r.second;
809 nBalance += allGeneratedMature;
811 return ValueFromAmount(nBalance);
814 string strAccount = AccountFromValue(params[0]);
816 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
818 return ValueFromAmount(nBalance);
822 Value movecmd(const Array& params, bool fHelp)
824 if (fHelp || params.size() < 3 || params.size() > 5)
826 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
827 "Move from one account in your wallet to another.");
829 string strFrom = AccountFromValue(params[0]);
830 string strTo = AccountFromValue(params[1]);
831 int64 nAmount = AmountFromValue(params[2]);
832 if (params.size() > 3)
833 // unused parameter, used to be nMinDepth, keep type-checking it though
834 (void)params[3].get_int();
836 if (params.size() > 4)
837 strComment = params[4].get_str();
839 CWalletDB walletdb(pwalletMain->strWalletFile);
842 int64 nNow = GetAdjustedTime();
845 CAccountingEntry debit;
846 debit.strAccount = strFrom;
847 debit.nCreditDebit = -nAmount;
849 debit.strOtherAccount = strTo;
850 debit.strComment = strComment;
851 walletdb.WriteAccountingEntry(debit);
854 CAccountingEntry credit;
855 credit.strAccount = strTo;
856 credit.nCreditDebit = nAmount;
858 credit.strOtherAccount = strFrom;
859 credit.strComment = strComment;
860 walletdb.WriteAccountingEntry(credit);
862 walletdb.TxnCommit();
868 Value sendfrom(const Array& params, bool fHelp)
870 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
872 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
873 "<amount> is a real and is rounded to the nearest 0.00000001\n"
874 "requires wallet passphrase to be set with walletpassphrase first");
875 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
877 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
878 "<amount> is a real and is rounded to the nearest 0.00000001");
880 string strAccount = AccountFromValue(params[0]);
881 CBitcoinAddress address(params[1].get_str());
882 if (!address.IsValid())
883 throw JSONRPCError(-5, "Invalid bitcoin address");
884 int64 nAmount = AmountFromValue(params[2]);
886 if (params.size() > 3)
887 nMinDepth = params[3].get_int();
890 wtx.strFromAccount = strAccount;
891 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
892 wtx.mapValue["comment"] = params[4].get_str();
893 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
894 wtx.mapValue["to"] = params[5].get_str();
896 if (pwalletMain->IsLocked())
897 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
900 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
901 if (nAmount > nBalance)
902 throw JSONRPCError(-6, "Account has insufficient funds");
905 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
907 throw JSONRPCError(-4, strError);
909 return wtx.GetHash().GetHex();
913 Value sendmany(const Array& params, bool fHelp)
915 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
917 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
918 "amounts are double-precision floating point numbers\n"
919 "requires wallet passphrase to be set with walletpassphrase first");
920 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
922 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
923 "amounts are double-precision floating point numbers");
925 string strAccount = AccountFromValue(params[0]);
926 Object sendTo = params[1].get_obj();
928 if (params.size() > 2)
929 nMinDepth = params[2].get_int();
932 wtx.strFromAccount = strAccount;
933 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
934 wtx.mapValue["comment"] = params[3].get_str();
936 set<CBitcoinAddress> setAddress;
937 vector<pair<CScript, int64> > vecSend;
939 int64 totalAmount = 0;
940 BOOST_FOREACH(const Pair& s, sendTo)
942 CBitcoinAddress address(s.name_);
943 if (!address.IsValid())
944 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
946 if (setAddress.count(address))
947 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
948 setAddress.insert(address);
950 CScript scriptPubKey;
951 scriptPubKey.SetBitcoinAddress(address);
952 int64 nAmount = AmountFromValue(s.value_);
953 totalAmount += nAmount;
955 vecSend.push_back(make_pair(scriptPubKey, nAmount));
958 if (pwalletMain->IsLocked())
959 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
962 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
963 if (totalAmount > nBalance)
964 throw JSONRPCError(-6, "Account has insufficient funds");
967 CReserveKey keyChange(pwalletMain);
968 int64 nFeeRequired = 0;
969 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
972 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
973 throw JSONRPCError(-6, "Insufficient funds");
974 throw JSONRPCError(-4, "Transaction creation failed");
976 if (!pwalletMain->CommitTransaction(wtx, keyChange))
977 throw JSONRPCError(-4, "Transaction commit failed");
979 return wtx.GetHash().GetHex();
982 Value addmultisigaddress(const Array& params, bool fHelp)
984 if (fHelp || params.size() < 2 || params.size() > 3)
986 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
987 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
988 "each key is a bitcoin address or hex-encoded public key\n"
989 "If [account] is specified, assign address to [account].";
990 throw runtime_error(msg);
993 throw runtime_error("addmultisigaddress available only when running -testnet\n");
995 int nRequired = params[0].get_int();
996 const Array& keys = params[1].get_array();
998 if (params.size() > 2)
999 strAccount = AccountFromValue(params[2]);
1001 // Gather public keys
1002 if (nRequired < 1 || keys.size() < nRequired)
1003 throw runtime_error(
1004 strprintf("wrong number of keys"
1005 "(got %d, need at least %d)", keys.size(), nRequired));
1006 std::vector<CKey> pubkeys;
1007 pubkeys.resize(keys.size());
1008 for (int i = 0; i < keys.size(); i++)
1010 const std::string& ks = keys[i].get_str();
1012 // Case 1: bitcoin address and we have full public key:
1013 CBitcoinAddress address(ks);
1014 if (address.IsValid())
1016 if (address.IsScript())
1017 throw runtime_error(
1018 strprintf("%s is a pay-to-script address",ks.c_str()));
1019 std::vector<unsigned char> vchPubKey;
1020 if (!pwalletMain->GetPubKey(address, vchPubKey))
1021 throw runtime_error(
1022 strprintf("no full public key for address %s",ks.c_str()));
1023 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1024 throw runtime_error(" Invalid public key: "+ks);
1027 // Case 2: hex public key
1030 vector<unsigned char> vchPubKey = ParseHex(ks);
1031 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1032 throw runtime_error(" Invalid public key: "+ks);
1036 throw runtime_error(" Invalid public key: "+ks);
1040 // Construct using pay-to-script-hash:
1042 inner.SetMultisig(nRequired, pubkeys);
1044 uint160 scriptHash = Hash160(inner);
1045 CScript scriptPubKey;
1046 scriptPubKey.SetPayToScriptHash(inner);
1047 pwalletMain->AddCScript(inner);
1048 CBitcoinAddress address;
1049 address.SetScriptHash160(scriptHash);
1051 pwalletMain->SetAddressBookName(address, strAccount);
1052 return address.ToString();
1063 nConf = std::numeric_limits<int>::max();
1067 Value ListReceived(const Array& params, bool fByAccounts)
1069 // Minimum confirmations
1071 if (params.size() > 0)
1072 nMinDepth = params[0].get_int();
1074 // Whether to include empty accounts
1075 bool fIncludeEmpty = false;
1076 if (params.size() > 1)
1077 fIncludeEmpty = params[1].get_bool();
1080 map<CBitcoinAddress, tallyitem> mapTally;
1081 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1083 const CWalletTx& wtx = (*it).second;
1085 if (wtx.IsCoinBase() || !wtx.IsFinal())
1088 int nDepth = wtx.GetDepthInMainChain();
1089 if (nDepth < nMinDepth)
1092 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1094 CBitcoinAddress address;
1095 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1098 tallyitem& item = mapTally[address];
1099 item.nAmount += txout.nValue;
1100 item.nConf = min(item.nConf, nDepth);
1106 map<string, tallyitem> mapAccountTally;
1107 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1109 const CBitcoinAddress& address = item.first;
1110 const string& strAccount = item.second;
1111 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1112 if (it == mapTally.end() && !fIncludeEmpty)
1116 int nConf = std::numeric_limits<int>::max();
1117 if (it != mapTally.end())
1119 nAmount = (*it).second.nAmount;
1120 nConf = (*it).second.nConf;
1125 tallyitem& item = mapAccountTally[strAccount];
1126 item.nAmount += nAmount;
1127 item.nConf = min(item.nConf, nConf);
1132 obj.push_back(Pair("address", address.ToString()));
1133 obj.push_back(Pair("account", strAccount));
1134 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1135 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1142 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1144 int64 nAmount = (*it).second.nAmount;
1145 int nConf = (*it).second.nConf;
1147 obj.push_back(Pair("account", (*it).first));
1148 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1149 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1157 Value listreceivedbyaddress(const Array& params, bool fHelp)
1159 if (fHelp || params.size() > 2)
1160 throw runtime_error(
1161 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1162 "[minconf] is the minimum number of confirmations before payments are included.\n"
1163 "[includeempty] whether to include addresses that haven't received any payments.\n"
1164 "Returns an array of objects containing:\n"
1165 " \"address\" : receiving address\n"
1166 " \"account\" : the account of the receiving address\n"
1167 " \"amount\" : total amount received by the address\n"
1168 " \"confirmations\" : number of confirmations of the most recent transaction included");
1170 return ListReceived(params, false);
1173 Value listreceivedbyaccount(const Array& params, bool fHelp)
1175 if (fHelp || params.size() > 2)
1176 throw runtime_error(
1177 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1178 "[minconf] is the minimum number of confirmations before payments are included.\n"
1179 "[includeempty] whether to include accounts that haven't received any payments.\n"
1180 "Returns an array of objects containing:\n"
1181 " \"account\" : the account of the receiving addresses\n"
1182 " \"amount\" : total amount received by addresses with this account\n"
1183 " \"confirmations\" : number of confirmations of the most recent transaction included");
1185 return ListReceived(params, true);
1188 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1190 int64 nGeneratedImmature, nGeneratedMature, nFee;
1191 string strSentAccount;
1192 list<pair<CBitcoinAddress, int64> > listReceived;
1193 list<pair<CBitcoinAddress, int64> > listSent;
1195 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1197 bool fAllAccounts = (strAccount == string("*"));
1199 // Generated blocks assigned to account ""
1200 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1203 entry.push_back(Pair("account", string("")));
1204 if (nGeneratedImmature)
1206 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1207 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1211 entry.push_back(Pair("category", "generate"));
1212 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1215 WalletTxToJSON(wtx, entry);
1216 ret.push_back(entry);
1220 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1222 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1225 entry.push_back(Pair("account", strSentAccount));
1226 entry.push_back(Pair("address", s.first.ToString()));
1227 entry.push_back(Pair("category", "send"));
1228 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1229 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1231 WalletTxToJSON(wtx, entry);
1232 ret.push_back(entry);
1237 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1238 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1241 if (pwalletMain->mapAddressBook.count(r.first))
1242 account = pwalletMain->mapAddressBook[r.first];
1243 if (fAllAccounts || (account == strAccount))
1246 entry.push_back(Pair("account", account));
1247 entry.push_back(Pair("address", r.first.ToString()));
1248 entry.push_back(Pair("category", "receive"));
1249 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1251 WalletTxToJSON(wtx, entry);
1252 ret.push_back(entry);
1257 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1259 bool fAllAccounts = (strAccount == string("*"));
1261 if (fAllAccounts || acentry.strAccount == strAccount)
1264 entry.push_back(Pair("account", acentry.strAccount));
1265 entry.push_back(Pair("category", "move"));
1266 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1267 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1268 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1269 entry.push_back(Pair("comment", acentry.strComment));
1270 ret.push_back(entry);
1274 Value listtransactions(const Array& params, bool fHelp)
1276 if (fHelp || params.size() > 3)
1277 throw runtime_error(
1278 "listtransactions [account] [count=10] [from=0]\n"
1279 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1281 string strAccount = "*";
1282 if (params.size() > 0)
1283 strAccount = params[0].get_str();
1285 if (params.size() > 1)
1286 nCount = params[1].get_int();
1288 if (params.size() > 2)
1289 nFrom = params[2].get_int();
1292 CWalletDB walletdb(pwalletMain->strWalletFile);
1294 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1295 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1296 typedef multimap<int64, TxPair > TxItems;
1299 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1301 CWalletTx* wtx = &((*it).second);
1302 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1304 list<CAccountingEntry> acentries;
1305 walletdb.ListAccountCreditDebit(strAccount, acentries);
1306 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1308 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1311 // Now: iterate backwards until we have nCount items to return:
1312 TxItems::reverse_iterator it = txByTime.rbegin();
1313 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1314 for (; it != txByTime.rend(); ++it)
1316 CWalletTx *const pwtx = (*it).second.first;
1318 ListTransactions(*pwtx, strAccount, 0, true, ret);
1319 CAccountingEntry *const pacentry = (*it).second.second;
1321 AcentryToJSON(*pacentry, strAccount, ret);
1323 if (ret.size() >= nCount) break;
1325 // ret is now newest to oldest
1327 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1328 if (ret.size() > nCount)
1330 Array::iterator last = ret.begin();
1331 std::advance(last, nCount);
1332 ret.erase(last, ret.end());
1334 std::reverse(ret.begin(), ret.end()); // oldest to newest
1339 Value listaccounts(const Array& params, bool fHelp)
1341 if (fHelp || params.size() > 1)
1342 throw runtime_error(
1343 "listaccounts [minconf=1]\n"
1344 "Returns Object that has account names as keys, account balances as values.");
1347 if (params.size() > 0)
1348 nMinDepth = params[0].get_int();
1350 map<string, int64> mapAccountBalances;
1351 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1352 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1353 mapAccountBalances[entry.second] = 0;
1356 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1358 const CWalletTx& wtx = (*it).second;
1359 int64 nGeneratedImmature, nGeneratedMature, nFee;
1360 string strSentAccount;
1361 list<pair<CBitcoinAddress, int64> > listReceived;
1362 list<pair<CBitcoinAddress, int64> > listSent;
1363 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1364 mapAccountBalances[strSentAccount] -= nFee;
1365 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1366 mapAccountBalances[strSentAccount] -= s.second;
1367 if (wtx.GetDepthInMainChain() >= nMinDepth)
1369 mapAccountBalances[""] += nGeneratedMature;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1371 if (pwalletMain->mapAddressBook.count(r.first))
1372 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1374 mapAccountBalances[""] += r.second;
1378 list<CAccountingEntry> acentries;
1379 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1380 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1381 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1384 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1385 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1390 Value listsinceblock(const Array& params, bool fHelp)
1393 throw runtime_error(
1394 "listsinceblock [blockid] [target-confirmations]\n"
1395 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1397 CBlockIndex *pindex = NULL;
1398 int target_confirms = 1;
1400 if (params.size() > 0)
1402 uint256 blockId = 0;
1404 blockId.SetHex(params[0].get_str());
1405 pindex = CBlockLocator(blockId).GetBlockIndex();
1408 if (params.size() > 1)
1410 target_confirms = params[1].get_int();
1412 if (target_confirms < 1)
1413 throw JSONRPCError(-8, "Invalid parameter");
1416 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1420 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1422 CWalletTx tx = (*it).second;
1424 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1425 ListTransactions(tx, "*", 0, true, transactions);
1430 if (target_confirms == 1)
1433 lastblock = hashBestChain;
1437 int target_height = pindexBest->nHeight + 1 - target_confirms;
1440 for (block = pindexBest;
1441 block && block->nHeight > target_height;
1442 block = block->pprev) { }
1444 lastblock = block ? block->GetBlockHash() : 0;
1448 ret.push_back(Pair("transactions", transactions));
1449 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1454 Value gettransaction(const Array& params, bool fHelp)
1456 if (fHelp || params.size() != 1)
1457 throw runtime_error(
1458 "gettransaction <txid>\n"
1459 "Get detailed information about <txid>");
1462 hash.SetHex(params[0].get_str());
1466 if (!pwalletMain->mapWallet.count(hash))
1467 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1468 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1470 int64 nCredit = wtx.GetCredit();
1471 int64 nDebit = wtx.GetDebit();
1472 int64 nNet = nCredit - nDebit;
1473 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1475 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1477 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1479 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1482 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1483 entry.push_back(Pair("details", details));
1489 Value backupwallet(const Array& params, bool fHelp)
1491 if (fHelp || params.size() != 1)
1492 throw runtime_error(
1493 "backupwallet <destination>\n"
1494 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1496 string strDest = params[0].get_str();
1497 BackupWallet(*pwalletMain, strDest);
1503 Value keypoolrefill(const Array& params, bool fHelp)
1505 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1506 throw runtime_error(
1508 "Fills the keypool, requires wallet passphrase to be set.");
1509 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1510 throw runtime_error(
1512 "Fills the keypool.");
1514 if (pwalletMain->IsLocked())
1515 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1517 pwalletMain->TopUpKeyPool();
1519 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1520 throw JSONRPCError(-4, "Error refreshing keypool.");
1526 void ThreadTopUpKeyPool(void* parg)
1528 pwalletMain->TopUpKeyPool();
1531 void ThreadCleanWalletPassphrase(void* parg)
1533 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1535 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1537 if (nWalletUnlockTime == 0)
1539 nWalletUnlockTime = nMyWakeTime;
1543 if (nWalletUnlockTime==0)
1545 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1549 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1551 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1555 if (nWalletUnlockTime)
1557 nWalletUnlockTime = 0;
1558 pwalletMain->Lock();
1563 if (nWalletUnlockTime < nMyWakeTime)
1564 nWalletUnlockTime = nMyWakeTime;
1567 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1569 delete (int64*)parg;
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 int64* pnSleepTime = new int64(params[1].get_int64());
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 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1659 pwalletMain->Lock();
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->UpdateTime(pindexPrev);
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->UpdateTime(pindexPrev);
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()));
1935 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1942 CDataStream ssBlock(ParseHex(params[0].get_str()));
1946 return ProcessBlock(NULL, &pblock);
1950 Value getblockhash(const Array& params, bool fHelp)
1952 if (fHelp || params.size() != 1)
1953 throw runtime_error(
1954 "getblockhash <index>\n"
1955 "Returns hash of block in best-block-chain at <index>.");
1957 int nHeight = params[0].get_int();
1958 if (nHeight < 0 || nHeight > nBestHeight)
1959 throw runtime_error("Block number out of range.");
1962 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1963 while (pblockindex->nHeight > nHeight)
1964 pblockindex = pblockindex->pprev;
1965 return pblockindex->phashBlock->GetHex();
1968 Value getblock(const Array& params, bool fHelp)
1970 if (fHelp || params.size() != 1)
1971 throw runtime_error(
1973 "Returns details of a block with given block-hash.");
1975 std::string strHash = params[0].get_str();
1976 uint256 hash(strHash);
1978 if (mapBlockIndex.count(hash) == 0)
1979 throw JSONRPCError(-5, "Block not found");
1982 CBlockIndex* pblockindex = mapBlockIndex[hash];
1983 block.ReadFromDisk(pblockindex, true);
1985 return blockToJSON(block, pblockindex);
2002 pair<string, rpcfn_type> pCallTable[] =
2004 make_pair("help", &help),
2005 make_pair("stop", &stop),
2006 make_pair("getblockcount", &getblockcount),
2007 make_pair("getblocknumber", &getblocknumber),
2008 make_pair("getconnectioncount", &getconnectioncount),
2009 make_pair("getdifficulty", &getdifficulty),
2010 make_pair("getgenerate", &getgenerate),
2011 make_pair("setgenerate", &setgenerate),
2012 make_pair("gethashespersec", &gethashespersec),
2013 make_pair("getinfo", &getinfo),
2014 make_pair("getmininginfo", &getmininginfo),
2015 make_pair("getnewaddress", &getnewaddress),
2016 make_pair("getaccountaddress", &getaccountaddress),
2017 make_pair("setaccount", &setaccount),
2018 make_pair("getaccount", &getaccount),
2019 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2020 make_pair("sendtoaddress", &sendtoaddress),
2021 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2022 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2023 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2024 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2025 make_pair("backupwallet", &backupwallet),
2026 make_pair("keypoolrefill", &keypoolrefill),
2027 make_pair("walletpassphrase", &walletpassphrase),
2028 make_pair("walletpassphrasechange", &walletpassphrasechange),
2029 make_pair("walletlock", &walletlock),
2030 make_pair("encryptwallet", &encryptwallet),
2031 make_pair("validateaddress", &validateaddress),
2032 make_pair("getbalance", &getbalance),
2033 make_pair("move", &movecmd),
2034 make_pair("sendfrom", &sendfrom),
2035 make_pair("sendmany", &sendmany),
2036 make_pair("addmultisigaddress", &addmultisigaddress),
2037 make_pair("getblock", &getblock),
2038 make_pair("getblockhash", &getblockhash),
2039 make_pair("gettransaction", &gettransaction),
2040 make_pair("listtransactions", &listtransactions),
2041 make_pair("signmessage", &signmessage),
2042 make_pair("verifymessage", &verifymessage),
2043 make_pair("getwork", &getwork),
2044 make_pair("listaccounts", &listaccounts),
2045 make_pair("settxfee", &settxfee),
2046 make_pair("getmemorypool", &getmemorypool),
2047 make_pair("listsinceblock", &listsinceblock),
2048 make_pair("dumpprivkey", &dumpprivkey),
2049 make_pair("importprivkey", &importprivkey)
2051 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2053 string pAllowInSafeMode[] =
2058 "getblocknumber", // deprecated
2059 "getconnectioncount",
2067 "getaccountaddress",
2069 "getaddressesbyaccount",
2078 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2086 // This ain't Apache. We're just using HTTP header for the length field
2087 // and to be compatible with other JSON-RPC implementations.
2090 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2093 s << "POST / HTTP/1.1\r\n"
2094 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2095 << "Host: 127.0.0.1\r\n"
2096 << "Content-Type: application/json\r\n"
2097 << "Content-Length: " << strMsg.size() << "\r\n"
2098 << "Connection: close\r\n"
2099 << "Accept: application/json\r\n";
2100 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2101 s << item.first << ": " << item.second << "\r\n";
2102 s << "\r\n" << strMsg;
2107 string rfc1123Time()
2112 struct tm* now_gmt = gmtime(&now);
2113 string locale(setlocale(LC_TIME, NULL));
2114 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2115 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2116 setlocale(LC_TIME, locale.c_str());
2117 return string(buffer);
2120 static string HTTPReply(int nStatus, const string& strMsg)
2123 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2125 "Server: bitcoin-json-rpc/%s\r\n"
2126 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2127 "Content-Type: text/html\r\n"
2128 "Content-Length: 296\r\n"
2130 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2131 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2134 "<TITLE>Error</TITLE>\r\n"
2135 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2137 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2138 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2139 const char *cStatus;
2140 if (nStatus == 200) cStatus = "OK";
2141 else if (nStatus == 400) cStatus = "Bad Request";
2142 else if (nStatus == 403) cStatus = "Forbidden";
2143 else if (nStatus == 404) cStatus = "Not Found";
2144 else if (nStatus == 500) cStatus = "Internal Server Error";
2147 "HTTP/1.1 %d %s\r\n"
2149 "Connection: close\r\n"
2150 "Content-Length: %d\r\n"
2151 "Content-Type: application/json\r\n"
2152 "Server: bitcoin-json-rpc/%s\r\n"
2157 rfc1123Time().c_str(),
2159 FormatFullVersion().c_str(),
2163 int ReadHTTPStatus(std::basic_istream<char>& stream)
2166 getline(stream, str);
2167 vector<string> vWords;
2168 boost::split(vWords, str, boost::is_any_of(" "));
2169 if (vWords.size() < 2)
2171 return atoi(vWords[1].c_str());
2174 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2180 std::getline(stream, str);
2181 if (str.empty() || str == "\r")
2183 string::size_type nColon = str.find(":");
2184 if (nColon != string::npos)
2186 string strHeader = str.substr(0, nColon);
2187 boost::trim(strHeader);
2188 boost::to_lower(strHeader);
2189 string strValue = str.substr(nColon+1);
2190 boost::trim(strValue);
2191 mapHeadersRet[strHeader] = strValue;
2192 if (strHeader == "content-length")
2193 nLen = atoi(strValue.c_str());
2199 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2201 mapHeadersRet.clear();
2205 int nStatus = ReadHTTPStatus(stream);
2208 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2209 if (nLen < 0 || nLen > MAX_SIZE)
2215 vector<char> vch(nLen);
2216 stream.read(&vch[0], nLen);
2217 strMessageRet = string(vch.begin(), vch.end());
2223 bool HTTPAuthorized(map<string, string>& mapHeaders)
2225 string strAuth = mapHeaders["authorization"];
2226 if (strAuth.substr(0,6) != "Basic ")
2228 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2229 string strUserPass = DecodeBase64(strUserPass64);
2230 return strUserPass == strRPCUserColonPass;
2234 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2235 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2236 // unspecified (HTTP errors and contents of 'error').
2238 // 1.0 spec: http://json-rpc.org/wiki/specification
2239 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2240 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2243 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2246 request.push_back(Pair("method", strMethod));
2247 request.push_back(Pair("params", params));
2248 request.push_back(Pair("id", id));
2249 return write_string(Value(request), false) + "\n";
2252 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2255 if (error.type() != null_type)
2256 reply.push_back(Pair("result", Value::null));
2258 reply.push_back(Pair("result", result));
2259 reply.push_back(Pair("error", error));
2260 reply.push_back(Pair("id", id));
2261 return write_string(Value(reply), false) + "\n";
2264 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2266 // Send error reply from json-rpc error object
2268 int code = find_value(objError, "code").get_int();
2269 if (code == -32600) nStatus = 400;
2270 else if (code == -32601) nStatus = 404;
2271 string strReply = JSONRPCReply(Value::null, objError, id);
2272 stream << HTTPReply(nStatus, strReply) << std::flush;
2275 bool ClientAllowed(const string& strAddress)
2277 if (strAddress == asio::ip::address_v4::loopback().to_string())
2279 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2280 BOOST_FOREACH(string strAllow, vAllow)
2281 if (WildcardMatch(strAddress, strAllow))
2288 // IOStream device that speaks SSL but can also speak non-SSL
2290 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2292 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2294 fUseSSL = fUseSSLIn;
2295 fNeedHandshake = fUseSSLIn;
2298 void handshake(ssl::stream_base::handshake_type role)
2300 if (!fNeedHandshake) return;
2301 fNeedHandshake = false;
2302 stream.handshake(role);
2304 std::streamsize read(char* s, std::streamsize n)
2306 handshake(ssl::stream_base::server); // HTTPS servers read first
2307 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2308 return stream.next_layer().read_some(asio::buffer(s, n));
2310 std::streamsize write(const char* s, std::streamsize n)
2312 handshake(ssl::stream_base::client); // HTTPS clients write first
2313 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2314 return asio::write(stream.next_layer(), asio::buffer(s, n));
2316 bool connect(const std::string& server, const std::string& port)
2318 ip::tcp::resolver resolver(stream.get_io_service());
2319 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2320 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2321 ip::tcp::resolver::iterator end;
2322 boost::system::error_code error = asio::error::host_not_found;
2323 while (error && endpoint_iterator != end)
2325 stream.lowest_layer().close();
2326 stream.lowest_layer().connect(*endpoint_iterator++, error);
2334 bool fNeedHandshake;
2340 void ThreadRPCServer(void* parg)
2342 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2345 vnThreadsRunning[THREAD_RPCSERVER]++;
2346 ThreadRPCServer2(parg);
2347 vnThreadsRunning[THREAD_RPCSERVER]--;
2349 catch (std::exception& e) {
2350 vnThreadsRunning[THREAD_RPCSERVER]--;
2351 PrintException(&e, "ThreadRPCServer()");
2353 vnThreadsRunning[THREAD_RPCSERVER]--;
2354 PrintException(NULL, "ThreadRPCServer()");
2356 printf("ThreadRPCServer exiting\n");
2359 void ThreadRPCServer2(void* parg)
2361 printf("ThreadRPCServer started\n");
2363 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2364 if (mapArgs["-rpcpassword"] == "")
2366 unsigned char rand_pwd[32];
2367 RAND_bytes(rand_pwd, 32);
2368 string strWhatAmI = "To use bitcoind";
2369 if (mapArgs.count("-server"))
2370 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2371 else if (mapArgs.count("-daemon"))
2372 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2374 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2375 "It is recommended you use the following random password:\n"
2376 "rpcuser=bitcoinrpc\n"
2378 "(you do not need to remember this password)\n"
2379 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2381 GetConfigFile().c_str(),
2382 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2384 CreateThread(Shutdown, NULL);
2389 bool fUseSSL = GetBoolArg("-rpcssl");
2390 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2392 asio::io_service io_service;
2393 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2394 ip::tcp::acceptor acceptor(io_service, endpoint);
2396 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2399 ssl::context context(io_service, ssl::context::sslv23);
2402 context.set_options(ssl::context::no_sslv2);
2403 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2404 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2405 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2406 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2407 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2408 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2409 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2410 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2412 string ciphers = GetArg("-rpcsslciphers",
2413 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2414 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2418 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2423 // Accept connection
2425 SSLStream sslStream(io_service, context);
2426 SSLIOStreamDevice d(sslStream, fUseSSL);
2427 iostreams::stream<SSLIOStreamDevice> stream(d);
2429 ip::tcp::iostream stream;
2432 ip::tcp::endpoint peer;
2433 vnThreadsRunning[THREAD_RPCSERVER]--;
2435 acceptor.accept(sslStream.lowest_layer(), peer);
2437 acceptor.accept(*stream.rdbuf(), peer);
2439 vnThreadsRunning[4]++;
2443 // Restrict callers by IP
2444 if (!ClientAllowed(peer.address().to_string()))
2446 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2448 stream << HTTPReply(403, "") << std::flush;
2452 map<string, string> mapHeaders;
2455 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2456 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2459 printf("ThreadRPCServer ReadHTTP timeout\n");
2463 // Check authorization
2464 if (mapHeaders.count("authorization") == 0)
2466 stream << HTTPReply(401, "") << std::flush;
2469 if (!HTTPAuthorized(mapHeaders))
2471 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2472 /* Deter brute-forcing short passwords.
2473 If this results in a DOS the user really
2474 shouldn't have their RPC port exposed.*/
2475 if (mapArgs["-rpcpassword"].size() < 20)
2478 stream << HTTPReply(401, "") << std::flush;
2482 Value id = Value::null;
2487 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2488 throw JSONRPCError(-32700, "Parse error");
2489 const Object& request = valRequest.get_obj();
2491 // Parse id now so errors from here on will have the id
2492 id = find_value(request, "id");
2495 Value valMethod = find_value(request, "method");
2496 if (valMethod.type() == null_type)
2497 throw JSONRPCError(-32600, "Missing method");
2498 if (valMethod.type() != str_type)
2499 throw JSONRPCError(-32600, "Method must be a string");
2500 string strMethod = valMethod.get_str();
2501 if (strMethod != "getwork" && strMethod != "getmemorypool")
2502 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2505 Value valParams = find_value(request, "params");
2507 if (valParams.type() == array_type)
2508 params = valParams.get_array();
2509 else if (valParams.type() == null_type)
2512 throw JSONRPCError(-32600, "Params must be an array");
2515 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2516 if (mi == mapCallTable.end())
2517 throw JSONRPCError(-32601, "Method not found");
2519 // Observe safe mode
2520 string strWarning = GetWarnings("rpc");
2521 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2522 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2528 CRITICAL_BLOCK(cs_main)
2529 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2530 result = (*(*mi).second)(params, false);
2533 string strReply = JSONRPCReply(result, Value::null, id);
2534 stream << HTTPReply(200, strReply) << std::flush;
2536 catch (std::exception& e)
2538 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2541 catch (Object& objError)
2543 ErrorReply(stream, objError, id);
2545 catch (std::exception& e)
2547 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2555 Object CallRPC(const string& strMethod, const Array& params)
2557 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2558 throw runtime_error(strprintf(
2559 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2560 "If the file does not exist, create it with owner-readable-only file permissions."),
2561 GetConfigFile().c_str()));
2563 // Connect to localhost
2564 bool fUseSSL = GetBoolArg("-rpcssl");
2566 asio::io_service io_service;
2567 ssl::context context(io_service, ssl::context::sslv23);
2568 context.set_options(ssl::context::no_sslv2);
2569 SSLStream sslStream(io_service, context);
2570 SSLIOStreamDevice d(sslStream, fUseSSL);
2571 iostreams::stream<SSLIOStreamDevice> stream(d);
2572 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2573 throw runtime_error("couldn't connect to server");
2576 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2578 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2580 throw runtime_error("couldn't connect to server");
2584 // HTTP basic authentication
2585 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2586 map<string, string> mapRequestHeaders;
2587 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2590 string strRequest = JSONRPCRequest(strMethod, params, 1);
2591 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2592 stream << strPost << std::flush;
2595 map<string, string> mapHeaders;
2597 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2599 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2600 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2601 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2602 else if (strReply.empty())
2603 throw runtime_error("no response from server");
2607 if (!read_string(strReply, valReply))
2608 throw runtime_error("couldn't parse reply from server");
2609 const Object& reply = valReply.get_obj();
2611 throw runtime_error("expected reply to have result, error and id properties");
2619 template<typename T>
2620 void ConvertTo(Value& value)
2622 if (value.type() == str_type)
2624 // reinterpret string as unquoted json value
2626 if (!read_string(value.get_str(), value2))
2627 throw runtime_error("type mismatch");
2628 value = value2.get_value<T>();
2632 value = value.get_value<T>();
2636 int CommandLineRPC(int argc, char *argv[])
2643 while (argc > 1 && IsSwitchChar(argv[1][0]))
2651 throw runtime_error("too few parameters");
2652 string strMethod = argv[1];
2654 // Parameters default to strings
2656 for (int i = 2; i < argc; i++)
2657 params.push_back(argv[i]);
2658 int n = params.size();
2661 // Special case non-string parameter types
2663 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2664 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2666 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2667 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2669 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2670 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2671 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2672 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2673 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2675 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2676 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2677 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2678 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2679 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2680 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2681 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2682 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2683 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2684 if (strMethod == "sendmany" && n > 1)
2686 string s = params[1].get_str();
2688 if (!read_string(s, v) || v.type() != obj_type)
2689 throw runtime_error("type mismatch");
2690 params[1] = v.get_obj();
2692 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2693 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2694 if (strMethod == "addmultisigaddress" && n > 1)
2696 string s = params[1].get_str();
2698 if (!read_string(s, v) || v.type() != array_type)
2699 throw runtime_error("type mismatch "+s);
2700 params[1] = v.get_array();
2704 Object reply = CallRPC(strMethod, params);
2707 const Value& result = find_value(reply, "result");
2708 const Value& error = find_value(reply, "error");
2710 if (error.type() != null_type)
2713 strPrint = "error: " + write_string(error, false);
2714 int code = find_value(error.get_obj(), "code").get_int();
2720 if (result.type() == null_type)
2722 else if (result.type() == str_type)
2723 strPrint = result.get_str();
2725 strPrint = write_string(result, true);
2728 catch (std::exception& e)
2730 strPrint = string("error: ") + e.what();
2735 PrintException(NULL, "CommandLineRPC()");
2740 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2749 int main(int argc, char *argv[])
2752 // Turn off microsoft heap dump noise
2753 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2754 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2756 setbuf(stdin, NULL);
2757 setbuf(stdout, NULL);
2758 setbuf(stderr, NULL);
2762 if (argc >= 2 && string(argv[1]) == "-server")
2764 printf("server ready\n");
2765 ThreadRPCServer(NULL);
2769 return CommandLineRPC(argc, argv);
2772 catch (std::exception& e) {
2773 PrintException(&e, "main()");
2775 PrintException(NULL, "main()");