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 "ui_interface.h"
14 #include <boost/asio.hpp>
15 #include <boost/filesystem.hpp>
16 #include <boost/iostreams/concepts.hpp>
17 #include <boost/iostreams/stream.hpp>
18 #include <boost/algorithm/string.hpp>
19 #include <boost/lexical_cast.hpp>
20 #include <boost/asio/ssl.hpp>
21 #include <boost/filesystem/fstream.hpp>
22 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
24 #include "json/json_spirit_reader_template.h"
25 #include "json/json_spirit_writer_template.h"
26 #include "json/json_spirit_utils.h"
27 #define printf OutputDebugStringF
28 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
29 // precompiled in headers.h. The problem might be when the pch file goes over
30 // a certain size around 145MB. If we need access to json_spirit outside this
31 // file, we could use the compiled json_spirit option.
34 using namespace boost;
35 using namespace boost::asio;
36 using namespace json_spirit;
38 void ThreadRPCServer2(void* parg);
39 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
40 extern map<string, rpcfn_type> mapCallTable;
42 static std::string strRPCUserColonPass;
44 static int64 nWalletUnlockTime;
45 static CCriticalSection cs_nWalletUnlockTime;
47 extern Value dumpprivkey(const Array& params, bool fHelp);
48 extern Value importprivkey(const Array& params, bool fHelp);
50 Object JSONRPCError(int code, const string& message)
53 error.push_back(Pair("code", code));
54 error.push_back(Pair("message", message));
58 double GetDifficulty(const CBlockIndex* blockindex = NULL)
60 // Floating point number that is a multiple of the minimum difficulty,
61 // minimum difficulty = 1.0.
62 if (blockindex == NULL)
64 if (pindexBest == NULL)
67 blockindex = pindexBest;
70 int nShift = (blockindex->nBits >> 24) & 0xff;
73 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
90 int64 AmountFromValue(const Value& value)
92 double dAmount = value.get_real();
93 if (dAmount <= 0.0 || dAmount > 21000000.0)
94 throw JSONRPCError(-3, "Invalid amount");
95 int64 nAmount = roundint64(dAmount * COIN);
96 if (!MoneyRange(nAmount))
97 throw JSONRPCError(-3, "Invalid amount");
101 Value ValueFromAmount(int64 amount)
103 return (double)amount / (double)COIN;
107 HexBits(unsigned int nBits)
113 uBits.nBits = htonl((int32_t)nBits);
114 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
117 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
119 int confirms = wtx.GetDepthInMainChain();
120 entry.push_back(Pair("confirmations", confirms));
123 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
124 entry.push_back(Pair("blockindex", wtx.nIndex));
126 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
127 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
128 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
129 entry.push_back(Pair(item.first, item.second));
132 string AccountFromValue(const Value& value)
134 string strAccount = value.get_str();
135 if (strAccount == "*")
136 throw JSONRPCError(-11, "Invalid account name");
140 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
143 result.push_back(Pair("hash", block.GetHash().GetHex()));
144 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
145 result.push_back(Pair("height", blockindex->nHeight));
146 result.push_back(Pair("version", block.nVersion));
147 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
148 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
149 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
150 result.push_back(Pair("bits", HexBits(block.nBits)));
151 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
153 BOOST_FOREACH (const CTransaction&tx, block.vtx)
154 txhashes.push_back(tx.GetHash().GetHex());
155 result.push_back(Pair("tx", txhashes));
157 if (blockindex->pprev)
158 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
159 if (blockindex->pnext)
160 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
167 /// Note: This interface may still be subject to change.
171 Value help(const Array& params, bool fHelp)
173 if (fHelp || params.size() > 1)
176 "List commands, or get help for a command.");
179 if (params.size() > 0)
180 strCommand = params[0].get_str();
183 set<rpcfn_type> setDone;
184 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
186 string strMethod = (*mi).first;
187 // We already filter duplicates, but these deprecated screw up the sort order
188 if (strMethod == "getamountreceived" ||
189 strMethod == "getallreceived" ||
190 strMethod == "getblocknumber" || // deprecated
191 (strMethod.find("label") != string::npos))
193 if (strCommand != "" && strMethod != strCommand)
198 rpcfn_type pfn = (*mi).second;
199 if (setDone.insert(pfn).second)
200 (*pfn)(params, true);
202 catch (std::exception& e)
204 // Help text is returned in an exception
205 string strHelp = string(e.what());
206 if (strCommand == "")
207 if (strHelp.find('\n') != string::npos)
208 strHelp = strHelp.substr(0, strHelp.find('\n'));
209 strRet += strHelp + "\n";
213 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
214 strRet = strRet.substr(0,strRet.size()-1);
219 Value stop(const Array& params, bool fHelp)
221 if (fHelp || params.size() != 0)
224 "Stop bitcoin server.");
225 // Shutdown will take long enough that the response should get back
227 return "bitcoin server stopping";
231 Value getblockcount(const Array& params, bool fHelp)
233 if (fHelp || params.size() != 0)
236 "Returns the number of blocks in the longest block chain.");
243 Value getblocknumber(const Array& params, bool fHelp)
245 if (fHelp || params.size() != 0)
248 "Deprecated. Use getblockcount.");
254 Value getconnectioncount(const Array& params, bool fHelp)
256 if (fHelp || params.size() != 0)
258 "getconnectioncount\n"
259 "Returns the number of connections to other nodes.");
261 return (int)vNodes.size();
265 Value getdifficulty(const Array& params, bool fHelp)
267 if (fHelp || params.size() != 0)
270 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
272 return GetDifficulty();
276 Value getgenerate(const Array& params, bool fHelp)
278 if (fHelp || params.size() != 0)
281 "Returns true or false.");
283 return GetBoolArg("-gen");
287 Value setgenerate(const Array& params, bool fHelp)
289 if (fHelp || params.size() < 1 || params.size() > 2)
291 "setgenerate <generate> [genproclimit]\n"
292 "<generate> is true or false to turn generation on or off.\n"
293 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
295 bool fGenerate = true;
296 if (params.size() > 0)
297 fGenerate = params[0].get_bool();
299 if (params.size() > 1)
301 int nGenProcLimit = params[1].get_int();
302 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
303 if (nGenProcLimit == 0)
306 mapArgs["-gen"] = (fGenerate ? "1" : "0");
308 GenerateBitcoins(fGenerate, pwalletMain);
313 Value gethashespersec(const Array& params, bool fHelp)
315 if (fHelp || params.size() != 0)
318 "Returns a recent hashes per second performance measurement while generating.");
320 if (GetTimeMillis() - nHPSTimerStart > 8000)
321 return (boost::int64_t)0;
322 return (boost::int64_t)dHashesPerSec;
326 Value getinfo(const Array& params, bool fHelp)
328 if (fHelp || params.size() != 0)
331 "Returns an object containing various state info.");
334 obj.push_back(Pair("version", (int)CLIENT_VERSION));
335 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
336 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
337 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
338 obj.push_back(Pair("blocks", (int)nBestHeight));
339 obj.push_back(Pair("connections", (int)vNodes.size()));
340 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
341 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
342 obj.push_back(Pair("testnet", fTestNet));
343 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
344 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
345 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
346 if (pwalletMain->IsCrypted())
347 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
348 obj.push_back(Pair("errors", GetWarnings("statusbar")));
353 Value getmininginfo(const Array& params, bool fHelp)
355 if (fHelp || params.size() != 0)
358 "Returns an object containing mining-related information.");
361 obj.push_back(Pair("blocks", (int)nBestHeight));
362 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
363 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
364 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
365 obj.push_back(Pair("errors", GetWarnings("statusbar")));
366 obj.push_back(Pair("generate", GetBoolArg("-gen")));
367 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
368 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
369 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
370 obj.push_back(Pair("testnet", fTestNet));
375 Value getnewaddress(const Array& params, bool fHelp)
377 if (fHelp || params.size() > 1)
379 "getnewaddress [account]\n"
380 "Returns a new bitcoin address for receiving payments. "
381 "If [account] is specified (recommended), it is added to the address book "
382 "so payments received with the address will be credited to [account].");
384 // Parse the account first so we don't generate a key if there's an error
386 if (params.size() > 0)
387 strAccount = AccountFromValue(params[0]);
389 if (!pwalletMain->IsLocked())
390 pwalletMain->TopUpKeyPool();
392 // Generate a new key that is added to wallet
393 std::vector<unsigned char> newKey;
394 if (!pwalletMain->GetKeyFromPool(newKey, false))
395 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
396 CBitcoinAddress address(newKey);
398 pwalletMain->SetAddressBookName(address, strAccount);
400 return address.ToString();
404 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
406 CWalletDB walletdb(pwalletMain->strWalletFile);
409 walletdb.ReadAccount(strAccount, account);
411 bool bKeyUsed = false;
413 // Check if the current key has been used
414 if (!account.vchPubKey.empty())
416 CScript scriptPubKey;
417 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
418 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
419 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
422 const CWalletTx& wtx = (*it).second;
423 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
424 if (txout.scriptPubKey == scriptPubKey)
429 // Generate a new key
430 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
432 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
433 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
435 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
436 walletdb.WriteAccount(strAccount, account);
439 return CBitcoinAddress(account.vchPubKey);
442 Value getaccountaddress(const Array& params, bool fHelp)
444 if (fHelp || params.size() != 1)
446 "getaccountaddress <account>\n"
447 "Returns the current bitcoin address for receiving payments to this account.");
449 // Parse the account first so we don't generate a key if there's an error
450 string strAccount = AccountFromValue(params[0]);
454 ret = GetAccountAddress(strAccount).ToString();
461 Value setaccount(const Array& params, bool fHelp)
463 if (fHelp || params.size() < 1 || params.size() > 2)
465 "setaccount <bitcoinaddress> <account>\n"
466 "Sets the account associated with the given address.");
468 CBitcoinAddress address(params[0].get_str());
469 if (!address.IsValid())
470 throw JSONRPCError(-5, "Invalid bitcoin address");
474 if (params.size() > 1)
475 strAccount = AccountFromValue(params[1]);
477 // Detect when changing the account of an address that is the 'unused current key' of another account:
478 if (pwalletMain->mapAddressBook.count(address))
480 string strOldAccount = pwalletMain->mapAddressBook[address];
481 if (address == GetAccountAddress(strOldAccount))
482 GetAccountAddress(strOldAccount, true);
485 pwalletMain->SetAddressBookName(address, strAccount);
491 Value getaccount(const Array& params, bool fHelp)
493 if (fHelp || params.size() != 1)
495 "getaccount <bitcoinaddress>\n"
496 "Returns the account associated with the given address.");
498 CBitcoinAddress address(params[0].get_str());
499 if (!address.IsValid())
500 throw JSONRPCError(-5, "Invalid bitcoin address");
503 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
504 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
505 strAccount = (*mi).second;
510 Value getaddressesbyaccount(const Array& params, bool fHelp)
512 if (fHelp || params.size() != 1)
514 "getaddressesbyaccount <account>\n"
515 "Returns the list of addresses for the given account.");
517 string strAccount = AccountFromValue(params[0]);
519 // Find all addresses that have the given account
521 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
523 const CBitcoinAddress& address = item.first;
524 const string& strName = item.second;
525 if (strName == strAccount)
526 ret.push_back(address.ToString());
531 Value settxfee(const Array& params, bool fHelp)
533 if (fHelp || params.size() < 1 || params.size() > 1)
535 "settxfee <amount>\n"
536 "<amount> is a real and is rounded to the nearest 0.00000001");
540 if (params[0].get_real() != 0.0)
541 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
543 nTransactionFee = nAmount;
547 Value sendtoaddress(const Array& params, bool fHelp)
549 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
551 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
552 "<amount> is a real and is rounded to the nearest 0.00000001\n"
553 "requires wallet passphrase to be set with walletpassphrase first");
554 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
556 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
557 "<amount> is a real and is rounded to the nearest 0.00000001");
559 CBitcoinAddress address(params[0].get_str());
560 if (!address.IsValid())
561 throw JSONRPCError(-5, "Invalid bitcoin address");
564 int64 nAmount = AmountFromValue(params[1]);
568 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
569 wtx.mapValue["comment"] = params[2].get_str();
570 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
571 wtx.mapValue["to"] = params[3].get_str();
573 if (pwalletMain->IsLocked())
574 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
576 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
578 throw JSONRPCError(-4, strError);
580 return wtx.GetHash().GetHex();
583 Value signmessage(const Array& params, bool fHelp)
585 if (fHelp || params.size() != 2)
587 "signmessage <bitcoinaddress> <message>\n"
588 "Sign a message with the private key of an address");
590 if (pwalletMain->IsLocked())
591 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
593 string strAddress = params[0].get_str();
594 string strMessage = params[1].get_str();
596 CBitcoinAddress addr(strAddress);
598 throw JSONRPCError(-3, "Invalid address");
601 if (!pwalletMain->GetKey(addr, key))
602 throw JSONRPCError(-4, "Private key not available");
604 CDataStream ss(SER_GETHASH);
605 ss << strMessageMagic;
608 vector<unsigned char> vchSig;
609 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
610 throw JSONRPCError(-5, "Sign failed");
612 return EncodeBase64(&vchSig[0], vchSig.size());
615 Value verifymessage(const Array& params, bool fHelp)
617 if (fHelp || params.size() != 3)
619 "verifymessage <bitcoinaddress> <signature> <message>\n"
620 "Verify a signed message");
622 string strAddress = params[0].get_str();
623 string strSign = params[1].get_str();
624 string strMessage = params[2].get_str();
626 CBitcoinAddress addr(strAddress);
628 throw JSONRPCError(-3, "Invalid address");
630 bool fInvalid = false;
631 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
634 throw JSONRPCError(-5, "Malformed base64 encoding");
636 CDataStream ss(SER_GETHASH);
637 ss << strMessageMagic;
641 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
644 return (CBitcoinAddress(key.GetPubKey()) == addr);
648 Value getreceivedbyaddress(const Array& params, bool fHelp)
650 if (fHelp || params.size() < 1 || params.size() > 2)
652 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
653 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
656 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
657 CScript scriptPubKey;
658 if (!address.IsValid())
659 throw JSONRPCError(-5, "Invalid bitcoin address");
660 scriptPubKey.SetBitcoinAddress(address);
661 if (!IsMine(*pwalletMain,scriptPubKey))
664 // Minimum confirmations
666 if (params.size() > 1)
667 nMinDepth = params[1].get_int();
671 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
673 const CWalletTx& wtx = (*it).second;
674 if (wtx.IsCoinBase() || !wtx.IsFinal())
677 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
678 if (txout.scriptPubKey == scriptPubKey)
679 if (wtx.GetDepthInMainChain() >= nMinDepth)
680 nAmount += txout.nValue;
683 return ValueFromAmount(nAmount);
687 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
689 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
691 const CBitcoinAddress& address = item.first;
692 const string& strName = item.second;
693 if (strName == strAccount)
694 setAddress.insert(address);
699 Value getreceivedbyaccount(const Array& params, bool fHelp)
701 if (fHelp || params.size() < 1 || params.size() > 2)
703 "getreceivedbyaccount <account> [minconf=1]\n"
704 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
706 // Minimum confirmations
708 if (params.size() > 1)
709 nMinDepth = params[1].get_int();
711 // Get the set of pub keys assigned to account
712 string strAccount = AccountFromValue(params[0]);
713 set<CBitcoinAddress> setAddress;
714 GetAccountAddresses(strAccount, setAddress);
718 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
720 const CWalletTx& wtx = (*it).second;
721 if (wtx.IsCoinBase() || !wtx.IsFinal())
724 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
726 CBitcoinAddress address;
727 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
728 if (wtx.GetDepthInMainChain() >= nMinDepth)
729 nAmount += txout.nValue;
733 return (double)nAmount / (double)COIN;
737 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
741 // Tally wallet transactions
742 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
744 const CWalletTx& wtx = (*it).second;
748 int64 nGenerated, nReceived, nSent, nFee;
749 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
751 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
752 nBalance += nReceived;
753 nBalance += nGenerated - nSent - nFee;
756 // Tally internal accounting entries
757 nBalance += walletdb.GetAccountCreditDebit(strAccount);
762 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
764 CWalletDB walletdb(pwalletMain->strWalletFile);
765 return GetAccountBalance(walletdb, strAccount, nMinDepth);
769 Value getbalance(const Array& params, bool fHelp)
771 if (fHelp || params.size() > 2)
773 "getbalance [account] [minconf=1]\n"
774 "If [account] is not specified, returns the server's total available balance.\n"
775 "If [account] is specified, returns the balance in the account.");
777 if (params.size() == 0)
778 return ValueFromAmount(pwalletMain->GetBalance());
781 if (params.size() > 1)
782 nMinDepth = params[1].get_int();
784 if (params[0].get_str() == "*") {
785 // Calculate total balance a different way from GetBalance()
786 // (GetBalance() sums up all unspent TxOuts)
787 // getbalance and getbalance '*' should always return the same number.
789 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
791 const CWalletTx& wtx = (*it).second;
795 int64 allGeneratedImmature, allGeneratedMature, allFee;
796 allGeneratedImmature = allGeneratedMature = allFee = 0;
797 string strSentAccount;
798 list<pair<CBitcoinAddress, int64> > listReceived;
799 list<pair<CBitcoinAddress, int64> > listSent;
800 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
801 if (wtx.GetDepthInMainChain() >= nMinDepth)
803 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
804 nBalance += r.second;
806 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
807 nBalance -= r.second;
809 nBalance += allGeneratedMature;
811 return ValueFromAmount(nBalance);
814 string strAccount = AccountFromValue(params[0]);
816 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
818 return ValueFromAmount(nBalance);
822 Value movecmd(const Array& params, bool fHelp)
824 if (fHelp || params.size() < 3 || params.size() > 5)
826 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
827 "Move from one account in your wallet to another.");
829 string strFrom = AccountFromValue(params[0]);
830 string strTo = AccountFromValue(params[1]);
831 int64 nAmount = AmountFromValue(params[2]);
832 if (params.size() > 3)
833 // unused parameter, used to be nMinDepth, keep type-checking it though
834 (void)params[3].get_int();
836 if (params.size() > 4)
837 strComment = params[4].get_str();
839 CWalletDB walletdb(pwalletMain->strWalletFile);
842 int64 nNow = GetAdjustedTime();
845 CAccountingEntry debit;
846 debit.strAccount = strFrom;
847 debit.nCreditDebit = -nAmount;
849 debit.strOtherAccount = strTo;
850 debit.strComment = strComment;
851 walletdb.WriteAccountingEntry(debit);
854 CAccountingEntry credit;
855 credit.strAccount = strTo;
856 credit.nCreditDebit = nAmount;
858 credit.strOtherAccount = strFrom;
859 credit.strComment = strComment;
860 walletdb.WriteAccountingEntry(credit);
862 walletdb.TxnCommit();
868 Value sendfrom(const Array& params, bool fHelp)
870 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
872 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
873 "<amount> is a real and is rounded to the nearest 0.00000001\n"
874 "requires wallet passphrase to be set with walletpassphrase first");
875 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
877 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
878 "<amount> is a real and is rounded to the nearest 0.00000001");
880 string strAccount = AccountFromValue(params[0]);
881 CBitcoinAddress address(params[1].get_str());
882 if (!address.IsValid())
883 throw JSONRPCError(-5, "Invalid bitcoin address");
884 int64 nAmount = AmountFromValue(params[2]);
886 if (params.size() > 3)
887 nMinDepth = params[3].get_int();
890 wtx.strFromAccount = strAccount;
891 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
892 wtx.mapValue["comment"] = params[4].get_str();
893 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
894 wtx.mapValue["to"] = params[5].get_str();
896 if (pwalletMain->IsLocked())
897 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
900 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
901 if (nAmount > nBalance)
902 throw JSONRPCError(-6, "Account has insufficient funds");
905 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
907 throw JSONRPCError(-4, strError);
909 return wtx.GetHash().GetHex();
913 Value sendmany(const Array& params, bool fHelp)
915 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
917 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
918 "amounts are double-precision floating point numbers\n"
919 "requires wallet passphrase to be set with walletpassphrase first");
920 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
922 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
923 "amounts are double-precision floating point numbers");
925 string strAccount = AccountFromValue(params[0]);
926 Object sendTo = params[1].get_obj();
928 if (params.size() > 2)
929 nMinDepth = params[2].get_int();
932 wtx.strFromAccount = strAccount;
933 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
934 wtx.mapValue["comment"] = params[3].get_str();
936 set<CBitcoinAddress> setAddress;
937 vector<pair<CScript, int64> > vecSend;
939 int64 totalAmount = 0;
940 BOOST_FOREACH(const Pair& s, sendTo)
942 CBitcoinAddress address(s.name_);
943 if (!address.IsValid())
944 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
946 if (setAddress.count(address))
947 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
948 setAddress.insert(address);
950 CScript scriptPubKey;
951 scriptPubKey.SetBitcoinAddress(address);
952 int64 nAmount = AmountFromValue(s.value_);
953 totalAmount += nAmount;
955 vecSend.push_back(make_pair(scriptPubKey, nAmount));
958 if (pwalletMain->IsLocked())
959 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
962 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
963 if (totalAmount > nBalance)
964 throw JSONRPCError(-6, "Account has insufficient funds");
967 CReserveKey keyChange(pwalletMain);
968 int64 nFeeRequired = 0;
969 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
972 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
973 throw JSONRPCError(-6, "Insufficient funds");
974 throw JSONRPCError(-4, "Transaction creation failed");
976 if (!pwalletMain->CommitTransaction(wtx, keyChange))
977 throw JSONRPCError(-4, "Transaction commit failed");
979 return wtx.GetHash().GetHex();
982 Value addmultisigaddress(const Array& params, bool fHelp)
984 if (fHelp || params.size() < 2 || params.size() > 3)
986 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
987 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
988 "each key is a bitcoin address or hex-encoded public key\n"
989 "If [account] is specified, assign address to [account].";
990 throw runtime_error(msg);
993 int nRequired = params[0].get_int();
994 const Array& keys = params[1].get_array();
996 if (params.size() > 2)
997 strAccount = AccountFromValue(params[2]);
999 // Gather public keys
1000 if (nRequired < 1 || keys.size() < nRequired)
1001 throw runtime_error(
1002 strprintf("wrong number of keys"
1003 "(got %d, need at least %d)", keys.size(), nRequired));
1004 std::vector<CKey> pubkeys;
1005 pubkeys.resize(keys.size());
1006 for (unsigned int i = 0; i < keys.size(); i++)
1008 const std::string& ks = keys[i].get_str();
1010 // Case 1: bitcoin address and we have full public key:
1011 CBitcoinAddress address(ks);
1012 if (address.IsValid())
1014 if (address.IsScript())
1015 throw runtime_error(
1016 strprintf("%s is a pay-to-script address",ks.c_str()));
1017 std::vector<unsigned char> vchPubKey;
1018 if (!pwalletMain->GetPubKey(address, vchPubKey))
1019 throw runtime_error(
1020 strprintf("no full public key for address %s",ks.c_str()));
1021 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1022 throw runtime_error(" Invalid public key: "+ks);
1025 // Case 2: hex public key
1028 vector<unsigned char> vchPubKey = ParseHex(ks);
1029 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1030 throw runtime_error(" Invalid public key: "+ks);
1034 throw runtime_error(" Invalid public key: "+ks);
1038 // Construct using pay-to-script-hash:
1040 inner.SetMultisig(nRequired, pubkeys);
1042 uint160 scriptHash = Hash160(inner);
1043 CScript scriptPubKey;
1044 scriptPubKey.SetPayToScriptHash(inner);
1045 pwalletMain->AddCScript(inner);
1046 CBitcoinAddress address;
1047 address.SetScriptHash160(scriptHash);
1049 pwalletMain->SetAddressBookName(address, strAccount);
1050 return address.ToString();
1061 nConf = std::numeric_limits<int>::max();
1065 Value ListReceived(const Array& params, bool fByAccounts)
1067 // Minimum confirmations
1069 if (params.size() > 0)
1070 nMinDepth = params[0].get_int();
1072 // Whether to include empty accounts
1073 bool fIncludeEmpty = false;
1074 if (params.size() > 1)
1075 fIncludeEmpty = params[1].get_bool();
1078 map<CBitcoinAddress, tallyitem> mapTally;
1079 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1081 const CWalletTx& wtx = (*it).second;
1083 if (wtx.IsCoinBase() || !wtx.IsFinal())
1086 int nDepth = wtx.GetDepthInMainChain();
1087 if (nDepth < nMinDepth)
1090 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1092 CBitcoinAddress address;
1093 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1096 tallyitem& item = mapTally[address];
1097 item.nAmount += txout.nValue;
1098 item.nConf = min(item.nConf, nDepth);
1104 map<string, tallyitem> mapAccountTally;
1105 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1107 const CBitcoinAddress& address = item.first;
1108 const string& strAccount = item.second;
1109 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1110 if (it == mapTally.end() && !fIncludeEmpty)
1114 int nConf = std::numeric_limits<int>::max();
1115 if (it != mapTally.end())
1117 nAmount = (*it).second.nAmount;
1118 nConf = (*it).second.nConf;
1123 tallyitem& item = mapAccountTally[strAccount];
1124 item.nAmount += nAmount;
1125 item.nConf = min(item.nConf, nConf);
1130 obj.push_back(Pair("address", address.ToString()));
1131 obj.push_back(Pair("account", strAccount));
1132 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1133 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1140 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1142 int64 nAmount = (*it).second.nAmount;
1143 int nConf = (*it).second.nConf;
1145 obj.push_back(Pair("account", (*it).first));
1146 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1147 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1155 Value listreceivedbyaddress(const Array& params, bool fHelp)
1157 if (fHelp || params.size() > 2)
1158 throw runtime_error(
1159 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1160 "[minconf] is the minimum number of confirmations before payments are included.\n"
1161 "[includeempty] whether to include addresses that haven't received any payments.\n"
1162 "Returns an array of objects containing:\n"
1163 " \"address\" : receiving address\n"
1164 " \"account\" : the account of the receiving address\n"
1165 " \"amount\" : total amount received by the address\n"
1166 " \"confirmations\" : number of confirmations of the most recent transaction included");
1168 return ListReceived(params, false);
1171 Value listreceivedbyaccount(const Array& params, bool fHelp)
1173 if (fHelp || params.size() > 2)
1174 throw runtime_error(
1175 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1176 "[minconf] is the minimum number of confirmations before payments are included.\n"
1177 "[includeempty] whether to include accounts that haven't received any payments.\n"
1178 "Returns an array of objects containing:\n"
1179 " \"account\" : the account of the receiving addresses\n"
1180 " \"amount\" : total amount received by addresses with this account\n"
1181 " \"confirmations\" : number of confirmations of the most recent transaction included");
1183 return ListReceived(params, true);
1186 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1188 int64 nGeneratedImmature, nGeneratedMature, nFee;
1189 string strSentAccount;
1190 list<pair<CBitcoinAddress, int64> > listReceived;
1191 list<pair<CBitcoinAddress, int64> > listSent;
1193 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1195 bool fAllAccounts = (strAccount == string("*"));
1197 // Generated blocks assigned to account ""
1198 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1201 entry.push_back(Pair("account", string("")));
1202 if (nGeneratedImmature)
1204 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1205 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1209 entry.push_back(Pair("category", "generate"));
1210 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1213 WalletTxToJSON(wtx, entry);
1214 ret.push_back(entry);
1218 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1220 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1223 entry.push_back(Pair("account", strSentAccount));
1224 entry.push_back(Pair("address", s.first.ToString()));
1225 entry.push_back(Pair("category", "send"));
1226 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1227 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1229 WalletTxToJSON(wtx, entry);
1230 ret.push_back(entry);
1235 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1237 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1240 if (pwalletMain->mapAddressBook.count(r.first))
1241 account = pwalletMain->mapAddressBook[r.first];
1242 if (fAllAccounts || (account == strAccount))
1245 entry.push_back(Pair("account", account));
1246 entry.push_back(Pair("address", r.first.ToString()));
1247 entry.push_back(Pair("category", "receive"));
1248 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1250 WalletTxToJSON(wtx, entry);
1251 ret.push_back(entry);
1257 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1259 bool fAllAccounts = (strAccount == string("*"));
1261 if (fAllAccounts || acentry.strAccount == strAccount)
1264 entry.push_back(Pair("account", acentry.strAccount));
1265 entry.push_back(Pair("category", "move"));
1266 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1267 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1268 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1269 entry.push_back(Pair("comment", acentry.strComment));
1270 ret.push_back(entry);
1274 Value listtransactions(const Array& params, bool fHelp)
1276 if (fHelp || params.size() > 3)
1277 throw runtime_error(
1278 "listtransactions [account] [count=10] [from=0]\n"
1279 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1281 string strAccount = "*";
1282 if (params.size() > 0)
1283 strAccount = params[0].get_str();
1285 if (params.size() > 1)
1286 nCount = params[1].get_int();
1288 if (params.size() > 2)
1289 nFrom = params[2].get_int();
1292 throw JSONRPCError(-8, "Negative count");
1294 throw JSONRPCError(-8, "Negative from");
1297 CWalletDB walletdb(pwalletMain->strWalletFile);
1299 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1300 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1301 typedef multimap<int64, TxPair > TxItems;
1304 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1305 // would make this much faster for applications that do this a lot.
1306 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1308 CWalletTx* wtx = &((*it).second);
1309 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1311 list<CAccountingEntry> acentries;
1312 walletdb.ListAccountCreditDebit(strAccount, acentries);
1313 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1315 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1318 // iterate backwards until we have nCount items to return:
1319 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1321 CWalletTx *const pwtx = (*it).second.first;
1323 ListTransactions(*pwtx, strAccount, 0, true, ret);
1324 CAccountingEntry *const pacentry = (*it).second.second;
1326 AcentryToJSON(*pacentry, strAccount, ret);
1328 if (ret.size() >= (nCount+nFrom)) break;
1330 // ret is newest to oldest
1332 if (nFrom > ret.size()) nFrom = ret.size();
1333 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1334 Array::iterator first = ret.begin();
1335 std::advance(first, nFrom);
1336 Array::iterator last = ret.begin();
1337 std::advance(last, nFrom+nCount);
1339 if (last != ret.end()) ret.erase(last, ret.end());
1340 if (first != ret.begin()) ret.erase(ret.begin(), first);
1342 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1347 Value listaccounts(const Array& params, bool fHelp)
1349 if (fHelp || params.size() > 1)
1350 throw runtime_error(
1351 "listaccounts [minconf=1]\n"
1352 "Returns Object that has account names as keys, account balances as values.");
1355 if (params.size() > 0)
1356 nMinDepth = params[0].get_int();
1358 map<string, int64> mapAccountBalances;
1359 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1360 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1361 mapAccountBalances[entry.second] = 0;
1364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1366 const CWalletTx& wtx = (*it).second;
1367 int64 nGeneratedImmature, nGeneratedMature, nFee;
1368 string strSentAccount;
1369 list<pair<CBitcoinAddress, int64> > listReceived;
1370 list<pair<CBitcoinAddress, int64> > listSent;
1371 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1372 mapAccountBalances[strSentAccount] -= nFee;
1373 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1374 mapAccountBalances[strSentAccount] -= s.second;
1375 if (wtx.GetDepthInMainChain() >= nMinDepth)
1377 mapAccountBalances[""] += nGeneratedMature;
1378 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1379 if (pwalletMain->mapAddressBook.count(r.first))
1380 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1382 mapAccountBalances[""] += r.second;
1386 list<CAccountingEntry> acentries;
1387 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1388 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1389 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1392 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1393 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1398 Value listsinceblock(const Array& params, bool fHelp)
1401 throw runtime_error(
1402 "listsinceblock [blockid] [target-confirmations]\n"
1403 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1405 CBlockIndex *pindex = NULL;
1406 int target_confirms = 1;
1408 if (params.size() > 0)
1410 uint256 blockId = 0;
1412 blockId.SetHex(params[0].get_str());
1413 pindex = CBlockLocator(blockId).GetBlockIndex();
1416 if (params.size() > 1)
1418 target_confirms = params[1].get_int();
1420 if (target_confirms < 1)
1421 throw JSONRPCError(-8, "Invalid parameter");
1424 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1428 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1430 CWalletTx tx = (*it).second;
1432 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1433 ListTransactions(tx, "*", 0, true, transactions);
1438 if (target_confirms == 1)
1441 lastblock = hashBestChain;
1445 int target_height = pindexBest->nHeight + 1 - target_confirms;
1448 for (block = pindexBest;
1449 block && block->nHeight > target_height;
1450 block = block->pprev) { }
1452 lastblock = block ? block->GetBlockHash() : 0;
1456 ret.push_back(Pair("transactions", transactions));
1457 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1462 Value gettransaction(const Array& params, bool fHelp)
1464 if (fHelp || params.size() != 1)
1465 throw runtime_error(
1466 "gettransaction <txid>\n"
1467 "Get detailed information about <txid>");
1470 hash.SetHex(params[0].get_str());
1474 if (!pwalletMain->mapWallet.count(hash))
1475 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1476 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1478 int64 nCredit = wtx.GetCredit();
1479 int64 nDebit = wtx.GetDebit();
1480 int64 nNet = nCredit - nDebit;
1481 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1483 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1485 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1487 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1490 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1491 entry.push_back(Pair("details", details));
1497 Value backupwallet(const Array& params, bool fHelp)
1499 if (fHelp || params.size() != 1)
1500 throw runtime_error(
1501 "backupwallet <destination>\n"
1502 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1504 string strDest = params[0].get_str();
1505 BackupWallet(*pwalletMain, strDest);
1511 Value keypoolrefill(const Array& params, bool fHelp)
1513 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1514 throw runtime_error(
1516 "Fills the keypool, requires wallet passphrase to be set.");
1517 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1518 throw runtime_error(
1520 "Fills the keypool.");
1522 if (pwalletMain->IsLocked())
1523 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1525 pwalletMain->TopUpKeyPool();
1527 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1528 throw JSONRPCError(-4, "Error refreshing keypool.");
1534 void ThreadTopUpKeyPool(void* parg)
1536 pwalletMain->TopUpKeyPool();
1539 void ThreadCleanWalletPassphrase(void* parg)
1541 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1543 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1545 if (nWalletUnlockTime == 0)
1547 nWalletUnlockTime = nMyWakeTime;
1551 if (nWalletUnlockTime==0)
1553 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1557 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1559 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1563 if (nWalletUnlockTime)
1565 nWalletUnlockTime = 0;
1566 pwalletMain->Lock();
1571 if (nWalletUnlockTime < nMyWakeTime)
1572 nWalletUnlockTime = nMyWakeTime;
1575 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1577 delete (int64*)parg;
1580 Value walletpassphrase(const Array& params, bool fHelp)
1582 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1583 throw runtime_error(
1584 "walletpassphrase <passphrase> <timeout>\n"
1585 "Stores the wallet decryption key in memory for <timeout> seconds.");
1588 if (!pwalletMain->IsCrypted())
1589 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1591 if (!pwalletMain->IsLocked())
1592 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1594 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1595 SecureString strWalletPass;
1596 strWalletPass.reserve(100);
1597 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1598 // Alternately, find a way to make params[0] mlock()'d to begin with.
1599 strWalletPass = params[0].get_str().c_str();
1601 if (strWalletPass.length() > 0)
1603 if (!pwalletMain->Unlock(strWalletPass))
1604 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1607 throw runtime_error(
1608 "walletpassphrase <passphrase> <timeout>\n"
1609 "Stores the wallet decryption key in memory for <timeout> seconds.");
1611 CreateThread(ThreadTopUpKeyPool, NULL);
1612 int64* pnSleepTime = new int64(params[1].get_int64());
1613 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1619 Value walletpassphrasechange(const Array& params, bool fHelp)
1621 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1622 throw runtime_error(
1623 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1624 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1627 if (!pwalletMain->IsCrypted())
1628 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1630 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1631 // Alternately, find a way to make params[0] mlock()'d to begin with.
1632 SecureString strOldWalletPass;
1633 strOldWalletPass.reserve(100);
1634 strOldWalletPass = params[0].get_str().c_str();
1636 SecureString strNewWalletPass;
1637 strNewWalletPass.reserve(100);
1638 strNewWalletPass = params[1].get_str().c_str();
1640 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1641 throw runtime_error(
1642 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1643 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1645 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1646 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1652 Value walletlock(const Array& params, bool fHelp)
1654 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1655 throw runtime_error(
1657 "Removes the wallet encryption key from memory, locking the wallet.\n"
1658 "After calling this method, you will need to call walletpassphrase again\n"
1659 "before being able to call any methods which require the wallet to be unlocked.");
1662 if (!pwalletMain->IsCrypted())
1663 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1666 LOCK(cs_nWalletUnlockTime);
1667 pwalletMain->Lock();
1668 nWalletUnlockTime = 0;
1675 Value encryptwallet(const Array& params, bool fHelp)
1677 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1678 throw runtime_error(
1679 "encryptwallet <passphrase>\n"
1680 "Encrypts the wallet with <passphrase>.");
1683 if (pwalletMain->IsCrypted())
1684 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1686 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1687 // Alternately, find a way to make params[0] mlock()'d to begin with.
1688 SecureString strWalletPass;
1689 strWalletPass.reserve(100);
1690 strWalletPass = params[0].get_str().c_str();
1692 if (strWalletPass.length() < 1)
1693 throw runtime_error(
1694 "encryptwallet <passphrase>\n"
1695 "Encrypts the wallet with <passphrase>.");
1697 if (!pwalletMain->EncryptWallet(strWalletPass))
1698 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1700 // BDB seems to have a bad habit of writing old data into
1701 // slack space in .dat files; that is bad if the old data is
1702 // unencrypted private keys. So:
1704 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1708 Value validateaddress(const Array& params, bool fHelp)
1710 if (fHelp || params.size() != 1)
1711 throw runtime_error(
1712 "validateaddress <bitcoinaddress>\n"
1713 "Return information about <bitcoinaddress>.");
1715 CBitcoinAddress address(params[0].get_str());
1716 bool isValid = address.IsValid();
1719 ret.push_back(Pair("isvalid", isValid));
1722 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1723 // version of the address:
1724 string currentAddress = address.ToString();
1725 ret.push_back(Pair("address", currentAddress));
1726 if (pwalletMain->HaveKey(address))
1728 ret.push_back(Pair("ismine", true));
1729 std::vector<unsigned char> vchPubKey;
1730 pwalletMain->GetPubKey(address, vchPubKey);
1731 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1733 key.SetPubKey(vchPubKey);
1734 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1736 else if (pwalletMain->HaveCScript(address.GetHash160()))
1738 ret.push_back(Pair("isscript", true));
1740 pwalletMain->GetCScript(address.GetHash160(), subscript);
1741 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1742 std::vector<CBitcoinAddress> addresses;
1743 txnouttype whichType;
1745 ExtractAddresses(subscript, whichType, addresses, nRequired);
1746 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1748 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1749 a.push_back(addr.ToString());
1750 ret.push_back(Pair("addresses", a));
1751 if (whichType == TX_MULTISIG)
1752 ret.push_back(Pair("sigsrequired", nRequired));
1755 ret.push_back(Pair("ismine", false));
1756 if (pwalletMain->mapAddressBook.count(address))
1757 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1762 Value getwork(const Array& params, bool fHelp)
1764 if (fHelp || params.size() > 1)
1765 throw runtime_error(
1767 "If [data] is not specified, returns formatted hash data to work on:\n"
1768 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1769 " \"data\" : block data\n"
1770 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1771 " \"target\" : little endian hash target\n"
1772 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1775 throw JSONRPCError(-9, "Bitcoin is not connected!");
1777 if (IsInitialBlockDownload())
1778 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1780 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1781 static mapNewBlock_t mapNewBlock;
1782 static vector<CBlock*> vNewBlock;
1783 static CReserveKey reservekey(pwalletMain);
1785 if (params.size() == 0)
1788 static unsigned int nTransactionsUpdatedLast;
1789 static CBlockIndex* pindexPrev;
1790 static int64 nStart;
1791 static CBlock* pblock;
1792 if (pindexPrev != pindexBest ||
1793 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1795 if (pindexPrev != pindexBest)
1797 // Deallocate old blocks since they're obsolete now
1798 mapNewBlock.clear();
1799 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1803 nTransactionsUpdatedLast = nTransactionsUpdated;
1804 pindexPrev = pindexBest;
1808 pblock = CreateNewBlock(reservekey);
1810 throw JSONRPCError(-7, "Out of memory");
1811 vNewBlock.push_back(pblock);
1815 pblock->UpdateTime(pindexPrev);
1818 // Update nExtraNonce
1819 static unsigned int nExtraNonce = 0;
1820 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1823 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1825 // Prebuild hash buffers
1829 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1831 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1834 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1835 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1836 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1837 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1843 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1844 if (vchData.size() != 128)
1845 throw JSONRPCError(-8, "Invalid parameter");
1846 CBlock* pdata = (CBlock*)&vchData[0];
1849 for (int i = 0; i < 128/4; i++)
1850 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1853 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1855 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1857 pblock->nTime = pdata->nTime;
1858 pblock->nNonce = pdata->nNonce;
1859 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1860 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1862 return CheckWork(pblock, *pwalletMain, reservekey);
1867 Value getmemorypool(const Array& params, bool fHelp)
1869 if (fHelp || params.size() > 1)
1870 throw runtime_error(
1871 "getmemorypool [data]\n"
1872 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1873 " \"version\" : block version\n"
1874 " \"previousblockhash\" : hash of current highest block\n"
1875 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1876 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1877 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1878 " \"time\" : timestamp appropriate for next block\n"
1879 " \"mintime\" : minimum timestamp appropriate for next block\n"
1880 " \"curtime\" : current timestamp\n"
1881 " \"bits\" : compressed target of next block\n"
1882 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1884 if (params.size() == 0)
1887 throw JSONRPCError(-9, "Bitcoin is not connected!");
1889 if (IsInitialBlockDownload())
1890 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1892 static CReserveKey reservekey(pwalletMain);
1895 static unsigned int nTransactionsUpdatedLast;
1896 static CBlockIndex* pindexPrev;
1897 static int64 nStart;
1898 static CBlock* pblock;
1899 if (pindexPrev != pindexBest ||
1900 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1902 nTransactionsUpdatedLast = nTransactionsUpdated;
1903 pindexPrev = pindexBest;
1909 pblock = CreateNewBlock(reservekey);
1911 throw JSONRPCError(-7, "Out of memory");
1915 pblock->UpdateTime(pindexPrev);
1919 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1926 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1930 result.push_back(Pair("version", pblock->nVersion));
1931 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1932 result.push_back(Pair("transactions", transactions));
1933 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1934 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1935 result.push_back(Pair("time", (int64_t)pblock->nTime));
1936 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1937 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1938 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1945 CDataStream ssBlock(ParseHex(params[0].get_str()));
1949 return ProcessBlock(NULL, &pblock);
1953 Value getblockhash(const Array& params, bool fHelp)
1955 if (fHelp || params.size() != 1)
1956 throw runtime_error(
1957 "getblockhash <index>\n"
1958 "Returns hash of block in best-block-chain at <index>.");
1960 int nHeight = params[0].get_int();
1961 if (nHeight < 0 || nHeight > nBestHeight)
1962 throw runtime_error("Block number out of range.");
1965 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1966 while (pblockindex->nHeight > nHeight)
1967 pblockindex = pblockindex->pprev;
1968 return pblockindex->phashBlock->GetHex();
1971 Value getblock(const Array& params, bool fHelp)
1973 if (fHelp || params.size() != 1)
1974 throw runtime_error(
1976 "Returns details of a block with given block-hash.");
1978 std::string strHash = params[0].get_str();
1979 uint256 hash(strHash);
1981 if (mapBlockIndex.count(hash) == 0)
1982 throw JSONRPCError(-5, "Block not found");
1985 CBlockIndex* pblockindex = mapBlockIndex[hash];
1986 block.ReadFromDisk(pblockindex, true);
1988 return blockToJSON(block, pblockindex);
2005 pair<string, rpcfn_type> pCallTable[] =
2007 make_pair("help", &help),
2008 make_pair("stop", &stop),
2009 make_pair("getblockcount", &getblockcount),
2010 make_pair("getblocknumber", &getblocknumber),
2011 make_pair("getconnectioncount", &getconnectioncount),
2012 make_pair("getdifficulty", &getdifficulty),
2013 make_pair("getgenerate", &getgenerate),
2014 make_pair("setgenerate", &setgenerate),
2015 make_pair("gethashespersec", &gethashespersec),
2016 make_pair("getinfo", &getinfo),
2017 make_pair("getmininginfo", &getmininginfo),
2018 make_pair("getnewaddress", &getnewaddress),
2019 make_pair("getaccountaddress", &getaccountaddress),
2020 make_pair("setaccount", &setaccount),
2021 make_pair("getaccount", &getaccount),
2022 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2023 make_pair("sendtoaddress", &sendtoaddress),
2024 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2025 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2026 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2027 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2028 make_pair("backupwallet", &backupwallet),
2029 make_pair("keypoolrefill", &keypoolrefill),
2030 make_pair("walletpassphrase", &walletpassphrase),
2031 make_pair("walletpassphrasechange", &walletpassphrasechange),
2032 make_pair("walletlock", &walletlock),
2033 make_pair("encryptwallet", &encryptwallet),
2034 make_pair("validateaddress", &validateaddress),
2035 make_pair("getbalance", &getbalance),
2036 make_pair("move", &movecmd),
2037 make_pair("sendfrom", &sendfrom),
2038 make_pair("sendmany", &sendmany),
2039 make_pair("addmultisigaddress", &addmultisigaddress),
2040 make_pair("getblock", &getblock),
2041 make_pair("getblockhash", &getblockhash),
2042 make_pair("gettransaction", &gettransaction),
2043 make_pair("listtransactions", &listtransactions),
2044 make_pair("signmessage", &signmessage),
2045 make_pair("verifymessage", &verifymessage),
2046 make_pair("getwork", &getwork),
2047 make_pair("listaccounts", &listaccounts),
2048 make_pair("settxfee", &settxfee),
2049 make_pair("getmemorypool", &getmemorypool),
2050 make_pair("listsinceblock", &listsinceblock),
2051 make_pair("dumpprivkey", &dumpprivkey),
2052 make_pair("importprivkey", &importprivkey)
2054 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2056 string pAllowInSafeMode[] =
2061 "getblocknumber", // deprecated
2062 "getconnectioncount",
2070 "getaccountaddress",
2072 "getaddressesbyaccount",
2081 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2089 // This ain't Apache. We're just using HTTP header for the length field
2090 // and to be compatible with other JSON-RPC implementations.
2093 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2096 s << "POST / HTTP/1.1\r\n"
2097 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2098 << "Host: 127.0.0.1\r\n"
2099 << "Content-Type: application/json\r\n"
2100 << "Content-Length: " << strMsg.size() << "\r\n"
2101 << "Connection: close\r\n"
2102 << "Accept: application/json\r\n";
2103 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2104 s << item.first << ": " << item.second << "\r\n";
2105 s << "\r\n" << strMsg;
2110 string rfc1123Time()
2115 struct tm* now_gmt = gmtime(&now);
2116 string locale(setlocale(LC_TIME, NULL));
2117 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2118 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2119 setlocale(LC_TIME, locale.c_str());
2120 return string(buffer);
2123 static string HTTPReply(int nStatus, const string& strMsg)
2126 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2128 "Server: bitcoin-json-rpc/%s\r\n"
2129 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2130 "Content-Type: text/html\r\n"
2131 "Content-Length: 296\r\n"
2133 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2134 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2137 "<TITLE>Error</TITLE>\r\n"
2138 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2140 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2141 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2142 const char *cStatus;
2143 if (nStatus == 200) cStatus = "OK";
2144 else if (nStatus == 400) cStatus = "Bad Request";
2145 else if (nStatus == 403) cStatus = "Forbidden";
2146 else if (nStatus == 404) cStatus = "Not Found";
2147 else if (nStatus == 500) cStatus = "Internal Server Error";
2150 "HTTP/1.1 %d %s\r\n"
2152 "Connection: close\r\n"
2153 "Content-Length: %d\r\n"
2154 "Content-Type: application/json\r\n"
2155 "Server: bitcoin-json-rpc/%s\r\n"
2160 rfc1123Time().c_str(),
2162 FormatFullVersion().c_str(),
2166 int ReadHTTPStatus(std::basic_istream<char>& stream)
2169 getline(stream, str);
2170 vector<string> vWords;
2171 boost::split(vWords, str, boost::is_any_of(" "));
2172 if (vWords.size() < 2)
2174 return atoi(vWords[1].c_str());
2177 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2183 std::getline(stream, str);
2184 if (str.empty() || str == "\r")
2186 string::size_type nColon = str.find(":");
2187 if (nColon != string::npos)
2189 string strHeader = str.substr(0, nColon);
2190 boost::trim(strHeader);
2191 boost::to_lower(strHeader);
2192 string strValue = str.substr(nColon+1);
2193 boost::trim(strValue);
2194 mapHeadersRet[strHeader] = strValue;
2195 if (strHeader == "content-length")
2196 nLen = atoi(strValue.c_str());
2202 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2204 mapHeadersRet.clear();
2208 int nStatus = ReadHTTPStatus(stream);
2211 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2212 if (nLen < 0 || nLen > MAX_SIZE)
2218 vector<char> vch(nLen);
2219 stream.read(&vch[0], nLen);
2220 strMessageRet = string(vch.begin(), vch.end());
2226 bool HTTPAuthorized(map<string, string>& mapHeaders)
2228 string strAuth = mapHeaders["authorization"];
2229 if (strAuth.substr(0,6) != "Basic ")
2231 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2232 string strUserPass = DecodeBase64(strUserPass64);
2233 return strUserPass == strRPCUserColonPass;
2237 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2238 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2239 // unspecified (HTTP errors and contents of 'error').
2241 // 1.0 spec: http://json-rpc.org/wiki/specification
2242 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2243 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2246 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2249 request.push_back(Pair("method", strMethod));
2250 request.push_back(Pair("params", params));
2251 request.push_back(Pair("id", id));
2252 return write_string(Value(request), false) + "\n";
2255 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2258 if (error.type() != null_type)
2259 reply.push_back(Pair("result", Value::null));
2261 reply.push_back(Pair("result", result));
2262 reply.push_back(Pair("error", error));
2263 reply.push_back(Pair("id", id));
2264 return write_string(Value(reply), false) + "\n";
2267 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2269 // Send error reply from json-rpc error object
2271 int code = find_value(objError, "code").get_int();
2272 if (code == -32600) nStatus = 400;
2273 else if (code == -32601) nStatus = 404;
2274 string strReply = JSONRPCReply(Value::null, objError, id);
2275 stream << HTTPReply(nStatus, strReply) << std::flush;
2278 bool ClientAllowed(const string& strAddress)
2280 if (strAddress == asio::ip::address_v4::loopback().to_string())
2282 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2283 BOOST_FOREACH(string strAllow, vAllow)
2284 if (WildcardMatch(strAddress, strAllow))
2290 // IOStream device that speaks SSL but can also speak non-SSL
2292 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2294 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2296 fUseSSL = fUseSSLIn;
2297 fNeedHandshake = fUseSSLIn;
2300 void handshake(ssl::stream_base::handshake_type role)
2302 if (!fNeedHandshake) return;
2303 fNeedHandshake = false;
2304 stream.handshake(role);
2306 std::streamsize read(char* s, std::streamsize n)
2308 handshake(ssl::stream_base::server); // HTTPS servers read first
2309 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2310 return stream.next_layer().read_some(asio::buffer(s, n));
2312 std::streamsize write(const char* s, std::streamsize n)
2314 handshake(ssl::stream_base::client); // HTTPS clients write first
2315 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2316 return asio::write(stream.next_layer(), asio::buffer(s, n));
2318 bool connect(const std::string& server, const std::string& port)
2320 ip::tcp::resolver resolver(stream.get_io_service());
2321 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2322 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2323 ip::tcp::resolver::iterator end;
2324 boost::system::error_code error = asio::error::host_not_found;
2325 while (error && endpoint_iterator != end)
2327 stream.lowest_layer().close();
2328 stream.lowest_layer().connect(*endpoint_iterator++, error);
2336 bool fNeedHandshake;
2341 void ThreadRPCServer(void* parg)
2343 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2346 vnThreadsRunning[THREAD_RPCSERVER]++;
2347 ThreadRPCServer2(parg);
2348 vnThreadsRunning[THREAD_RPCSERVER]--;
2350 catch (std::exception& e) {
2351 vnThreadsRunning[THREAD_RPCSERVER]--;
2352 PrintException(&e, "ThreadRPCServer()");
2354 vnThreadsRunning[THREAD_RPCSERVER]--;
2355 PrintException(NULL, "ThreadRPCServer()");
2357 printf("ThreadRPCServer exiting\n");
2360 void ThreadRPCServer2(void* parg)
2362 printf("ThreadRPCServer started\n");
2364 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2365 if (mapArgs["-rpcpassword"] == "")
2367 unsigned char rand_pwd[32];
2368 RAND_bytes(rand_pwd, 32);
2369 string strWhatAmI = "To use bitcoind";
2370 if (mapArgs.count("-server"))
2371 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2372 else if (mapArgs.count("-daemon"))
2373 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2374 ThreadSafeMessageBox(strprintf(
2375 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2376 "It is recommended you use the following random password:\n"
2377 "rpcuser=bitcoinrpc\n"
2379 "(you do not need to remember this password)\n"
2380 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2382 GetConfigFile().string().c_str(),
2383 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2384 _("Error"), wxOK | wxMODAL);
2389 bool fUseSSL = GetBoolArg("-rpcssl");
2390 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2392 asio::io_service io_service;
2393 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2394 ip::tcp::acceptor acceptor(io_service);
2397 acceptor.open(endpoint.protocol());
2398 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2399 acceptor.bind(endpoint);
2400 acceptor.listen(socket_base::max_connections);
2402 catch(boost::system::system_error &e)
2404 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2405 _("Error"), wxOK | wxMODAL);
2410 ssl::context context(io_service, ssl::context::sslv23);
2413 context.set_options(ssl::context::no_sslv2);
2415 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2416 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2417 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2418 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2420 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2421 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2422 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2423 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2425 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2426 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2431 // Accept connection
2432 SSLStream sslStream(io_service, context);
2433 SSLIOStreamDevice d(sslStream, fUseSSL);
2434 iostreams::stream<SSLIOStreamDevice> stream(d);
2436 ip::tcp::endpoint peer;
2437 vnThreadsRunning[THREAD_RPCSERVER]--;
2438 acceptor.accept(sslStream.lowest_layer(), peer);
2439 vnThreadsRunning[4]++;
2443 // Restrict callers by IP
2444 if (!ClientAllowed(peer.address().to_string()))
2446 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2448 stream << HTTPReply(403, "") << std::flush;
2452 map<string, string> mapHeaders;
2455 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2456 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2459 printf("ThreadRPCServer ReadHTTP timeout\n");
2463 // Check authorization
2464 if (mapHeaders.count("authorization") == 0)
2466 stream << HTTPReply(401, "") << std::flush;
2469 if (!HTTPAuthorized(mapHeaders))
2471 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2472 /* Deter brute-forcing short passwords.
2473 If this results in a DOS the user really
2474 shouldn't have their RPC port exposed.*/
2475 if (mapArgs["-rpcpassword"].size() < 20)
2478 stream << HTTPReply(401, "") << std::flush;
2482 Value id = Value::null;
2487 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2488 throw JSONRPCError(-32700, "Parse error");
2489 const Object& request = valRequest.get_obj();
2491 // Parse id now so errors from here on will have the id
2492 id = find_value(request, "id");
2495 Value valMethod = find_value(request, "method");
2496 if (valMethod.type() == null_type)
2497 throw JSONRPCError(-32600, "Missing method");
2498 if (valMethod.type() != str_type)
2499 throw JSONRPCError(-32600, "Method must be a string");
2500 string strMethod = valMethod.get_str();
2501 if (strMethod != "getwork" && strMethod != "getmemorypool")
2502 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2505 Value valParams = find_value(request, "params");
2507 if (valParams.type() == array_type)
2508 params = valParams.get_array();
2509 else if (valParams.type() == null_type)
2512 throw JSONRPCError(-32600, "Params must be an array");
2515 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2516 if (mi == mapCallTable.end())
2517 throw JSONRPCError(-32601, "Method not found");
2519 // Observe safe mode
2520 string strWarning = GetWarnings("rpc");
2521 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2522 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2529 LOCK2(cs_main, pwalletMain->cs_wallet);
2530 result = (*(*mi).second)(params, false);
2534 string strReply = JSONRPCReply(result, Value::null, id);
2535 stream << HTTPReply(200, strReply) << std::flush;
2537 catch (std::exception& e)
2539 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2542 catch (Object& objError)
2544 ErrorReply(stream, objError, id);
2546 catch (std::exception& e)
2548 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2556 Object CallRPC(const string& strMethod, const Array& params)
2558 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2559 throw runtime_error(strprintf(
2560 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2561 "If the file does not exist, create it with owner-readable-only file permissions."),
2562 GetConfigFile().string().c_str()));
2564 // Connect to localhost
2565 bool fUseSSL = GetBoolArg("-rpcssl");
2566 asio::io_service io_service;
2567 ssl::context context(io_service, ssl::context::sslv23);
2568 context.set_options(ssl::context::no_sslv2);
2569 SSLStream sslStream(io_service, context);
2570 SSLIOStreamDevice d(sslStream, fUseSSL);
2571 iostreams::stream<SSLIOStreamDevice> stream(d);
2572 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2573 throw runtime_error("couldn't connect to server");
2575 // HTTP basic authentication
2576 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2577 map<string, string> mapRequestHeaders;
2578 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2581 string strRequest = JSONRPCRequest(strMethod, params, 1);
2582 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2583 stream << strPost << std::flush;
2586 map<string, string> mapHeaders;
2588 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2590 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2591 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2592 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2593 else if (strReply.empty())
2594 throw runtime_error("no response from server");
2598 if (!read_string(strReply, valReply))
2599 throw runtime_error("couldn't parse reply from server");
2600 const Object& reply = valReply.get_obj();
2602 throw runtime_error("expected reply to have result, error and id properties");
2610 template<typename T>
2611 void ConvertTo(Value& value)
2613 if (value.type() == str_type)
2615 // reinterpret string as unquoted json value
2617 if (!read_string(value.get_str(), value2))
2618 throw runtime_error("type mismatch");
2619 value = value2.get_value<T>();
2623 value = value.get_value<T>();
2627 int CommandLineRPC(int argc, char *argv[])
2634 while (argc > 1 && IsSwitchChar(argv[1][0]))
2642 throw runtime_error("too few parameters");
2643 string strMethod = argv[1];
2645 // Parameters default to strings
2647 for (int i = 2; i < argc; i++)
2648 params.push_back(argv[i]);
2649 int n = params.size();
2652 // Special case non-string parameter types
2654 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2655 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2657 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2658 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2660 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2661 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2662 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2663 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2664 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2666 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2667 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2668 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2669 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2670 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2672 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2673 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "sendmany" && n > 1)
2677 string s = params[1].get_str();
2679 if (!read_string(s, v) || v.type() != obj_type)
2680 throw runtime_error("type mismatch");
2681 params[1] = v.get_obj();
2683 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2684 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2685 if (strMethod == "addmultisigaddress" && n > 1)
2687 string s = params[1].get_str();
2689 if (!read_string(s, v) || v.type() != array_type)
2690 throw runtime_error("type mismatch "+s);
2691 params[1] = v.get_array();
2695 Object reply = CallRPC(strMethod, params);
2698 const Value& result = find_value(reply, "result");
2699 const Value& error = find_value(reply, "error");
2701 if (error.type() != null_type)
2704 strPrint = "error: " + write_string(error, false);
2705 int code = find_value(error.get_obj(), "code").get_int();
2711 if (result.type() == null_type)
2713 else if (result.type() == str_type)
2714 strPrint = result.get_str();
2716 strPrint = write_string(result, true);
2719 catch (std::exception& e)
2721 strPrint = string("error: ") + e.what();
2726 PrintException(NULL, "CommandLineRPC()");
2731 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2740 int main(int argc, char *argv[])
2743 // Turn off microsoft heap dump noise
2744 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2745 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2747 setbuf(stdin, NULL);
2748 setbuf(stdout, NULL);
2749 setbuf(stderr, NULL);
2753 if (argc >= 2 && string(argv[1]) == "-server")
2755 printf("server ready\n");
2756 ThreadRPCServer(NULL);
2760 return CommandLineRPC(argc, argv);
2763 catch (std::exception& e) {
2764 PrintException(&e, "main()");
2766 PrintException(NULL, "main()");