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>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem/fstream.hpp>
19 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #include "json/json_spirit_reader_template.h"
22 #include "json/json_spirit_writer_template.h"
23 #include "json/json_spirit_utils.h"
24 #define printf OutputDebugStringF
25 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
26 // precompiled in headers.h. The problem might be when the pch file goes over
27 // a certain size around 145MB. If we need access to json_spirit outside this
28 // file, we could use the compiled json_spirit option.
31 using namespace boost;
32 using namespace boost::asio;
33 using namespace json_spirit;
35 void ThreadRPCServer2(void* parg);
36 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
37 extern map<string, rpcfn_type> mapCallTable;
39 static std::string strRPCUserColonPass;
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
44 extern Value dumpprivkey(const Array& params, bool fHelp);
45 extern Value importprivkey(const Array& params, bool fHelp);
47 Object JSONRPCError(int code, const string& message)
50 error.push_back(Pair("code", code));
51 error.push_back(Pair("message", message));
55 double GetDifficulty(const CBlockIndex* blockindex = NULL)
57 // Floating point number that is a multiple of the minimum difficulty,
58 // minimum difficulty = 1.0.
59 if (blockindex == NULL)
61 if (pindexBest == NULL)
64 blockindex = pindexBest;
67 int nShift = (blockindex->nBits >> 24) & 0xff;
70 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
87 int64 AmountFromValue(const Value& value)
89 double dAmount = value.get_real();
90 if (dAmount <= 0.0 || dAmount > 21000000.0)
91 throw JSONRPCError(-3, "Invalid amount");
92 int64 nAmount = roundint64(dAmount * COIN);
93 if (!MoneyRange(nAmount))
94 throw JSONRPCError(-3, "Invalid amount");
98 Value ValueFromAmount(int64 amount)
100 return (double)amount / (double)COIN;
104 HexBits(unsigned int nBits)
110 uBits.nBits = htonl((int32_t)nBits);
111 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
114 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
116 int confirms = wtx.GetDepthInMainChain();
117 entry.push_back(Pair("confirmations", confirms));
120 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
121 entry.push_back(Pair("blockindex", wtx.nIndex));
123 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
124 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
125 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
126 entry.push_back(Pair(item.first, item.second));
129 string AccountFromValue(const Value& value)
131 string strAccount = value.get_str();
132 if (strAccount == "*")
133 throw JSONRPCError(-11, "Invalid account name");
137 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
140 result.push_back(Pair("hash", block.GetHash().GetHex()));
141 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
142 result.push_back(Pair("height", blockindex->nHeight));
143 result.push_back(Pair("version", block.nVersion));
144 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
145 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
146 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
147 result.push_back(Pair("bits", HexBits(block.nBits)));
148 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
150 BOOST_FOREACH (const CTransaction&tx, block.vtx)
151 txhashes.push_back(tx.GetHash().GetHex());
152 result.push_back(Pair("tx", txhashes));
154 if (blockindex->pprev)
155 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
156 if (blockindex->pnext)
157 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
164 /// Note: This interface may still be subject to change.
168 Value help(const Array& params, bool fHelp)
170 if (fHelp || params.size() > 1)
173 "List commands, or get help for a command.");
176 if (params.size() > 0)
177 strCommand = params[0].get_str();
180 set<rpcfn_type> setDone;
181 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
183 string strMethod = (*mi).first;
184 // We already filter duplicates, but these deprecated screw up the sort order
185 if (strMethod == "getamountreceived" ||
186 strMethod == "getallreceived" ||
187 strMethod == "getblocknumber" || // deprecated
188 (strMethod.find("label") != string::npos))
190 if (strCommand != "" && strMethod != strCommand)
195 rpcfn_type pfn = (*mi).second;
196 if (setDone.insert(pfn).second)
197 (*pfn)(params, true);
199 catch (std::exception& e)
201 // Help text is returned in an exception
202 string strHelp = string(e.what());
203 if (strCommand == "")
204 if (strHelp.find('\n') != string::npos)
205 strHelp = strHelp.substr(0, strHelp.find('\n'));
206 strRet += strHelp + "\n";
210 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
211 strRet = strRet.substr(0,strRet.size()-1);
216 Value stop(const Array& params, bool fHelp)
218 if (fHelp || params.size() != 0)
221 "Stop bitcoin server.");
222 // Shutdown will take long enough that the response should get back
224 return "bitcoin server stopping";
228 Value getblockcount(const Array& params, bool fHelp)
230 if (fHelp || params.size() != 0)
233 "Returns the number of blocks in the longest block chain.");
240 Value getblocknumber(const Array& params, bool fHelp)
242 if (fHelp || params.size() != 0)
245 "Deprecated. Use getblockcount.");
251 Value getconnectioncount(const Array& params, bool fHelp)
253 if (fHelp || params.size() != 0)
255 "getconnectioncount\n"
256 "Returns the number of connections to other nodes.");
258 return (int)vNodes.size();
262 Value getdifficulty(const Array& params, bool fHelp)
264 if (fHelp || params.size() != 0)
267 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
269 return GetDifficulty();
273 Value getgenerate(const Array& params, bool fHelp)
275 if (fHelp || params.size() != 0)
278 "Returns true or false.");
280 return GetBoolArg("-gen");
284 Value setgenerate(const Array& params, bool fHelp)
286 if (fHelp || params.size() < 1 || params.size() > 2)
288 "setgenerate <generate> [genproclimit]\n"
289 "<generate> is true or false to turn generation on or off.\n"
290 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
292 bool fGenerate = true;
293 if (params.size() > 0)
294 fGenerate = params[0].get_bool();
296 if (params.size() > 1)
298 int nGenProcLimit = params[1].get_int();
299 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
300 if (nGenProcLimit == 0)
303 mapArgs["-gen"] = (fGenerate ? "1" : "0");
305 GenerateBitcoins(fGenerate, pwalletMain);
310 Value gethashespersec(const Array& params, bool fHelp)
312 if (fHelp || params.size() != 0)
315 "Returns a recent hashes per second performance measurement while generating.");
317 if (GetTimeMillis() - nHPSTimerStart > 8000)
318 return (boost::int64_t)0;
319 return (boost::int64_t)dHashesPerSec;
323 Value getinfo(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 0)
328 "Returns an object containing various state info.");
331 obj.push_back(Pair("version", (int)CLIENT_VERSION));
332 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
333 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
334 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
335 obj.push_back(Pair("blocks", (int)nBestHeight));
336 obj.push_back(Pair("connections", (int)vNodes.size()));
337 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
338 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
339 obj.push_back(Pair("testnet", fTestNet));
340 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
341 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
342 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
343 if (pwalletMain->IsCrypted())
344 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
345 obj.push_back(Pair("errors", GetWarnings("statusbar")));
350 Value getmininginfo(const Array& params, bool fHelp)
352 if (fHelp || params.size() != 0)
355 "Returns an object containing mining-related information.");
358 obj.push_back(Pair("blocks", (int)nBestHeight));
359 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
360 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
361 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
362 obj.push_back(Pair("errors", GetWarnings("statusbar")));
363 obj.push_back(Pair("generate", GetBoolArg("-gen")));
364 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
365 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
366 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
367 obj.push_back(Pair("testnet", fTestNet));
372 Value getnewaddress(const Array& params, bool fHelp)
374 if (fHelp || params.size() > 1)
376 "getnewaddress [account]\n"
377 "Returns a new bitcoin address for receiving payments. "
378 "If [account] is specified (recommended), it is added to the address book "
379 "so payments received with the address will be credited to [account].");
381 // Parse the account first so we don't generate a key if there's an error
383 if (params.size() > 0)
384 strAccount = AccountFromValue(params[0]);
386 if (!pwalletMain->IsLocked())
387 pwalletMain->TopUpKeyPool();
389 // Generate a new key that is added to wallet
390 std::vector<unsigned char> newKey;
391 if (!pwalletMain->GetKeyFromPool(newKey, false))
392 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
393 CBitcoinAddress address(newKey);
395 pwalletMain->SetAddressBookName(address, strAccount);
397 return address.ToString();
401 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
403 CWalletDB walletdb(pwalletMain->strWalletFile);
406 walletdb.ReadAccount(strAccount, account);
408 bool bKeyUsed = false;
410 // Check if the current key has been used
411 if (!account.vchPubKey.empty())
413 CScript scriptPubKey;
414 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
415 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
416 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
419 const CWalletTx& wtx = (*it).second;
420 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
421 if (txout.scriptPubKey == scriptPubKey)
426 // Generate a new key
427 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
429 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
430 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
432 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
433 walletdb.WriteAccount(strAccount, account);
436 return CBitcoinAddress(account.vchPubKey);
439 Value getaccountaddress(const Array& params, bool fHelp)
441 if (fHelp || params.size() != 1)
443 "getaccountaddress <account>\n"
444 "Returns the current bitcoin address for receiving payments to this account.");
446 // Parse the account first so we don't generate a key if there's an error
447 string strAccount = AccountFromValue(params[0]);
451 ret = GetAccountAddress(strAccount).ToString();
458 Value setaccount(const Array& params, bool fHelp)
460 if (fHelp || params.size() < 1 || params.size() > 2)
462 "setaccount <bitcoinaddress> <account>\n"
463 "Sets the account associated with the given address.");
465 CBitcoinAddress address(params[0].get_str());
466 if (!address.IsValid())
467 throw JSONRPCError(-5, "Invalid bitcoin address");
471 if (params.size() > 1)
472 strAccount = AccountFromValue(params[1]);
474 // Detect when changing the account of an address that is the 'unused current key' of another account:
475 if (pwalletMain->mapAddressBook.count(address))
477 string strOldAccount = pwalletMain->mapAddressBook[address];
478 if (address == GetAccountAddress(strOldAccount))
479 GetAccountAddress(strOldAccount, true);
482 pwalletMain->SetAddressBookName(address, strAccount);
488 Value getaccount(const Array& params, bool fHelp)
490 if (fHelp || params.size() != 1)
492 "getaccount <bitcoinaddress>\n"
493 "Returns the account associated with the given address.");
495 CBitcoinAddress address(params[0].get_str());
496 if (!address.IsValid())
497 throw JSONRPCError(-5, "Invalid bitcoin address");
500 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
501 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
502 strAccount = (*mi).second;
507 Value getaddressesbyaccount(const Array& params, bool fHelp)
509 if (fHelp || params.size() != 1)
511 "getaddressesbyaccount <account>\n"
512 "Returns the list of addresses for the given account.");
514 string strAccount = AccountFromValue(params[0]);
516 // Find all addresses that have the given account
518 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
520 const CBitcoinAddress& address = item.first;
521 const string& strName = item.second;
522 if (strName == strAccount)
523 ret.push_back(address.ToString());
528 Value settxfee(const Array& params, bool fHelp)
530 if (fHelp || params.size() < 1 || params.size() > 1)
532 "settxfee <amount>\n"
533 "<amount> is a real and is rounded to the nearest 0.00000001");
537 if (params[0].get_real() != 0.0)
538 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
540 nTransactionFee = nAmount;
544 Value sendtoaddress(const Array& params, bool fHelp)
546 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
548 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
549 "<amount> is a real and is rounded to the nearest 0.00000001\n"
550 "requires wallet passphrase to be set with walletpassphrase first");
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");
556 CBitcoinAddress address(params[0].get_str());
557 if (!address.IsValid())
558 throw JSONRPCError(-5, "Invalid bitcoin address");
561 int64 nAmount = AmountFromValue(params[1]);
565 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
566 wtx.mapValue["comment"] = params[2].get_str();
567 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
568 wtx.mapValue["to"] = params[3].get_str();
570 if (pwalletMain->IsLocked())
571 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
573 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
575 throw JSONRPCError(-4, strError);
577 return wtx.GetHash().GetHex();
580 Value signmessage(const Array& params, bool fHelp)
582 if (fHelp || params.size() != 2)
584 "signmessage <bitcoinaddress> <message>\n"
585 "Sign a message with the private key of an address");
587 if (pwalletMain->IsLocked())
588 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
590 string strAddress = params[0].get_str();
591 string strMessage = params[1].get_str();
593 CBitcoinAddress addr(strAddress);
595 throw JSONRPCError(-3, "Invalid address");
598 if (!pwalletMain->GetKey(addr, key))
599 throw JSONRPCError(-4, "Private key not available");
601 CDataStream ss(SER_GETHASH);
602 ss << strMessageMagic;
605 vector<unsigned char> vchSig;
606 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
607 throw JSONRPCError(-5, "Sign failed");
609 return EncodeBase64(&vchSig[0], vchSig.size());
612 Value verifymessage(const Array& params, bool fHelp)
614 if (fHelp || params.size() != 3)
616 "verifymessage <bitcoinaddress> <signature> <message>\n"
617 "Verify a signed message");
619 string strAddress = params[0].get_str();
620 string strSign = params[1].get_str();
621 string strMessage = params[2].get_str();
623 CBitcoinAddress addr(strAddress);
625 throw JSONRPCError(-3, "Invalid address");
627 bool fInvalid = false;
628 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
631 throw JSONRPCError(-5, "Malformed base64 encoding");
633 CDataStream ss(SER_GETHASH);
634 ss << strMessageMagic;
638 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
641 return (CBitcoinAddress(key.GetPubKey()) == addr);
645 Value getreceivedbyaddress(const Array& params, bool fHelp)
647 if (fHelp || params.size() < 1 || params.size() > 2)
649 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
650 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
653 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
654 CScript scriptPubKey;
655 if (!address.IsValid())
656 throw JSONRPCError(-5, "Invalid bitcoin address");
657 scriptPubKey.SetBitcoinAddress(address);
658 if (!IsMine(*pwalletMain,scriptPubKey))
661 // Minimum confirmations
663 if (params.size() > 1)
664 nMinDepth = params[1].get_int();
668 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
670 const CWalletTx& wtx = (*it).second;
671 if (wtx.IsCoinBase() || !wtx.IsFinal())
674 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
675 if (txout.scriptPubKey == scriptPubKey)
676 if (wtx.GetDepthInMainChain() >= nMinDepth)
677 nAmount += txout.nValue;
680 return ValueFromAmount(nAmount);
684 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
686 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
688 const CBitcoinAddress& address = item.first;
689 const string& strName = item.second;
690 if (strName == strAccount)
691 setAddress.insert(address);
696 Value getreceivedbyaccount(const Array& params, bool fHelp)
698 if (fHelp || params.size() < 1 || params.size() > 2)
700 "getreceivedbyaccount <account> [minconf=1]\n"
701 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
703 // Minimum confirmations
705 if (params.size() > 1)
706 nMinDepth = params[1].get_int();
708 // Get the set of pub keys assigned to account
709 string strAccount = AccountFromValue(params[0]);
710 set<CBitcoinAddress> setAddress;
711 GetAccountAddresses(strAccount, setAddress);
715 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
717 const CWalletTx& wtx = (*it).second;
718 if (wtx.IsCoinBase() || !wtx.IsFinal())
721 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
723 CBitcoinAddress address;
724 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
725 if (wtx.GetDepthInMainChain() >= nMinDepth)
726 nAmount += txout.nValue;
730 return (double)nAmount / (double)COIN;
734 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
738 // Tally wallet transactions
739 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
741 const CWalletTx& wtx = (*it).second;
745 int64 nGenerated, nReceived, nSent, nFee;
746 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
748 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
749 nBalance += nReceived;
750 nBalance += nGenerated - nSent - nFee;
753 // Tally internal accounting entries
754 nBalance += walletdb.GetAccountCreditDebit(strAccount);
759 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
761 CWalletDB walletdb(pwalletMain->strWalletFile);
762 return GetAccountBalance(walletdb, strAccount, nMinDepth);
766 Value getbalance(const Array& params, bool fHelp)
768 if (fHelp || params.size() > 2)
770 "getbalance [account] [minconf=1]\n"
771 "If [account] is not specified, returns the server's total available balance.\n"
772 "If [account] is specified, returns the balance in the account.");
774 if (params.size() == 0)
775 return ValueFromAmount(pwalletMain->GetBalance());
778 if (params.size() > 1)
779 nMinDepth = params[1].get_int();
781 if (params[0].get_str() == "*") {
782 // Calculate total balance a different way from GetBalance()
783 // (GetBalance() sums up all unspent TxOuts)
784 // getbalance and getbalance '*' should always return the same number.
786 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
788 const CWalletTx& wtx = (*it).second;
792 int64 allGeneratedImmature, allGeneratedMature, allFee;
793 allGeneratedImmature = allGeneratedMature = allFee = 0;
794 string strSentAccount;
795 list<pair<CBitcoinAddress, int64> > listReceived;
796 list<pair<CBitcoinAddress, int64> > listSent;
797 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
798 if (wtx.GetDepthInMainChain() >= nMinDepth)
800 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
801 nBalance += r.second;
803 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
804 nBalance -= r.second;
806 nBalance += allGeneratedMature;
808 return ValueFromAmount(nBalance);
811 string strAccount = AccountFromValue(params[0]);
813 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
815 return ValueFromAmount(nBalance);
819 Value movecmd(const Array& params, bool fHelp)
821 if (fHelp || params.size() < 3 || params.size() > 5)
823 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
824 "Move from one account in your wallet to another.");
826 string strFrom = AccountFromValue(params[0]);
827 string strTo = AccountFromValue(params[1]);
828 int64 nAmount = AmountFromValue(params[2]);
829 if (params.size() > 3)
830 // unused parameter, used to be nMinDepth, keep type-checking it though
831 (void)params[3].get_int();
833 if (params.size() > 4)
834 strComment = params[4].get_str();
836 CWalletDB walletdb(pwalletMain->strWalletFile);
839 int64 nNow = GetAdjustedTime();
842 CAccountingEntry debit;
843 debit.strAccount = strFrom;
844 debit.nCreditDebit = -nAmount;
846 debit.strOtherAccount = strTo;
847 debit.strComment = strComment;
848 walletdb.WriteAccountingEntry(debit);
851 CAccountingEntry credit;
852 credit.strAccount = strTo;
853 credit.nCreditDebit = nAmount;
855 credit.strOtherAccount = strFrom;
856 credit.strComment = strComment;
857 walletdb.WriteAccountingEntry(credit);
859 walletdb.TxnCommit();
865 Value sendfrom(const Array& params, bool fHelp)
867 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
869 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
870 "<amount> is a real and is rounded to the nearest 0.00000001\n"
871 "requires wallet passphrase to be set with walletpassphrase first");
872 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
874 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
875 "<amount> is a real and is rounded to the nearest 0.00000001");
877 string strAccount = AccountFromValue(params[0]);
878 CBitcoinAddress address(params[1].get_str());
879 if (!address.IsValid())
880 throw JSONRPCError(-5, "Invalid bitcoin address");
881 int64 nAmount = AmountFromValue(params[2]);
883 if (params.size() > 3)
884 nMinDepth = params[3].get_int();
887 wtx.strFromAccount = strAccount;
888 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
889 wtx.mapValue["comment"] = params[4].get_str();
890 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
891 wtx.mapValue["to"] = params[5].get_str();
893 if (pwalletMain->IsLocked())
894 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
897 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
898 if (nAmount > nBalance)
899 throw JSONRPCError(-6, "Account has insufficient funds");
902 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
904 throw JSONRPCError(-4, strError);
906 return wtx.GetHash().GetHex();
910 Value sendmany(const Array& params, bool fHelp)
912 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
914 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
915 "amounts are double-precision floating point numbers\n"
916 "requires wallet passphrase to be set with walletpassphrase first");
917 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
919 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
920 "amounts are double-precision floating point numbers");
922 string strAccount = AccountFromValue(params[0]);
923 Object sendTo = params[1].get_obj();
925 if (params.size() > 2)
926 nMinDepth = params[2].get_int();
929 wtx.strFromAccount = strAccount;
930 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
931 wtx.mapValue["comment"] = params[3].get_str();
933 set<CBitcoinAddress> setAddress;
934 vector<pair<CScript, int64> > vecSend;
936 int64 totalAmount = 0;
937 BOOST_FOREACH(const Pair& s, sendTo)
939 CBitcoinAddress address(s.name_);
940 if (!address.IsValid())
941 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
943 if (setAddress.count(address))
944 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
945 setAddress.insert(address);
947 CScript scriptPubKey;
948 scriptPubKey.SetBitcoinAddress(address);
949 int64 nAmount = AmountFromValue(s.value_);
950 totalAmount += nAmount;
952 vecSend.push_back(make_pair(scriptPubKey, nAmount));
955 if (pwalletMain->IsLocked())
956 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
959 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
960 if (totalAmount > nBalance)
961 throw JSONRPCError(-6, "Account has insufficient funds");
964 CReserveKey keyChange(pwalletMain);
965 int64 nFeeRequired = 0;
966 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
969 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
970 throw JSONRPCError(-6, "Insufficient funds");
971 throw JSONRPCError(-4, "Transaction creation failed");
973 if (!pwalletMain->CommitTransaction(wtx, keyChange))
974 throw JSONRPCError(-4, "Transaction commit failed");
976 return wtx.GetHash().GetHex();
979 Value addmultisigaddress(const Array& params, bool fHelp)
981 if (fHelp || params.size() < 2 || params.size() > 3)
983 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
984 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
985 "each key is a bitcoin address or hex-encoded public key\n"
986 "If [account] is specified, assign address to [account].";
987 throw runtime_error(msg);
990 int nRequired = params[0].get_int();
991 const Array& keys = params[1].get_array();
993 if (params.size() > 2)
994 strAccount = AccountFromValue(params[2]);
996 // Gather public keys
997 if (nRequired < 1 || keys.size() < nRequired)
999 strprintf("wrong number of keys"
1000 "(got %d, need at least %d)", keys.size(), nRequired));
1001 std::vector<CKey> pubkeys;
1002 pubkeys.resize(keys.size());
1003 for (int i = 0; i < keys.size(); i++)
1005 const std::string& ks = keys[i].get_str();
1007 // Case 1: bitcoin address and we have full public key:
1008 CBitcoinAddress address(ks);
1009 if (address.IsValid())
1011 if (address.IsScript())
1012 throw runtime_error(
1013 strprintf("%s is a pay-to-script address",ks.c_str()));
1014 std::vector<unsigned char> vchPubKey;
1015 if (!pwalletMain->GetPubKey(address, vchPubKey))
1016 throw runtime_error(
1017 strprintf("no full public key for address %s",ks.c_str()));
1018 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1019 throw runtime_error(" Invalid public key: "+ks);
1022 // Case 2: hex public key
1025 vector<unsigned char> vchPubKey = ParseHex(ks);
1026 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1027 throw runtime_error(" Invalid public key: "+ks);
1031 throw runtime_error(" Invalid public key: "+ks);
1035 // Construct using pay-to-script-hash:
1037 inner.SetMultisig(nRequired, pubkeys);
1039 uint160 scriptHash = Hash160(inner);
1040 CScript scriptPubKey;
1041 scriptPubKey.SetPayToScriptHash(inner);
1042 pwalletMain->AddCScript(inner);
1043 CBitcoinAddress address;
1044 address.SetScriptHash160(scriptHash);
1046 pwalletMain->SetAddressBookName(address, strAccount);
1047 return address.ToString();
1058 nConf = std::numeric_limits<int>::max();
1062 Value ListReceived(const Array& params, bool fByAccounts)
1064 // Minimum confirmations
1066 if (params.size() > 0)
1067 nMinDepth = params[0].get_int();
1069 // Whether to include empty accounts
1070 bool fIncludeEmpty = false;
1071 if (params.size() > 1)
1072 fIncludeEmpty = params[1].get_bool();
1075 map<CBitcoinAddress, tallyitem> mapTally;
1076 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1078 const CWalletTx& wtx = (*it).second;
1080 if (wtx.IsCoinBase() || !wtx.IsFinal())
1083 int nDepth = wtx.GetDepthInMainChain();
1084 if (nDepth < nMinDepth)
1087 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1089 CBitcoinAddress address;
1090 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1093 tallyitem& item = mapTally[address];
1094 item.nAmount += txout.nValue;
1095 item.nConf = min(item.nConf, nDepth);
1101 map<string, tallyitem> mapAccountTally;
1102 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1104 const CBitcoinAddress& address = item.first;
1105 const string& strAccount = item.second;
1106 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1107 if (it == mapTally.end() && !fIncludeEmpty)
1111 int nConf = std::numeric_limits<int>::max();
1112 if (it != mapTally.end())
1114 nAmount = (*it).second.nAmount;
1115 nConf = (*it).second.nConf;
1120 tallyitem& item = mapAccountTally[strAccount];
1121 item.nAmount += nAmount;
1122 item.nConf = min(item.nConf, nConf);
1127 obj.push_back(Pair("address", address.ToString()));
1128 obj.push_back(Pair("account", strAccount));
1129 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1130 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1137 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1139 int64 nAmount = (*it).second.nAmount;
1140 int nConf = (*it).second.nConf;
1142 obj.push_back(Pair("account", (*it).first));
1143 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1144 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1152 Value listreceivedbyaddress(const Array& params, bool fHelp)
1154 if (fHelp || params.size() > 2)
1155 throw runtime_error(
1156 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1157 "[minconf] is the minimum number of confirmations before payments are included.\n"
1158 "[includeempty] whether to include addresses that haven't received any payments.\n"
1159 "Returns an array of objects containing:\n"
1160 " \"address\" : receiving address\n"
1161 " \"account\" : the account of the receiving address\n"
1162 " \"amount\" : total amount received by the address\n"
1163 " \"confirmations\" : number of confirmations of the most recent transaction included");
1165 return ListReceived(params, false);
1168 Value listreceivedbyaccount(const Array& params, bool fHelp)
1170 if (fHelp || params.size() > 2)
1171 throw runtime_error(
1172 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1173 "[minconf] is the minimum number of confirmations before payments are included.\n"
1174 "[includeempty] whether to include accounts that haven't received any payments.\n"
1175 "Returns an array of objects containing:\n"
1176 " \"account\" : the account of the receiving addresses\n"
1177 " \"amount\" : total amount received by addresses with this account\n"
1178 " \"confirmations\" : number of confirmations of the most recent transaction included");
1180 return ListReceived(params, true);
1183 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1185 int64 nGeneratedImmature, nGeneratedMature, nFee;
1186 string strSentAccount;
1187 list<pair<CBitcoinAddress, int64> > listReceived;
1188 list<pair<CBitcoinAddress, int64> > listSent;
1190 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1192 bool fAllAccounts = (strAccount == string("*"));
1194 // Generated blocks assigned to account ""
1195 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1198 entry.push_back(Pair("account", string("")));
1199 if (nGeneratedImmature)
1201 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1202 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1206 entry.push_back(Pair("category", "generate"));
1207 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1210 WalletTxToJSON(wtx, entry);
1211 ret.push_back(entry);
1215 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1217 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1220 entry.push_back(Pair("account", strSentAccount));
1221 entry.push_back(Pair("address", s.first.ToString()));
1222 entry.push_back(Pair("category", "send"));
1223 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1224 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1226 WalletTxToJSON(wtx, entry);
1227 ret.push_back(entry);
1232 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1234 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1237 if (pwalletMain->mapAddressBook.count(r.first))
1238 account = pwalletMain->mapAddressBook[r.first];
1239 if (fAllAccounts || (account == strAccount))
1242 entry.push_back(Pair("account", account));
1243 entry.push_back(Pair("address", r.first.ToString()));
1244 entry.push_back(Pair("category", "receive"));
1245 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1247 WalletTxToJSON(wtx, entry);
1248 ret.push_back(entry);
1254 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1256 bool fAllAccounts = (strAccount == string("*"));
1258 if (fAllAccounts || acentry.strAccount == strAccount)
1261 entry.push_back(Pair("account", acentry.strAccount));
1262 entry.push_back(Pair("category", "move"));
1263 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1264 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1265 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1266 entry.push_back(Pair("comment", acentry.strComment));
1267 ret.push_back(entry);
1271 Value listtransactions(const Array& params, bool fHelp)
1273 if (fHelp || params.size() > 3)
1274 throw runtime_error(
1275 "listtransactions [account] [count=10] [from=0]\n"
1276 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1278 string strAccount = "*";
1279 if (params.size() > 0)
1280 strAccount = params[0].get_str();
1282 if (params.size() > 1)
1283 nCount = params[1].get_int();
1285 if (params.size() > 2)
1286 nFrom = params[2].get_int();
1289 throw JSONRPCError(-8, "Negative count");
1291 throw JSONRPCError(-8, "Negative from");
1294 CWalletDB walletdb(pwalletMain->strWalletFile);
1296 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1297 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1298 typedef multimap<int64, TxPair > TxItems;
1301 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1302 // would make this much faster for applications that do this a lot.
1303 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1305 CWalletTx* wtx = &((*it).second);
1306 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1308 list<CAccountingEntry> acentries;
1309 walletdb.ListAccountCreditDebit(strAccount, acentries);
1310 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1312 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1315 // iterate backwards until we have nCount items to return:
1316 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1318 CWalletTx *const pwtx = (*it).second.first;
1320 ListTransactions(*pwtx, strAccount, 0, true, ret);
1321 CAccountingEntry *const pacentry = (*it).second.second;
1323 AcentryToJSON(*pacentry, strAccount, ret);
1325 if (ret.size() >= (nCount+nFrom)) break;
1327 // ret is newest to oldest
1329 if (nFrom > ret.size()) nFrom = ret.size();
1330 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1331 Array::iterator first = ret.begin();
1332 std::advance(first, nFrom);
1333 Array::iterator last = ret.begin();
1334 std::advance(last, nFrom+nCount);
1336 if (last != ret.end()) ret.erase(last, ret.end());
1337 if (first != ret.begin()) ret.erase(ret.begin(), first);
1339 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1344 Value listaccounts(const Array& params, bool fHelp)
1346 if (fHelp || params.size() > 1)
1347 throw runtime_error(
1348 "listaccounts [minconf=1]\n"
1349 "Returns Object that has account names as keys, account balances as values.");
1352 if (params.size() > 0)
1353 nMinDepth = params[0].get_int();
1355 map<string, int64> mapAccountBalances;
1356 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1357 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1358 mapAccountBalances[entry.second] = 0;
1361 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1363 const CWalletTx& wtx = (*it).second;
1364 int64 nGeneratedImmature, nGeneratedMature, nFee;
1365 string strSentAccount;
1366 list<pair<CBitcoinAddress, int64> > listReceived;
1367 list<pair<CBitcoinAddress, int64> > listSent;
1368 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1369 mapAccountBalances[strSentAccount] -= nFee;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1371 mapAccountBalances[strSentAccount] -= s.second;
1372 if (wtx.GetDepthInMainChain() >= nMinDepth)
1374 mapAccountBalances[""] += nGeneratedMature;
1375 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1376 if (pwalletMain->mapAddressBook.count(r.first))
1377 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1379 mapAccountBalances[""] += r.second;
1383 list<CAccountingEntry> acentries;
1384 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1385 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1386 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1389 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1390 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1395 Value listsinceblock(const Array& params, bool fHelp)
1398 throw runtime_error(
1399 "listsinceblock [blockid] [target-confirmations]\n"
1400 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1402 CBlockIndex *pindex = NULL;
1403 int target_confirms = 1;
1405 if (params.size() > 0)
1407 uint256 blockId = 0;
1409 blockId.SetHex(params[0].get_str());
1410 pindex = CBlockLocator(blockId).GetBlockIndex();
1413 if (params.size() > 1)
1415 target_confirms = params[1].get_int();
1417 if (target_confirms < 1)
1418 throw JSONRPCError(-8, "Invalid parameter");
1421 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1425 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1427 CWalletTx tx = (*it).second;
1429 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1430 ListTransactions(tx, "*", 0, true, transactions);
1435 if (target_confirms == 1)
1438 lastblock = hashBestChain;
1442 int target_height = pindexBest->nHeight + 1 - target_confirms;
1445 for (block = pindexBest;
1446 block && block->nHeight > target_height;
1447 block = block->pprev) { }
1449 lastblock = block ? block->GetBlockHash() : 0;
1453 ret.push_back(Pair("transactions", transactions));
1454 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1459 Value gettransaction(const Array& params, bool fHelp)
1461 if (fHelp || params.size() != 1)
1462 throw runtime_error(
1463 "gettransaction <txid>\n"
1464 "Get detailed information about <txid>");
1467 hash.SetHex(params[0].get_str());
1471 if (!pwalletMain->mapWallet.count(hash))
1472 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1473 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1475 int64 nCredit = wtx.GetCredit();
1476 int64 nDebit = wtx.GetDebit();
1477 int64 nNet = nCredit - nDebit;
1478 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1480 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1482 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1484 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1487 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1488 entry.push_back(Pair("details", details));
1494 Value backupwallet(const Array& params, bool fHelp)
1496 if (fHelp || params.size() != 1)
1497 throw runtime_error(
1498 "backupwallet <destination>\n"
1499 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1501 string strDest = params[0].get_str();
1502 BackupWallet(*pwalletMain, strDest);
1508 Value keypoolrefill(const Array& params, bool fHelp)
1510 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511 throw runtime_error(
1513 "Fills the keypool, requires wallet passphrase to be set.");
1514 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1515 throw runtime_error(
1517 "Fills the keypool.");
1519 if (pwalletMain->IsLocked())
1520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1522 pwalletMain->TopUpKeyPool();
1524 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1525 throw JSONRPCError(-4, "Error refreshing keypool.");
1531 void ThreadTopUpKeyPool(void* parg)
1533 pwalletMain->TopUpKeyPool();
1536 void ThreadCleanWalletPassphrase(void* parg)
1538 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1540 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1542 if (nWalletUnlockTime == 0)
1544 nWalletUnlockTime = nMyWakeTime;
1548 if (nWalletUnlockTime==0)
1550 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1554 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1560 if (nWalletUnlockTime)
1562 nWalletUnlockTime = 0;
1563 pwalletMain->Lock();
1568 if (nWalletUnlockTime < nMyWakeTime)
1569 nWalletUnlockTime = nMyWakeTime;
1572 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1574 delete (int64*)parg;
1577 Value walletpassphrase(const Array& params, bool fHelp)
1579 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1580 throw runtime_error(
1581 "walletpassphrase <passphrase> <timeout>\n"
1582 "Stores the wallet decryption key in memory for <timeout> seconds.");
1585 if (!pwalletMain->IsCrypted())
1586 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1588 if (!pwalletMain->IsLocked())
1589 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1591 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1592 SecureString strWalletPass;
1593 strWalletPass.reserve(100);
1594 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1595 // Alternately, find a way to make params[0] mlock()'d to begin with.
1596 strWalletPass = params[0].get_str().c_str();
1598 if (strWalletPass.length() > 0)
1600 if (!pwalletMain->Unlock(strWalletPass))
1601 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1604 throw runtime_error(
1605 "walletpassphrase <passphrase> <timeout>\n"
1606 "Stores the wallet decryption key in memory for <timeout> seconds.");
1608 CreateThread(ThreadTopUpKeyPool, NULL);
1609 int64* pnSleepTime = new int64(params[1].get_int64());
1610 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1616 Value walletpassphrasechange(const Array& params, bool fHelp)
1618 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1619 throw runtime_error(
1620 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1621 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1624 if (!pwalletMain->IsCrypted())
1625 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1627 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1628 // Alternately, find a way to make params[0] mlock()'d to begin with.
1629 SecureString strOldWalletPass;
1630 strOldWalletPass.reserve(100);
1631 strOldWalletPass = params[0].get_str().c_str();
1633 SecureString strNewWalletPass;
1634 strNewWalletPass.reserve(100);
1635 strNewWalletPass = params[1].get_str().c_str();
1637 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1638 throw runtime_error(
1639 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1640 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1642 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1643 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1649 Value walletlock(const Array& params, bool fHelp)
1651 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1652 throw runtime_error(
1654 "Removes the wallet encryption key from memory, locking the wallet.\n"
1655 "After calling this method, you will need to call walletpassphrase again\n"
1656 "before being able to call any methods which require the wallet to be unlocked.");
1659 if (!pwalletMain->IsCrypted())
1660 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1663 LOCK(cs_nWalletUnlockTime);
1664 pwalletMain->Lock();
1665 nWalletUnlockTime = 0;
1672 Value encryptwallet(const Array& params, bool fHelp)
1674 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1675 throw runtime_error(
1676 "encryptwallet <passphrase>\n"
1677 "Encrypts the wallet with <passphrase>.");
1680 if (pwalletMain->IsCrypted())
1681 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
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:
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))
2287 // IOStream device that speaks SSL but can also speak non-SSL
2289 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2291 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2293 fUseSSL = fUseSSLIn;
2294 fNeedHandshake = fUseSSLIn;
2297 void handshake(ssl::stream_base::handshake_type role)
2299 if (!fNeedHandshake) return;
2300 fNeedHandshake = false;
2301 stream.handshake(role);
2303 std::streamsize read(char* s, std::streamsize n)
2305 handshake(ssl::stream_base::server); // HTTPS servers read first
2306 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2307 return stream.next_layer().read_some(asio::buffer(s, n));
2309 std::streamsize write(const char* s, std::streamsize n)
2311 handshake(ssl::stream_base::client); // HTTPS clients write first
2312 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2313 return asio::write(stream.next_layer(), asio::buffer(s, n));
2315 bool connect(const std::string& server, const std::string& port)
2317 ip::tcp::resolver resolver(stream.get_io_service());
2318 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2319 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2320 ip::tcp::resolver::iterator end;
2321 boost::system::error_code error = asio::error::host_not_found;
2322 while (error && endpoint_iterator != end)
2324 stream.lowest_layer().close();
2325 stream.lowest_layer().connect(*endpoint_iterator++, error);
2333 bool fNeedHandshake;
2338 void ThreadRPCServer(void* parg)
2340 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2343 vnThreadsRunning[THREAD_RPCSERVER]++;
2344 ThreadRPCServer2(parg);
2345 vnThreadsRunning[THREAD_RPCSERVER]--;
2347 catch (std::exception& e) {
2348 vnThreadsRunning[THREAD_RPCSERVER]--;
2349 PrintException(&e, "ThreadRPCServer()");
2351 vnThreadsRunning[THREAD_RPCSERVER]--;
2352 PrintException(NULL, "ThreadRPCServer()");
2354 printf("ThreadRPCServer exiting\n");
2357 void ThreadRPCServer2(void* parg)
2359 printf("ThreadRPCServer started\n");
2361 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2362 if (mapArgs["-rpcpassword"] == "")
2364 unsigned char rand_pwd[32];
2365 RAND_bytes(rand_pwd, 32);
2366 string strWhatAmI = "To use bitcoind";
2367 if (mapArgs.count("-server"))
2368 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2369 else if (mapArgs.count("-daemon"))
2370 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2371 ThreadSafeMessageBox(strprintf(
2372 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2373 "It is recommended you use the following random password:\n"
2374 "rpcuser=bitcoinrpc\n"
2376 "(you do not need to remember this password)\n"
2377 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2379 GetConfigFile().string().c_str(),
2380 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2381 _("Error"), wxOK | wxMODAL);
2386 bool fUseSSL = GetBoolArg("-rpcssl");
2387 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2389 asio::io_service io_service;
2390 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2391 ip::tcp::acceptor acceptor(io_service);
2394 acceptor.open(endpoint.protocol());
2395 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2396 acceptor.bind(endpoint);
2397 acceptor.listen(socket_base::max_connections);
2399 catch(boost::system::system_error &e)
2401 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2402 _("Error"), wxOK | wxMODAL);
2407 ssl::context context(io_service, ssl::context::sslv23);
2410 context.set_options(ssl::context::no_sslv2);
2412 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2413 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2414 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2415 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2417 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2418 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2419 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2420 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2422 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2423 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2428 // Accept connection
2429 SSLStream sslStream(io_service, context);
2430 SSLIOStreamDevice d(sslStream, fUseSSL);
2431 iostreams::stream<SSLIOStreamDevice> stream(d);
2433 ip::tcp::endpoint peer;
2434 vnThreadsRunning[THREAD_RPCSERVER]--;
2435 acceptor.accept(sslStream.lowest_layer(), peer);
2436 vnThreadsRunning[4]++;
2440 // Restrict callers by IP
2441 if (!ClientAllowed(peer.address().to_string()))
2443 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2445 stream << HTTPReply(403, "") << std::flush;
2449 map<string, string> mapHeaders;
2452 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2453 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2456 printf("ThreadRPCServer ReadHTTP timeout\n");
2460 // Check authorization
2461 if (mapHeaders.count("authorization") == 0)
2463 stream << HTTPReply(401, "") << std::flush;
2466 if (!HTTPAuthorized(mapHeaders))
2468 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2469 /* Deter brute-forcing short passwords.
2470 If this results in a DOS the user really
2471 shouldn't have their RPC port exposed.*/
2472 if (mapArgs["-rpcpassword"].size() < 20)
2475 stream << HTTPReply(401, "") << std::flush;
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);
2526 LOCK2(cs_main, pwalletMain->cs_wallet);
2527 result = (*(*mi).second)(params, false);
2531 string strReply = JSONRPCReply(result, Value::null, id);
2532 stream << HTTPReply(200, strReply) << std::flush;
2534 catch (std::exception& e)
2536 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2539 catch (Object& objError)
2541 ErrorReply(stream, objError, id);
2543 catch (std::exception& e)
2545 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2553 Object CallRPC(const string& strMethod, const Array& params)
2555 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2556 throw runtime_error(strprintf(
2557 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2558 "If the file does not exist, create it with owner-readable-only file permissions."),
2559 GetConfigFile().string().c_str()));
2561 // Connect to localhost
2562 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");
2572 // HTTP basic authentication
2573 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2574 map<string, string> mapRequestHeaders;
2575 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2578 string strRequest = JSONRPCRequest(strMethod, params, 1);
2579 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2580 stream << strPost << std::flush;
2583 map<string, string> mapHeaders;
2585 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2587 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2588 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2589 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2590 else if (strReply.empty())
2591 throw runtime_error("no response from server");
2595 if (!read_string(strReply, valReply))
2596 throw runtime_error("couldn't parse reply from server");
2597 const Object& reply = valReply.get_obj();
2599 throw runtime_error("expected reply to have result, error and id properties");
2607 template<typename T>
2608 void ConvertTo(Value& value)
2610 if (value.type() == str_type)
2612 // reinterpret string as unquoted json value
2614 if (!read_string(value.get_str(), value2))
2615 throw runtime_error("type mismatch");
2616 value = value2.get_value<T>();
2620 value = value.get_value<T>();
2624 int CommandLineRPC(int argc, char *argv[])
2631 while (argc > 1 && IsSwitchChar(argv[1][0]))
2639 throw runtime_error("too few parameters");
2640 string strMethod = argv[1];
2642 // Parameters default to strings
2644 for (int i = 2; i < argc; i++)
2645 params.push_back(argv[i]);
2646 int n = params.size();
2649 // Special case non-string parameter types
2651 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2652 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2654 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2655 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2657 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2658 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2659 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2661 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2662 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2663 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2664 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2665 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2666 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2667 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2669 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2670 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2672 if (strMethod == "sendmany" && n > 1)
2674 string s = params[1].get_str();
2676 if (!read_string(s, v) || v.type() != obj_type)
2677 throw runtime_error("type mismatch");
2678 params[1] = v.get_obj();
2680 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2681 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2682 if (strMethod == "addmultisigaddress" && n > 1)
2684 string s = params[1].get_str();
2686 if (!read_string(s, v) || v.type() != array_type)
2687 throw runtime_error("type mismatch "+s);
2688 params[1] = v.get_array();
2692 Object reply = CallRPC(strMethod, params);
2695 const Value& result = find_value(reply, "result");
2696 const Value& error = find_value(reply, "error");
2698 if (error.type() != null_type)
2701 strPrint = "error: " + write_string(error, false);
2702 int code = find_value(error.get_obj(), "code").get_int();
2708 if (result.type() == null_type)
2710 else if (result.type() == str_type)
2711 strPrint = result.get_str();
2713 strPrint = write_string(result, true);
2716 catch (std::exception& e)
2718 strPrint = string("error: ") + e.what();
2723 PrintException(NULL, "CommandLineRPC()");
2728 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2737 int main(int argc, char *argv[])
2740 // Turn off microsoft heap dump noise
2741 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2742 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2744 setbuf(stdin, NULL);
2745 setbuf(stdout, NULL);
2746 setbuf(stderr, NULL);
2750 if (argc >= 2 && string(argv[1]) == "-server")
2752 printf("server ready\n");
2753 ThreadRPCServer(NULL);
2757 return CommandLineRPC(argc, argv);
2760 catch (std::exception& e) {
2761 PrintException(&e, "main()");
2763 PrintException(NULL, "main()");