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') != -1)
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)
799 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
800 nBalance += r.second;
801 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
802 nBalance -= r.second;
804 nBalance += allGeneratedMature;
806 return ValueFromAmount(nBalance);
809 string strAccount = AccountFromValue(params[0]);
811 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
813 return ValueFromAmount(nBalance);
817 Value movecmd(const Array& params, bool fHelp)
819 if (fHelp || params.size() < 3 || params.size() > 5)
821 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
822 "Move from one account in your wallet to another.");
824 string strFrom = AccountFromValue(params[0]);
825 string strTo = AccountFromValue(params[1]);
826 int64 nAmount = AmountFromValue(params[2]);
827 if (params.size() > 3)
828 // unused parameter, used to be nMinDepth, keep type-checking it though
829 (void)params[3].get_int();
831 if (params.size() > 4)
832 strComment = params[4].get_str();
834 CWalletDB walletdb(pwalletMain->strWalletFile);
837 int64 nNow = GetAdjustedTime();
840 CAccountingEntry debit;
841 debit.strAccount = strFrom;
842 debit.nCreditDebit = -nAmount;
844 debit.strOtherAccount = strTo;
845 debit.strComment = strComment;
846 walletdb.WriteAccountingEntry(debit);
849 CAccountingEntry credit;
850 credit.strAccount = strTo;
851 credit.nCreditDebit = nAmount;
853 credit.strOtherAccount = strFrom;
854 credit.strComment = strComment;
855 walletdb.WriteAccountingEntry(credit);
857 walletdb.TxnCommit();
863 Value sendfrom(const Array& params, bool fHelp)
865 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
867 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
868 "<amount> is a real and is rounded to the nearest 0.00000001\n"
869 "requires wallet passphrase to be set with walletpassphrase first");
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");
875 string strAccount = AccountFromValue(params[0]);
876 CBitcoinAddress address(params[1].get_str());
877 if (!address.IsValid())
878 throw JSONRPCError(-5, "Invalid bitcoin address");
879 int64 nAmount = AmountFromValue(params[2]);
881 if (params.size() > 3)
882 nMinDepth = params[3].get_int();
885 wtx.strFromAccount = strAccount;
886 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
887 wtx.mapValue["comment"] = params[4].get_str();
888 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
889 wtx.mapValue["to"] = params[5].get_str();
891 if (pwalletMain->IsLocked())
892 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
895 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
896 if (nAmount > nBalance)
897 throw JSONRPCError(-6, "Account has insufficient funds");
900 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
902 throw JSONRPCError(-4, strError);
904 return wtx.GetHash().GetHex();
908 Value sendmany(const Array& params, bool fHelp)
910 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
912 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
913 "amounts are double-precision floating point numbers\n"
914 "requires wallet passphrase to be set with walletpassphrase first");
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");
920 string strAccount = AccountFromValue(params[0]);
921 Object sendTo = params[1].get_obj();
923 if (params.size() > 2)
924 nMinDepth = params[2].get_int();
927 wtx.strFromAccount = strAccount;
928 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
929 wtx.mapValue["comment"] = params[3].get_str();
931 set<CBitcoinAddress> setAddress;
932 vector<pair<CScript, int64> > vecSend;
934 int64 totalAmount = 0;
935 BOOST_FOREACH(const Pair& s, sendTo)
937 CBitcoinAddress address(s.name_);
938 if (!address.IsValid())
939 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
941 if (setAddress.count(address))
942 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
943 setAddress.insert(address);
945 CScript scriptPubKey;
946 scriptPubKey.SetBitcoinAddress(address);
947 int64 nAmount = AmountFromValue(s.value_);
948 totalAmount += nAmount;
950 vecSend.push_back(make_pair(scriptPubKey, nAmount));
953 if (pwalletMain->IsLocked())
954 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
957 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
958 if (totalAmount > nBalance)
959 throw JSONRPCError(-6, "Account has insufficient funds");
962 CReserveKey keyChange(pwalletMain);
963 int64 nFeeRequired = 0;
964 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
967 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
968 throw JSONRPCError(-6, "Insufficient funds");
969 throw JSONRPCError(-4, "Transaction creation failed");
971 if (!pwalletMain->CommitTransaction(wtx, keyChange))
972 throw JSONRPCError(-4, "Transaction commit failed");
974 return wtx.GetHash().GetHex();
977 Value addmultisigaddress(const Array& params, bool fHelp)
979 if (fHelp || params.size() < 2 || params.size() > 3)
981 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
982 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
983 "each key is a bitcoin address or hex-encoded public key\n"
984 "If [account] is specified, assign address to [account].";
985 throw runtime_error(msg);
988 int nRequired = params[0].get_int();
989 const Array& keys = params[1].get_array();
991 if (params.size() > 2)
992 strAccount = AccountFromValue(params[2]);
994 // Gather public keys
995 if (nRequired < 1 || keys.size() < nRequired)
997 strprintf("wrong number of keys"
998 "(got %d, need at least %d)", keys.size(), nRequired));
999 std::vector<CKey> pubkeys;
1000 pubkeys.resize(keys.size());
1001 for (int i = 0; i < keys.size(); i++)
1003 const std::string& ks = keys[i].get_str();
1005 // Case 1: bitcoin address and we have full public key:
1006 CBitcoinAddress address(ks);
1007 if (address.IsValid())
1009 if (address.IsScript())
1010 throw runtime_error(
1011 strprintf("%s is a pay-to-script address",ks.c_str()));
1012 std::vector<unsigned char> vchPubKey;
1013 if (!pwalletMain->GetPubKey(address, vchPubKey))
1014 throw runtime_error(
1015 strprintf("no full public key for address %s",ks.c_str()));
1016 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1017 throw runtime_error(" Invalid public key: "+ks);
1020 // Case 2: hex public key
1023 vector<unsigned char> vchPubKey = ParseHex(ks);
1024 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1025 throw runtime_error(" Invalid public key: "+ks);
1029 throw runtime_error(" Invalid public key: "+ks);
1033 // Construct using pay-to-script-hash:
1035 inner.SetMultisig(nRequired, pubkeys);
1037 uint160 scriptHash = Hash160(inner);
1038 CScript scriptPubKey;
1039 scriptPubKey.SetPayToScriptHash(inner);
1040 pwalletMain->AddCScript(inner);
1041 CBitcoinAddress address;
1042 address.SetScriptHash160(scriptHash);
1044 pwalletMain->SetAddressBookName(address, strAccount);
1045 return address.ToString();
1056 nConf = std::numeric_limits<int>::max();
1060 Value ListReceived(const Array& params, bool fByAccounts)
1062 // Minimum confirmations
1064 if (params.size() > 0)
1065 nMinDepth = params[0].get_int();
1067 // Whether to include empty accounts
1068 bool fIncludeEmpty = false;
1069 if (params.size() > 1)
1070 fIncludeEmpty = params[1].get_bool();
1073 map<CBitcoinAddress, tallyitem> mapTally;
1074 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1076 const CWalletTx& wtx = (*it).second;
1078 if (wtx.IsCoinBase() || !wtx.IsFinal())
1081 int nDepth = wtx.GetDepthInMainChain();
1082 if (nDepth < nMinDepth)
1085 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1087 CBitcoinAddress address;
1088 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1091 tallyitem& item = mapTally[address];
1092 item.nAmount += txout.nValue;
1093 item.nConf = min(item.nConf, nDepth);
1099 map<string, tallyitem> mapAccountTally;
1100 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1102 const CBitcoinAddress& address = item.first;
1103 const string& strAccount = item.second;
1104 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1105 if (it == mapTally.end() && !fIncludeEmpty)
1109 int nConf = std::numeric_limits<int>::max();
1110 if (it != mapTally.end())
1112 nAmount = (*it).second.nAmount;
1113 nConf = (*it).second.nConf;
1118 tallyitem& item = mapAccountTally[strAccount];
1119 item.nAmount += nAmount;
1120 item.nConf = min(item.nConf, nConf);
1125 obj.push_back(Pair("address", address.ToString()));
1126 obj.push_back(Pair("account", strAccount));
1127 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1128 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1135 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1137 int64 nAmount = (*it).second.nAmount;
1138 int nConf = (*it).second.nConf;
1140 obj.push_back(Pair("account", (*it).first));
1141 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1142 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1150 Value listreceivedbyaddress(const Array& params, bool fHelp)
1152 if (fHelp || params.size() > 2)
1153 throw runtime_error(
1154 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1155 "[minconf] is the minimum number of confirmations before payments are included.\n"
1156 "[includeempty] whether to include addresses that haven't received any payments.\n"
1157 "Returns an array of objects containing:\n"
1158 " \"address\" : receiving address\n"
1159 " \"account\" : the account of the receiving address\n"
1160 " \"amount\" : total amount received by the address\n"
1161 " \"confirmations\" : number of confirmations of the most recent transaction included");
1163 return ListReceived(params, false);
1166 Value listreceivedbyaccount(const Array& params, bool fHelp)
1168 if (fHelp || params.size() > 2)
1169 throw runtime_error(
1170 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1171 "[minconf] is the minimum number of confirmations before payments are included.\n"
1172 "[includeempty] whether to include accounts that haven't received any payments.\n"
1173 "Returns an array of objects containing:\n"
1174 " \"account\" : the account of the receiving addresses\n"
1175 " \"amount\" : total amount received by addresses with this account\n"
1176 " \"confirmations\" : number of confirmations of the most recent transaction included");
1178 return ListReceived(params, true);
1181 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1183 int64 nGeneratedImmature, nGeneratedMature, nFee;
1184 string strSentAccount;
1185 list<pair<CBitcoinAddress, int64> > listReceived;
1186 list<pair<CBitcoinAddress, int64> > listSent;
1188 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1190 bool fAllAccounts = (strAccount == string("*"));
1192 // Generated blocks assigned to account ""
1193 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1196 entry.push_back(Pair("account", string("")));
1197 if (nGeneratedImmature)
1199 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1200 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1204 entry.push_back(Pair("category", "generate"));
1205 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1208 WalletTxToJSON(wtx, entry);
1209 ret.push_back(entry);
1213 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1215 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1218 entry.push_back(Pair("account", strSentAccount));
1219 entry.push_back(Pair("address", s.first.ToString()));
1220 entry.push_back(Pair("category", "send"));
1221 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1222 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1224 WalletTxToJSON(wtx, entry);
1225 ret.push_back(entry);
1230 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1231 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1234 if (pwalletMain->mapAddressBook.count(r.first))
1235 account = pwalletMain->mapAddressBook[r.first];
1236 if (fAllAccounts || (account == strAccount))
1239 entry.push_back(Pair("account", account));
1240 entry.push_back(Pair("address", r.first.ToString()));
1241 entry.push_back(Pair("category", "receive"));
1242 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1244 WalletTxToJSON(wtx, entry);
1245 ret.push_back(entry);
1250 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1252 bool fAllAccounts = (strAccount == string("*"));
1254 if (fAllAccounts || acentry.strAccount == strAccount)
1257 entry.push_back(Pair("account", acentry.strAccount));
1258 entry.push_back(Pair("category", "move"));
1259 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1260 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1261 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1262 entry.push_back(Pair("comment", acentry.strComment));
1263 ret.push_back(entry);
1267 Value listtransactions(const Array& params, bool fHelp)
1269 if (fHelp || params.size() > 3)
1270 throw runtime_error(
1271 "listtransactions [account] [count=10] [from=0]\n"
1272 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1274 string strAccount = "*";
1275 if (params.size() > 0)
1276 strAccount = params[0].get_str();
1278 if (params.size() > 1)
1279 nCount = params[1].get_int();
1281 if (params.size() > 2)
1282 nFrom = params[2].get_int();
1285 CWalletDB walletdb(pwalletMain->strWalletFile);
1287 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1288 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1289 typedef multimap<int64, TxPair > TxItems;
1292 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1294 CWalletTx* wtx = &((*it).second);
1295 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1297 list<CAccountingEntry> acentries;
1298 walletdb.ListAccountCreditDebit(strAccount, acentries);
1299 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1301 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1304 // Now: iterate backwards until we have nCount items to return:
1305 TxItems::reverse_iterator it = txByTime.rbegin();
1306 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1307 for (; it != txByTime.rend(); ++it)
1309 CWalletTx *const pwtx = (*it).second.first;
1311 ListTransactions(*pwtx, strAccount, 0, true, ret);
1312 CAccountingEntry *const pacentry = (*it).second.second;
1314 AcentryToJSON(*pacentry, strAccount, ret);
1316 if (ret.size() >= nCount) break;
1318 // ret is now newest to oldest
1320 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1321 if (ret.size() > nCount)
1323 Array::iterator last = ret.begin();
1324 std::advance(last, nCount);
1325 ret.erase(last, ret.end());
1327 std::reverse(ret.begin(), ret.end()); // oldest to newest
1332 Value listaccounts(const Array& params, bool fHelp)
1334 if (fHelp || params.size() > 1)
1335 throw runtime_error(
1336 "listaccounts [minconf=1]\n"
1337 "Returns Object that has account names as keys, account balances as values.");
1340 if (params.size() > 0)
1341 nMinDepth = params[0].get_int();
1343 map<string, int64> mapAccountBalances;
1344 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1345 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1346 mapAccountBalances[entry.second] = 0;
1349 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1351 const CWalletTx& wtx = (*it).second;
1352 int64 nGeneratedImmature, nGeneratedMature, nFee;
1353 string strSentAccount;
1354 list<pair<CBitcoinAddress, int64> > listReceived;
1355 list<pair<CBitcoinAddress, int64> > listSent;
1356 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1357 mapAccountBalances[strSentAccount] -= nFee;
1358 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1359 mapAccountBalances[strSentAccount] -= s.second;
1360 if (wtx.GetDepthInMainChain() >= nMinDepth)
1362 mapAccountBalances[""] += nGeneratedMature;
1363 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1364 if (pwalletMain->mapAddressBook.count(r.first))
1365 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1367 mapAccountBalances[""] += r.second;
1371 list<CAccountingEntry> acentries;
1372 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1373 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1374 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1377 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1378 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1383 Value listsinceblock(const Array& params, bool fHelp)
1386 throw runtime_error(
1387 "listsinceblock [blockid] [target-confirmations]\n"
1388 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1390 CBlockIndex *pindex = NULL;
1391 int target_confirms = 1;
1393 if (params.size() > 0)
1395 uint256 blockId = 0;
1397 blockId.SetHex(params[0].get_str());
1398 pindex = CBlockLocator(blockId).GetBlockIndex();
1401 if (params.size() > 1)
1403 target_confirms = params[1].get_int();
1405 if (target_confirms < 1)
1406 throw JSONRPCError(-8, "Invalid parameter");
1409 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1413 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1415 CWalletTx tx = (*it).second;
1417 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1418 ListTransactions(tx, "*", 0, true, transactions);
1423 if (target_confirms == 1)
1426 lastblock = hashBestChain;
1430 int target_height = pindexBest->nHeight + 1 - target_confirms;
1433 for (block = pindexBest;
1434 block && block->nHeight > target_height;
1435 block = block->pprev) { }
1437 lastblock = block ? block->GetBlockHash() : 0;
1441 ret.push_back(Pair("transactions", transactions));
1442 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1447 Value gettransaction(const Array& params, bool fHelp)
1449 if (fHelp || params.size() != 1)
1450 throw runtime_error(
1451 "gettransaction <txid>\n"
1452 "Get detailed information about <txid>");
1455 hash.SetHex(params[0].get_str());
1459 if (!pwalletMain->mapWallet.count(hash))
1460 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1461 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1463 int64 nCredit = wtx.GetCredit();
1464 int64 nDebit = wtx.GetDebit();
1465 int64 nNet = nCredit - nDebit;
1466 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1468 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1470 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1472 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1475 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1476 entry.push_back(Pair("details", details));
1482 Value backupwallet(const Array& params, bool fHelp)
1484 if (fHelp || params.size() != 1)
1485 throw runtime_error(
1486 "backupwallet <destination>\n"
1487 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1489 string strDest = params[0].get_str();
1490 BackupWallet(*pwalletMain, strDest);
1496 Value keypoolrefill(const Array& params, bool fHelp)
1498 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1499 throw runtime_error(
1501 "Fills the keypool, requires wallet passphrase to be set.");
1502 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1503 throw runtime_error(
1505 "Fills the keypool.");
1507 if (pwalletMain->IsLocked())
1508 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1510 pwalletMain->TopUpKeyPool();
1512 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1513 throw JSONRPCError(-4, "Error refreshing keypool.");
1519 void ThreadTopUpKeyPool(void* parg)
1521 pwalletMain->TopUpKeyPool();
1524 void ThreadCleanWalletPassphrase(void* parg)
1526 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1528 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1530 if (nWalletUnlockTime == 0)
1532 nWalletUnlockTime = nMyWakeTime;
1536 if (nWalletUnlockTime==0)
1538 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1542 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1544 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1548 if (nWalletUnlockTime)
1550 nWalletUnlockTime = 0;
1551 pwalletMain->Lock();
1556 if (nWalletUnlockTime < nMyWakeTime)
1557 nWalletUnlockTime = nMyWakeTime;
1560 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1562 delete (int64*)parg;
1565 Value walletpassphrase(const Array& params, bool fHelp)
1567 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1568 throw runtime_error(
1569 "walletpassphrase <passphrase> <timeout>\n"
1570 "Stores the wallet decryption key in memory for <timeout> seconds.");
1573 if (!pwalletMain->IsCrypted())
1574 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1576 if (!pwalletMain->IsLocked())
1577 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1579 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1580 SecureString strWalletPass;
1581 strWalletPass.reserve(100);
1582 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1583 // Alternately, find a way to make params[0] mlock()'d to begin with.
1584 strWalletPass = params[0].get_str().c_str();
1586 if (strWalletPass.length() > 0)
1588 if (!pwalletMain->Unlock(strWalletPass))
1589 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1592 throw runtime_error(
1593 "walletpassphrase <passphrase> <timeout>\n"
1594 "Stores the wallet decryption key in memory for <timeout> seconds.");
1596 CreateThread(ThreadTopUpKeyPool, NULL);
1597 int64* pnSleepTime = new int64(params[1].get_int64());
1598 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1604 Value walletpassphrasechange(const Array& params, bool fHelp)
1606 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1607 throw runtime_error(
1608 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1609 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1612 if (!pwalletMain->IsCrypted())
1613 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1615 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1616 // Alternately, find a way to make params[0] mlock()'d to begin with.
1617 SecureString strOldWalletPass;
1618 strOldWalletPass.reserve(100);
1619 strOldWalletPass = params[0].get_str().c_str();
1621 SecureString strNewWalletPass;
1622 strNewWalletPass.reserve(100);
1623 strNewWalletPass = params[1].get_str().c_str();
1625 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1626 throw runtime_error(
1627 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1628 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1630 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1631 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1637 Value walletlock(const Array& params, bool fHelp)
1639 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1640 throw runtime_error(
1642 "Removes the wallet encryption key from memory, locking the wallet.\n"
1643 "After calling this method, you will need to call walletpassphrase again\n"
1644 "before being able to call any methods which require the wallet to be unlocked.");
1647 if (!pwalletMain->IsCrypted())
1648 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1651 LOCK(cs_nWalletUnlockTime);
1652 pwalletMain->Lock();
1653 nWalletUnlockTime = 0;
1660 Value encryptwallet(const Array& params, bool fHelp)
1662 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1663 throw runtime_error(
1664 "encryptwallet <passphrase>\n"
1665 "Encrypts the wallet with <passphrase>.");
1668 if (pwalletMain->IsCrypted())
1669 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1671 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1672 // Alternately, find a way to make params[0] mlock()'d to begin with.
1673 SecureString strWalletPass;
1674 strWalletPass.reserve(100);
1675 strWalletPass = params[0].get_str().c_str();
1677 if (strWalletPass.length() < 1)
1678 throw runtime_error(
1679 "encryptwallet <passphrase>\n"
1680 "Encrypts the wallet with <passphrase>.");
1682 if (!pwalletMain->EncryptWallet(strWalletPass))
1683 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1685 // BDB seems to have a bad habit of writing old data into
1686 // slack space in .dat files; that is bad if the old data is
1687 // unencrypted private keys. So:
1689 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1693 Value validateaddress(const Array& params, bool fHelp)
1695 if (fHelp || params.size() != 1)
1696 throw runtime_error(
1697 "validateaddress <bitcoinaddress>\n"
1698 "Return information about <bitcoinaddress>.");
1700 CBitcoinAddress address(params[0].get_str());
1701 bool isValid = address.IsValid();
1704 ret.push_back(Pair("isvalid", isValid));
1707 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1708 // version of the address:
1709 string currentAddress = address.ToString();
1710 ret.push_back(Pair("address", currentAddress));
1711 if (pwalletMain->HaveKey(address))
1713 ret.push_back(Pair("ismine", true));
1714 std::vector<unsigned char> vchPubKey;
1715 pwalletMain->GetPubKey(address, vchPubKey);
1716 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1718 key.SetPubKey(vchPubKey);
1719 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1721 else if (pwalletMain->HaveCScript(address.GetHash160()))
1723 ret.push_back(Pair("isscript", true));
1725 pwalletMain->GetCScript(address.GetHash160(), subscript);
1726 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1727 std::vector<CBitcoinAddress> addresses;
1728 txnouttype whichType;
1730 ExtractAddresses(subscript, whichType, addresses, nRequired);
1731 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1733 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1734 a.push_back(addr.ToString());
1735 ret.push_back(Pair("addresses", a));
1736 if (whichType == TX_MULTISIG)
1737 ret.push_back(Pair("sigsrequired", nRequired));
1740 ret.push_back(Pair("ismine", false));
1741 if (pwalletMain->mapAddressBook.count(address))
1742 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1747 Value getwork(const Array& params, bool fHelp)
1749 if (fHelp || params.size() > 1)
1750 throw runtime_error(
1752 "If [data] is not specified, returns formatted hash data to work on:\n"
1753 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1754 " \"data\" : block data\n"
1755 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1756 " \"target\" : little endian hash target\n"
1757 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1760 throw JSONRPCError(-9, "Bitcoin is not connected!");
1762 if (IsInitialBlockDownload())
1763 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1765 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1766 static mapNewBlock_t mapNewBlock;
1767 static vector<CBlock*> vNewBlock;
1768 static CReserveKey reservekey(pwalletMain);
1770 if (params.size() == 0)
1773 static unsigned int nTransactionsUpdatedLast;
1774 static CBlockIndex* pindexPrev;
1775 static int64 nStart;
1776 static CBlock* pblock;
1777 if (pindexPrev != pindexBest ||
1778 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1780 if (pindexPrev != pindexBest)
1782 // Deallocate old blocks since they're obsolete now
1783 mapNewBlock.clear();
1784 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1788 nTransactionsUpdatedLast = nTransactionsUpdated;
1789 pindexPrev = pindexBest;
1793 pblock = CreateNewBlock(reservekey);
1795 throw JSONRPCError(-7, "Out of memory");
1796 vNewBlock.push_back(pblock);
1800 pblock->UpdateTime(pindexPrev);
1803 // Update nExtraNonce
1804 static unsigned int nExtraNonce = 0;
1805 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1808 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1810 // Prebuild hash buffers
1814 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1816 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1819 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1820 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1821 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1822 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1828 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1829 if (vchData.size() != 128)
1830 throw JSONRPCError(-8, "Invalid parameter");
1831 CBlock* pdata = (CBlock*)&vchData[0];
1834 for (int i = 0; i < 128/4; i++)
1835 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1838 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1840 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1842 pblock->nTime = pdata->nTime;
1843 pblock->nNonce = pdata->nNonce;
1844 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1845 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1847 return CheckWork(pblock, *pwalletMain, reservekey);
1852 Value getmemorypool(const Array& params, bool fHelp)
1854 if (fHelp || params.size() > 1)
1855 throw runtime_error(
1856 "getmemorypool [data]\n"
1857 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1858 " \"version\" : block version\n"
1859 " \"previousblockhash\" : hash of current highest block\n"
1860 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1861 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1862 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1863 " \"time\" : timestamp appropriate for next block\n"
1864 " \"mintime\" : minimum timestamp appropriate for next block\n"
1865 " \"curtime\" : current timestamp\n"
1866 " \"bits\" : compressed target of next block\n"
1867 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1869 if (params.size() == 0)
1872 throw JSONRPCError(-9, "Bitcoin is not connected!");
1874 if (IsInitialBlockDownload())
1875 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1877 static CReserveKey reservekey(pwalletMain);
1880 static unsigned int nTransactionsUpdatedLast;
1881 static CBlockIndex* pindexPrev;
1882 static int64 nStart;
1883 static CBlock* pblock;
1884 if (pindexPrev != pindexBest ||
1885 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1887 nTransactionsUpdatedLast = nTransactionsUpdated;
1888 pindexPrev = pindexBest;
1894 pblock = CreateNewBlock(reservekey);
1896 throw JSONRPCError(-7, "Out of memory");
1900 pblock->UpdateTime(pindexPrev);
1904 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1911 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1915 result.push_back(Pair("version", pblock->nVersion));
1916 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1917 result.push_back(Pair("transactions", transactions));
1918 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1919 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1920 result.push_back(Pair("time", (int64_t)pblock->nTime));
1921 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1922 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1923 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1930 CDataStream ssBlock(ParseHex(params[0].get_str()));
1934 return ProcessBlock(NULL, &pblock);
1938 Value getblockhash(const Array& params, bool fHelp)
1940 if (fHelp || params.size() != 1)
1941 throw runtime_error(
1942 "getblockhash <index>\n"
1943 "Returns hash of block in best-block-chain at <index>.");
1945 int nHeight = params[0].get_int();
1946 if (nHeight < 0 || nHeight > nBestHeight)
1947 throw runtime_error("Block number out of range.");
1950 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1951 while (pblockindex->nHeight > nHeight)
1952 pblockindex = pblockindex->pprev;
1953 return pblockindex->phashBlock->GetHex();
1956 Value getblock(const Array& params, bool fHelp)
1958 if (fHelp || params.size() != 1)
1959 throw runtime_error(
1961 "Returns details of a block with given block-hash.");
1963 std::string strHash = params[0].get_str();
1964 uint256 hash(strHash);
1966 if (mapBlockIndex.count(hash) == 0)
1967 throw JSONRPCError(-5, "Block not found");
1970 CBlockIndex* pblockindex = mapBlockIndex[hash];
1971 block.ReadFromDisk(pblockindex, true);
1973 return blockToJSON(block, pblockindex);
1990 pair<string, rpcfn_type> pCallTable[] =
1992 make_pair("help", &help),
1993 make_pair("stop", &stop),
1994 make_pair("getblockcount", &getblockcount),
1995 make_pair("getblocknumber", &getblocknumber),
1996 make_pair("getconnectioncount", &getconnectioncount),
1997 make_pair("getdifficulty", &getdifficulty),
1998 make_pair("getgenerate", &getgenerate),
1999 make_pair("setgenerate", &setgenerate),
2000 make_pair("gethashespersec", &gethashespersec),
2001 make_pair("getinfo", &getinfo),
2002 make_pair("getmininginfo", &getmininginfo),
2003 make_pair("getnewaddress", &getnewaddress),
2004 make_pair("getaccountaddress", &getaccountaddress),
2005 make_pair("setaccount", &setaccount),
2006 make_pair("getaccount", &getaccount),
2007 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2008 make_pair("sendtoaddress", &sendtoaddress),
2009 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2010 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2011 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2012 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2013 make_pair("backupwallet", &backupwallet),
2014 make_pair("keypoolrefill", &keypoolrefill),
2015 make_pair("walletpassphrase", &walletpassphrase),
2016 make_pair("walletpassphrasechange", &walletpassphrasechange),
2017 make_pair("walletlock", &walletlock),
2018 make_pair("encryptwallet", &encryptwallet),
2019 make_pair("validateaddress", &validateaddress),
2020 make_pair("getbalance", &getbalance),
2021 make_pair("move", &movecmd),
2022 make_pair("sendfrom", &sendfrom),
2023 make_pair("sendmany", &sendmany),
2024 make_pair("addmultisigaddress", &addmultisigaddress),
2025 make_pair("getblock", &getblock),
2026 make_pair("getblockhash", &getblockhash),
2027 make_pair("gettransaction", &gettransaction),
2028 make_pair("listtransactions", &listtransactions),
2029 make_pair("signmessage", &signmessage),
2030 make_pair("verifymessage", &verifymessage),
2031 make_pair("getwork", &getwork),
2032 make_pair("listaccounts", &listaccounts),
2033 make_pair("settxfee", &settxfee),
2034 make_pair("getmemorypool", &getmemorypool),
2035 make_pair("listsinceblock", &listsinceblock),
2036 make_pair("dumpprivkey", &dumpprivkey),
2037 make_pair("importprivkey", &importprivkey)
2039 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2041 string pAllowInSafeMode[] =
2046 "getblocknumber", // deprecated
2047 "getconnectioncount",
2055 "getaccountaddress",
2057 "getaddressesbyaccount",
2066 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2074 // This ain't Apache. We're just using HTTP header for the length field
2075 // and to be compatible with other JSON-RPC implementations.
2078 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2081 s << "POST / HTTP/1.1\r\n"
2082 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2083 << "Host: 127.0.0.1\r\n"
2084 << "Content-Type: application/json\r\n"
2085 << "Content-Length: " << strMsg.size() << "\r\n"
2086 << "Connection: close\r\n"
2087 << "Accept: application/json\r\n";
2088 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2089 s << item.first << ": " << item.second << "\r\n";
2090 s << "\r\n" << strMsg;
2095 string rfc1123Time()
2100 struct tm* now_gmt = gmtime(&now);
2101 string locale(setlocale(LC_TIME, NULL));
2102 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2103 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2104 setlocale(LC_TIME, locale.c_str());
2105 return string(buffer);
2108 static string HTTPReply(int nStatus, const string& strMsg)
2111 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2113 "Server: bitcoin-json-rpc/%s\r\n"
2114 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2115 "Content-Type: text/html\r\n"
2116 "Content-Length: 296\r\n"
2118 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2119 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2122 "<TITLE>Error</TITLE>\r\n"
2123 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2125 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2126 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2127 const char *cStatus;
2128 if (nStatus == 200) cStatus = "OK";
2129 else if (nStatus == 400) cStatus = "Bad Request";
2130 else if (nStatus == 403) cStatus = "Forbidden";
2131 else if (nStatus == 404) cStatus = "Not Found";
2132 else if (nStatus == 500) cStatus = "Internal Server Error";
2135 "HTTP/1.1 %d %s\r\n"
2137 "Connection: close\r\n"
2138 "Content-Length: %d\r\n"
2139 "Content-Type: application/json\r\n"
2140 "Server: bitcoin-json-rpc/%s\r\n"
2145 rfc1123Time().c_str(),
2147 FormatFullVersion().c_str(),
2151 int ReadHTTPStatus(std::basic_istream<char>& stream)
2154 getline(stream, str);
2155 vector<string> vWords;
2156 boost::split(vWords, str, boost::is_any_of(" "));
2157 if (vWords.size() < 2)
2159 return atoi(vWords[1].c_str());
2162 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2168 std::getline(stream, str);
2169 if (str.empty() || str == "\r")
2171 string::size_type nColon = str.find(":");
2172 if (nColon != string::npos)
2174 string strHeader = str.substr(0, nColon);
2175 boost::trim(strHeader);
2176 boost::to_lower(strHeader);
2177 string strValue = str.substr(nColon+1);
2178 boost::trim(strValue);
2179 mapHeadersRet[strHeader] = strValue;
2180 if (strHeader == "content-length")
2181 nLen = atoi(strValue.c_str());
2187 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2189 mapHeadersRet.clear();
2193 int nStatus = ReadHTTPStatus(stream);
2196 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2197 if (nLen < 0 || nLen > MAX_SIZE)
2203 vector<char> vch(nLen);
2204 stream.read(&vch[0], nLen);
2205 strMessageRet = string(vch.begin(), vch.end());
2211 bool HTTPAuthorized(map<string, string>& mapHeaders)
2213 string strAuth = mapHeaders["authorization"];
2214 if (strAuth.substr(0,6) != "Basic ")
2216 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2217 string strUserPass = DecodeBase64(strUserPass64);
2218 return strUserPass == strRPCUserColonPass;
2222 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2223 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2224 // unspecified (HTTP errors and contents of 'error').
2226 // 1.0 spec: http://json-rpc.org/wiki/specification
2227 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2228 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2231 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2234 request.push_back(Pair("method", strMethod));
2235 request.push_back(Pair("params", params));
2236 request.push_back(Pair("id", id));
2237 return write_string(Value(request), false) + "\n";
2240 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2243 if (error.type() != null_type)
2244 reply.push_back(Pair("result", Value::null));
2246 reply.push_back(Pair("result", result));
2247 reply.push_back(Pair("error", error));
2248 reply.push_back(Pair("id", id));
2249 return write_string(Value(reply), false) + "\n";
2252 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2254 // Send error reply from json-rpc error object
2256 int code = find_value(objError, "code").get_int();
2257 if (code == -32600) nStatus = 400;
2258 else if (code == -32601) nStatus = 404;
2259 string strReply = JSONRPCReply(Value::null, objError, id);
2260 stream << HTTPReply(nStatus, strReply) << std::flush;
2263 bool ClientAllowed(const string& strAddress)
2265 if (strAddress == asio::ip::address_v4::loopback().to_string())
2267 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2268 BOOST_FOREACH(string strAllow, vAllow)
2269 if (WildcardMatch(strAddress, strAllow))
2275 // IOStream device that speaks SSL but can also speak non-SSL
2277 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2279 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2281 fUseSSL = fUseSSLIn;
2282 fNeedHandshake = fUseSSLIn;
2285 void handshake(ssl::stream_base::handshake_type role)
2287 if (!fNeedHandshake) return;
2288 fNeedHandshake = false;
2289 stream.handshake(role);
2291 std::streamsize read(char* s, std::streamsize n)
2293 handshake(ssl::stream_base::server); // HTTPS servers read first
2294 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2295 return stream.next_layer().read_some(asio::buffer(s, n));
2297 std::streamsize write(const char* s, std::streamsize n)
2299 handshake(ssl::stream_base::client); // HTTPS clients write first
2300 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2301 return asio::write(stream.next_layer(), asio::buffer(s, n));
2303 bool connect(const std::string& server, const std::string& port)
2305 ip::tcp::resolver resolver(stream.get_io_service());
2306 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2307 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2308 ip::tcp::resolver::iterator end;
2309 boost::system::error_code error = asio::error::host_not_found;
2310 while (error && endpoint_iterator != end)
2312 stream.lowest_layer().close();
2313 stream.lowest_layer().connect(*endpoint_iterator++, error);
2321 bool fNeedHandshake;
2326 void ThreadRPCServer(void* parg)
2328 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2331 vnThreadsRunning[THREAD_RPCSERVER]++;
2332 ThreadRPCServer2(parg);
2333 vnThreadsRunning[THREAD_RPCSERVER]--;
2335 catch (std::exception& e) {
2336 vnThreadsRunning[THREAD_RPCSERVER]--;
2337 PrintException(&e, "ThreadRPCServer()");
2339 vnThreadsRunning[THREAD_RPCSERVER]--;
2340 PrintException(NULL, "ThreadRPCServer()");
2342 printf("ThreadRPCServer exiting\n");
2345 void ThreadRPCServer2(void* parg)
2347 printf("ThreadRPCServer started\n");
2349 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2350 if (mapArgs["-rpcpassword"] == "")
2352 unsigned char rand_pwd[32];
2353 RAND_bytes(rand_pwd, 32);
2354 string strWhatAmI = "To use bitcoind";
2355 if (mapArgs.count("-server"))
2356 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2357 else if (mapArgs.count("-daemon"))
2358 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2359 ThreadSafeMessageBox(strprintf(
2360 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2361 "It is recommended you use the following random password:\n"
2362 "rpcuser=bitcoinrpc\n"
2364 "(you do not need to remember this password)\n"
2365 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2367 GetConfigFile().c_str(),
2368 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2369 _("Error"), wxOK | wxMODAL);
2374 bool fUseSSL = GetBoolArg("-rpcssl");
2375 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2377 asio::io_service io_service;
2378 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2379 ip::tcp::acceptor acceptor(io_service, endpoint);
2381 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2383 ssl::context context(io_service, ssl::context::sslv23);
2386 context.set_options(ssl::context::no_sslv2);
2388 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2389 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2390 pathCertFile.make_preferred();
2391 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string().c_str());
2392 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2394 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2395 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2396 pathPKFile.make_preferred();
2397 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string().c_str(), ssl::context::pem);
2398 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2400 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2401 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2406 // Accept connection
2407 SSLStream sslStream(io_service, context);
2408 SSLIOStreamDevice d(sslStream, fUseSSL);
2409 iostreams::stream<SSLIOStreamDevice> stream(d);
2411 ip::tcp::endpoint peer;
2412 vnThreadsRunning[THREAD_RPCSERVER]--;
2413 acceptor.accept(sslStream.lowest_layer(), peer);
2414 vnThreadsRunning[4]++;
2418 // Restrict callers by IP
2419 if (!ClientAllowed(peer.address().to_string()))
2421 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2423 stream << HTTPReply(403, "") << std::flush;
2427 map<string, string> mapHeaders;
2430 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2431 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2434 printf("ThreadRPCServer ReadHTTP timeout\n");
2438 // Check authorization
2439 if (mapHeaders.count("authorization") == 0)
2441 stream << HTTPReply(401, "") << std::flush;
2444 if (!HTTPAuthorized(mapHeaders))
2446 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2447 /* Deter brute-forcing short passwords.
2448 If this results in a DOS the user really
2449 shouldn't have their RPC port exposed.*/
2450 if (mapArgs["-rpcpassword"].size() < 20)
2453 stream << HTTPReply(401, "") << std::flush;
2457 Value id = Value::null;
2462 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2463 throw JSONRPCError(-32700, "Parse error");
2464 const Object& request = valRequest.get_obj();
2466 // Parse id now so errors from here on will have the id
2467 id = find_value(request, "id");
2470 Value valMethod = find_value(request, "method");
2471 if (valMethod.type() == null_type)
2472 throw JSONRPCError(-32600, "Missing method");
2473 if (valMethod.type() != str_type)
2474 throw JSONRPCError(-32600, "Method must be a string");
2475 string strMethod = valMethod.get_str();
2476 if (strMethod != "getwork" && strMethod != "getmemorypool")
2477 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2480 Value valParams = find_value(request, "params");
2482 if (valParams.type() == array_type)
2483 params = valParams.get_array();
2484 else if (valParams.type() == null_type)
2487 throw JSONRPCError(-32600, "Params must be an array");
2490 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2491 if (mi == mapCallTable.end())
2492 throw JSONRPCError(-32601, "Method not found");
2494 // Observe safe mode
2495 string strWarning = GetWarnings("rpc");
2496 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2497 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2504 LOCK2(cs_main, pwalletMain->cs_wallet);
2505 result = (*(*mi).second)(params, false);
2509 string strReply = JSONRPCReply(result, Value::null, id);
2510 stream << HTTPReply(200, strReply) << std::flush;
2512 catch (std::exception& e)
2514 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2517 catch (Object& objError)
2519 ErrorReply(stream, objError, id);
2521 catch (std::exception& e)
2523 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2531 Object CallRPC(const string& strMethod, const Array& params)
2533 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2534 throw runtime_error(strprintf(
2535 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2536 "If the file does not exist, create it with owner-readable-only file permissions."),
2537 GetConfigFile().c_str()));
2539 // Connect to localhost
2540 bool fUseSSL = GetBoolArg("-rpcssl");
2541 asio::io_service io_service;
2542 ssl::context context(io_service, ssl::context::sslv23);
2543 context.set_options(ssl::context::no_sslv2);
2544 SSLStream sslStream(io_service, context);
2545 SSLIOStreamDevice d(sslStream, fUseSSL);
2546 iostreams::stream<SSLIOStreamDevice> stream(d);
2547 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2548 throw runtime_error("couldn't connect to server");
2550 // HTTP basic authentication
2551 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2552 map<string, string> mapRequestHeaders;
2553 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2556 string strRequest = JSONRPCRequest(strMethod, params, 1);
2557 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2558 stream << strPost << std::flush;
2561 map<string, string> mapHeaders;
2563 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2565 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2566 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2567 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2568 else if (strReply.empty())
2569 throw runtime_error("no response from server");
2573 if (!read_string(strReply, valReply))
2574 throw runtime_error("couldn't parse reply from server");
2575 const Object& reply = valReply.get_obj();
2577 throw runtime_error("expected reply to have result, error and id properties");
2585 template<typename T>
2586 void ConvertTo(Value& value)
2588 if (value.type() == str_type)
2590 // reinterpret string as unquoted json value
2592 if (!read_string(value.get_str(), value2))
2593 throw runtime_error("type mismatch");
2594 value = value2.get_value<T>();
2598 value = value.get_value<T>();
2602 int CommandLineRPC(int argc, char *argv[])
2609 while (argc > 1 && IsSwitchChar(argv[1][0]))
2617 throw runtime_error("too few parameters");
2618 string strMethod = argv[1];
2620 // Parameters default to strings
2622 for (int i = 2; i < argc; i++)
2623 params.push_back(argv[i]);
2624 int n = params.size();
2627 // Special case non-string parameter types
2629 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2630 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2631 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2632 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2633 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2634 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2635 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2636 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2637 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2638 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2639 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2640 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2641 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2642 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2643 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2644 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2645 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2646 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2647 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2648 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2649 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2650 if (strMethod == "sendmany" && n > 1)
2652 string s = params[1].get_str();
2654 if (!read_string(s, v) || v.type() != obj_type)
2655 throw runtime_error("type mismatch");
2656 params[1] = v.get_obj();
2658 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2659 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660 if (strMethod == "addmultisigaddress" && n > 1)
2662 string s = params[1].get_str();
2664 if (!read_string(s, v) || v.type() != array_type)
2665 throw runtime_error("type mismatch "+s);
2666 params[1] = v.get_array();
2670 Object reply = CallRPC(strMethod, params);
2673 const Value& result = find_value(reply, "result");
2674 const Value& error = find_value(reply, "error");
2676 if (error.type() != null_type)
2679 strPrint = "error: " + write_string(error, false);
2680 int code = find_value(error.get_obj(), "code").get_int();
2686 if (result.type() == null_type)
2688 else if (result.type() == str_type)
2689 strPrint = result.get_str();
2691 strPrint = write_string(result, true);
2694 catch (std::exception& e)
2696 strPrint = string("error: ") + e.what();
2701 PrintException(NULL, "CommandLineRPC()");
2706 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2715 int main(int argc, char *argv[])
2718 // Turn off microsoft heap dump noise
2719 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2720 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2722 setbuf(stdin, NULL);
2723 setbuf(stdout, NULL);
2724 setbuf(stderr, NULL);
2728 if (argc >= 2 && string(argv[1]) == "-server")
2730 printf("server ready\n");
2731 ThreadRPCServer(NULL);
2735 return CommandLineRPC(argc, argv);
2738 catch (std::exception& e) {
2739 PrintException(&e, "main()");
2741 PrintException(NULL, "main()");