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.
12 #include "ui_interface.h"
15 #include <boost/asio.hpp>
16 #include <boost/filesystem.hpp>
17 #include <boost/iostreams/concepts.hpp>
18 #include <boost/iostreams/stream.hpp>
19 #include <boost/algorithm/string.hpp>
20 #include <boost/lexical_cast.hpp>
21 #include <boost/asio/ssl.hpp>
22 #include <boost/filesystem/fstream.hpp>
23 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
25 #include "json/json_spirit_reader_template.h"
26 #include "json/json_spirit_writer_template.h"
27 #include "json/json_spirit_utils.h"
28 #define printf OutputDebugStringF
29 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
30 // precompiled in headers.h. The problem might be when the pch file goes over
31 // a certain size around 145MB. If we need access to json_spirit outside this
32 // file, we could use the compiled json_spirit option.
35 using namespace boost;
36 using namespace boost::asio;
37 using namespace json_spirit;
39 void ThreadRPCServer2(void* parg);
40 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
41 extern map<string, rpcfn_type> mapCallTable;
43 static std::string strRPCUserColonPass;
45 static int64 nWalletUnlockTime;
46 static CCriticalSection cs_nWalletUnlockTime;
48 extern Value dumpprivkey(const Array& params, bool fHelp);
49 extern Value importprivkey(const Array& params, bool fHelp);
51 Object JSONRPCError(int code, const string& message)
54 error.push_back(Pair("code", code));
55 error.push_back(Pair("message", message));
59 double GetDifficulty(const CBlockIndex* blockindex = NULL)
61 // Floating point number that is a multiple of the minimum difficulty,
62 // minimum difficulty = 1.0.
63 if (blockindex == NULL)
65 if (pindexBest == NULL)
68 blockindex = pindexBest;
71 int nShift = (blockindex->nBits >> 24) & 0xff;
74 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
91 int64 AmountFromValue(const Value& value)
93 double dAmount = value.get_real();
94 if (dAmount <= 0.0 || dAmount > 21000000.0)
95 throw JSONRPCError(-3, "Invalid amount");
96 int64 nAmount = roundint64(dAmount * COIN);
97 if (!MoneyRange(nAmount))
98 throw JSONRPCError(-3, "Invalid amount");
102 Value ValueFromAmount(int64 amount)
104 return (double)amount / (double)COIN;
108 HexBits(unsigned int nBits)
114 uBits.nBits = htonl((int32_t)nBits);
115 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
118 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
120 int confirms = wtx.GetDepthInMainChain();
121 entry.push_back(Pair("confirmations", confirms));
124 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
125 entry.push_back(Pair("blockindex", wtx.nIndex));
127 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
128 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
129 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
130 entry.push_back(Pair(item.first, item.second));
133 string AccountFromValue(const Value& value)
135 string strAccount = value.get_str();
136 if (strAccount == "*")
137 throw JSONRPCError(-11, "Invalid account name");
141 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
144 result.push_back(Pair("hash", block.GetHash().GetHex()));
145 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
146 result.push_back(Pair("height", blockindex->nHeight));
147 result.push_back(Pair("version", block.nVersion));
148 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
149 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
150 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
151 result.push_back(Pair("bits", HexBits(block.nBits)));
152 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
154 BOOST_FOREACH (const CTransaction&tx, block.vtx)
155 txhashes.push_back(tx.GetHash().GetHex());
156 result.push_back(Pair("tx", txhashes));
158 if (blockindex->pprev)
159 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
160 if (blockindex->pnext)
161 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
168 /// Note: This interface may still be subject to change.
172 Value help(const Array& params, bool fHelp)
174 if (fHelp || params.size() > 1)
177 "List commands, or get help for a command.");
180 if (params.size() > 0)
181 strCommand = params[0].get_str();
184 set<rpcfn_type> setDone;
185 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
187 string strMethod = (*mi).first;
188 // We already filter duplicates, but these deprecated screw up the sort order
189 if (strMethod == "getamountreceived" ||
190 strMethod == "getallreceived" ||
191 strMethod == "getblocknumber" || // deprecated
192 (strMethod.find("label") != string::npos))
194 if (strCommand != "" && strMethod != strCommand)
199 rpcfn_type pfn = (*mi).second;
200 if (setDone.insert(pfn).second)
201 (*pfn)(params, true);
203 catch (std::exception& e)
205 // Help text is returned in an exception
206 string strHelp = string(e.what());
207 if (strCommand == "")
208 if (strHelp.find('\n') != string::npos)
209 strHelp = strHelp.substr(0, strHelp.find('\n'));
210 strRet += strHelp + "\n";
214 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
215 strRet = strRet.substr(0,strRet.size()-1);
220 Value stop(const Array& params, bool fHelp)
222 if (fHelp || params.size() != 0)
225 "Stop bitcoin server.");
226 // Shutdown will take long enough that the response should get back
228 return "bitcoin server stopping";
232 Value getblockcount(const Array& params, bool fHelp)
234 if (fHelp || params.size() != 0)
237 "Returns the number of blocks in the longest block chain.");
244 Value getblocknumber(const Array& params, bool fHelp)
246 if (fHelp || params.size() != 0)
249 "Deprecated. Use getblockcount.");
255 Value getconnectioncount(const Array& params, bool fHelp)
257 if (fHelp || params.size() != 0)
259 "getconnectioncount\n"
260 "Returns the number of connections to other nodes.");
262 return (int)vNodes.size();
266 Value getdifficulty(const Array& params, bool fHelp)
268 if (fHelp || params.size() != 0)
271 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
273 return GetDifficulty();
277 Value getgenerate(const Array& params, bool fHelp)
279 if (fHelp || params.size() != 0)
282 "Returns true or false.");
284 return GetBoolArg("-gen");
288 Value setgenerate(const Array& params, bool fHelp)
290 if (fHelp || params.size() < 1 || params.size() > 2)
292 "setgenerate <generate> [genproclimit]\n"
293 "<generate> is true or false to turn generation on or off.\n"
294 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
296 bool fGenerate = true;
297 if (params.size() > 0)
298 fGenerate = params[0].get_bool();
300 if (params.size() > 1)
302 int nGenProcLimit = params[1].get_int();
303 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
304 if (nGenProcLimit == 0)
307 mapArgs["-gen"] = (fGenerate ? "1" : "0");
309 GenerateBitcoins(fGenerate, pwalletMain);
314 Value gethashespersec(const Array& params, bool fHelp)
316 if (fHelp || params.size() != 0)
319 "Returns a recent hashes per second performance measurement while generating.");
321 if (GetTimeMillis() - nHPSTimerStart > 8000)
322 return (boost::int64_t)0;
323 return (boost::int64_t)dHashesPerSec;
327 Value getinfo(const Array& params, bool fHelp)
329 if (fHelp || params.size() != 0)
332 "Returns an object containing various state info.");
335 obj.push_back(Pair("version", (int)CLIENT_VERSION));
336 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
337 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
338 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
339 obj.push_back(Pair("blocks", (int)nBestHeight));
340 obj.push_back(Pair("connections", (int)vNodes.size()));
341 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
342 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
343 obj.push_back(Pair("testnet", fTestNet));
344 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
345 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
346 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
347 if (pwalletMain->IsCrypted())
348 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
349 obj.push_back(Pair("errors", GetWarnings("statusbar")));
354 Value getmininginfo(const Array& params, bool fHelp)
356 if (fHelp || params.size() != 0)
359 "Returns an object containing mining-related information.");
362 obj.push_back(Pair("blocks", (int)nBestHeight));
363 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
364 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
365 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
366 obj.push_back(Pair("errors", GetWarnings("statusbar")));
367 obj.push_back(Pair("generate", GetBoolArg("-gen")));
368 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
369 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
370 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
371 obj.push_back(Pair("testnet", fTestNet));
376 Value getnewaddress(const Array& params, bool fHelp)
378 if (fHelp || params.size() > 1)
380 "getnewaddress [account]\n"
381 "Returns a new bitcoin address for receiving payments. "
382 "If [account] is specified (recommended), it is added to the address book "
383 "so payments received with the address will be credited to [account].");
385 // Parse the account first so we don't generate a key if there's an error
387 if (params.size() > 0)
388 strAccount = AccountFromValue(params[0]);
390 if (!pwalletMain->IsLocked())
391 pwalletMain->TopUpKeyPool();
393 // Generate a new key that is added to wallet
394 std::vector<unsigned char> newKey;
395 if (!pwalletMain->GetKeyFromPool(newKey, false))
396 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
397 CBitcoinAddress address(newKey);
399 pwalletMain->SetAddressBookName(address, strAccount);
401 return address.ToString();
405 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
407 CWalletDB walletdb(pwalletMain->strWalletFile);
410 walletdb.ReadAccount(strAccount, account);
412 bool bKeyUsed = false;
414 // Check if the current key has been used
415 if (!account.vchPubKey.empty())
417 CScript scriptPubKey;
418 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
419 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
420 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
423 const CWalletTx& wtx = (*it).second;
424 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
425 if (txout.scriptPubKey == scriptPubKey)
430 // Generate a new key
431 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
433 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
434 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
436 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
437 walletdb.WriteAccount(strAccount, account);
440 return CBitcoinAddress(account.vchPubKey);
443 Value getaccountaddress(const Array& params, bool fHelp)
445 if (fHelp || params.size() != 1)
447 "getaccountaddress <account>\n"
448 "Returns the current bitcoin address for receiving payments to this account.");
450 // Parse the account first so we don't generate a key if there's an error
451 string strAccount = AccountFromValue(params[0]);
455 ret = GetAccountAddress(strAccount).ToString();
462 Value setaccount(const Array& params, bool fHelp)
464 if (fHelp || params.size() < 1 || params.size() > 2)
466 "setaccount <bitcoinaddress> <account>\n"
467 "Sets the account associated with the given address.");
469 CBitcoinAddress address(params[0].get_str());
470 if (!address.IsValid())
471 throw JSONRPCError(-5, "Invalid bitcoin address");
475 if (params.size() > 1)
476 strAccount = AccountFromValue(params[1]);
478 // Detect when changing the account of an address that is the 'unused current key' of another account:
479 if (pwalletMain->mapAddressBook.count(address))
481 string strOldAccount = pwalletMain->mapAddressBook[address];
482 if (address == GetAccountAddress(strOldAccount))
483 GetAccountAddress(strOldAccount, true);
486 pwalletMain->SetAddressBookName(address, strAccount);
492 Value getaccount(const Array& params, bool fHelp)
494 if (fHelp || params.size() != 1)
496 "getaccount <bitcoinaddress>\n"
497 "Returns the account associated with the given address.");
499 CBitcoinAddress address(params[0].get_str());
500 if (!address.IsValid())
501 throw JSONRPCError(-5, "Invalid bitcoin address");
504 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
505 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
506 strAccount = (*mi).second;
511 Value getaddressesbyaccount(const Array& params, bool fHelp)
513 if (fHelp || params.size() != 1)
515 "getaddressesbyaccount <account>\n"
516 "Returns the list of addresses for the given account.");
518 string strAccount = AccountFromValue(params[0]);
520 // Find all addresses that have the given account
522 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
524 const CBitcoinAddress& address = item.first;
525 const string& strName = item.second;
526 if (strName == strAccount)
527 ret.push_back(address.ToString());
532 Value settxfee(const Array& params, bool fHelp)
534 if (fHelp || params.size() < 1 || params.size() > 1)
536 "settxfee <amount>\n"
537 "<amount> is a real and is rounded to the nearest 0.00000001");
541 if (params[0].get_real() != 0.0)
542 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
544 nTransactionFee = nAmount;
548 Value sendtoaddress(const Array& params, bool fHelp)
550 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
552 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
553 "<amount> is a real and is rounded to the nearest 0.00000001\n"
554 "requires wallet passphrase to be set with walletpassphrase first");
555 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
557 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
558 "<amount> is a real and is rounded to the nearest 0.00000001");
560 CBitcoinAddress address(params[0].get_str());
561 if (!address.IsValid())
562 throw JSONRPCError(-5, "Invalid bitcoin address");
565 int64 nAmount = AmountFromValue(params[1]);
569 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
570 wtx.mapValue["comment"] = params[2].get_str();
571 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
572 wtx.mapValue["to"] = params[3].get_str();
574 if (pwalletMain->IsLocked())
575 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
577 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
579 throw JSONRPCError(-4, strError);
581 return wtx.GetHash().GetHex();
584 Value signmessage(const Array& params, bool fHelp)
586 if (fHelp || params.size() != 2)
588 "signmessage <bitcoinaddress> <message>\n"
589 "Sign a message with the private key of an address");
591 if (pwalletMain->IsLocked())
592 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
594 string strAddress = params[0].get_str();
595 string strMessage = params[1].get_str();
597 CBitcoinAddress addr(strAddress);
599 throw JSONRPCError(-3, "Invalid address");
602 if (!pwalletMain->GetKey(addr, key))
603 throw JSONRPCError(-4, "Private key not available");
605 CDataStream ss(SER_GETHASH);
606 ss << strMessageMagic;
609 vector<unsigned char> vchSig;
610 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
611 throw JSONRPCError(-5, "Sign failed");
613 return EncodeBase64(&vchSig[0], vchSig.size());
616 Value verifymessage(const Array& params, bool fHelp)
618 if (fHelp || params.size() != 3)
620 "verifymessage <bitcoinaddress> <signature> <message>\n"
621 "Verify a signed message");
623 string strAddress = params[0].get_str();
624 string strSign = params[1].get_str();
625 string strMessage = params[2].get_str();
627 CBitcoinAddress addr(strAddress);
629 throw JSONRPCError(-3, "Invalid address");
631 bool fInvalid = false;
632 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
635 throw JSONRPCError(-5, "Malformed base64 encoding");
637 CDataStream ss(SER_GETHASH);
638 ss << strMessageMagic;
642 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
645 return (CBitcoinAddress(key.GetPubKey()) == addr);
649 Value getreceivedbyaddress(const Array& params, bool fHelp)
651 if (fHelp || params.size() < 1 || params.size() > 2)
653 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
654 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
657 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
658 CScript scriptPubKey;
659 if (!address.IsValid())
660 throw JSONRPCError(-5, "Invalid bitcoin address");
661 scriptPubKey.SetBitcoinAddress(address);
662 if (!IsMine(*pwalletMain,scriptPubKey))
665 // Minimum confirmations
667 if (params.size() > 1)
668 nMinDepth = params[1].get_int();
672 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
674 const CWalletTx& wtx = (*it).second;
675 if (wtx.IsCoinBase() || !wtx.IsFinal())
678 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
679 if (txout.scriptPubKey == scriptPubKey)
680 if (wtx.GetDepthInMainChain() >= nMinDepth)
681 nAmount += txout.nValue;
684 return ValueFromAmount(nAmount);
688 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
690 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
692 const CBitcoinAddress& address = item.first;
693 const string& strName = item.second;
694 if (strName == strAccount)
695 setAddress.insert(address);
700 Value getreceivedbyaccount(const Array& params, bool fHelp)
702 if (fHelp || params.size() < 1 || params.size() > 2)
704 "getreceivedbyaccount <account> [minconf=1]\n"
705 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
707 // Minimum confirmations
709 if (params.size() > 1)
710 nMinDepth = params[1].get_int();
712 // Get the set of pub keys assigned to account
713 string strAccount = AccountFromValue(params[0]);
714 set<CBitcoinAddress> setAddress;
715 GetAccountAddresses(strAccount, setAddress);
719 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
721 const CWalletTx& wtx = (*it).second;
722 if (wtx.IsCoinBase() || !wtx.IsFinal())
725 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
727 CBitcoinAddress address;
728 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
729 if (wtx.GetDepthInMainChain() >= nMinDepth)
730 nAmount += txout.nValue;
734 return (double)nAmount / (double)COIN;
738 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
742 // Tally wallet transactions
743 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
745 const CWalletTx& wtx = (*it).second;
749 int64 nGenerated, nReceived, nSent, nFee;
750 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
752 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
753 nBalance += nReceived;
754 nBalance += nGenerated - nSent - nFee;
757 // Tally internal accounting entries
758 nBalance += walletdb.GetAccountCreditDebit(strAccount);
763 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
765 CWalletDB walletdb(pwalletMain->strWalletFile);
766 return GetAccountBalance(walletdb, strAccount, nMinDepth);
770 Value getbalance(const Array& params, bool fHelp)
772 if (fHelp || params.size() > 2)
774 "getbalance [account] [minconf=1]\n"
775 "If [account] is not specified, returns the server's total available balance.\n"
776 "If [account] is specified, returns the balance in the account.");
778 if (params.size() == 0)
779 return ValueFromAmount(pwalletMain->GetBalance());
782 if (params.size() > 1)
783 nMinDepth = params[1].get_int();
785 if (params[0].get_str() == "*") {
786 // Calculate total balance a different way from GetBalance()
787 // (GetBalance() sums up all unspent TxOuts)
788 // getbalance and getbalance '*' should always return the same number.
790 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
792 const CWalletTx& wtx = (*it).second;
796 int64 allGeneratedImmature, allGeneratedMature, allFee;
797 allGeneratedImmature = allGeneratedMature = allFee = 0;
798 string strSentAccount;
799 list<pair<CBitcoinAddress, int64> > listReceived;
800 list<pair<CBitcoinAddress, int64> > listSent;
801 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
802 if (wtx.GetDepthInMainChain() >= nMinDepth)
804 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
805 nBalance += r.second;
807 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
808 nBalance -= r.second;
810 nBalance += allGeneratedMature;
812 return ValueFromAmount(nBalance);
815 string strAccount = AccountFromValue(params[0]);
817 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
819 return ValueFromAmount(nBalance);
823 Value movecmd(const Array& params, bool fHelp)
825 if (fHelp || params.size() < 3 || params.size() > 5)
827 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
828 "Move from one account in your wallet to another.");
830 string strFrom = AccountFromValue(params[0]);
831 string strTo = AccountFromValue(params[1]);
832 int64 nAmount = AmountFromValue(params[2]);
833 if (params.size() > 3)
834 // unused parameter, used to be nMinDepth, keep type-checking it though
835 (void)params[3].get_int();
837 if (params.size() > 4)
838 strComment = params[4].get_str();
840 CWalletDB walletdb(pwalletMain->strWalletFile);
843 int64 nNow = GetAdjustedTime();
846 CAccountingEntry debit;
847 debit.strAccount = strFrom;
848 debit.nCreditDebit = -nAmount;
850 debit.strOtherAccount = strTo;
851 debit.strComment = strComment;
852 walletdb.WriteAccountingEntry(debit);
855 CAccountingEntry credit;
856 credit.strAccount = strTo;
857 credit.nCreditDebit = nAmount;
859 credit.strOtherAccount = strFrom;
860 credit.strComment = strComment;
861 walletdb.WriteAccountingEntry(credit);
863 walletdb.TxnCommit();
869 Value sendfrom(const Array& params, bool fHelp)
871 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
873 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
874 "<amount> is a real and is rounded to the nearest 0.00000001\n"
875 "requires wallet passphrase to be set with walletpassphrase first");
876 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
878 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
879 "<amount> is a real and is rounded to the nearest 0.00000001");
881 string strAccount = AccountFromValue(params[0]);
882 CBitcoinAddress address(params[1].get_str());
883 if (!address.IsValid())
884 throw JSONRPCError(-5, "Invalid bitcoin address");
885 int64 nAmount = AmountFromValue(params[2]);
887 if (params.size() > 3)
888 nMinDepth = params[3].get_int();
891 wtx.strFromAccount = strAccount;
892 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
893 wtx.mapValue["comment"] = params[4].get_str();
894 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
895 wtx.mapValue["to"] = params[5].get_str();
897 if (pwalletMain->IsLocked())
898 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
901 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
902 if (nAmount > nBalance)
903 throw JSONRPCError(-6, "Account has insufficient funds");
906 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
908 throw JSONRPCError(-4, strError);
910 return wtx.GetHash().GetHex();
914 Value sendmany(const Array& params, bool fHelp)
916 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
918 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
919 "amounts are double-precision floating point numbers\n"
920 "requires wallet passphrase to be set with walletpassphrase first");
921 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
923 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
924 "amounts are double-precision floating point numbers");
926 string strAccount = AccountFromValue(params[0]);
927 Object sendTo = params[1].get_obj();
929 if (params.size() > 2)
930 nMinDepth = params[2].get_int();
933 wtx.strFromAccount = strAccount;
934 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
935 wtx.mapValue["comment"] = params[3].get_str();
937 set<CBitcoinAddress> setAddress;
938 vector<pair<CScript, int64> > vecSend;
940 int64 totalAmount = 0;
941 BOOST_FOREACH(const Pair& s, sendTo)
943 CBitcoinAddress address(s.name_);
944 if (!address.IsValid())
945 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
947 if (setAddress.count(address))
948 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
949 setAddress.insert(address);
951 CScript scriptPubKey;
952 scriptPubKey.SetBitcoinAddress(address);
953 int64 nAmount = AmountFromValue(s.value_);
954 totalAmount += nAmount;
956 vecSend.push_back(make_pair(scriptPubKey, nAmount));
959 if (pwalletMain->IsLocked())
960 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
963 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
964 if (totalAmount > nBalance)
965 throw JSONRPCError(-6, "Account has insufficient funds");
968 CReserveKey keyChange(pwalletMain);
969 int64 nFeeRequired = 0;
970 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
973 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
974 throw JSONRPCError(-6, "Insufficient funds");
975 throw JSONRPCError(-4, "Transaction creation failed");
977 if (!pwalletMain->CommitTransaction(wtx, keyChange))
978 throw JSONRPCError(-4, "Transaction commit failed");
980 return wtx.GetHash().GetHex();
983 Value addmultisigaddress(const Array& params, bool fHelp)
985 if (fHelp || params.size() < 2 || params.size() > 3)
987 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
988 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
989 "each key is a bitcoin address or hex-encoded public key\n"
990 "If [account] is specified, assign address to [account].";
991 throw runtime_error(msg);
994 int nRequired = params[0].get_int();
995 const Array& keys = params[1].get_array();
997 if (params.size() > 2)
998 strAccount = AccountFromValue(params[2]);
1000 // Gather public keys
1001 if (nRequired < 1 || keys.size() < nRequired)
1002 throw runtime_error(
1003 strprintf("wrong number of keys"
1004 "(got %d, need at least %d)", keys.size(), nRequired));
1005 std::vector<CKey> pubkeys;
1006 pubkeys.resize(keys.size());
1007 for (unsigned int i = 0; i < keys.size(); i++)
1009 const std::string& ks = keys[i].get_str();
1011 // Case 1: bitcoin address and we have full public key:
1012 CBitcoinAddress address(ks);
1013 if (address.IsValid())
1015 if (address.IsScript())
1016 throw runtime_error(
1017 strprintf("%s is a pay-to-script address",ks.c_str()));
1018 std::vector<unsigned char> vchPubKey;
1019 if (!pwalletMain->GetPubKey(address, vchPubKey))
1020 throw runtime_error(
1021 strprintf("no full public key for address %s",ks.c_str()));
1022 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1023 throw runtime_error(" Invalid public key: "+ks);
1026 // Case 2: hex public key
1029 vector<unsigned char> vchPubKey = ParseHex(ks);
1030 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1031 throw runtime_error(" Invalid public key: "+ks);
1035 throw runtime_error(" Invalid public key: "+ks);
1039 // Construct using pay-to-script-hash:
1041 inner.SetMultisig(nRequired, pubkeys);
1043 uint160 scriptHash = Hash160(inner);
1044 CScript scriptPubKey;
1045 scriptPubKey.SetPayToScriptHash(inner);
1046 pwalletMain->AddCScript(inner);
1047 CBitcoinAddress address;
1048 address.SetScriptHash160(scriptHash);
1050 pwalletMain->SetAddressBookName(address, strAccount);
1051 return address.ToString();
1062 nConf = std::numeric_limits<int>::max();
1066 Value ListReceived(const Array& params, bool fByAccounts)
1068 // Minimum confirmations
1070 if (params.size() > 0)
1071 nMinDepth = params[0].get_int();
1073 // Whether to include empty accounts
1074 bool fIncludeEmpty = false;
1075 if (params.size() > 1)
1076 fIncludeEmpty = params[1].get_bool();
1079 map<CBitcoinAddress, tallyitem> mapTally;
1080 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1082 const CWalletTx& wtx = (*it).second;
1084 if (wtx.IsCoinBase() || !wtx.IsFinal())
1087 int nDepth = wtx.GetDepthInMainChain();
1088 if (nDepth < nMinDepth)
1091 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1093 CBitcoinAddress address;
1094 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1097 tallyitem& item = mapTally[address];
1098 item.nAmount += txout.nValue;
1099 item.nConf = min(item.nConf, nDepth);
1105 map<string, tallyitem> mapAccountTally;
1106 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1108 const CBitcoinAddress& address = item.first;
1109 const string& strAccount = item.second;
1110 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1111 if (it == mapTally.end() && !fIncludeEmpty)
1115 int nConf = std::numeric_limits<int>::max();
1116 if (it != mapTally.end())
1118 nAmount = (*it).second.nAmount;
1119 nConf = (*it).second.nConf;
1124 tallyitem& item = mapAccountTally[strAccount];
1125 item.nAmount += nAmount;
1126 item.nConf = min(item.nConf, nConf);
1131 obj.push_back(Pair("address", address.ToString()));
1132 obj.push_back(Pair("account", strAccount));
1133 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1134 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1141 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1143 int64 nAmount = (*it).second.nAmount;
1144 int nConf = (*it).second.nConf;
1146 obj.push_back(Pair("account", (*it).first));
1147 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1148 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1156 Value listreceivedbyaddress(const Array& params, bool fHelp)
1158 if (fHelp || params.size() > 2)
1159 throw runtime_error(
1160 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1161 "[minconf] is the minimum number of confirmations before payments are included.\n"
1162 "[includeempty] whether to include addresses that haven't received any payments.\n"
1163 "Returns an array of objects containing:\n"
1164 " \"address\" : receiving address\n"
1165 " \"account\" : the account of the receiving address\n"
1166 " \"amount\" : total amount received by the address\n"
1167 " \"confirmations\" : number of confirmations of the most recent transaction included");
1169 return ListReceived(params, false);
1172 Value listreceivedbyaccount(const Array& params, bool fHelp)
1174 if (fHelp || params.size() > 2)
1175 throw runtime_error(
1176 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1177 "[minconf] is the minimum number of confirmations before payments are included.\n"
1178 "[includeempty] whether to include accounts that haven't received any payments.\n"
1179 "Returns an array of objects containing:\n"
1180 " \"account\" : the account of the receiving addresses\n"
1181 " \"amount\" : total amount received by addresses with this account\n"
1182 " \"confirmations\" : number of confirmations of the most recent transaction included");
1184 return ListReceived(params, true);
1187 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1189 int64 nGeneratedImmature, nGeneratedMature, nFee;
1190 string strSentAccount;
1191 list<pair<CBitcoinAddress, int64> > listReceived;
1192 list<pair<CBitcoinAddress, int64> > listSent;
1194 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1196 bool fAllAccounts = (strAccount == string("*"));
1198 // Generated blocks assigned to account ""
1199 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1202 entry.push_back(Pair("account", string("")));
1203 if (nGeneratedImmature)
1205 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1206 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1210 entry.push_back(Pair("category", "generate"));
1211 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1214 WalletTxToJSON(wtx, entry);
1215 ret.push_back(entry);
1219 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1221 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1224 entry.push_back(Pair("account", strSentAccount));
1225 entry.push_back(Pair("address", s.first.ToString()));
1226 entry.push_back(Pair("category", "send"));
1227 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1228 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1230 WalletTxToJSON(wtx, entry);
1231 ret.push_back(entry);
1236 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1238 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1241 if (pwalletMain->mapAddressBook.count(r.first))
1242 account = pwalletMain->mapAddressBook[r.first];
1243 if (fAllAccounts || (account == strAccount))
1246 entry.push_back(Pair("account", account));
1247 entry.push_back(Pair("address", r.first.ToString()));
1248 entry.push_back(Pair("category", "receive"));
1249 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1251 WalletTxToJSON(wtx, entry);
1252 ret.push_back(entry);
1258 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1260 bool fAllAccounts = (strAccount == string("*"));
1262 if (fAllAccounts || acentry.strAccount == strAccount)
1265 entry.push_back(Pair("account", acentry.strAccount));
1266 entry.push_back(Pair("category", "move"));
1267 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1268 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1269 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1270 entry.push_back(Pair("comment", acentry.strComment));
1271 ret.push_back(entry);
1275 Value listtransactions(const Array& params, bool fHelp)
1277 if (fHelp || params.size() > 3)
1278 throw runtime_error(
1279 "listtransactions [account] [count=10] [from=0]\n"
1280 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1282 string strAccount = "*";
1283 if (params.size() > 0)
1284 strAccount = params[0].get_str();
1286 if (params.size() > 1)
1287 nCount = params[1].get_int();
1289 if (params.size() > 2)
1290 nFrom = params[2].get_int();
1293 throw JSONRPCError(-8, "Negative count");
1295 throw JSONRPCError(-8, "Negative from");
1298 CWalletDB walletdb(pwalletMain->strWalletFile);
1300 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1301 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1302 typedef multimap<int64, TxPair > TxItems;
1305 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1306 // would make this much faster for applications that do this a lot.
1307 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1309 CWalletTx* wtx = &((*it).second);
1310 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1312 list<CAccountingEntry> acentries;
1313 walletdb.ListAccountCreditDebit(strAccount, acentries);
1314 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1316 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1319 // iterate backwards until we have nCount items to return:
1320 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1322 CWalletTx *const pwtx = (*it).second.first;
1324 ListTransactions(*pwtx, strAccount, 0, true, ret);
1325 CAccountingEntry *const pacentry = (*it).second.second;
1327 AcentryToJSON(*pacentry, strAccount, ret);
1329 if (ret.size() >= (nCount+nFrom)) break;
1331 // ret is newest to oldest
1333 if (nFrom > ret.size()) nFrom = ret.size();
1334 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1335 Array::iterator first = ret.begin();
1336 std::advance(first, nFrom);
1337 Array::iterator last = ret.begin();
1338 std::advance(last, nFrom+nCount);
1340 if (last != ret.end()) ret.erase(last, ret.end());
1341 if (first != ret.begin()) ret.erase(ret.begin(), first);
1343 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1348 Value listaccounts(const Array& params, bool fHelp)
1350 if (fHelp || params.size() > 1)
1351 throw runtime_error(
1352 "listaccounts [minconf=1]\n"
1353 "Returns Object that has account names as keys, account balances as values.");
1356 if (params.size() > 0)
1357 nMinDepth = params[0].get_int();
1359 map<string, int64> mapAccountBalances;
1360 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1361 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1362 mapAccountBalances[entry.second] = 0;
1365 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1367 const CWalletTx& wtx = (*it).second;
1368 int64 nGeneratedImmature, nGeneratedMature, nFee;
1369 string strSentAccount;
1370 list<pair<CBitcoinAddress, int64> > listReceived;
1371 list<pair<CBitcoinAddress, int64> > listSent;
1372 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1373 mapAccountBalances[strSentAccount] -= nFee;
1374 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1375 mapAccountBalances[strSentAccount] -= s.second;
1376 if (wtx.GetDepthInMainChain() >= nMinDepth)
1378 mapAccountBalances[""] += nGeneratedMature;
1379 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1380 if (pwalletMain->mapAddressBook.count(r.first))
1381 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1383 mapAccountBalances[""] += r.second;
1387 list<CAccountingEntry> acentries;
1388 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1389 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1390 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1393 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1394 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1399 Value listsinceblock(const Array& params, bool fHelp)
1402 throw runtime_error(
1403 "listsinceblock [blockid] [target-confirmations]\n"
1404 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1406 CBlockIndex *pindex = NULL;
1407 int target_confirms = 1;
1409 if (params.size() > 0)
1411 uint256 blockId = 0;
1413 blockId.SetHex(params[0].get_str());
1414 pindex = CBlockLocator(blockId).GetBlockIndex();
1417 if (params.size() > 1)
1419 target_confirms = params[1].get_int();
1421 if (target_confirms < 1)
1422 throw JSONRPCError(-8, "Invalid parameter");
1425 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1429 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1431 CWalletTx tx = (*it).second;
1433 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1434 ListTransactions(tx, "*", 0, true, transactions);
1439 if (target_confirms == 1)
1442 lastblock = hashBestChain;
1446 int target_height = pindexBest->nHeight + 1 - target_confirms;
1449 for (block = pindexBest;
1450 block && block->nHeight > target_height;
1451 block = block->pprev) { }
1453 lastblock = block ? block->GetBlockHash() : 0;
1457 ret.push_back(Pair("transactions", transactions));
1458 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1463 Value gettransaction(const Array& params, bool fHelp)
1465 if (fHelp || params.size() != 1)
1466 throw runtime_error(
1467 "gettransaction <txid>\n"
1468 "Get detailed information about <txid>");
1471 hash.SetHex(params[0].get_str());
1475 if (!pwalletMain->mapWallet.count(hash))
1476 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1477 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1479 int64 nCredit = wtx.GetCredit();
1480 int64 nDebit = wtx.GetDebit();
1481 int64 nNet = nCredit - nDebit;
1482 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1484 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1486 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1488 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1491 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1492 entry.push_back(Pair("details", details));
1498 Value backupwallet(const Array& params, bool fHelp)
1500 if (fHelp || params.size() != 1)
1501 throw runtime_error(
1502 "backupwallet <destination>\n"
1503 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1505 string strDest = params[0].get_str();
1506 BackupWallet(*pwalletMain, strDest);
1512 Value keypoolrefill(const Array& params, bool fHelp)
1514 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1515 throw runtime_error(
1517 "Fills the keypool, requires wallet passphrase to be set.");
1518 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1519 throw runtime_error(
1521 "Fills the keypool.");
1523 if (pwalletMain->IsLocked())
1524 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1526 pwalletMain->TopUpKeyPool();
1528 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1529 throw JSONRPCError(-4, "Error refreshing keypool.");
1535 void ThreadTopUpKeyPool(void* parg)
1537 pwalletMain->TopUpKeyPool();
1540 void ThreadCleanWalletPassphrase(void* parg)
1542 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1544 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1546 if (nWalletUnlockTime == 0)
1548 nWalletUnlockTime = nMyWakeTime;
1552 if (nWalletUnlockTime==0)
1554 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1558 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1560 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1564 if (nWalletUnlockTime)
1566 nWalletUnlockTime = 0;
1567 pwalletMain->Lock();
1572 if (nWalletUnlockTime < nMyWakeTime)
1573 nWalletUnlockTime = nMyWakeTime;
1576 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1578 delete (int64*)parg;
1581 Value walletpassphrase(const Array& params, bool fHelp)
1583 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1584 throw runtime_error(
1585 "walletpassphrase <passphrase> <timeout>\n"
1586 "Stores the wallet decryption key in memory for <timeout> seconds.");
1589 if (!pwalletMain->IsCrypted())
1590 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1592 if (!pwalletMain->IsLocked())
1593 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1595 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1596 SecureString strWalletPass;
1597 strWalletPass.reserve(100);
1598 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1599 // Alternately, find a way to make params[0] mlock()'d to begin with.
1600 strWalletPass = params[0].get_str().c_str();
1602 if (strWalletPass.length() > 0)
1604 if (!pwalletMain->Unlock(strWalletPass))
1605 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1608 throw runtime_error(
1609 "walletpassphrase <passphrase> <timeout>\n"
1610 "Stores the wallet decryption key in memory for <timeout> seconds.");
1612 CreateThread(ThreadTopUpKeyPool, NULL);
1613 int64* pnSleepTime = new int64(params[1].get_int64());
1614 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1620 Value walletpassphrasechange(const Array& params, bool fHelp)
1622 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1623 throw runtime_error(
1624 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1625 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1628 if (!pwalletMain->IsCrypted())
1629 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1631 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1632 // Alternately, find a way to make params[0] mlock()'d to begin with.
1633 SecureString strOldWalletPass;
1634 strOldWalletPass.reserve(100);
1635 strOldWalletPass = params[0].get_str().c_str();
1637 SecureString strNewWalletPass;
1638 strNewWalletPass.reserve(100);
1639 strNewWalletPass = params[1].get_str().c_str();
1641 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1642 throw runtime_error(
1643 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1644 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1646 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1647 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1653 Value walletlock(const Array& params, bool fHelp)
1655 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1656 throw runtime_error(
1658 "Removes the wallet encryption key from memory, locking the wallet.\n"
1659 "After calling this method, you will need to call walletpassphrase again\n"
1660 "before being able to call any methods which require the wallet to be unlocked.");
1663 if (!pwalletMain->IsCrypted())
1664 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1667 LOCK(cs_nWalletUnlockTime);
1668 pwalletMain->Lock();
1669 nWalletUnlockTime = 0;
1676 Value encryptwallet(const Array& params, bool fHelp)
1678 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1679 throw runtime_error(
1680 "encryptwallet <passphrase>\n"
1681 "Encrypts the wallet with <passphrase>.");
1684 if (pwalletMain->IsCrypted())
1685 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1687 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1688 // Alternately, find a way to make params[0] mlock()'d to begin with.
1689 SecureString strWalletPass;
1690 strWalletPass.reserve(100);
1691 strWalletPass = params[0].get_str().c_str();
1693 if (strWalletPass.length() < 1)
1694 throw runtime_error(
1695 "encryptwallet <passphrase>\n"
1696 "Encrypts the wallet with <passphrase>.");
1698 if (!pwalletMain->EncryptWallet(strWalletPass))
1699 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1701 // BDB seems to have a bad habit of writing old data into
1702 // slack space in .dat files; that is bad if the old data is
1703 // unencrypted private keys. So:
1705 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1709 Value validateaddress(const Array& params, bool fHelp)
1711 if (fHelp || params.size() != 1)
1712 throw runtime_error(
1713 "validateaddress <bitcoinaddress>\n"
1714 "Return information about <bitcoinaddress>.");
1716 CBitcoinAddress address(params[0].get_str());
1717 bool isValid = address.IsValid();
1720 ret.push_back(Pair("isvalid", isValid));
1723 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1724 // version of the address:
1725 string currentAddress = address.ToString();
1726 ret.push_back(Pair("address", currentAddress));
1727 if (pwalletMain->HaveKey(address))
1729 ret.push_back(Pair("ismine", true));
1730 std::vector<unsigned char> vchPubKey;
1731 pwalletMain->GetPubKey(address, vchPubKey);
1732 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1734 key.SetPubKey(vchPubKey);
1735 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1737 else if (pwalletMain->HaveCScript(address.GetHash160()))
1739 ret.push_back(Pair("isscript", true));
1741 pwalletMain->GetCScript(address.GetHash160(), subscript);
1742 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1743 std::vector<CBitcoinAddress> addresses;
1744 txnouttype whichType;
1746 ExtractAddresses(subscript, whichType, addresses, nRequired);
1747 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1749 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1750 a.push_back(addr.ToString());
1751 ret.push_back(Pair("addresses", a));
1752 if (whichType == TX_MULTISIG)
1753 ret.push_back(Pair("sigsrequired", nRequired));
1756 ret.push_back(Pair("ismine", false));
1757 if (pwalletMain->mapAddressBook.count(address))
1758 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1763 Value getwork(const Array& params, bool fHelp)
1765 if (fHelp || params.size() > 1)
1766 throw runtime_error(
1768 "If [data] is not specified, returns formatted hash data to work on:\n"
1769 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1770 " \"data\" : block data\n"
1771 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1772 " \"target\" : little endian hash target\n"
1773 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1776 throw JSONRPCError(-9, "Bitcoin is not connected!");
1778 if (IsInitialBlockDownload())
1779 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1781 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1782 static mapNewBlock_t mapNewBlock;
1783 static vector<CBlock*> vNewBlock;
1784 static CReserveKey reservekey(pwalletMain);
1786 if (params.size() == 0)
1789 static unsigned int nTransactionsUpdatedLast;
1790 static CBlockIndex* pindexPrev;
1791 static int64 nStart;
1792 static CBlock* pblock;
1793 if (pindexPrev != pindexBest ||
1794 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1796 if (pindexPrev != pindexBest)
1798 // Deallocate old blocks since they're obsolete now
1799 mapNewBlock.clear();
1800 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1804 nTransactionsUpdatedLast = nTransactionsUpdated;
1805 pindexPrev = pindexBest;
1809 pblock = CreateNewBlock(reservekey);
1811 throw JSONRPCError(-7, "Out of memory");
1812 vNewBlock.push_back(pblock);
1816 pblock->UpdateTime(pindexPrev);
1819 // Update nExtraNonce
1820 static unsigned int nExtraNonce = 0;
1821 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1824 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1826 // Prebuild hash buffers
1830 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1832 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1835 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1836 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1837 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1838 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1844 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1845 if (vchData.size() != 128)
1846 throw JSONRPCError(-8, "Invalid parameter");
1847 CBlock* pdata = (CBlock*)&vchData[0];
1850 for (int i = 0; i < 128/4; i++)
1851 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1854 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1856 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1858 pblock->nTime = pdata->nTime;
1859 pblock->nNonce = pdata->nNonce;
1860 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1861 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1863 return CheckWork(pblock, *pwalletMain, reservekey);
1868 Value getmemorypool(const Array& params, bool fHelp)
1870 if (fHelp || params.size() > 1)
1871 throw runtime_error(
1872 "getmemorypool [data]\n"
1873 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1874 " \"version\" : block version\n"
1875 " \"previousblockhash\" : hash of current highest block\n"
1876 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1877 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1878 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1879 " \"time\" : timestamp appropriate for next block\n"
1880 " \"mintime\" : minimum timestamp appropriate for next block\n"
1881 " \"curtime\" : current timestamp\n"
1882 " \"bits\" : compressed target of next block\n"
1883 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1885 if (params.size() == 0)
1888 throw JSONRPCError(-9, "Bitcoin is not connected!");
1890 if (IsInitialBlockDownload())
1891 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1893 static CReserveKey reservekey(pwalletMain);
1896 static unsigned int nTransactionsUpdatedLast;
1897 static CBlockIndex* pindexPrev;
1898 static int64 nStart;
1899 static CBlock* pblock;
1900 if (pindexPrev != pindexBest ||
1901 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1903 nTransactionsUpdatedLast = nTransactionsUpdated;
1904 pindexPrev = pindexBest;
1910 pblock = CreateNewBlock(reservekey);
1912 throw JSONRPCError(-7, "Out of memory");
1916 pblock->UpdateTime(pindexPrev);
1920 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1927 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1931 result.push_back(Pair("version", pblock->nVersion));
1932 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1933 result.push_back(Pair("transactions", transactions));
1934 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1935 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1936 result.push_back(Pair("time", (int64_t)pblock->nTime));
1937 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1938 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1939 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1946 CDataStream ssBlock(ParseHex(params[0].get_str()));
1950 return ProcessBlock(NULL, &pblock);
1954 Value getblockhash(const Array& params, bool fHelp)
1956 if (fHelp || params.size() != 1)
1957 throw runtime_error(
1958 "getblockhash <index>\n"
1959 "Returns hash of block in best-block-chain at <index>.");
1961 int nHeight = params[0].get_int();
1962 if (nHeight < 0 || nHeight > nBestHeight)
1963 throw runtime_error("Block number out of range.");
1966 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1967 while (pblockindex->nHeight > nHeight)
1968 pblockindex = pblockindex->pprev;
1969 return pblockindex->phashBlock->GetHex();
1972 Value getblock(const Array& params, bool fHelp)
1974 if (fHelp || params.size() != 1)
1975 throw runtime_error(
1977 "Returns details of a block with given block-hash.");
1979 std::string strHash = params[0].get_str();
1980 uint256 hash(strHash);
1982 if (mapBlockIndex.count(hash) == 0)
1983 throw JSONRPCError(-5, "Block not found");
1986 CBlockIndex* pblockindex = mapBlockIndex[hash];
1987 block.ReadFromDisk(pblockindex, true);
1989 return blockToJSON(block, pblockindex);
2006 pair<string, rpcfn_type> pCallTable[] =
2008 make_pair("help", &help),
2009 make_pair("stop", &stop),
2010 make_pair("getblockcount", &getblockcount),
2011 make_pair("getblocknumber", &getblocknumber),
2012 make_pair("getconnectioncount", &getconnectioncount),
2013 make_pair("getdifficulty", &getdifficulty),
2014 make_pair("getgenerate", &getgenerate),
2015 make_pair("setgenerate", &setgenerate),
2016 make_pair("gethashespersec", &gethashespersec),
2017 make_pair("getinfo", &getinfo),
2018 make_pair("getmininginfo", &getmininginfo),
2019 make_pair("getnewaddress", &getnewaddress),
2020 make_pair("getaccountaddress", &getaccountaddress),
2021 make_pair("setaccount", &setaccount),
2022 make_pair("getaccount", &getaccount),
2023 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2024 make_pair("sendtoaddress", &sendtoaddress),
2025 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2026 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2027 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2028 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2029 make_pair("backupwallet", &backupwallet),
2030 make_pair("keypoolrefill", &keypoolrefill),
2031 make_pair("walletpassphrase", &walletpassphrase),
2032 make_pair("walletpassphrasechange", &walletpassphrasechange),
2033 make_pair("walletlock", &walletlock),
2034 make_pair("encryptwallet", &encryptwallet),
2035 make_pair("validateaddress", &validateaddress),
2036 make_pair("getbalance", &getbalance),
2037 make_pair("move", &movecmd),
2038 make_pair("sendfrom", &sendfrom),
2039 make_pair("sendmany", &sendmany),
2040 make_pair("addmultisigaddress", &addmultisigaddress),
2041 make_pair("getblock", &getblock),
2042 make_pair("getblockhash", &getblockhash),
2043 make_pair("gettransaction", &gettransaction),
2044 make_pair("listtransactions", &listtransactions),
2045 make_pair("signmessage", &signmessage),
2046 make_pair("verifymessage", &verifymessage),
2047 make_pair("getwork", &getwork),
2048 make_pair("listaccounts", &listaccounts),
2049 make_pair("settxfee", &settxfee),
2050 make_pair("getmemorypool", &getmemorypool),
2051 make_pair("listsinceblock", &listsinceblock),
2052 make_pair("dumpprivkey", &dumpprivkey),
2053 make_pair("importprivkey", &importprivkey)
2055 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2057 string pAllowInSafeMode[] =
2062 "getblocknumber", // deprecated
2063 "getconnectioncount",
2071 "getaccountaddress",
2073 "getaddressesbyaccount",
2082 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2090 // This ain't Apache. We're just using HTTP header for the length field
2091 // and to be compatible with other JSON-RPC implementations.
2094 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2097 s << "POST / HTTP/1.1\r\n"
2098 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2099 << "Host: 127.0.0.1\r\n"
2100 << "Content-Type: application/json\r\n"
2101 << "Content-Length: " << strMsg.size() << "\r\n"
2102 << "Connection: close\r\n"
2103 << "Accept: application/json\r\n";
2104 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2105 s << item.first << ": " << item.second << "\r\n";
2106 s << "\r\n" << strMsg;
2111 string rfc1123Time()
2116 struct tm* now_gmt = gmtime(&now);
2117 string locale(setlocale(LC_TIME, NULL));
2118 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2119 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2120 setlocale(LC_TIME, locale.c_str());
2121 return string(buffer);
2124 static string HTTPReply(int nStatus, const string& strMsg)
2127 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2129 "Server: bitcoin-json-rpc/%s\r\n"
2130 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2131 "Content-Type: text/html\r\n"
2132 "Content-Length: 296\r\n"
2134 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2135 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2138 "<TITLE>Error</TITLE>\r\n"
2139 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2141 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2142 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2143 const char *cStatus;
2144 if (nStatus == 200) cStatus = "OK";
2145 else if (nStatus == 400) cStatus = "Bad Request";
2146 else if (nStatus == 403) cStatus = "Forbidden";
2147 else if (nStatus == 404) cStatus = "Not Found";
2148 else if (nStatus == 500) cStatus = "Internal Server Error";
2151 "HTTP/1.1 %d %s\r\n"
2153 "Connection: close\r\n"
2154 "Content-Length: %d\r\n"
2155 "Content-Type: application/json\r\n"
2156 "Server: bitcoin-json-rpc/%s\r\n"
2161 rfc1123Time().c_str(),
2163 FormatFullVersion().c_str(),
2167 int ReadHTTPStatus(std::basic_istream<char>& stream)
2170 getline(stream, str);
2171 vector<string> vWords;
2172 boost::split(vWords, str, boost::is_any_of(" "));
2173 if (vWords.size() < 2)
2175 return atoi(vWords[1].c_str());
2178 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2184 std::getline(stream, str);
2185 if (str.empty() || str == "\r")
2187 string::size_type nColon = str.find(":");
2188 if (nColon != string::npos)
2190 string strHeader = str.substr(0, nColon);
2191 boost::trim(strHeader);
2192 boost::to_lower(strHeader);
2193 string strValue = str.substr(nColon+1);
2194 boost::trim(strValue);
2195 mapHeadersRet[strHeader] = strValue;
2196 if (strHeader == "content-length")
2197 nLen = atoi(strValue.c_str());
2203 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2205 mapHeadersRet.clear();
2209 int nStatus = ReadHTTPStatus(stream);
2212 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2213 if (nLen < 0 || nLen > MAX_SIZE)
2219 vector<char> vch(nLen);
2220 stream.read(&vch[0], nLen);
2221 strMessageRet = string(vch.begin(), vch.end());
2227 bool HTTPAuthorized(map<string, string>& mapHeaders)
2229 string strAuth = mapHeaders["authorization"];
2230 if (strAuth.substr(0,6) != "Basic ")
2232 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2233 string strUserPass = DecodeBase64(strUserPass64);
2234 return strUserPass == strRPCUserColonPass;
2238 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2239 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2240 // unspecified (HTTP errors and contents of 'error').
2242 // 1.0 spec: http://json-rpc.org/wiki/specification
2243 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2244 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2247 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2250 request.push_back(Pair("method", strMethod));
2251 request.push_back(Pair("params", params));
2252 request.push_back(Pair("id", id));
2253 return write_string(Value(request), false) + "\n";
2256 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2259 if (error.type() != null_type)
2260 reply.push_back(Pair("result", Value::null));
2262 reply.push_back(Pair("result", result));
2263 reply.push_back(Pair("error", error));
2264 reply.push_back(Pair("id", id));
2265 return write_string(Value(reply), false) + "\n";
2268 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2270 // Send error reply from json-rpc error object
2272 int code = find_value(objError, "code").get_int();
2273 if (code == -32600) nStatus = 400;
2274 else if (code == -32601) nStatus = 404;
2275 string strReply = JSONRPCReply(Value::null, objError, id);
2276 stream << HTTPReply(nStatus, strReply) << std::flush;
2279 bool ClientAllowed(const string& strAddress)
2281 if (strAddress == asio::ip::address_v4::loopback().to_string())
2283 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2284 BOOST_FOREACH(string strAllow, vAllow)
2285 if (WildcardMatch(strAddress, strAllow))
2291 // IOStream device that speaks SSL but can also speak non-SSL
2293 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2295 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2297 fUseSSL = fUseSSLIn;
2298 fNeedHandshake = fUseSSLIn;
2301 void handshake(ssl::stream_base::handshake_type role)
2303 if (!fNeedHandshake) return;
2304 fNeedHandshake = false;
2305 stream.handshake(role);
2307 std::streamsize read(char* s, std::streamsize n)
2309 handshake(ssl::stream_base::server); // HTTPS servers read first
2310 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2311 return stream.next_layer().read_some(asio::buffer(s, n));
2313 std::streamsize write(const char* s, std::streamsize n)
2315 handshake(ssl::stream_base::client); // HTTPS clients write first
2316 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2317 return asio::write(stream.next_layer(), asio::buffer(s, n));
2319 bool connect(const std::string& server, const std::string& port)
2321 ip::tcp::resolver resolver(stream.get_io_service());
2322 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2323 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2324 ip::tcp::resolver::iterator end;
2325 boost::system::error_code error = asio::error::host_not_found;
2326 while (error && endpoint_iterator != end)
2328 stream.lowest_layer().close();
2329 stream.lowest_layer().connect(*endpoint_iterator++, error);
2337 bool fNeedHandshake;
2342 void ThreadRPCServer(void* parg)
2344 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2347 vnThreadsRunning[THREAD_RPCSERVER]++;
2348 ThreadRPCServer2(parg);
2349 vnThreadsRunning[THREAD_RPCSERVER]--;
2351 catch (std::exception& e) {
2352 vnThreadsRunning[THREAD_RPCSERVER]--;
2353 PrintException(&e, "ThreadRPCServer()");
2355 vnThreadsRunning[THREAD_RPCSERVER]--;
2356 PrintException(NULL, "ThreadRPCServer()");
2358 printf("ThreadRPCServer exiting\n");
2361 void ThreadRPCServer2(void* parg)
2363 printf("ThreadRPCServer started\n");
2365 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2366 if (mapArgs["-rpcpassword"] == "")
2368 unsigned char rand_pwd[32];
2369 RAND_bytes(rand_pwd, 32);
2370 string strWhatAmI = "To use bitcoind";
2371 if (mapArgs.count("-server"))
2372 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2373 else if (mapArgs.count("-daemon"))
2374 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2375 ThreadSafeMessageBox(strprintf(
2376 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2377 "It is recommended you use the following random password:\n"
2378 "rpcuser=bitcoinrpc\n"
2380 "(you do not need to remember this password)\n"
2381 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2383 GetConfigFile().string().c_str(),
2384 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2385 _("Error"), wxOK | wxMODAL);
2390 bool fUseSSL = GetBoolArg("-rpcssl");
2391 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2393 asio::io_service io_service;
2394 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2395 ip::tcp::acceptor acceptor(io_service);
2398 acceptor.open(endpoint.protocol());
2399 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2400 acceptor.bind(endpoint);
2401 acceptor.listen(socket_base::max_connections);
2403 catch(boost::system::system_error &e)
2405 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2406 _("Error"), wxOK | wxMODAL);
2411 ssl::context context(io_service, ssl::context::sslv23);
2414 context.set_options(ssl::context::no_sslv2);
2416 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2417 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2418 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2419 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2421 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2422 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2423 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2424 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2426 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2427 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2432 // Accept connection
2433 SSLStream sslStream(io_service, context);
2434 SSLIOStreamDevice d(sslStream, fUseSSL);
2435 iostreams::stream<SSLIOStreamDevice> stream(d);
2437 ip::tcp::endpoint peer;
2438 vnThreadsRunning[THREAD_RPCSERVER]--;
2439 acceptor.accept(sslStream.lowest_layer(), peer);
2440 vnThreadsRunning[4]++;
2444 // Restrict callers by IP
2445 if (!ClientAllowed(peer.address().to_string()))
2447 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2449 stream << HTTPReply(403, "") << std::flush;
2453 map<string, string> mapHeaders;
2456 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2457 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2460 printf("ThreadRPCServer ReadHTTP timeout\n");
2464 // Check authorization
2465 if (mapHeaders.count("authorization") == 0)
2467 stream << HTTPReply(401, "") << std::flush;
2470 if (!HTTPAuthorized(mapHeaders))
2472 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2473 /* Deter brute-forcing short passwords.
2474 If this results in a DOS the user really
2475 shouldn't have their RPC port exposed.*/
2476 if (mapArgs["-rpcpassword"].size() < 20)
2479 stream << HTTPReply(401, "") << std::flush;
2483 Value id = Value::null;
2488 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2489 throw JSONRPCError(-32700, "Parse error");
2490 const Object& request = valRequest.get_obj();
2492 // Parse id now so errors from here on will have the id
2493 id = find_value(request, "id");
2496 Value valMethod = find_value(request, "method");
2497 if (valMethod.type() == null_type)
2498 throw JSONRPCError(-32600, "Missing method");
2499 if (valMethod.type() != str_type)
2500 throw JSONRPCError(-32600, "Method must be a string");
2501 string strMethod = valMethod.get_str();
2502 if (strMethod != "getwork" && strMethod != "getmemorypool")
2503 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2506 Value valParams = find_value(request, "params");
2508 if (valParams.type() == array_type)
2509 params = valParams.get_array();
2510 else if (valParams.type() == null_type)
2513 throw JSONRPCError(-32600, "Params must be an array");
2516 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2517 if (mi == mapCallTable.end())
2518 throw JSONRPCError(-32601, "Method not found");
2520 // Observe safe mode
2521 string strWarning = GetWarnings("rpc");
2522 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2523 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2530 LOCK2(cs_main, pwalletMain->cs_wallet);
2531 result = (*(*mi).second)(params, false);
2535 string strReply = JSONRPCReply(result, Value::null, id);
2536 stream << HTTPReply(200, strReply) << std::flush;
2538 catch (std::exception& e)
2540 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2543 catch (Object& objError)
2545 ErrorReply(stream, objError, id);
2547 catch (std::exception& e)
2549 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2557 Object CallRPC(const string& strMethod, const Array& params)
2559 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2560 throw runtime_error(strprintf(
2561 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2562 "If the file does not exist, create it with owner-readable-only file permissions."),
2563 GetConfigFile().string().c_str()));
2565 // Connect to localhost
2566 bool fUseSSL = GetBoolArg("-rpcssl");
2567 asio::io_service io_service;
2568 ssl::context context(io_service, ssl::context::sslv23);
2569 context.set_options(ssl::context::no_sslv2);
2570 SSLStream sslStream(io_service, context);
2571 SSLIOStreamDevice d(sslStream, fUseSSL);
2572 iostreams::stream<SSLIOStreamDevice> stream(d);
2573 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2574 throw runtime_error("couldn't connect to server");
2576 // HTTP basic authentication
2577 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2578 map<string, string> mapRequestHeaders;
2579 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2582 string strRequest = JSONRPCRequest(strMethod, params, 1);
2583 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2584 stream << strPost << std::flush;
2587 map<string, string> mapHeaders;
2589 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2591 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2592 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2593 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2594 else if (strReply.empty())
2595 throw runtime_error("no response from server");
2599 if (!read_string(strReply, valReply))
2600 throw runtime_error("couldn't parse reply from server");
2601 const Object& reply = valReply.get_obj();
2603 throw runtime_error("expected reply to have result, error and id properties");
2611 template<typename T>
2612 void ConvertTo(Value& value)
2614 if (value.type() == str_type)
2616 // reinterpret string as unquoted json value
2618 if (!read_string(value.get_str(), value2))
2619 throw runtime_error("type mismatch");
2620 value = value2.get_value<T>();
2624 value = value.get_value<T>();
2628 int CommandLineRPC(int argc, char *argv[])
2635 while (argc > 1 && IsSwitchChar(argv[1][0]))
2643 throw runtime_error("too few parameters");
2644 string strMethod = argv[1];
2646 // Parameters default to strings
2648 for (int i = 2; i < argc; i++)
2649 params.push_back(argv[i]);
2650 int n = params.size();
2653 // Special case non-string parameter types
2655 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2656 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2657 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2658 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2659 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2660 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2661 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2662 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2663 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2664 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2665 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2666 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2668 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2669 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2670 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2671 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2672 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2673 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2674 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2676 if (strMethod == "sendmany" && n > 1)
2678 string s = params[1].get_str();
2680 if (!read_string(s, v) || v.type() != obj_type)
2681 throw runtime_error("type mismatch");
2682 params[1] = v.get_obj();
2684 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2685 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2686 if (strMethod == "addmultisigaddress" && n > 1)
2688 string s = params[1].get_str();
2690 if (!read_string(s, v) || v.type() != array_type)
2691 throw runtime_error("type mismatch "+s);
2692 params[1] = v.get_array();
2696 Object reply = CallRPC(strMethod, params);
2699 const Value& result = find_value(reply, "result");
2700 const Value& error = find_value(reply, "error");
2702 if (error.type() != null_type)
2705 strPrint = "error: " + write_string(error, false);
2706 int code = find_value(error.get_obj(), "code").get_int();
2712 if (result.type() == null_type)
2714 else if (result.type() == str_type)
2715 strPrint = result.get_str();
2717 strPrint = write_string(result, true);
2720 catch (std::exception& e)
2722 strPrint = string("error: ") + e.what();
2727 PrintException(NULL, "CommandLineRPC()");
2732 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2741 int main(int argc, char *argv[])
2744 // Turn off microsoft heap dump noise
2745 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2746 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2748 setbuf(stdin, NULL);
2749 setbuf(stdout, NULL);
2750 setbuf(stderr, NULL);
2754 if (argc >= 2 && string(argv[1]) == "-server")
2756 printf("server ready\n");
2757 ThreadRPCServer(NULL);
2761 return CommandLineRPC(argc, argv);
2764 catch (std::exception& e) {
2765 PrintException(&e, "main()");
2767 PrintException(NULL, "main()");