1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
18 #include <boost/asio/ssl.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
41 static std::string strRPCUserColonPass;
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
49 Object JSONRPCError(int code, const string& message)
52 error.push_back(Pair("code", code));
53 error.push_back(Pair("message", message));
57 double GetDifficulty(const CBlockIndex* blockindex = NULL)
59 // Floating point number that is a multiple of the minimum difficulty,
60 // minimum difficulty = 1.0.
61 if (blockindex == NULL)
63 if (pindexBest == NULL)
66 blockindex = pindexBest;
69 int nShift = (blockindex->nBits >> 24) & 0xff;
72 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
89 int64 AmountFromValue(const Value& value)
91 double dAmount = value.get_real();
92 if (dAmount <= 0.0 || dAmount > 21000000.0)
93 throw JSONRPCError(-3, "Invalid amount");
94 int64 nAmount = roundint64(dAmount * COIN);
95 if (!MoneyRange(nAmount))
96 throw JSONRPCError(-3, "Invalid amount");
100 Value ValueFromAmount(int64 amount)
102 return (double)amount / (double)COIN;
106 HexBits(unsigned int nBits)
112 uBits.nBits = htonl((int32_t)nBits);
113 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
116 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
118 int confirms = wtx.GetDepthInMainChain();
119 entry.push_back(Pair("confirmations", confirms));
122 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
123 entry.push_back(Pair("blockindex", wtx.nIndex));
125 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
126 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
127 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
128 entry.push_back(Pair(item.first, item.second));
131 string AccountFromValue(const Value& value)
133 string strAccount = value.get_str();
134 if (strAccount == "*")
135 throw JSONRPCError(-11, "Invalid account name");
139 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
142 result.push_back(Pair("hash", block.GetHash().GetHex()));
143 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
144 result.push_back(Pair("height", blockindex->nHeight));
145 result.push_back(Pair("version", block.nVersion));
146 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
147 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
148 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
149 result.push_back(Pair("bits", HexBits(block.nBits)));
150 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
152 BOOST_FOREACH (const CTransaction&tx, block.vtx)
153 txhashes.push_back(tx.GetHash().GetHex());
154 result.push_back(Pair("tx", txhashes));
156 if (blockindex->pprev)
157 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
158 if (blockindex->pnext)
159 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
166 /// Note: This interface may still be subject to change.
170 Value help(const Array& params, bool fHelp)
172 if (fHelp || params.size() > 1)
175 "List commands, or get help for a command.");
178 if (params.size() > 0)
179 strCommand = params[0].get_str();
182 set<rpcfn_type> setDone;
183 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
185 string strMethod = (*mi).first;
186 // We already filter duplicates, but these deprecated screw up the sort order
187 if (strMethod == "getamountreceived" ||
188 strMethod == "getallreceived" ||
189 strMethod == "getblocknumber" || // deprecated
190 (strMethod.find("label") != string::npos))
192 if (strCommand != "" && strMethod != strCommand)
197 rpcfn_type pfn = (*mi).second;
198 if (setDone.insert(pfn).second)
199 (*pfn)(params, true);
201 catch (std::exception& e)
203 // Help text is returned in an exception
204 string strHelp = string(e.what());
205 if (strCommand == "")
206 if (strHelp.find('\n') != -1)
207 strHelp = strHelp.substr(0, strHelp.find('\n'));
208 strRet += strHelp + "\n";
212 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
213 strRet = strRet.substr(0,strRet.size()-1);
218 Value stop(const Array& params, bool fHelp)
220 if (fHelp || params.size() != 0)
223 "Stop bitcoin server.");
224 // Shutdown will take long enough that the response should get back
226 return "bitcoin server stopping";
230 Value getblockcount(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Returns the number of blocks in the longest block chain.");
242 Value getblocknumber(const Array& params, bool fHelp)
244 if (fHelp || params.size() != 0)
247 "Deprecated. Use getblockcount.");
253 Value getconnectioncount(const Array& params, bool fHelp)
255 if (fHelp || params.size() != 0)
257 "getconnectioncount\n"
258 "Returns the number of connections to other nodes.");
260 return (int)vNodes.size();
264 Value getdifficulty(const Array& params, bool fHelp)
266 if (fHelp || params.size() != 0)
269 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
271 return GetDifficulty();
275 Value getgenerate(const Array& params, bool fHelp)
277 if (fHelp || params.size() != 0)
280 "Returns true or false.");
282 return GetBoolArg("-gen");
286 Value setgenerate(const Array& params, bool fHelp)
288 if (fHelp || params.size() < 1 || params.size() > 2)
290 "setgenerate <generate> [genproclimit]\n"
291 "<generate> is true or false to turn generation on or off.\n"
292 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
294 bool fGenerate = true;
295 if (params.size() > 0)
296 fGenerate = params[0].get_bool();
298 if (params.size() > 1)
300 int nGenProcLimit = params[1].get_int();
301 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
302 if (nGenProcLimit == 0)
305 mapArgs["-gen"] = (fGenerate ? "1" : "0");
307 GenerateBitcoins(fGenerate, pwalletMain);
312 Value gethashespersec(const Array& params, bool fHelp)
314 if (fHelp || params.size() != 0)
317 "Returns a recent hashes per second performance measurement while generating.");
319 if (GetTimeMillis() - nHPSTimerStart > 8000)
320 return (boost::int64_t)0;
321 return (boost::int64_t)dHashesPerSec;
325 Value getinfo(const Array& params, bool fHelp)
327 if (fHelp || params.size() != 0)
330 "Returns an object containing various state info.");
333 obj.push_back(Pair("version", (int)CLIENT_VERSION));
334 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
335 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
336 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
337 obj.push_back(Pair("blocks", (int)nBestHeight));
338 obj.push_back(Pair("connections", (int)vNodes.size()));
339 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
340 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
341 obj.push_back(Pair("testnet", fTestNet));
342 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
343 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
344 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
345 if (pwalletMain->IsCrypted())
346 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
347 obj.push_back(Pair("errors", GetWarnings("statusbar")));
352 Value getmininginfo(const Array& params, bool fHelp)
354 if (fHelp || params.size() != 0)
357 "Returns an object containing mining-related information.");
360 obj.push_back(Pair("blocks", (int)nBestHeight));
361 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
362 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
363 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
364 obj.push_back(Pair("errors", GetWarnings("statusbar")));
365 obj.push_back(Pair("generate", GetBoolArg("-gen")));
366 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
367 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
368 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
369 obj.push_back(Pair("testnet", fTestNet));
374 Value getnewaddress(const Array& params, bool fHelp)
376 if (fHelp || params.size() > 1)
378 "getnewaddress [account]\n"
379 "Returns a new bitcoin address for receiving payments. "
380 "If [account] is specified (recommended), it is added to the address book "
381 "so payments received with the address will be credited to [account].");
383 // Parse the account first so we don't generate a key if there's an error
385 if (params.size() > 0)
386 strAccount = AccountFromValue(params[0]);
388 if (!pwalletMain->IsLocked())
389 pwalletMain->TopUpKeyPool();
391 // Generate a new key that is added to wallet
392 std::vector<unsigned char> newKey;
393 if (!pwalletMain->GetKeyFromPool(newKey, false))
394 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
395 CBitcoinAddress address(newKey);
397 pwalletMain->SetAddressBookName(address, strAccount);
399 return address.ToString();
403 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
405 CWalletDB walletdb(pwalletMain->strWalletFile);
408 walletdb.ReadAccount(strAccount, account);
410 bool bKeyUsed = false;
412 // Check if the current key has been used
413 if (!account.vchPubKey.empty())
415 CScript scriptPubKey;
416 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
417 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
418 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
421 const CWalletTx& wtx = (*it).second;
422 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
423 if (txout.scriptPubKey == scriptPubKey)
428 // Generate a new key
429 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
431 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
432 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
434 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
435 walletdb.WriteAccount(strAccount, account);
438 return CBitcoinAddress(account.vchPubKey);
441 Value getaccountaddress(const Array& params, bool fHelp)
443 if (fHelp || params.size() != 1)
445 "getaccountaddress <account>\n"
446 "Returns the current bitcoin address for receiving payments to this account.");
448 // Parse the account first so we don't generate a key if there's an error
449 string strAccount = AccountFromValue(params[0]);
453 ret = GetAccountAddress(strAccount).ToString();
460 Value setaccount(const Array& params, bool fHelp)
462 if (fHelp || params.size() < 1 || params.size() > 2)
464 "setaccount <bitcoinaddress> <account>\n"
465 "Sets the account associated with the given address.");
467 CBitcoinAddress address(params[0].get_str());
468 if (!address.IsValid())
469 throw JSONRPCError(-5, "Invalid bitcoin address");
473 if (params.size() > 1)
474 strAccount = AccountFromValue(params[1]);
476 // Detect when changing the account of an address that is the 'unused current key' of another account:
477 if (pwalletMain->mapAddressBook.count(address))
479 string strOldAccount = pwalletMain->mapAddressBook[address];
480 if (address == GetAccountAddress(strOldAccount))
481 GetAccountAddress(strOldAccount, true);
484 pwalletMain->SetAddressBookName(address, strAccount);
490 Value getaccount(const Array& params, bool fHelp)
492 if (fHelp || params.size() != 1)
494 "getaccount <bitcoinaddress>\n"
495 "Returns the account associated with the given address.");
497 CBitcoinAddress address(params[0].get_str());
498 if (!address.IsValid())
499 throw JSONRPCError(-5, "Invalid bitcoin address");
502 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
503 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
504 strAccount = (*mi).second;
509 Value getaddressesbyaccount(const Array& params, bool fHelp)
511 if (fHelp || params.size() != 1)
513 "getaddressesbyaccount <account>\n"
514 "Returns the list of addresses for the given account.");
516 string strAccount = AccountFromValue(params[0]);
518 // Find all addresses that have the given account
520 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
522 const CBitcoinAddress& address = item.first;
523 const string& strName = item.second;
524 if (strName == strAccount)
525 ret.push_back(address.ToString());
530 Value settxfee(const Array& params, bool fHelp)
532 if (fHelp || params.size() < 1 || params.size() > 1)
534 "settxfee <amount>\n"
535 "<amount> is a real and is rounded to the nearest 0.00000001");
539 if (params[0].get_real() != 0.0)
540 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
542 nTransactionFee = nAmount;
546 Value sendtoaddress(const Array& params, bool fHelp)
548 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
550 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
551 "<amount> is a real and is rounded to the nearest 0.00000001\n"
552 "requires wallet passphrase to be set with walletpassphrase first");
553 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
555 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
556 "<amount> is a real and is rounded to the nearest 0.00000001");
558 CBitcoinAddress address(params[0].get_str());
559 if (!address.IsValid())
560 throw JSONRPCError(-5, "Invalid bitcoin address");
563 int64 nAmount = AmountFromValue(params[1]);
567 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
568 wtx.mapValue["comment"] = params[2].get_str();
569 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
570 wtx.mapValue["to"] = params[3].get_str();
572 if (pwalletMain->IsLocked())
573 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
575 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
577 throw JSONRPCError(-4, strError);
579 return wtx.GetHash().GetHex();
582 Value signmessage(const Array& params, bool fHelp)
584 if (fHelp || params.size() != 2)
586 "signmessage <bitcoinaddress> <message>\n"
587 "Sign a message with the private key of an address");
589 if (pwalletMain->IsLocked())
590 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
592 string strAddress = params[0].get_str();
593 string strMessage = params[1].get_str();
595 CBitcoinAddress addr(strAddress);
597 throw JSONRPCError(-3, "Invalid address");
600 if (!pwalletMain->GetKey(addr, key))
601 throw JSONRPCError(-4, "Private key not available");
603 CDataStream ss(SER_GETHASH);
604 ss << strMessageMagic;
607 vector<unsigned char> vchSig;
608 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
609 throw JSONRPCError(-5, "Sign failed");
611 return EncodeBase64(&vchSig[0], vchSig.size());
614 Value verifymessage(const Array& params, bool fHelp)
616 if (fHelp || params.size() != 3)
618 "verifymessage <bitcoinaddress> <signature> <message>\n"
619 "Verify a signed message");
621 string strAddress = params[0].get_str();
622 string strSign = params[1].get_str();
623 string strMessage = params[2].get_str();
625 CBitcoinAddress addr(strAddress);
627 throw JSONRPCError(-3, "Invalid address");
629 bool fInvalid = false;
630 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
633 throw JSONRPCError(-5, "Malformed base64 encoding");
635 CDataStream ss(SER_GETHASH);
636 ss << strMessageMagic;
640 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
643 return (CBitcoinAddress(key.GetPubKey()) == addr);
647 Value getreceivedbyaddress(const Array& params, bool fHelp)
649 if (fHelp || params.size() < 1 || params.size() > 2)
651 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
652 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
655 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
656 CScript scriptPubKey;
657 if (!address.IsValid())
658 throw JSONRPCError(-5, "Invalid bitcoin address");
659 scriptPubKey.SetBitcoinAddress(address);
660 if (!IsMine(*pwalletMain,scriptPubKey))
663 // Minimum confirmations
665 if (params.size() > 1)
666 nMinDepth = params[1].get_int();
670 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
672 const CWalletTx& wtx = (*it).second;
673 if (wtx.IsCoinBase() || !wtx.IsFinal())
676 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
677 if (txout.scriptPubKey == scriptPubKey)
678 if (wtx.GetDepthInMainChain() >= nMinDepth)
679 nAmount += txout.nValue;
682 return ValueFromAmount(nAmount);
686 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
688 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
690 const CBitcoinAddress& address = item.first;
691 const string& strName = item.second;
692 if (strName == strAccount)
693 setAddress.insert(address);
698 Value getreceivedbyaccount(const Array& params, bool fHelp)
700 if (fHelp || params.size() < 1 || params.size() > 2)
702 "getreceivedbyaccount <account> [minconf=1]\n"
703 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
705 // Minimum confirmations
707 if (params.size() > 1)
708 nMinDepth = params[1].get_int();
710 // Get the set of pub keys assigned to account
711 string strAccount = AccountFromValue(params[0]);
712 set<CBitcoinAddress> setAddress;
713 GetAccountAddresses(strAccount, setAddress);
717 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
719 const CWalletTx& wtx = (*it).second;
720 if (wtx.IsCoinBase() || !wtx.IsFinal())
723 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
725 CBitcoinAddress address;
726 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
727 if (wtx.GetDepthInMainChain() >= nMinDepth)
728 nAmount += txout.nValue;
732 return (double)nAmount / (double)COIN;
736 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
740 // Tally wallet transactions
741 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
743 const CWalletTx& wtx = (*it).second;
747 int64 nGenerated, nReceived, nSent, nFee;
748 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
750 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
751 nBalance += nReceived;
752 nBalance += nGenerated - nSent - nFee;
755 // Tally internal accounting entries
756 nBalance += walletdb.GetAccountCreditDebit(strAccount);
761 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
763 CWalletDB walletdb(pwalletMain->strWalletFile);
764 return GetAccountBalance(walletdb, strAccount, nMinDepth);
768 Value getbalance(const Array& params, bool fHelp)
770 if (fHelp || params.size() > 2)
772 "getbalance [account] [minconf=1]\n"
773 "If [account] is not specified, returns the server's total available balance.\n"
774 "If [account] is specified, returns the balance in the account.");
776 if (params.size() == 0)
777 return ValueFromAmount(pwalletMain->GetBalance());
780 if (params.size() > 1)
781 nMinDepth = params[1].get_int();
783 if (params[0].get_str() == "*") {
784 // Calculate total balance a different way from GetBalance()
785 // (GetBalance() sums up all unspent TxOuts)
786 // getbalance and getbalance '*' should always return the same number.
788 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
790 const CWalletTx& wtx = (*it).second;
794 int64 allGeneratedImmature, allGeneratedMature, allFee;
795 allGeneratedImmature = allGeneratedMature = allFee = 0;
796 string strSentAccount;
797 list<pair<CBitcoinAddress, int64> > listReceived;
798 list<pair<CBitcoinAddress, int64> > listSent;
799 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
800 if (wtx.GetDepthInMainChain() >= nMinDepth)
801 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
802 nBalance += r.second;
803 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
804 nBalance -= r.second;
806 nBalance += allGeneratedMature;
808 return ValueFromAmount(nBalance);
811 string strAccount = AccountFromValue(params[0]);
813 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
815 return ValueFromAmount(nBalance);
819 Value movecmd(const Array& params, bool fHelp)
821 if (fHelp || params.size() < 3 || params.size() > 5)
823 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
824 "Move from one account in your wallet to another.");
826 string strFrom = AccountFromValue(params[0]);
827 string strTo = AccountFromValue(params[1]);
828 int64 nAmount = AmountFromValue(params[2]);
829 if (params.size() > 3)
830 // unused parameter, used to be nMinDepth, keep type-checking it though
831 (void)params[3].get_int();
833 if (params.size() > 4)
834 strComment = params[4].get_str();
836 CWalletDB walletdb(pwalletMain->strWalletFile);
839 int64 nNow = GetAdjustedTime();
842 CAccountingEntry debit;
843 debit.strAccount = strFrom;
844 debit.nCreditDebit = -nAmount;
846 debit.strOtherAccount = strTo;
847 debit.strComment = strComment;
848 walletdb.WriteAccountingEntry(debit);
851 CAccountingEntry credit;
852 credit.strAccount = strTo;
853 credit.nCreditDebit = nAmount;
855 credit.strOtherAccount = strFrom;
856 credit.strComment = strComment;
857 walletdb.WriteAccountingEntry(credit);
859 walletdb.TxnCommit();
865 Value sendfrom(const Array& params, bool fHelp)
867 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
869 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
870 "<amount> is a real and is rounded to the nearest 0.00000001\n"
871 "requires wallet passphrase to be set with walletpassphrase first");
872 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
874 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
875 "<amount> is a real and is rounded to the nearest 0.00000001");
877 string strAccount = AccountFromValue(params[0]);
878 CBitcoinAddress address(params[1].get_str());
879 if (!address.IsValid())
880 throw JSONRPCError(-5, "Invalid bitcoin address");
881 int64 nAmount = AmountFromValue(params[2]);
883 if (params.size() > 3)
884 nMinDepth = params[3].get_int();
887 wtx.strFromAccount = strAccount;
888 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
889 wtx.mapValue["comment"] = params[4].get_str();
890 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
891 wtx.mapValue["to"] = params[5].get_str();
893 if (pwalletMain->IsLocked())
894 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
897 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
898 if (nAmount > nBalance)
899 throw JSONRPCError(-6, "Account has insufficient funds");
902 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
904 throw JSONRPCError(-4, strError);
906 return wtx.GetHash().GetHex();
910 Value sendmany(const Array& params, bool fHelp)
912 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
914 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
915 "amounts are double-precision floating point numbers\n"
916 "requires wallet passphrase to be set with walletpassphrase first");
917 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
919 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
920 "amounts are double-precision floating point numbers");
922 string strAccount = AccountFromValue(params[0]);
923 Object sendTo = params[1].get_obj();
925 if (params.size() > 2)
926 nMinDepth = params[2].get_int();
929 wtx.strFromAccount = strAccount;
930 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
931 wtx.mapValue["comment"] = params[3].get_str();
933 set<CBitcoinAddress> setAddress;
934 vector<pair<CScript, int64> > vecSend;
936 int64 totalAmount = 0;
937 BOOST_FOREACH(const Pair& s, sendTo)
939 CBitcoinAddress address(s.name_);
940 if (!address.IsValid())
941 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
943 if (setAddress.count(address))
944 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
945 setAddress.insert(address);
947 CScript scriptPubKey;
948 scriptPubKey.SetBitcoinAddress(address);
949 int64 nAmount = AmountFromValue(s.value_);
950 totalAmount += nAmount;
952 vecSend.push_back(make_pair(scriptPubKey, nAmount));
955 if (pwalletMain->IsLocked())
956 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
959 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
960 if (totalAmount > nBalance)
961 throw JSONRPCError(-6, "Account has insufficient funds");
964 CReserveKey keyChange(pwalletMain);
965 int64 nFeeRequired = 0;
966 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
969 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
970 throw JSONRPCError(-6, "Insufficient funds");
971 throw JSONRPCError(-4, "Transaction creation failed");
973 if (!pwalletMain->CommitTransaction(wtx, keyChange))
974 throw JSONRPCError(-4, "Transaction commit failed");
976 return wtx.GetHash().GetHex();
979 Value addmultisigaddress(const Array& params, bool fHelp)
981 if (fHelp || params.size() < 2 || params.size() > 3)
983 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
984 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
985 "each key is a bitcoin address or hex-encoded public key\n"
986 "If [account] is specified, assign address to [account].";
987 throw runtime_error(msg);
990 int nRequired = params[0].get_int();
991 const Array& keys = params[1].get_array();
993 if (params.size() > 2)
994 strAccount = AccountFromValue(params[2]);
996 // Gather public keys
997 if (nRequired < 1 || keys.size() < nRequired)
999 strprintf("wrong number of keys"
1000 "(got %d, need at least %d)", keys.size(), nRequired));
1001 std::vector<CKey> pubkeys;
1002 pubkeys.resize(keys.size());
1003 for (int i = 0; i < keys.size(); i++)
1005 const std::string& ks = keys[i].get_str();
1007 // Case 1: bitcoin address and we have full public key:
1008 CBitcoinAddress address(ks);
1009 if (address.IsValid())
1011 if (address.IsScript())
1012 throw runtime_error(
1013 strprintf("%s is a pay-to-script address",ks.c_str()));
1014 std::vector<unsigned char> vchPubKey;
1015 if (!pwalletMain->GetPubKey(address, vchPubKey))
1016 throw runtime_error(
1017 strprintf("no full public key for address %s",ks.c_str()));
1018 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1019 throw runtime_error(" Invalid public key: "+ks);
1022 // Case 2: hex public key
1025 vector<unsigned char> vchPubKey = ParseHex(ks);
1026 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1027 throw runtime_error(" Invalid public key: "+ks);
1031 throw runtime_error(" Invalid public key: "+ks);
1035 // Construct using pay-to-script-hash:
1037 inner.SetMultisig(nRequired, pubkeys);
1039 uint160 scriptHash = Hash160(inner);
1040 CScript scriptPubKey;
1041 scriptPubKey.SetPayToScriptHash(inner);
1042 pwalletMain->AddCScript(inner);
1043 CBitcoinAddress address;
1044 address.SetScriptHash160(scriptHash);
1046 pwalletMain->SetAddressBookName(address, strAccount);
1047 return address.ToString();
1058 nConf = std::numeric_limits<int>::max();
1062 Value ListReceived(const Array& params, bool fByAccounts)
1064 // Minimum confirmations
1066 if (params.size() > 0)
1067 nMinDepth = params[0].get_int();
1069 // Whether to include empty accounts
1070 bool fIncludeEmpty = false;
1071 if (params.size() > 1)
1072 fIncludeEmpty = params[1].get_bool();
1075 map<CBitcoinAddress, tallyitem> mapTally;
1076 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1078 const CWalletTx& wtx = (*it).second;
1080 if (wtx.IsCoinBase() || !wtx.IsFinal())
1083 int nDepth = wtx.GetDepthInMainChain();
1084 if (nDepth < nMinDepth)
1087 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1089 CBitcoinAddress address;
1090 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1093 tallyitem& item = mapTally[address];
1094 item.nAmount += txout.nValue;
1095 item.nConf = min(item.nConf, nDepth);
1101 map<string, tallyitem> mapAccountTally;
1102 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1104 const CBitcoinAddress& address = item.first;
1105 const string& strAccount = item.second;
1106 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1107 if (it == mapTally.end() && !fIncludeEmpty)
1111 int nConf = std::numeric_limits<int>::max();
1112 if (it != mapTally.end())
1114 nAmount = (*it).second.nAmount;
1115 nConf = (*it).second.nConf;
1120 tallyitem& item = mapAccountTally[strAccount];
1121 item.nAmount += nAmount;
1122 item.nConf = min(item.nConf, nConf);
1127 obj.push_back(Pair("address", address.ToString()));
1128 obj.push_back(Pair("account", strAccount));
1129 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1130 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1137 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1139 int64 nAmount = (*it).second.nAmount;
1140 int nConf = (*it).second.nConf;
1142 obj.push_back(Pair("account", (*it).first));
1143 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1144 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1152 Value listreceivedbyaddress(const Array& params, bool fHelp)
1154 if (fHelp || params.size() > 2)
1155 throw runtime_error(
1156 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1157 "[minconf] is the minimum number of confirmations before payments are included.\n"
1158 "[includeempty] whether to include addresses that haven't received any payments.\n"
1159 "Returns an array of objects containing:\n"
1160 " \"address\" : receiving address\n"
1161 " \"account\" : the account of the receiving address\n"
1162 " \"amount\" : total amount received by the address\n"
1163 " \"confirmations\" : number of confirmations of the most recent transaction included");
1165 return ListReceived(params, false);
1168 Value listreceivedbyaccount(const Array& params, bool fHelp)
1170 if (fHelp || params.size() > 2)
1171 throw runtime_error(
1172 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1173 "[minconf] is the minimum number of confirmations before payments are included.\n"
1174 "[includeempty] whether to include accounts that haven't received any payments.\n"
1175 "Returns an array of objects containing:\n"
1176 " \"account\" : the account of the receiving addresses\n"
1177 " \"amount\" : total amount received by addresses with this account\n"
1178 " \"confirmations\" : number of confirmations of the most recent transaction included");
1180 return ListReceived(params, true);
1183 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1185 int64 nGeneratedImmature, nGeneratedMature, nFee;
1186 string strSentAccount;
1187 list<pair<CBitcoinAddress, int64> > listReceived;
1188 list<pair<CBitcoinAddress, int64> > listSent;
1190 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1192 bool fAllAccounts = (strAccount == string("*"));
1194 // Generated blocks assigned to account ""
1195 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1198 entry.push_back(Pair("account", string("")));
1199 if (nGeneratedImmature)
1201 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1202 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1206 entry.push_back(Pair("category", "generate"));
1207 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1210 WalletTxToJSON(wtx, entry);
1211 ret.push_back(entry);
1215 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1217 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1220 entry.push_back(Pair("account", strSentAccount));
1221 entry.push_back(Pair("address", s.first.ToString()));
1222 entry.push_back(Pair("category", "send"));
1223 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1224 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1226 WalletTxToJSON(wtx, entry);
1227 ret.push_back(entry);
1232 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1233 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1236 if (pwalletMain->mapAddressBook.count(r.first))
1237 account = pwalletMain->mapAddressBook[r.first];
1238 if (fAllAccounts || (account == strAccount))
1241 entry.push_back(Pair("account", account));
1242 entry.push_back(Pair("address", r.first.ToString()));
1243 entry.push_back(Pair("category", "receive"));
1244 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1246 WalletTxToJSON(wtx, entry);
1247 ret.push_back(entry);
1252 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1254 bool fAllAccounts = (strAccount == string("*"));
1256 if (fAllAccounts || acentry.strAccount == strAccount)
1259 entry.push_back(Pair("account", acentry.strAccount));
1260 entry.push_back(Pair("category", "move"));
1261 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1262 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1263 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1264 entry.push_back(Pair("comment", acentry.strComment));
1265 ret.push_back(entry);
1269 Value listtransactions(const Array& params, bool fHelp)
1271 if (fHelp || params.size() > 3)
1272 throw runtime_error(
1273 "listtransactions [account] [count=10] [from=0]\n"
1274 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1276 string strAccount = "*";
1277 if (params.size() > 0)
1278 strAccount = params[0].get_str();
1280 if (params.size() > 1)
1281 nCount = params[1].get_int();
1283 if (params.size() > 2)
1284 nFrom = params[2].get_int();
1287 CWalletDB walletdb(pwalletMain->strWalletFile);
1289 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1290 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1291 typedef multimap<int64, TxPair > TxItems;
1294 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1296 CWalletTx* wtx = &((*it).second);
1297 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1299 list<CAccountingEntry> acentries;
1300 walletdb.ListAccountCreditDebit(strAccount, acentries);
1301 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1303 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1306 // Now: iterate backwards until we have nCount items to return:
1307 TxItems::reverse_iterator it = txByTime.rbegin();
1308 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1309 for (; it != txByTime.rend(); ++it)
1311 CWalletTx *const pwtx = (*it).second.first;
1313 ListTransactions(*pwtx, strAccount, 0, true, ret);
1314 CAccountingEntry *const pacentry = (*it).second.second;
1316 AcentryToJSON(*pacentry, strAccount, ret);
1318 if (ret.size() >= nCount) break;
1320 // ret is now newest to oldest
1322 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1323 if (ret.size() > nCount)
1325 Array::iterator last = ret.begin();
1326 std::advance(last, nCount);
1327 ret.erase(last, ret.end());
1329 std::reverse(ret.begin(), ret.end()); // oldest to newest
1334 Value listaccounts(const Array& params, bool fHelp)
1336 if (fHelp || params.size() > 1)
1337 throw runtime_error(
1338 "listaccounts [minconf=1]\n"
1339 "Returns Object that has account names as keys, account balances as values.");
1342 if (params.size() > 0)
1343 nMinDepth = params[0].get_int();
1345 map<string, int64> mapAccountBalances;
1346 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1347 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1348 mapAccountBalances[entry.second] = 0;
1351 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1353 const CWalletTx& wtx = (*it).second;
1354 int64 nGeneratedImmature, nGeneratedMature, nFee;
1355 string strSentAccount;
1356 list<pair<CBitcoinAddress, int64> > listReceived;
1357 list<pair<CBitcoinAddress, int64> > listSent;
1358 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1359 mapAccountBalances[strSentAccount] -= nFee;
1360 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1361 mapAccountBalances[strSentAccount] -= s.second;
1362 if (wtx.GetDepthInMainChain() >= nMinDepth)
1364 mapAccountBalances[""] += nGeneratedMature;
1365 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1366 if (pwalletMain->mapAddressBook.count(r.first))
1367 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1369 mapAccountBalances[""] += r.second;
1373 list<CAccountingEntry> acentries;
1374 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1375 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1376 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1379 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1380 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1385 Value listsinceblock(const Array& params, bool fHelp)
1388 throw runtime_error(
1389 "listsinceblock [blockid] [target-confirmations]\n"
1390 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1392 CBlockIndex *pindex = NULL;
1393 int target_confirms = 1;
1395 if (params.size() > 0)
1397 uint256 blockId = 0;
1399 blockId.SetHex(params[0].get_str());
1400 pindex = CBlockLocator(blockId).GetBlockIndex();
1403 if (params.size() > 1)
1405 target_confirms = params[1].get_int();
1407 if (target_confirms < 1)
1408 throw JSONRPCError(-8, "Invalid parameter");
1411 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1415 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1417 CWalletTx tx = (*it).second;
1419 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1420 ListTransactions(tx, "*", 0, true, transactions);
1425 if (target_confirms == 1)
1428 lastblock = hashBestChain;
1432 int target_height = pindexBest->nHeight + 1 - target_confirms;
1435 for (block = pindexBest;
1436 block && block->nHeight > target_height;
1437 block = block->pprev) { }
1439 lastblock = block ? block->GetBlockHash() : 0;
1443 ret.push_back(Pair("transactions", transactions));
1444 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1449 Value gettransaction(const Array& params, bool fHelp)
1451 if (fHelp || params.size() != 1)
1452 throw runtime_error(
1453 "gettransaction <txid>\n"
1454 "Get detailed information about <txid>");
1457 hash.SetHex(params[0].get_str());
1461 if (!pwalletMain->mapWallet.count(hash))
1462 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1463 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1465 int64 nCredit = wtx.GetCredit();
1466 int64 nDebit = wtx.GetDebit();
1467 int64 nNet = nCredit - nDebit;
1468 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1470 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1472 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1474 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1477 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1478 entry.push_back(Pair("details", details));
1484 Value backupwallet(const Array& params, bool fHelp)
1486 if (fHelp || params.size() != 1)
1487 throw runtime_error(
1488 "backupwallet <destination>\n"
1489 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1491 string strDest = params[0].get_str();
1492 BackupWallet(*pwalletMain, strDest);
1498 Value keypoolrefill(const Array& params, bool fHelp)
1500 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1501 throw runtime_error(
1503 "Fills the keypool, requires wallet passphrase to be set.");
1504 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1505 throw runtime_error(
1507 "Fills the keypool.");
1509 if (pwalletMain->IsLocked())
1510 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1512 pwalletMain->TopUpKeyPool();
1514 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1515 throw JSONRPCError(-4, "Error refreshing keypool.");
1521 void ThreadTopUpKeyPool(void* parg)
1523 pwalletMain->TopUpKeyPool();
1526 void ThreadCleanWalletPassphrase(void* parg)
1528 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1530 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1532 if (nWalletUnlockTime == 0)
1534 nWalletUnlockTime = nMyWakeTime;
1538 if (nWalletUnlockTime==0)
1540 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1544 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1546 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1550 if (nWalletUnlockTime)
1552 nWalletUnlockTime = 0;
1553 pwalletMain->Lock();
1558 if (nWalletUnlockTime < nMyWakeTime)
1559 nWalletUnlockTime = nMyWakeTime;
1562 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1564 delete (int64*)parg;
1567 Value walletpassphrase(const Array& params, bool fHelp)
1569 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1570 throw runtime_error(
1571 "walletpassphrase <passphrase> <timeout>\n"
1572 "Stores the wallet decryption key in memory for <timeout> seconds.");
1575 if (!pwalletMain->IsCrypted())
1576 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1578 if (!pwalletMain->IsLocked())
1579 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1581 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1582 SecureString strWalletPass;
1583 strWalletPass.reserve(100);
1584 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1585 // Alternately, find a way to make params[0] mlock()'d to begin with.
1586 strWalletPass = params[0].get_str().c_str();
1588 if (strWalletPass.length() > 0)
1590 if (!pwalletMain->Unlock(strWalletPass))
1591 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1594 throw runtime_error(
1595 "walletpassphrase <passphrase> <timeout>\n"
1596 "Stores the wallet decryption key in memory for <timeout> seconds.");
1598 CreateThread(ThreadTopUpKeyPool, NULL);
1599 int64* pnSleepTime = new int64(params[1].get_int64());
1600 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1606 Value walletpassphrasechange(const Array& params, bool fHelp)
1608 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1609 throw runtime_error(
1610 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1611 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1614 if (!pwalletMain->IsCrypted())
1615 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1617 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1618 // Alternately, find a way to make params[0] mlock()'d to begin with.
1619 SecureString strOldWalletPass;
1620 strOldWalletPass.reserve(100);
1621 strOldWalletPass = params[0].get_str().c_str();
1623 SecureString strNewWalletPass;
1624 strNewWalletPass.reserve(100);
1625 strNewWalletPass = params[1].get_str().c_str();
1627 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1628 throw runtime_error(
1629 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1630 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1632 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1633 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1639 Value walletlock(const Array& params, bool fHelp)
1641 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1642 throw runtime_error(
1644 "Removes the wallet encryption key from memory, locking the wallet.\n"
1645 "After calling this method, you will need to call walletpassphrase again\n"
1646 "before being able to call any methods which require the wallet to be unlocked.");
1649 if (!pwalletMain->IsCrypted())
1650 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1652 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1654 pwalletMain->Lock();
1655 nWalletUnlockTime = 0;
1662 Value encryptwallet(const Array& params, bool fHelp)
1664 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1665 throw runtime_error(
1666 "encryptwallet <passphrase>\n"
1667 "Encrypts the wallet with <passphrase>.");
1670 if (pwalletMain->IsCrypted())
1671 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1673 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1674 // Alternately, find a way to make params[0] mlock()'d to begin with.
1675 SecureString strWalletPass;
1676 strWalletPass.reserve(100);
1677 strWalletPass = params[0].get_str().c_str();
1679 if (strWalletPass.length() < 1)
1680 throw runtime_error(
1681 "encryptwallet <passphrase>\n"
1682 "Encrypts the wallet with <passphrase>.");
1684 if (!pwalletMain->EncryptWallet(strWalletPass))
1685 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1687 // BDB seems to have a bad habit of writing old data into
1688 // slack space in .dat files; that is bad if the old data is
1689 // unencrypted private keys. So:
1691 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1695 Value validateaddress(const Array& params, bool fHelp)
1697 if (fHelp || params.size() != 1)
1698 throw runtime_error(
1699 "validateaddress <bitcoinaddress>\n"
1700 "Return information about <bitcoinaddress>.");
1702 CBitcoinAddress address(params[0].get_str());
1703 bool isValid = address.IsValid();
1706 ret.push_back(Pair("isvalid", isValid));
1709 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1710 // version of the address:
1711 string currentAddress = address.ToString();
1712 ret.push_back(Pair("address", currentAddress));
1713 if (pwalletMain->HaveKey(address))
1715 ret.push_back(Pair("ismine", true));
1716 std::vector<unsigned char> vchPubKey;
1717 pwalletMain->GetPubKey(address, vchPubKey);
1718 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1720 key.SetPubKey(vchPubKey);
1721 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1723 else if (pwalletMain->HaveCScript(address.GetHash160()))
1725 ret.push_back(Pair("isscript", true));
1727 pwalletMain->GetCScript(address.GetHash160(), subscript);
1728 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1729 std::vector<CBitcoinAddress> addresses;
1730 txnouttype whichType;
1732 ExtractAddresses(subscript, whichType, addresses, nRequired);
1733 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1735 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1736 a.push_back(addr.ToString());
1737 ret.push_back(Pair("addresses", a));
1738 if (whichType == TX_MULTISIG)
1739 ret.push_back(Pair("sigsrequired", nRequired));
1742 ret.push_back(Pair("ismine", false));
1743 if (pwalletMain->mapAddressBook.count(address))
1744 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1749 Value getwork(const Array& params, bool fHelp)
1751 if (fHelp || params.size() > 1)
1752 throw runtime_error(
1754 "If [data] is not specified, returns formatted hash data to work on:\n"
1755 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1756 " \"data\" : block data\n"
1757 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1758 " \"target\" : little endian hash target\n"
1759 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1762 throw JSONRPCError(-9, "Bitcoin is not connected!");
1764 if (IsInitialBlockDownload())
1765 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1767 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1768 static mapNewBlock_t mapNewBlock;
1769 static vector<CBlock*> vNewBlock;
1770 static CReserveKey reservekey(pwalletMain);
1772 if (params.size() == 0)
1775 static unsigned int nTransactionsUpdatedLast;
1776 static CBlockIndex* pindexPrev;
1777 static int64 nStart;
1778 static CBlock* pblock;
1779 if (pindexPrev != pindexBest ||
1780 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1782 if (pindexPrev != pindexBest)
1784 // Deallocate old blocks since they're obsolete now
1785 mapNewBlock.clear();
1786 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1790 nTransactionsUpdatedLast = nTransactionsUpdated;
1791 pindexPrev = pindexBest;
1795 pblock = CreateNewBlock(reservekey);
1797 throw JSONRPCError(-7, "Out of memory");
1798 vNewBlock.push_back(pblock);
1802 pblock->UpdateTime(pindexPrev);
1805 // Update nExtraNonce
1806 static unsigned int nExtraNonce = 0;
1807 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1810 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1812 // Prebuild hash buffers
1816 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1818 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1821 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1822 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1823 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1824 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1830 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1831 if (vchData.size() != 128)
1832 throw JSONRPCError(-8, "Invalid parameter");
1833 CBlock* pdata = (CBlock*)&vchData[0];
1836 for (int i = 0; i < 128/4; i++)
1837 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1840 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1842 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1844 pblock->nTime = pdata->nTime;
1845 pblock->nNonce = pdata->nNonce;
1846 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1847 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1849 return CheckWork(pblock, *pwalletMain, reservekey);
1854 Value getmemorypool(const Array& params, bool fHelp)
1856 if (fHelp || params.size() > 1)
1857 throw runtime_error(
1858 "getmemorypool [data]\n"
1859 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1860 " \"version\" : block version\n"
1861 " \"previousblockhash\" : hash of current highest block\n"
1862 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1863 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1864 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1865 " \"time\" : timestamp appropriate for next block\n"
1866 " \"mintime\" : minimum timestamp appropriate for next block\n"
1867 " \"curtime\" : current timestamp\n"
1868 " \"bits\" : compressed target of next block\n"
1869 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1871 if (params.size() == 0)
1874 throw JSONRPCError(-9, "Bitcoin is not connected!");
1876 if (IsInitialBlockDownload())
1877 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1879 static CReserveKey reservekey(pwalletMain);
1882 static unsigned int nTransactionsUpdatedLast;
1883 static CBlockIndex* pindexPrev;
1884 static int64 nStart;
1885 static CBlock* pblock;
1886 if (pindexPrev != pindexBest ||
1887 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1889 nTransactionsUpdatedLast = nTransactionsUpdated;
1890 pindexPrev = pindexBest;
1896 pblock = CreateNewBlock(reservekey);
1898 throw JSONRPCError(-7, "Out of memory");
1902 pblock->UpdateTime(pindexPrev);
1906 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1913 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1917 result.push_back(Pair("version", pblock->nVersion));
1918 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1919 result.push_back(Pair("transactions", transactions));
1920 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1921 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1922 result.push_back(Pair("time", (int64_t)pblock->nTime));
1923 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1924 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1925 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1932 CDataStream ssBlock(ParseHex(params[0].get_str()));
1936 return ProcessBlock(NULL, &pblock);
1940 Value getblockhash(const Array& params, bool fHelp)
1942 if (fHelp || params.size() != 1)
1943 throw runtime_error(
1944 "getblockhash <index>\n"
1945 "Returns hash of block in best-block-chain at <index>.");
1947 int nHeight = params[0].get_int();
1948 if (nHeight < 0 || nHeight > nBestHeight)
1949 throw runtime_error("Block number out of range.");
1952 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1953 while (pblockindex->nHeight > nHeight)
1954 pblockindex = pblockindex->pprev;
1955 return pblockindex->phashBlock->GetHex();
1958 Value getblock(const Array& params, bool fHelp)
1960 if (fHelp || params.size() != 1)
1961 throw runtime_error(
1963 "Returns details of a block with given block-hash.");
1965 std::string strHash = params[0].get_str();
1966 uint256 hash(strHash);
1968 if (mapBlockIndex.count(hash) == 0)
1969 throw JSONRPCError(-5, "Block not found");
1972 CBlockIndex* pblockindex = mapBlockIndex[hash];
1973 block.ReadFromDisk(pblockindex, true);
1975 return blockToJSON(block, pblockindex);
1992 pair<string, rpcfn_type> pCallTable[] =
1994 make_pair("help", &help),
1995 make_pair("stop", &stop),
1996 make_pair("getblockcount", &getblockcount),
1997 make_pair("getblocknumber", &getblocknumber),
1998 make_pair("getconnectioncount", &getconnectioncount),
1999 make_pair("getdifficulty", &getdifficulty),
2000 make_pair("getgenerate", &getgenerate),
2001 make_pair("setgenerate", &setgenerate),
2002 make_pair("gethashespersec", &gethashespersec),
2003 make_pair("getinfo", &getinfo),
2004 make_pair("getmininginfo", &getmininginfo),
2005 make_pair("getnewaddress", &getnewaddress),
2006 make_pair("getaccountaddress", &getaccountaddress),
2007 make_pair("setaccount", &setaccount),
2008 make_pair("getaccount", &getaccount),
2009 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2010 make_pair("sendtoaddress", &sendtoaddress),
2011 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2012 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2013 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2014 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2015 make_pair("backupwallet", &backupwallet),
2016 make_pair("keypoolrefill", &keypoolrefill),
2017 make_pair("walletpassphrase", &walletpassphrase),
2018 make_pair("walletpassphrasechange", &walletpassphrasechange),
2019 make_pair("walletlock", &walletlock),
2020 make_pair("encryptwallet", &encryptwallet),
2021 make_pair("validateaddress", &validateaddress),
2022 make_pair("getbalance", &getbalance),
2023 make_pair("move", &movecmd),
2024 make_pair("sendfrom", &sendfrom),
2025 make_pair("sendmany", &sendmany),
2026 make_pair("addmultisigaddress", &addmultisigaddress),
2027 make_pair("getblock", &getblock),
2028 make_pair("getblockhash", &getblockhash),
2029 make_pair("gettransaction", &gettransaction),
2030 make_pair("listtransactions", &listtransactions),
2031 make_pair("signmessage", &signmessage),
2032 make_pair("verifymessage", &verifymessage),
2033 make_pair("getwork", &getwork),
2034 make_pair("listaccounts", &listaccounts),
2035 make_pair("settxfee", &settxfee),
2036 make_pair("getmemorypool", &getmemorypool),
2037 make_pair("listsinceblock", &listsinceblock),
2038 make_pair("dumpprivkey", &dumpprivkey),
2039 make_pair("importprivkey", &importprivkey)
2041 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2043 string pAllowInSafeMode[] =
2048 "getblocknumber", // deprecated
2049 "getconnectioncount",
2057 "getaccountaddress",
2059 "getaddressesbyaccount",
2068 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2076 // This ain't Apache. We're just using HTTP header for the length field
2077 // and to be compatible with other JSON-RPC implementations.
2080 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2083 s << "POST / HTTP/1.1\r\n"
2084 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2085 << "Host: 127.0.0.1\r\n"
2086 << "Content-Type: application/json\r\n"
2087 << "Content-Length: " << strMsg.size() << "\r\n"
2088 << "Connection: close\r\n"
2089 << "Accept: application/json\r\n";
2090 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2091 s << item.first << ": " << item.second << "\r\n";
2092 s << "\r\n" << strMsg;
2097 string rfc1123Time()
2102 struct tm* now_gmt = gmtime(&now);
2103 string locale(setlocale(LC_TIME, NULL));
2104 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2105 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2106 setlocale(LC_TIME, locale.c_str());
2107 return string(buffer);
2110 static string HTTPReply(int nStatus, const string& strMsg)
2113 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2115 "Server: bitcoin-json-rpc/%s\r\n"
2116 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2117 "Content-Type: text/html\r\n"
2118 "Content-Length: 296\r\n"
2120 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2121 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2124 "<TITLE>Error</TITLE>\r\n"
2125 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2127 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2128 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2129 const char *cStatus;
2130 if (nStatus == 200) cStatus = "OK";
2131 else if (nStatus == 400) cStatus = "Bad Request";
2132 else if (nStatus == 403) cStatus = "Forbidden";
2133 else if (nStatus == 404) cStatus = "Not Found";
2134 else if (nStatus == 500) cStatus = "Internal Server Error";
2137 "HTTP/1.1 %d %s\r\n"
2139 "Connection: close\r\n"
2140 "Content-Length: %d\r\n"
2141 "Content-Type: application/json\r\n"
2142 "Server: bitcoin-json-rpc/%s\r\n"
2147 rfc1123Time().c_str(),
2149 FormatFullVersion().c_str(),
2153 int ReadHTTPStatus(std::basic_istream<char>& stream)
2156 getline(stream, str);
2157 vector<string> vWords;
2158 boost::split(vWords, str, boost::is_any_of(" "));
2159 if (vWords.size() < 2)
2161 return atoi(vWords[1].c_str());
2164 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2170 std::getline(stream, str);
2171 if (str.empty() || str == "\r")
2173 string::size_type nColon = str.find(":");
2174 if (nColon != string::npos)
2176 string strHeader = str.substr(0, nColon);
2177 boost::trim(strHeader);
2178 boost::to_lower(strHeader);
2179 string strValue = str.substr(nColon+1);
2180 boost::trim(strValue);
2181 mapHeadersRet[strHeader] = strValue;
2182 if (strHeader == "content-length")
2183 nLen = atoi(strValue.c_str());
2189 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2191 mapHeadersRet.clear();
2195 int nStatus = ReadHTTPStatus(stream);
2198 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2199 if (nLen < 0 || nLen > MAX_SIZE)
2205 vector<char> vch(nLen);
2206 stream.read(&vch[0], nLen);
2207 strMessageRet = string(vch.begin(), vch.end());
2213 bool HTTPAuthorized(map<string, string>& mapHeaders)
2215 string strAuth = mapHeaders["authorization"];
2216 if (strAuth.substr(0,6) != "Basic ")
2218 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2219 string strUserPass = DecodeBase64(strUserPass64);
2220 return strUserPass == strRPCUserColonPass;
2224 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2225 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2226 // unspecified (HTTP errors and contents of 'error').
2228 // 1.0 spec: http://json-rpc.org/wiki/specification
2229 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2230 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2233 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2236 request.push_back(Pair("method", strMethod));
2237 request.push_back(Pair("params", params));
2238 request.push_back(Pair("id", id));
2239 return write_string(Value(request), false) + "\n";
2242 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2245 if (error.type() != null_type)
2246 reply.push_back(Pair("result", Value::null));
2248 reply.push_back(Pair("result", result));
2249 reply.push_back(Pair("error", error));
2250 reply.push_back(Pair("id", id));
2251 return write_string(Value(reply), false) + "\n";
2254 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2256 // Send error reply from json-rpc error object
2258 int code = find_value(objError, "code").get_int();
2259 if (code == -32600) nStatus = 400;
2260 else if (code == -32601) nStatus = 404;
2261 string strReply = JSONRPCReply(Value::null, objError, id);
2262 stream << HTTPReply(nStatus, strReply) << std::flush;
2265 bool ClientAllowed(const string& strAddress)
2267 if (strAddress == asio::ip::address_v4::loopback().to_string())
2269 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2270 BOOST_FOREACH(string strAllow, vAllow)
2271 if (WildcardMatch(strAddress, strAllow))
2278 // IOStream device that speaks SSL but can also speak non-SSL
2280 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2282 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2284 fUseSSL = fUseSSLIn;
2285 fNeedHandshake = fUseSSLIn;
2288 void handshake(ssl::stream_base::handshake_type role)
2290 if (!fNeedHandshake) return;
2291 fNeedHandshake = false;
2292 stream.handshake(role);
2294 std::streamsize read(char* s, std::streamsize n)
2296 handshake(ssl::stream_base::server); // HTTPS servers read first
2297 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2298 return stream.next_layer().read_some(asio::buffer(s, n));
2300 std::streamsize write(const char* s, std::streamsize n)
2302 handshake(ssl::stream_base::client); // HTTPS clients write first
2303 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2304 return asio::write(stream.next_layer(), asio::buffer(s, n));
2306 bool connect(const std::string& server, const std::string& port)
2308 ip::tcp::resolver resolver(stream.get_io_service());
2309 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2310 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2311 ip::tcp::resolver::iterator end;
2312 boost::system::error_code error = asio::error::host_not_found;
2313 while (error && endpoint_iterator != end)
2315 stream.lowest_layer().close();
2316 stream.lowest_layer().connect(*endpoint_iterator++, error);
2324 bool fNeedHandshake;
2330 void ThreadRPCServer(void* parg)
2332 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2335 vnThreadsRunning[THREAD_RPCSERVER]++;
2336 ThreadRPCServer2(parg);
2337 vnThreadsRunning[THREAD_RPCSERVER]--;
2339 catch (std::exception& e) {
2340 vnThreadsRunning[THREAD_RPCSERVER]--;
2341 PrintException(&e, "ThreadRPCServer()");
2343 vnThreadsRunning[THREAD_RPCSERVER]--;
2344 PrintException(NULL, "ThreadRPCServer()");
2346 printf("ThreadRPCServer exiting\n");
2349 void ThreadRPCServer2(void* parg)
2351 printf("ThreadRPCServer started\n");
2353 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2354 if (mapArgs["-rpcpassword"] == "")
2356 unsigned char rand_pwd[32];
2357 RAND_bytes(rand_pwd, 32);
2358 string strWhatAmI = "To use bitcoind";
2359 if (mapArgs.count("-server"))
2360 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2361 else if (mapArgs.count("-daemon"))
2362 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2363 ThreadSafeMessageBox(strprintf(
2364 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2365 "It is recommended you use the following random password:\n"
2366 "rpcuser=bitcoinrpc\n"
2368 "(you do not need to remember this password)\n"
2369 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2371 GetConfigFile().c_str(),
2372 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2373 _("Error"), wxOK | wxMODAL);
2378 bool fUseSSL = GetBoolArg("-rpcssl");
2379 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2381 asio::io_service io_service;
2382 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2383 ip::tcp::acceptor acceptor(io_service, endpoint);
2385 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2388 ssl::context context(io_service, ssl::context::sslv23);
2391 context.set_options(ssl::context::no_sslv2);
2392 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2393 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2394 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2395 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2396 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2397 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2398 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2399 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2401 string ciphers = GetArg("-rpcsslciphers",
2402 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2403 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2407 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2412 // Accept connection
2414 SSLStream sslStream(io_service, context);
2415 SSLIOStreamDevice d(sslStream, fUseSSL);
2416 iostreams::stream<SSLIOStreamDevice> stream(d);
2418 ip::tcp::iostream stream;
2421 ip::tcp::endpoint peer;
2422 vnThreadsRunning[THREAD_RPCSERVER]--;
2424 acceptor.accept(sslStream.lowest_layer(), peer);
2426 acceptor.accept(*stream.rdbuf(), peer);
2428 vnThreadsRunning[4]++;
2432 // Restrict callers by IP
2433 if (!ClientAllowed(peer.address().to_string()))
2435 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2437 stream << HTTPReply(403, "") << std::flush;
2441 map<string, string> mapHeaders;
2444 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2445 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2448 printf("ThreadRPCServer ReadHTTP timeout\n");
2452 // Check authorization
2453 if (mapHeaders.count("authorization") == 0)
2455 stream << HTTPReply(401, "") << std::flush;
2458 if (!HTTPAuthorized(mapHeaders))
2460 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2461 /* Deter brute-forcing short passwords.
2462 If this results in a DOS the user really
2463 shouldn't have their RPC port exposed.*/
2464 if (mapArgs["-rpcpassword"].size() < 20)
2467 stream << HTTPReply(401, "") << std::flush;
2471 Value id = Value::null;
2476 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2477 throw JSONRPCError(-32700, "Parse error");
2478 const Object& request = valRequest.get_obj();
2480 // Parse id now so errors from here on will have the id
2481 id = find_value(request, "id");
2484 Value valMethod = find_value(request, "method");
2485 if (valMethod.type() == null_type)
2486 throw JSONRPCError(-32600, "Missing method");
2487 if (valMethod.type() != str_type)
2488 throw JSONRPCError(-32600, "Method must be a string");
2489 string strMethod = valMethod.get_str();
2490 if (strMethod != "getwork" && strMethod != "getmemorypool")
2491 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2494 Value valParams = find_value(request, "params");
2496 if (valParams.type() == array_type)
2497 params = valParams.get_array();
2498 else if (valParams.type() == null_type)
2501 throw JSONRPCError(-32600, "Params must be an array");
2504 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2505 if (mi == mapCallTable.end())
2506 throw JSONRPCError(-32601, "Method not found");
2508 // Observe safe mode
2509 string strWarning = GetWarnings("rpc");
2510 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2511 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2517 CRITICAL_BLOCK(cs_main)
2518 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2519 result = (*(*mi).second)(params, false);
2522 string strReply = JSONRPCReply(result, Value::null, id);
2523 stream << HTTPReply(200, strReply) << std::flush;
2525 catch (std::exception& e)
2527 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2530 catch (Object& objError)
2532 ErrorReply(stream, objError, id);
2534 catch (std::exception& e)
2536 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2544 Object CallRPC(const string& strMethod, const Array& params)
2546 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2547 throw runtime_error(strprintf(
2548 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2549 "If the file does not exist, create it with owner-readable-only file permissions."),
2550 GetConfigFile().c_str()));
2552 // Connect to localhost
2553 bool fUseSSL = GetBoolArg("-rpcssl");
2555 asio::io_service io_service;
2556 ssl::context context(io_service, ssl::context::sslv23);
2557 context.set_options(ssl::context::no_sslv2);
2558 SSLStream sslStream(io_service, context);
2559 SSLIOStreamDevice d(sslStream, fUseSSL);
2560 iostreams::stream<SSLIOStreamDevice> stream(d);
2561 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2562 throw runtime_error("couldn't connect to server");
2565 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2567 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2569 throw runtime_error("couldn't connect to server");
2573 // HTTP basic authentication
2574 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2575 map<string, string> mapRequestHeaders;
2576 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2579 string strRequest = JSONRPCRequest(strMethod, params, 1);
2580 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2581 stream << strPost << std::flush;
2584 map<string, string> mapHeaders;
2586 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2588 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2589 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2590 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2591 else if (strReply.empty())
2592 throw runtime_error("no response from server");
2596 if (!read_string(strReply, valReply))
2597 throw runtime_error("couldn't parse reply from server");
2598 const Object& reply = valReply.get_obj();
2600 throw runtime_error("expected reply to have result, error and id properties");
2608 template<typename T>
2609 void ConvertTo(Value& value)
2611 if (value.type() == str_type)
2613 // reinterpret string as unquoted json value
2615 if (!read_string(value.get_str(), value2))
2616 throw runtime_error("type mismatch");
2617 value = value2.get_value<T>();
2621 value = value.get_value<T>();
2625 int CommandLineRPC(int argc, char *argv[])
2632 while (argc > 1 && IsSwitchChar(argv[1][0]))
2640 throw runtime_error("too few parameters");
2641 string strMethod = argv[1];
2643 // Parameters default to strings
2645 for (int i = 2; i < argc; i++)
2646 params.push_back(argv[i]);
2647 int n = params.size();
2650 // Special case non-string parameter types
2652 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2653 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2654 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2655 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2656 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2657 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2658 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2659 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2660 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2661 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2662 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2663 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2664 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2665 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2666 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2667 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2668 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2669 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2670 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2671 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2672 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2673 if (strMethod == "sendmany" && n > 1)
2675 string s = params[1].get_str();
2677 if (!read_string(s, v) || v.type() != obj_type)
2678 throw runtime_error("type mismatch");
2679 params[1] = v.get_obj();
2681 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2682 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2683 if (strMethod == "addmultisigaddress" && n > 1)
2685 string s = params[1].get_str();
2687 if (!read_string(s, v) || v.type() != array_type)
2688 throw runtime_error("type mismatch "+s);
2689 params[1] = v.get_array();
2693 Object reply = CallRPC(strMethod, params);
2696 const Value& result = find_value(reply, "result");
2697 const Value& error = find_value(reply, "error");
2699 if (error.type() != null_type)
2702 strPrint = "error: " + write_string(error, false);
2703 int code = find_value(error.get_obj(), "code").get_int();
2709 if (result.type() == null_type)
2711 else if (result.type() == str_type)
2712 strPrint = result.get_str();
2714 strPrint = write_string(result, true);
2717 catch (std::exception& e)
2719 strPrint = string("error: ") + e.what();
2724 PrintException(NULL, "CommandLineRPC()");
2729 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2738 int main(int argc, char *argv[])
2741 // Turn off microsoft heap dump noise
2742 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2743 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2745 setbuf(stdin, NULL);
2746 setbuf(stdout, NULL);
2747 setbuf(stderr, NULL);
2751 if (argc >= 2 && string(argv[1]) == "-server")
2753 printf("server ready\n");
2754 ThreadRPCServer(NULL);
2758 return CommandLineRPC(argc, argv);
2761 catch (std::exception& e) {
2762 PrintException(&e, "main()");
2764 PrintException(NULL, "main()");