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 throw JSONRPCError(-8, "Negative count");
1287 throw JSONRPCError(-8, "Negative from");
1290 CWalletDB walletdb(pwalletMain->strWalletFile);
1292 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1293 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1294 typedef multimap<int64, TxPair > TxItems;
1297 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1298 // would make this much faster for applications that do this a lot.
1299 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1301 CWalletTx* wtx = &((*it).second);
1302 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1304 list<CAccountingEntry> acentries;
1305 walletdb.ListAccountCreditDebit(strAccount, acentries);
1306 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1308 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1311 // iterate backwards until we have nCount items to return:
1312 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1314 CWalletTx *const pwtx = (*it).second.first;
1316 ListTransactions(*pwtx, strAccount, 0, true, ret);
1317 CAccountingEntry *const pacentry = (*it).second.second;
1319 AcentryToJSON(*pacentry, strAccount, ret);
1321 if (ret.size() >= (nCount+nFrom)) break;
1323 // ret is newest to oldest
1325 if (nFrom > ret.size()) nFrom = ret.size();
1326 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1327 Array::iterator first = ret.begin();
1328 std::advance(first, nFrom);
1329 Array::iterator last = ret.begin();
1330 std::advance(last, nFrom+nCount);
1332 if (last != ret.end()) ret.erase(last, ret.end());
1333 if (first != ret.begin()) ret.erase(ret.begin(), first);
1335 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1340 Value listaccounts(const Array& params, bool fHelp)
1342 if (fHelp || params.size() > 1)
1343 throw runtime_error(
1344 "listaccounts [minconf=1]\n"
1345 "Returns Object that has account names as keys, account balances as values.");
1348 if (params.size() > 0)
1349 nMinDepth = params[0].get_int();
1351 map<string, int64> mapAccountBalances;
1352 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1353 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1354 mapAccountBalances[entry.second] = 0;
1357 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1359 const CWalletTx& wtx = (*it).second;
1360 int64 nGeneratedImmature, nGeneratedMature, nFee;
1361 string strSentAccount;
1362 list<pair<CBitcoinAddress, int64> > listReceived;
1363 list<pair<CBitcoinAddress, int64> > listSent;
1364 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1365 mapAccountBalances[strSentAccount] -= nFee;
1366 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1367 mapAccountBalances[strSentAccount] -= s.second;
1368 if (wtx.GetDepthInMainChain() >= nMinDepth)
1370 mapAccountBalances[""] += nGeneratedMature;
1371 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1372 if (pwalletMain->mapAddressBook.count(r.first))
1373 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1375 mapAccountBalances[""] += r.second;
1379 list<CAccountingEntry> acentries;
1380 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1381 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1382 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1385 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1386 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1391 Value listsinceblock(const Array& params, bool fHelp)
1394 throw runtime_error(
1395 "listsinceblock [blockid] [target-confirmations]\n"
1396 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1398 CBlockIndex *pindex = NULL;
1399 int target_confirms = 1;
1401 if (params.size() > 0)
1403 uint256 blockId = 0;
1405 blockId.SetHex(params[0].get_str());
1406 pindex = CBlockLocator(blockId).GetBlockIndex();
1409 if (params.size() > 1)
1411 target_confirms = params[1].get_int();
1413 if (target_confirms < 1)
1414 throw JSONRPCError(-8, "Invalid parameter");
1417 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1421 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1423 CWalletTx tx = (*it).second;
1425 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1426 ListTransactions(tx, "*", 0, true, transactions);
1431 if (target_confirms == 1)
1434 lastblock = hashBestChain;
1438 int target_height = pindexBest->nHeight + 1 - target_confirms;
1441 for (block = pindexBest;
1442 block && block->nHeight > target_height;
1443 block = block->pprev) { }
1445 lastblock = block ? block->GetBlockHash() : 0;
1449 ret.push_back(Pair("transactions", transactions));
1450 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1455 Value gettransaction(const Array& params, bool fHelp)
1457 if (fHelp || params.size() != 1)
1458 throw runtime_error(
1459 "gettransaction <txid>\n"
1460 "Get detailed information about <txid>");
1463 hash.SetHex(params[0].get_str());
1467 if (!pwalletMain->mapWallet.count(hash))
1468 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1469 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1471 int64 nCredit = wtx.GetCredit();
1472 int64 nDebit = wtx.GetDebit();
1473 int64 nNet = nCredit - nDebit;
1474 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1476 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1478 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1480 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1483 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1484 entry.push_back(Pair("details", details));
1490 Value backupwallet(const Array& params, bool fHelp)
1492 if (fHelp || params.size() != 1)
1493 throw runtime_error(
1494 "backupwallet <destination>\n"
1495 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1497 string strDest = params[0].get_str();
1498 BackupWallet(*pwalletMain, strDest);
1504 Value keypoolrefill(const Array& params, bool fHelp)
1506 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1507 throw runtime_error(
1509 "Fills the keypool, requires wallet passphrase to be set.");
1510 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511 throw runtime_error(
1513 "Fills the keypool.");
1515 if (pwalletMain->IsLocked())
1516 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1518 pwalletMain->TopUpKeyPool();
1520 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1521 throw JSONRPCError(-4, "Error refreshing keypool.");
1527 void ThreadTopUpKeyPool(void* parg)
1529 pwalletMain->TopUpKeyPool();
1532 void ThreadCleanWalletPassphrase(void* parg)
1534 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1536 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1538 if (nWalletUnlockTime == 0)
1540 nWalletUnlockTime = nMyWakeTime;
1544 if (nWalletUnlockTime==0)
1546 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1550 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1552 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 if (nWalletUnlockTime)
1558 nWalletUnlockTime = 0;
1559 pwalletMain->Lock();
1564 if (nWalletUnlockTime < nMyWakeTime)
1565 nWalletUnlockTime = nMyWakeTime;
1568 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1570 delete (int64*)parg;
1573 Value walletpassphrase(const Array& params, bool fHelp)
1575 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1576 throw runtime_error(
1577 "walletpassphrase <passphrase> <timeout>\n"
1578 "Stores the wallet decryption key in memory for <timeout> seconds.");
1581 if (!pwalletMain->IsCrypted())
1582 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1584 if (!pwalletMain->IsLocked())
1585 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1587 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1588 SecureString strWalletPass;
1589 strWalletPass.reserve(100);
1590 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1591 // Alternately, find a way to make params[0] mlock()'d to begin with.
1592 strWalletPass = params[0].get_str().c_str();
1594 if (strWalletPass.length() > 0)
1596 if (!pwalletMain->Unlock(strWalletPass))
1597 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1600 throw runtime_error(
1601 "walletpassphrase <passphrase> <timeout>\n"
1602 "Stores the wallet decryption key in memory for <timeout> seconds.");
1604 CreateThread(ThreadTopUpKeyPool, NULL);
1605 int64* pnSleepTime = new int64(params[1].get_int64());
1606 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1612 Value walletpassphrasechange(const Array& params, bool fHelp)
1614 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1615 throw runtime_error(
1616 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1617 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1620 if (!pwalletMain->IsCrypted())
1621 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1623 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1624 // Alternately, find a way to make params[0] mlock()'d to begin with.
1625 SecureString strOldWalletPass;
1626 strOldWalletPass.reserve(100);
1627 strOldWalletPass = params[0].get_str().c_str();
1629 SecureString strNewWalletPass;
1630 strNewWalletPass.reserve(100);
1631 strNewWalletPass = params[1].get_str().c_str();
1633 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1634 throw runtime_error(
1635 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1636 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1638 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1639 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1645 Value walletlock(const Array& params, bool fHelp)
1647 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1648 throw runtime_error(
1650 "Removes the wallet encryption key from memory, locking the wallet.\n"
1651 "After calling this method, you will need to call walletpassphrase again\n"
1652 "before being able to call any methods which require the wallet to be unlocked.");
1655 if (!pwalletMain->IsCrypted())
1656 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1659 LOCK(cs_nWalletUnlockTime);
1660 pwalletMain->Lock();
1661 nWalletUnlockTime = 0;
1668 Value encryptwallet(const Array& params, bool fHelp)
1670 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1671 throw runtime_error(
1672 "encryptwallet <passphrase>\n"
1673 "Encrypts the wallet with <passphrase>.");
1676 if (pwalletMain->IsCrypted())
1677 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1679 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1680 // Alternately, find a way to make params[0] mlock()'d to begin with.
1681 SecureString strWalletPass;
1682 strWalletPass.reserve(100);
1683 strWalletPass = params[0].get_str().c_str();
1685 if (strWalletPass.length() < 1)
1686 throw runtime_error(
1687 "encryptwallet <passphrase>\n"
1688 "Encrypts the wallet with <passphrase>.");
1690 if (!pwalletMain->EncryptWallet(strWalletPass))
1691 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1693 // BDB seems to have a bad habit of writing old data into
1694 // slack space in .dat files; that is bad if the old data is
1695 // unencrypted private keys. So:
1697 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1701 Value validateaddress(const Array& params, bool fHelp)
1703 if (fHelp || params.size() != 1)
1704 throw runtime_error(
1705 "validateaddress <bitcoinaddress>\n"
1706 "Return information about <bitcoinaddress>.");
1708 CBitcoinAddress address(params[0].get_str());
1709 bool isValid = address.IsValid();
1712 ret.push_back(Pair("isvalid", isValid));
1715 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1716 // version of the address:
1717 string currentAddress = address.ToString();
1718 ret.push_back(Pair("address", currentAddress));
1719 if (pwalletMain->HaveKey(address))
1721 ret.push_back(Pair("ismine", true));
1722 std::vector<unsigned char> vchPubKey;
1723 pwalletMain->GetPubKey(address, vchPubKey);
1724 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1726 key.SetPubKey(vchPubKey);
1727 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1729 else if (pwalletMain->HaveCScript(address.GetHash160()))
1731 ret.push_back(Pair("isscript", true));
1733 pwalletMain->GetCScript(address.GetHash160(), subscript);
1734 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1735 std::vector<CBitcoinAddress> addresses;
1736 txnouttype whichType;
1738 ExtractAddresses(subscript, whichType, addresses, nRequired);
1739 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1741 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1742 a.push_back(addr.ToString());
1743 ret.push_back(Pair("addresses", a));
1744 if (whichType == TX_MULTISIG)
1745 ret.push_back(Pair("sigsrequired", nRequired));
1748 ret.push_back(Pair("ismine", false));
1749 if (pwalletMain->mapAddressBook.count(address))
1750 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1755 Value getwork(const Array& params, bool fHelp)
1757 if (fHelp || params.size() > 1)
1758 throw runtime_error(
1760 "If [data] is not specified, returns formatted hash data to work on:\n"
1761 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1762 " \"data\" : block data\n"
1763 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1764 " \"target\" : little endian hash target\n"
1765 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1768 throw JSONRPCError(-9, "Bitcoin is not connected!");
1770 if (IsInitialBlockDownload())
1771 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1773 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1774 static mapNewBlock_t mapNewBlock;
1775 static vector<CBlock*> vNewBlock;
1776 static CReserveKey reservekey(pwalletMain);
1778 if (params.size() == 0)
1781 static unsigned int nTransactionsUpdatedLast;
1782 static CBlockIndex* pindexPrev;
1783 static int64 nStart;
1784 static CBlock* pblock;
1785 if (pindexPrev != pindexBest ||
1786 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1788 if (pindexPrev != pindexBest)
1790 // Deallocate old blocks since they're obsolete now
1791 mapNewBlock.clear();
1792 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1796 nTransactionsUpdatedLast = nTransactionsUpdated;
1797 pindexPrev = pindexBest;
1801 pblock = CreateNewBlock(reservekey);
1803 throw JSONRPCError(-7, "Out of memory");
1804 vNewBlock.push_back(pblock);
1808 pblock->UpdateTime(pindexPrev);
1811 // Update nExtraNonce
1812 static unsigned int nExtraNonce = 0;
1813 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1816 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1818 // Prebuild hash buffers
1822 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1824 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1827 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1828 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1829 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1830 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1836 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1837 if (vchData.size() != 128)
1838 throw JSONRPCError(-8, "Invalid parameter");
1839 CBlock* pdata = (CBlock*)&vchData[0];
1842 for (int i = 0; i < 128/4; i++)
1843 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1846 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1848 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1850 pblock->nTime = pdata->nTime;
1851 pblock->nNonce = pdata->nNonce;
1852 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1853 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1855 return CheckWork(pblock, *pwalletMain, reservekey);
1860 Value getmemorypool(const Array& params, bool fHelp)
1862 if (fHelp || params.size() > 1)
1863 throw runtime_error(
1864 "getmemorypool [data]\n"
1865 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1866 " \"version\" : block version\n"
1867 " \"previousblockhash\" : hash of current highest block\n"
1868 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1869 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1870 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1871 " \"time\" : timestamp appropriate for next block\n"
1872 " \"mintime\" : minimum timestamp appropriate for next block\n"
1873 " \"curtime\" : current timestamp\n"
1874 " \"bits\" : compressed target of next block\n"
1875 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1877 if (params.size() == 0)
1880 throw JSONRPCError(-9, "Bitcoin is not connected!");
1882 if (IsInitialBlockDownload())
1883 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1885 static CReserveKey reservekey(pwalletMain);
1888 static unsigned int nTransactionsUpdatedLast;
1889 static CBlockIndex* pindexPrev;
1890 static int64 nStart;
1891 static CBlock* pblock;
1892 if (pindexPrev != pindexBest ||
1893 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1895 nTransactionsUpdatedLast = nTransactionsUpdated;
1896 pindexPrev = pindexBest;
1902 pblock = CreateNewBlock(reservekey);
1904 throw JSONRPCError(-7, "Out of memory");
1908 pblock->UpdateTime(pindexPrev);
1912 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1919 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1923 result.push_back(Pair("version", pblock->nVersion));
1924 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1925 result.push_back(Pair("transactions", transactions));
1926 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1927 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1928 result.push_back(Pair("time", (int64_t)pblock->nTime));
1929 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1930 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1931 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1938 CDataStream ssBlock(ParseHex(params[0].get_str()));
1942 return ProcessBlock(NULL, &pblock);
1946 Value getblockhash(const Array& params, bool fHelp)
1948 if (fHelp || params.size() != 1)
1949 throw runtime_error(
1950 "getblockhash <index>\n"
1951 "Returns hash of block in best-block-chain at <index>.");
1953 int nHeight = params[0].get_int();
1954 if (nHeight < 0 || nHeight > nBestHeight)
1955 throw runtime_error("Block number out of range.");
1958 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1959 while (pblockindex->nHeight > nHeight)
1960 pblockindex = pblockindex->pprev;
1961 return pblockindex->phashBlock->GetHex();
1964 Value getblock(const Array& params, bool fHelp)
1966 if (fHelp || params.size() != 1)
1967 throw runtime_error(
1969 "Returns details of a block with given block-hash.");
1971 std::string strHash = params[0].get_str();
1972 uint256 hash(strHash);
1974 if (mapBlockIndex.count(hash) == 0)
1975 throw JSONRPCError(-5, "Block not found");
1978 CBlockIndex* pblockindex = mapBlockIndex[hash];
1979 block.ReadFromDisk(pblockindex, true);
1981 return blockToJSON(block, pblockindex);
1998 pair<string, rpcfn_type> pCallTable[] =
2000 make_pair("help", &help),
2001 make_pair("stop", &stop),
2002 make_pair("getblockcount", &getblockcount),
2003 make_pair("getblocknumber", &getblocknumber),
2004 make_pair("getconnectioncount", &getconnectioncount),
2005 make_pair("getdifficulty", &getdifficulty),
2006 make_pair("getgenerate", &getgenerate),
2007 make_pair("setgenerate", &setgenerate),
2008 make_pair("gethashespersec", &gethashespersec),
2009 make_pair("getinfo", &getinfo),
2010 make_pair("getmininginfo", &getmininginfo),
2011 make_pair("getnewaddress", &getnewaddress),
2012 make_pair("getaccountaddress", &getaccountaddress),
2013 make_pair("setaccount", &setaccount),
2014 make_pair("getaccount", &getaccount),
2015 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2016 make_pair("sendtoaddress", &sendtoaddress),
2017 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2018 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2019 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2020 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2021 make_pair("backupwallet", &backupwallet),
2022 make_pair("keypoolrefill", &keypoolrefill),
2023 make_pair("walletpassphrase", &walletpassphrase),
2024 make_pair("walletpassphrasechange", &walletpassphrasechange),
2025 make_pair("walletlock", &walletlock),
2026 make_pair("encryptwallet", &encryptwallet),
2027 make_pair("validateaddress", &validateaddress),
2028 make_pair("getbalance", &getbalance),
2029 make_pair("move", &movecmd),
2030 make_pair("sendfrom", &sendfrom),
2031 make_pair("sendmany", &sendmany),
2032 make_pair("addmultisigaddress", &addmultisigaddress),
2033 make_pair("getblock", &getblock),
2034 make_pair("getblockhash", &getblockhash),
2035 make_pair("gettransaction", &gettransaction),
2036 make_pair("listtransactions", &listtransactions),
2037 make_pair("signmessage", &signmessage),
2038 make_pair("verifymessage", &verifymessage),
2039 make_pair("getwork", &getwork),
2040 make_pair("listaccounts", &listaccounts),
2041 make_pair("settxfee", &settxfee),
2042 make_pair("getmemorypool", &getmemorypool),
2043 make_pair("listsinceblock", &listsinceblock),
2044 make_pair("dumpprivkey", &dumpprivkey),
2045 make_pair("importprivkey", &importprivkey)
2047 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2049 string pAllowInSafeMode[] =
2054 "getblocknumber", // deprecated
2055 "getconnectioncount",
2063 "getaccountaddress",
2065 "getaddressesbyaccount",
2074 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2082 // This ain't Apache. We're just using HTTP header for the length field
2083 // and to be compatible with other JSON-RPC implementations.
2086 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2089 s << "POST / HTTP/1.1\r\n"
2090 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2091 << "Host: 127.0.0.1\r\n"
2092 << "Content-Type: application/json\r\n"
2093 << "Content-Length: " << strMsg.size() << "\r\n"
2094 << "Connection: close\r\n"
2095 << "Accept: application/json\r\n";
2096 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2097 s << item.first << ": " << item.second << "\r\n";
2098 s << "\r\n" << strMsg;
2103 string rfc1123Time()
2108 struct tm* now_gmt = gmtime(&now);
2109 string locale(setlocale(LC_TIME, NULL));
2110 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2111 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2112 setlocale(LC_TIME, locale.c_str());
2113 return string(buffer);
2116 static string HTTPReply(int nStatus, const string& strMsg)
2119 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2121 "Server: bitcoin-json-rpc/%s\r\n"
2122 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2123 "Content-Type: text/html\r\n"
2124 "Content-Length: 296\r\n"
2126 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2127 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2130 "<TITLE>Error</TITLE>\r\n"
2131 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2133 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2134 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2135 const char *cStatus;
2136 if (nStatus == 200) cStatus = "OK";
2137 else if (nStatus == 400) cStatus = "Bad Request";
2138 else if (nStatus == 403) cStatus = "Forbidden";
2139 else if (nStatus == 404) cStatus = "Not Found";
2140 else if (nStatus == 500) cStatus = "Internal Server Error";
2143 "HTTP/1.1 %d %s\r\n"
2145 "Connection: close\r\n"
2146 "Content-Length: %d\r\n"
2147 "Content-Type: application/json\r\n"
2148 "Server: bitcoin-json-rpc/%s\r\n"
2153 rfc1123Time().c_str(),
2155 FormatFullVersion().c_str(),
2159 int ReadHTTPStatus(std::basic_istream<char>& stream)
2162 getline(stream, str);
2163 vector<string> vWords;
2164 boost::split(vWords, str, boost::is_any_of(" "));
2165 if (vWords.size() < 2)
2167 return atoi(vWords[1].c_str());
2170 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2176 std::getline(stream, str);
2177 if (str.empty() || str == "\r")
2179 string::size_type nColon = str.find(":");
2180 if (nColon != string::npos)
2182 string strHeader = str.substr(0, nColon);
2183 boost::trim(strHeader);
2184 boost::to_lower(strHeader);
2185 string strValue = str.substr(nColon+1);
2186 boost::trim(strValue);
2187 mapHeadersRet[strHeader] = strValue;
2188 if (strHeader == "content-length")
2189 nLen = atoi(strValue.c_str());
2195 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2197 mapHeadersRet.clear();
2201 int nStatus = ReadHTTPStatus(stream);
2204 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2205 if (nLen < 0 || nLen > MAX_SIZE)
2211 vector<char> vch(nLen);
2212 stream.read(&vch[0], nLen);
2213 strMessageRet = string(vch.begin(), vch.end());
2219 bool HTTPAuthorized(map<string, string>& mapHeaders)
2221 string strAuth = mapHeaders["authorization"];
2222 if (strAuth.substr(0,6) != "Basic ")
2224 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2225 string strUserPass = DecodeBase64(strUserPass64);
2226 return strUserPass == strRPCUserColonPass;
2230 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2231 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2232 // unspecified (HTTP errors and contents of 'error').
2234 // 1.0 spec: http://json-rpc.org/wiki/specification
2235 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2236 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2239 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2242 request.push_back(Pair("method", strMethod));
2243 request.push_back(Pair("params", params));
2244 request.push_back(Pair("id", id));
2245 return write_string(Value(request), false) + "\n";
2248 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2251 if (error.type() != null_type)
2252 reply.push_back(Pair("result", Value::null));
2254 reply.push_back(Pair("result", result));
2255 reply.push_back(Pair("error", error));
2256 reply.push_back(Pair("id", id));
2257 return write_string(Value(reply), false) + "\n";
2260 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2262 // Send error reply from json-rpc error object
2264 int code = find_value(objError, "code").get_int();
2265 if (code == -32600) nStatus = 400;
2266 else if (code == -32601) nStatus = 404;
2267 string strReply = JSONRPCReply(Value::null, objError, id);
2268 stream << HTTPReply(nStatus, strReply) << std::flush;
2271 bool ClientAllowed(const string& strAddress)
2273 if (strAddress == asio::ip::address_v4::loopback().to_string())
2275 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2276 BOOST_FOREACH(string strAllow, vAllow)
2277 if (WildcardMatch(strAddress, strAllow))
2283 // IOStream device that speaks SSL but can also speak non-SSL
2285 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2287 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2289 fUseSSL = fUseSSLIn;
2290 fNeedHandshake = fUseSSLIn;
2293 void handshake(ssl::stream_base::handshake_type role)
2295 if (!fNeedHandshake) return;
2296 fNeedHandshake = false;
2297 stream.handshake(role);
2299 std::streamsize read(char* s, std::streamsize n)
2301 handshake(ssl::stream_base::server); // HTTPS servers read first
2302 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2303 return stream.next_layer().read_some(asio::buffer(s, n));
2305 std::streamsize write(const char* s, std::streamsize n)
2307 handshake(ssl::stream_base::client); // HTTPS clients write first
2308 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2309 return asio::write(stream.next_layer(), asio::buffer(s, n));
2311 bool connect(const std::string& server, const std::string& port)
2313 ip::tcp::resolver resolver(stream.get_io_service());
2314 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2315 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2316 ip::tcp::resolver::iterator end;
2317 boost::system::error_code error = asio::error::host_not_found;
2318 while (error && endpoint_iterator != end)
2320 stream.lowest_layer().close();
2321 stream.lowest_layer().connect(*endpoint_iterator++, error);
2329 bool fNeedHandshake;
2334 void ThreadRPCServer(void* parg)
2336 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2339 vnThreadsRunning[THREAD_RPCSERVER]++;
2340 ThreadRPCServer2(parg);
2341 vnThreadsRunning[THREAD_RPCSERVER]--;
2343 catch (std::exception& e) {
2344 vnThreadsRunning[THREAD_RPCSERVER]--;
2345 PrintException(&e, "ThreadRPCServer()");
2347 vnThreadsRunning[THREAD_RPCSERVER]--;
2348 PrintException(NULL, "ThreadRPCServer()");
2350 printf("ThreadRPCServer exiting\n");
2353 void ThreadRPCServer2(void* parg)
2355 printf("ThreadRPCServer started\n");
2357 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2358 if (mapArgs["-rpcpassword"] == "")
2360 unsigned char rand_pwd[32];
2361 RAND_bytes(rand_pwd, 32);
2362 string strWhatAmI = "To use bitcoind";
2363 if (mapArgs.count("-server"))
2364 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2365 else if (mapArgs.count("-daemon"))
2366 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2367 ThreadSafeMessageBox(strprintf(
2368 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2369 "It is recommended you use the following random password:\n"
2370 "rpcuser=bitcoinrpc\n"
2372 "(you do not need to remember this password)\n"
2373 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2375 GetConfigFile().string().c_str(),
2376 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2377 _("Error"), wxOK | wxMODAL);
2382 bool fUseSSL = GetBoolArg("-rpcssl");
2383 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2385 asio::io_service io_service;
2386 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2387 ip::tcp::acceptor acceptor(io_service);
2390 acceptor.open(endpoint.protocol());
2391 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2392 acceptor.bind(endpoint);
2393 acceptor.listen(socket_base::max_connections);
2395 catch(boost::system::system_error &e)
2397 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2398 _("Error"), wxOK | wxMODAL);
2403 ssl::context context(io_service, ssl::context::sslv23);
2406 context.set_options(ssl::context::no_sslv2);
2408 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2409 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2410 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2411 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2413 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2414 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2415 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2416 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2418 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2419 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2424 // Accept connection
2425 SSLStream sslStream(io_service, context);
2426 SSLIOStreamDevice d(sslStream, fUseSSL);
2427 iostreams::stream<SSLIOStreamDevice> stream(d);
2429 ip::tcp::endpoint peer;
2430 vnThreadsRunning[THREAD_RPCSERVER]--;
2431 acceptor.accept(sslStream.lowest_layer(), peer);
2432 vnThreadsRunning[4]++;
2436 // Restrict callers by IP
2437 if (!ClientAllowed(peer.address().to_string()))
2439 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2441 stream << HTTPReply(403, "") << std::flush;
2445 map<string, string> mapHeaders;
2448 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2449 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2452 printf("ThreadRPCServer ReadHTTP timeout\n");
2456 // Check authorization
2457 if (mapHeaders.count("authorization") == 0)
2459 stream << HTTPReply(401, "") << std::flush;
2462 if (!HTTPAuthorized(mapHeaders))
2464 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2465 /* Deter brute-forcing short passwords.
2466 If this results in a DOS the user really
2467 shouldn't have their RPC port exposed.*/
2468 if (mapArgs["-rpcpassword"].size() < 20)
2471 stream << HTTPReply(401, "") << std::flush;
2475 Value id = Value::null;
2480 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2481 throw JSONRPCError(-32700, "Parse error");
2482 const Object& request = valRequest.get_obj();
2484 // Parse id now so errors from here on will have the id
2485 id = find_value(request, "id");
2488 Value valMethod = find_value(request, "method");
2489 if (valMethod.type() == null_type)
2490 throw JSONRPCError(-32600, "Missing method");
2491 if (valMethod.type() != str_type)
2492 throw JSONRPCError(-32600, "Method must be a string");
2493 string strMethod = valMethod.get_str();
2494 if (strMethod != "getwork" && strMethod != "getmemorypool")
2495 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2498 Value valParams = find_value(request, "params");
2500 if (valParams.type() == array_type)
2501 params = valParams.get_array();
2502 else if (valParams.type() == null_type)
2505 throw JSONRPCError(-32600, "Params must be an array");
2508 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2509 if (mi == mapCallTable.end())
2510 throw JSONRPCError(-32601, "Method not found");
2512 // Observe safe mode
2513 string strWarning = GetWarnings("rpc");
2514 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2515 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2522 LOCK2(cs_main, pwalletMain->cs_wallet);
2523 result = (*(*mi).second)(params, false);
2527 string strReply = JSONRPCReply(result, Value::null, id);
2528 stream << HTTPReply(200, strReply) << std::flush;
2530 catch (std::exception& e)
2532 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2535 catch (Object& objError)
2537 ErrorReply(stream, objError, id);
2539 catch (std::exception& e)
2541 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2549 Object CallRPC(const string& strMethod, const Array& params)
2551 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2552 throw runtime_error(strprintf(
2553 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2554 "If the file does not exist, create it with owner-readable-only file permissions."),
2555 GetConfigFile().string().c_str()));
2557 // Connect to localhost
2558 bool fUseSSL = GetBoolArg("-rpcssl");
2559 asio::io_service io_service;
2560 ssl::context context(io_service, ssl::context::sslv23);
2561 context.set_options(ssl::context::no_sslv2);
2562 SSLStream sslStream(io_service, context);
2563 SSLIOStreamDevice d(sslStream, fUseSSL);
2564 iostreams::stream<SSLIOStreamDevice> stream(d);
2565 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2566 throw runtime_error("couldn't connect to server");
2568 // HTTP basic authentication
2569 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2570 map<string, string> mapRequestHeaders;
2571 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2574 string strRequest = JSONRPCRequest(strMethod, params, 1);
2575 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2576 stream << strPost << std::flush;
2579 map<string, string> mapHeaders;
2581 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2583 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2584 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2585 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2586 else if (strReply.empty())
2587 throw runtime_error("no response from server");
2591 if (!read_string(strReply, valReply))
2592 throw runtime_error("couldn't parse reply from server");
2593 const Object& reply = valReply.get_obj();
2595 throw runtime_error("expected reply to have result, error and id properties");
2603 template<typename T>
2604 void ConvertTo(Value& value)
2606 if (value.type() == str_type)
2608 // reinterpret string as unquoted json value
2610 if (!read_string(value.get_str(), value2))
2611 throw runtime_error("type mismatch");
2612 value = value2.get_value<T>();
2616 value = value.get_value<T>();
2620 int CommandLineRPC(int argc, char *argv[])
2627 while (argc > 1 && IsSwitchChar(argv[1][0]))
2635 throw runtime_error("too few parameters");
2636 string strMethod = argv[1];
2638 // Parameters default to strings
2640 for (int i = 2; i < argc; i++)
2641 params.push_back(argv[i]);
2642 int n = params.size();
2645 // Special case non-string parameter types
2647 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2648 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2649 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2650 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2651 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2652 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2654 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2655 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2656 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2657 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2658 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2659 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2660 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2661 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2662 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2663 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2664 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2665 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2666 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2667 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "sendmany" && n > 1)
2670 string s = params[1].get_str();
2672 if (!read_string(s, v) || v.type() != obj_type)
2673 throw runtime_error("type mismatch");
2674 params[1] = v.get_obj();
2676 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2677 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2678 if (strMethod == "addmultisigaddress" && n > 1)
2680 string s = params[1].get_str();
2682 if (!read_string(s, v) || v.type() != array_type)
2683 throw runtime_error("type mismatch "+s);
2684 params[1] = v.get_array();
2688 Object reply = CallRPC(strMethod, params);
2691 const Value& result = find_value(reply, "result");
2692 const Value& error = find_value(reply, "error");
2694 if (error.type() != null_type)
2697 strPrint = "error: " + write_string(error, false);
2698 int code = find_value(error.get_obj(), "code").get_int();
2704 if (result.type() == null_type)
2706 else if (result.type() == str_type)
2707 strPrint = result.get_str();
2709 strPrint = write_string(result, true);
2712 catch (std::exception& e)
2714 strPrint = string("error: ") + e.what();
2719 PrintException(NULL, "CommandLineRPC()");
2724 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2733 int main(int argc, char *argv[])
2736 // Turn off microsoft heap dump noise
2737 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2738 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2740 setbuf(stdin, NULL);
2741 setbuf(stdout, NULL);
2742 setbuf(stderr, NULL);
2746 if (argc >= 2 && string(argv[1]) == "-server")
2748 printf("server ready\n");
2749 ThreadRPCServer(NULL);
2753 return CommandLineRPC(argc, argv);
2756 catch (std::exception& e) {
2757 PrintException(&e, "main()");
2759 PrintException(NULL, "main()");