1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static std::string strRPCUserColonPass;
42 static int64 nWalletUnlockTime;
43 static CCriticalSection cs_nWalletUnlockTime;
45 extern Value dumpprivkey(const Array& params, bool fHelp);
46 extern Value importprivkey(const Array& params, bool fHelp);
48 Object JSONRPCError(int code, const string& message)
51 error.push_back(Pair("code", code));
52 error.push_back(Pair("message", message));
56 double GetDifficulty(const CBlockIndex* blockindex = NULL)
58 // Floating point number that is a multiple of the minimum difficulty,
59 // minimum difficulty = 1.0.
60 if (blockindex == NULL)
62 if (pindexBest == NULL)
65 blockindex = pindexBest;
68 int nShift = (blockindex->nBits >> 24) & 0xff;
71 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
88 int64 AmountFromValue(const Value& value)
90 double dAmount = value.get_real();
91 if (dAmount <= 0.0 || dAmount > 21000000.0)
92 throw JSONRPCError(-3, "Invalid amount");
93 int64 nAmount = roundint64(dAmount * COIN);
94 if (!MoneyRange(nAmount))
95 throw JSONRPCError(-3, "Invalid amount");
99 Value ValueFromAmount(int64 amount)
101 return (double)amount / (double)COIN;
105 HexBits(unsigned int nBits)
111 uBits.nBits = htonl((int32_t)nBits);
112 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
115 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
117 int confirms = wtx.GetDepthInMainChain();
118 entry.push_back(Pair("confirmations", confirms));
121 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
122 entry.push_back(Pair("blockindex", wtx.nIndex));
124 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
125 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
126 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
127 entry.push_back(Pair(item.first, item.second));
130 string AccountFromValue(const Value& value)
132 string strAccount = value.get_str();
133 if (strAccount == "*")
134 throw JSONRPCError(-11, "Invalid account name");
138 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
141 result.push_back(Pair("hash", block.GetHash().GetHex()));
142 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
143 result.push_back(Pair("height", blockindex->nHeight));
144 result.push_back(Pair("version", block.nVersion));
145 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
146 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
147 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
148 result.push_back(Pair("bits", HexBits(block.nBits)));
149 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
151 BOOST_FOREACH (const CTransaction&tx, block.vtx)
152 txhashes.push_back(tx.GetHash().GetHex());
153 result.push_back(Pair("tx", txhashes));
155 if (blockindex->pprev)
156 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
157 if (blockindex->pnext)
158 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
165 /// Note: This interface may still be subject to change.
169 Value help(const Array& params, bool fHelp)
171 if (fHelp || params.size() > 1)
174 "List commands, or get help for a command.");
177 if (params.size() > 0)
178 strCommand = params[0].get_str();
181 set<rpcfn_type> setDone;
182 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
184 string strMethod = (*mi).first;
185 // We already filter duplicates, but these deprecated screw up the sort order
186 if (strMethod == "getamountreceived" ||
187 strMethod == "getallreceived" ||
188 strMethod == "getblocknumber" || // deprecated
189 (strMethod.find("label") != string::npos))
191 if (strCommand != "" && strMethod != strCommand)
196 rpcfn_type pfn = (*mi).second;
197 if (setDone.insert(pfn).second)
198 (*pfn)(params, true);
200 catch (std::exception& e)
202 // Help text is returned in an exception
203 string strHelp = string(e.what());
204 if (strCommand == "")
205 if (strHelp.find('\n') != -1)
206 strHelp = strHelp.substr(0, strHelp.find('\n'));
207 strRet += strHelp + "\n";
211 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
212 strRet = strRet.substr(0,strRet.size()-1);
217 Value stop(const Array& params, bool fHelp)
219 if (fHelp || params.size() != 0)
222 "Stop bitcoin server.");
223 // Shutdown will take long enough that the response should get back
225 return "bitcoin server stopping";
229 Value getblockcount(const Array& params, bool fHelp)
231 if (fHelp || params.size() != 0)
234 "Returns the number of blocks in the longest block chain.");
241 Value getblocknumber(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Deprecated. Use getblockcount.");
252 Value getconnectioncount(const Array& params, bool fHelp)
254 if (fHelp || params.size() != 0)
256 "getconnectioncount\n"
257 "Returns the number of connections to other nodes.");
259 return (int)vNodes.size();
263 Value getdifficulty(const Array& params, bool fHelp)
265 if (fHelp || params.size() != 0)
268 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
270 return GetDifficulty();
274 Value getgenerate(const Array& params, bool fHelp)
276 if (fHelp || params.size() != 0)
279 "Returns true or false.");
281 return GetBoolArg("-gen");
285 Value setgenerate(const Array& params, bool fHelp)
287 if (fHelp || params.size() < 1 || params.size() > 2)
289 "setgenerate <generate> [genproclimit]\n"
290 "<generate> is true or false to turn generation on or off.\n"
291 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
293 bool fGenerate = true;
294 if (params.size() > 0)
295 fGenerate = params[0].get_bool();
297 if (params.size() > 1)
299 int nGenProcLimit = params[1].get_int();
300 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
301 if (nGenProcLimit == 0)
304 mapArgs["-gen"] = (fGenerate ? "1" : "0");
306 GenerateBitcoins(fGenerate, pwalletMain);
311 Value gethashespersec(const Array& params, bool fHelp)
313 if (fHelp || params.size() != 0)
316 "Returns a recent hashes per second performance measurement while generating.");
318 if (GetTimeMillis() - nHPSTimerStart > 8000)
319 return (boost::int64_t)0;
320 return (boost::int64_t)dHashesPerSec;
324 Value getinfo(const Array& params, bool fHelp)
326 if (fHelp || params.size() != 0)
329 "Returns an object containing various state info.");
332 obj.push_back(Pair("version", (int)CLIENT_VERSION));
333 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
334 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
335 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
336 obj.push_back(Pair("blocks", (int)nBestHeight));
337 obj.push_back(Pair("connections", (int)vNodes.size()));
338 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
339 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
340 obj.push_back(Pair("testnet", fTestNet));
341 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
342 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
343 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
344 if (pwalletMain->IsCrypted())
345 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
346 obj.push_back(Pair("errors", GetWarnings("statusbar")));
351 Value getmininginfo(const Array& params, bool fHelp)
353 if (fHelp || params.size() != 0)
356 "Returns an object containing mining-related information.");
359 obj.push_back(Pair("blocks", (int)nBestHeight));
360 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
361 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
362 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
363 obj.push_back(Pair("errors", GetWarnings("statusbar")));
364 obj.push_back(Pair("generate", GetBoolArg("-gen")));
365 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
366 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
367 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
368 obj.push_back(Pair("testnet", fTestNet));
373 Value getnewaddress(const Array& params, bool fHelp)
375 if (fHelp || params.size() > 1)
377 "getnewaddress [account]\n"
378 "Returns a new bitcoin address for receiving payments. "
379 "If [account] is specified (recommended), it is added to the address book "
380 "so payments received with the address will be credited to [account].");
382 // Parse the account first so we don't generate a key if there's an error
384 if (params.size() > 0)
385 strAccount = AccountFromValue(params[0]);
387 if (!pwalletMain->IsLocked())
388 pwalletMain->TopUpKeyPool();
390 // Generate a new key that is added to wallet
391 std::vector<unsigned char> newKey;
392 if (!pwalletMain->GetKeyFromPool(newKey, false))
393 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
394 CBitcoinAddress address(newKey);
396 pwalletMain->SetAddressBookName(address, strAccount);
398 return address.ToString();
402 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
404 CWalletDB walletdb(pwalletMain->strWalletFile);
407 walletdb.ReadAccount(strAccount, account);
409 bool bKeyUsed = false;
411 // Check if the current key has been used
412 if (!account.vchPubKey.empty())
414 CScript scriptPubKey;
415 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
416 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
417 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
420 const CWalletTx& wtx = (*it).second;
421 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
422 if (txout.scriptPubKey == scriptPubKey)
427 // Generate a new key
428 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
430 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
431 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
433 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
434 walletdb.WriteAccount(strAccount, account);
437 return CBitcoinAddress(account.vchPubKey);
440 Value getaccountaddress(const Array& params, bool fHelp)
442 if (fHelp || params.size() != 1)
444 "getaccountaddress <account>\n"
445 "Returns the current bitcoin address for receiving payments to this account.");
447 // Parse the account first so we don't generate a key if there's an error
448 string strAccount = AccountFromValue(params[0]);
452 ret = GetAccountAddress(strAccount).ToString();
459 Value setaccount(const Array& params, bool fHelp)
461 if (fHelp || params.size() < 1 || params.size() > 2)
463 "setaccount <bitcoinaddress> <account>\n"
464 "Sets the account associated with the given address.");
466 CBitcoinAddress address(params[0].get_str());
467 if (!address.IsValid())
468 throw JSONRPCError(-5, "Invalid bitcoin address");
472 if (params.size() > 1)
473 strAccount = AccountFromValue(params[1]);
475 // Detect when changing the account of an address that is the 'unused current key' of another account:
476 if (pwalletMain->mapAddressBook.count(address))
478 string strOldAccount = pwalletMain->mapAddressBook[address];
479 if (address == GetAccountAddress(strOldAccount))
480 GetAccountAddress(strOldAccount, true);
483 pwalletMain->SetAddressBookName(address, strAccount);
489 Value getaccount(const Array& params, bool fHelp)
491 if (fHelp || params.size() != 1)
493 "getaccount <bitcoinaddress>\n"
494 "Returns the account associated with the given address.");
496 CBitcoinAddress address(params[0].get_str());
497 if (!address.IsValid())
498 throw JSONRPCError(-5, "Invalid bitcoin address");
501 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
502 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
503 strAccount = (*mi).second;
508 Value getaddressesbyaccount(const Array& params, bool fHelp)
510 if (fHelp || params.size() != 1)
512 "getaddressesbyaccount <account>\n"
513 "Returns the list of addresses for the given account.");
515 string strAccount = AccountFromValue(params[0]);
517 // Find all addresses that have the given account
519 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
521 const CBitcoinAddress& address = item.first;
522 const string& strName = item.second;
523 if (strName == strAccount)
524 ret.push_back(address.ToString());
529 Value settxfee(const Array& params, bool fHelp)
531 if (fHelp || params.size() < 1 || params.size() > 1)
533 "settxfee <amount>\n"
534 "<amount> is a real and is rounded to the nearest 0.00000001");
538 if (params[0].get_real() != 0.0)
539 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
541 nTransactionFee = nAmount;
545 Value sendtoaddress(const Array& params, bool fHelp)
547 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
549 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
550 "<amount> is a real and is rounded to the nearest 0.00000001\n"
551 "requires wallet passphrase to be set with walletpassphrase first");
552 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
554 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
555 "<amount> is a real and is rounded to the nearest 0.00000001");
557 CBitcoinAddress address(params[0].get_str());
558 if (!address.IsValid())
559 throw JSONRPCError(-5, "Invalid bitcoin address");
562 int64 nAmount = AmountFromValue(params[1]);
566 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
567 wtx.mapValue["comment"] = params[2].get_str();
568 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
569 wtx.mapValue["to"] = params[3].get_str();
571 if (pwalletMain->IsLocked())
572 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
574 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
576 throw JSONRPCError(-4, strError);
578 return wtx.GetHash().GetHex();
581 Value signmessage(const Array& params, bool fHelp)
583 if (fHelp || params.size() != 2)
585 "signmessage <bitcoinaddress> <message>\n"
586 "Sign a message with the private key of an address");
588 if (pwalletMain->IsLocked())
589 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
591 string strAddress = params[0].get_str();
592 string strMessage = params[1].get_str();
594 CBitcoinAddress addr(strAddress);
596 throw JSONRPCError(-3, "Invalid address");
599 if (!pwalletMain->GetKey(addr, key))
600 throw JSONRPCError(-4, "Private key not available");
602 CDataStream ss(SER_GETHASH);
603 ss << strMessageMagic;
606 vector<unsigned char> vchSig;
607 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
608 throw JSONRPCError(-5, "Sign failed");
610 return EncodeBase64(&vchSig[0], vchSig.size());
613 Value verifymessage(const Array& params, bool fHelp)
615 if (fHelp || params.size() != 3)
617 "verifymessage <bitcoinaddress> <signature> <message>\n"
618 "Verify a signed message");
620 string strAddress = params[0].get_str();
621 string strSign = params[1].get_str();
622 string strMessage = params[2].get_str();
624 CBitcoinAddress addr(strAddress);
626 throw JSONRPCError(-3, "Invalid address");
628 bool fInvalid = false;
629 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
632 throw JSONRPCError(-5, "Malformed base64 encoding");
634 CDataStream ss(SER_GETHASH);
635 ss << strMessageMagic;
639 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
642 return (CBitcoinAddress(key.GetPubKey()) == addr);
646 Value getreceivedbyaddress(const Array& params, bool fHelp)
648 if (fHelp || params.size() < 1 || params.size() > 2)
650 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
651 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
654 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
655 CScript scriptPubKey;
656 if (!address.IsValid())
657 throw JSONRPCError(-5, "Invalid bitcoin address");
658 scriptPubKey.SetBitcoinAddress(address);
659 if (!IsMine(*pwalletMain,scriptPubKey))
662 // Minimum confirmations
664 if (params.size() > 1)
665 nMinDepth = params[1].get_int();
669 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
671 const CWalletTx& wtx = (*it).second;
672 if (wtx.IsCoinBase() || !wtx.IsFinal())
675 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
676 if (txout.scriptPubKey == scriptPubKey)
677 if (wtx.GetDepthInMainChain() >= nMinDepth)
678 nAmount += txout.nValue;
681 return ValueFromAmount(nAmount);
685 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
687 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
689 const CBitcoinAddress& address = item.first;
690 const string& strName = item.second;
691 if (strName == strAccount)
692 setAddress.insert(address);
697 Value getreceivedbyaccount(const Array& params, bool fHelp)
699 if (fHelp || params.size() < 1 || params.size() > 2)
701 "getreceivedbyaccount <account> [minconf=1]\n"
702 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
704 // Minimum confirmations
706 if (params.size() > 1)
707 nMinDepth = params[1].get_int();
709 // Get the set of pub keys assigned to account
710 string strAccount = AccountFromValue(params[0]);
711 set<CBitcoinAddress> setAddress;
712 GetAccountAddresses(strAccount, setAddress);
716 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
718 const CWalletTx& wtx = (*it).second;
719 if (wtx.IsCoinBase() || !wtx.IsFinal())
722 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
724 CBitcoinAddress address;
725 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
726 if (wtx.GetDepthInMainChain() >= nMinDepth)
727 nAmount += txout.nValue;
731 return (double)nAmount / (double)COIN;
735 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
739 // Tally wallet transactions
740 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
742 const CWalletTx& wtx = (*it).second;
746 int64 nGenerated, nReceived, nSent, nFee;
747 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
749 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
750 nBalance += nReceived;
751 nBalance += nGenerated - nSent - nFee;
754 // Tally internal accounting entries
755 nBalance += walletdb.GetAccountCreditDebit(strAccount);
760 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
762 CWalletDB walletdb(pwalletMain->strWalletFile);
763 return GetAccountBalance(walletdb, strAccount, nMinDepth);
767 Value getbalance(const Array& params, bool fHelp)
769 if (fHelp || params.size() > 2)
771 "getbalance [account] [minconf=1]\n"
772 "If [account] is not specified, returns the server's total available balance.\n"
773 "If [account] is specified, returns the balance in the account.");
775 if (params.size() == 0)
776 return ValueFromAmount(pwalletMain->GetBalance());
779 if (params.size() > 1)
780 nMinDepth = params[1].get_int();
782 if (params[0].get_str() == "*") {
783 // Calculate total balance a different way from GetBalance()
784 // (GetBalance() sums up all unspent TxOuts)
785 // getbalance and getbalance '*' should always return the same number.
787 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
789 const CWalletTx& wtx = (*it).second;
793 int64 allGeneratedImmature, allGeneratedMature, allFee;
794 allGeneratedImmature = allGeneratedMature = allFee = 0;
795 string strSentAccount;
796 list<pair<CBitcoinAddress, int64> > listReceived;
797 list<pair<CBitcoinAddress, int64> > listSent;
798 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
799 if (wtx.GetDepthInMainChain() >= nMinDepth)
800 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
801 nBalance += r.second;
802 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
803 nBalance -= r.second;
805 nBalance += allGeneratedMature;
807 return ValueFromAmount(nBalance);
810 string strAccount = AccountFromValue(params[0]);
812 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
814 return ValueFromAmount(nBalance);
818 Value movecmd(const Array& params, bool fHelp)
820 if (fHelp || params.size() < 3 || params.size() > 5)
822 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
823 "Move from one account in your wallet to another.");
825 string strFrom = AccountFromValue(params[0]);
826 string strTo = AccountFromValue(params[1]);
827 int64 nAmount = AmountFromValue(params[2]);
828 if (params.size() > 3)
829 // unused parameter, used to be nMinDepth, keep type-checking it though
830 (void)params[3].get_int();
832 if (params.size() > 4)
833 strComment = params[4].get_str();
835 CWalletDB walletdb(pwalletMain->strWalletFile);
838 int64 nNow = GetAdjustedTime();
841 CAccountingEntry debit;
842 debit.strAccount = strFrom;
843 debit.nCreditDebit = -nAmount;
845 debit.strOtherAccount = strTo;
846 debit.strComment = strComment;
847 walletdb.WriteAccountingEntry(debit);
850 CAccountingEntry credit;
851 credit.strAccount = strTo;
852 credit.nCreditDebit = nAmount;
854 credit.strOtherAccount = strFrom;
855 credit.strComment = strComment;
856 walletdb.WriteAccountingEntry(credit);
858 walletdb.TxnCommit();
864 Value sendfrom(const Array& params, bool fHelp)
866 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
868 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
869 "<amount> is a real and is rounded to the nearest 0.00000001\n"
870 "requires wallet passphrase to be set with walletpassphrase first");
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");
876 string strAccount = AccountFromValue(params[0]);
877 CBitcoinAddress address(params[1].get_str());
878 if (!address.IsValid())
879 throw JSONRPCError(-5, "Invalid bitcoin address");
880 int64 nAmount = AmountFromValue(params[2]);
882 if (params.size() > 3)
883 nMinDepth = params[3].get_int();
886 wtx.strFromAccount = strAccount;
887 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
888 wtx.mapValue["comment"] = params[4].get_str();
889 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
890 wtx.mapValue["to"] = params[5].get_str();
892 if (pwalletMain->IsLocked())
893 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
896 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
897 if (nAmount > nBalance)
898 throw JSONRPCError(-6, "Account has insufficient funds");
901 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
903 throw JSONRPCError(-4, strError);
905 return wtx.GetHash().GetHex();
909 Value sendmany(const Array& params, bool fHelp)
911 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
913 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
914 "amounts are double-precision floating point numbers\n"
915 "requires wallet passphrase to be set with walletpassphrase first");
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");
921 string strAccount = AccountFromValue(params[0]);
922 Object sendTo = params[1].get_obj();
924 if (params.size() > 2)
925 nMinDepth = params[2].get_int();
928 wtx.strFromAccount = strAccount;
929 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
930 wtx.mapValue["comment"] = params[3].get_str();
932 set<CBitcoinAddress> setAddress;
933 vector<pair<CScript, int64> > vecSend;
935 int64 totalAmount = 0;
936 BOOST_FOREACH(const Pair& s, sendTo)
938 CBitcoinAddress address(s.name_);
939 if (!address.IsValid())
940 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
942 if (setAddress.count(address))
943 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
944 setAddress.insert(address);
946 CScript scriptPubKey;
947 scriptPubKey.SetBitcoinAddress(address);
948 int64 nAmount = AmountFromValue(s.value_);
949 totalAmount += nAmount;
951 vecSend.push_back(make_pair(scriptPubKey, nAmount));
954 if (pwalletMain->IsLocked())
955 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
958 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
959 if (totalAmount > nBalance)
960 throw JSONRPCError(-6, "Account has insufficient funds");
963 CReserveKey keyChange(pwalletMain);
964 int64 nFeeRequired = 0;
965 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
968 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
969 throw JSONRPCError(-6, "Insufficient funds");
970 throw JSONRPCError(-4, "Transaction creation failed");
972 if (!pwalletMain->CommitTransaction(wtx, keyChange))
973 throw JSONRPCError(-4, "Transaction commit failed");
975 return wtx.GetHash().GetHex();
978 Value addmultisigaddress(const Array& params, bool fHelp)
980 if (fHelp || params.size() < 2 || params.size() > 3)
982 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
983 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
984 "each key is a bitcoin address or hex-encoded public key\n"
985 "If [account] is specified, assign address to [account].";
986 throw runtime_error(msg);
989 int nRequired = params[0].get_int();
990 const Array& keys = params[1].get_array();
992 if (params.size() > 2)
993 strAccount = AccountFromValue(params[2]);
995 // Gather public keys
996 if (nRequired < 1 || keys.size() < nRequired)
998 strprintf("wrong number of keys"
999 "(got %d, need at least %d)", keys.size(), nRequired));
1000 std::vector<CKey> pubkeys;
1001 pubkeys.resize(keys.size());
1002 for (int i = 0; i < keys.size(); i++)
1004 const std::string& ks = keys[i].get_str();
1006 // Case 1: bitcoin address and we have full public key:
1007 CBitcoinAddress address(ks);
1008 if (address.IsValid())
1010 if (address.IsScript())
1011 throw runtime_error(
1012 strprintf("%s is a pay-to-script address",ks.c_str()));
1013 std::vector<unsigned char> vchPubKey;
1014 if (!pwalletMain->GetPubKey(address, vchPubKey))
1015 throw runtime_error(
1016 strprintf("no full public key for address %s",ks.c_str()));
1017 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1018 throw runtime_error(" Invalid public key: "+ks);
1021 // Case 2: hex public key
1024 vector<unsigned char> vchPubKey = ParseHex(ks);
1025 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1026 throw runtime_error(" Invalid public key: "+ks);
1030 throw runtime_error(" Invalid public key: "+ks);
1034 // Construct using pay-to-script-hash:
1036 inner.SetMultisig(nRequired, pubkeys);
1038 uint160 scriptHash = Hash160(inner);
1039 CScript scriptPubKey;
1040 scriptPubKey.SetPayToScriptHash(inner);
1041 pwalletMain->AddCScript(inner);
1042 CBitcoinAddress address;
1043 address.SetScriptHash160(scriptHash);
1045 pwalletMain->SetAddressBookName(address, strAccount);
1046 return address.ToString();
1057 nConf = std::numeric_limits<int>::max();
1061 Value ListReceived(const Array& params, bool fByAccounts)
1063 // Minimum confirmations
1065 if (params.size() > 0)
1066 nMinDepth = params[0].get_int();
1068 // Whether to include empty accounts
1069 bool fIncludeEmpty = false;
1070 if (params.size() > 1)
1071 fIncludeEmpty = params[1].get_bool();
1074 map<CBitcoinAddress, tallyitem> mapTally;
1075 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1077 const CWalletTx& wtx = (*it).second;
1079 if (wtx.IsCoinBase() || !wtx.IsFinal())
1082 int nDepth = wtx.GetDepthInMainChain();
1083 if (nDepth < nMinDepth)
1086 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1088 CBitcoinAddress address;
1089 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1092 tallyitem& item = mapTally[address];
1093 item.nAmount += txout.nValue;
1094 item.nConf = min(item.nConf, nDepth);
1100 map<string, tallyitem> mapAccountTally;
1101 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1103 const CBitcoinAddress& address = item.first;
1104 const string& strAccount = item.second;
1105 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1106 if (it == mapTally.end() && !fIncludeEmpty)
1110 int nConf = std::numeric_limits<int>::max();
1111 if (it != mapTally.end())
1113 nAmount = (*it).second.nAmount;
1114 nConf = (*it).second.nConf;
1119 tallyitem& item = mapAccountTally[strAccount];
1120 item.nAmount += nAmount;
1121 item.nConf = min(item.nConf, nConf);
1126 obj.push_back(Pair("address", address.ToString()));
1127 obj.push_back(Pair("account", strAccount));
1128 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1129 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1136 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1138 int64 nAmount = (*it).second.nAmount;
1139 int nConf = (*it).second.nConf;
1141 obj.push_back(Pair("account", (*it).first));
1142 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1143 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1151 Value listreceivedbyaddress(const Array& params, bool fHelp)
1153 if (fHelp || params.size() > 2)
1154 throw runtime_error(
1155 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1156 "[minconf] is the minimum number of confirmations before payments are included.\n"
1157 "[includeempty] whether to include addresses that haven't received any payments.\n"
1158 "Returns an array of objects containing:\n"
1159 " \"address\" : receiving address\n"
1160 " \"account\" : the account of the receiving address\n"
1161 " \"amount\" : total amount received by the address\n"
1162 " \"confirmations\" : number of confirmations of the most recent transaction included");
1164 return ListReceived(params, false);
1167 Value listreceivedbyaccount(const Array& params, bool fHelp)
1169 if (fHelp || params.size() > 2)
1170 throw runtime_error(
1171 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1172 "[minconf] is the minimum number of confirmations before payments are included.\n"
1173 "[includeempty] whether to include accounts that haven't received any payments.\n"
1174 "Returns an array of objects containing:\n"
1175 " \"account\" : the account of the receiving addresses\n"
1176 " \"amount\" : total amount received by addresses with this account\n"
1177 " \"confirmations\" : number of confirmations of the most recent transaction included");
1179 return ListReceived(params, true);
1182 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1184 int64 nGeneratedImmature, nGeneratedMature, nFee;
1185 string strSentAccount;
1186 list<pair<CBitcoinAddress, int64> > listReceived;
1187 list<pair<CBitcoinAddress, int64> > listSent;
1189 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1191 bool fAllAccounts = (strAccount == string("*"));
1193 // Generated blocks assigned to account ""
1194 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1197 entry.push_back(Pair("account", string("")));
1198 if (nGeneratedImmature)
1200 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1201 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1205 entry.push_back(Pair("category", "generate"));
1206 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1209 WalletTxToJSON(wtx, entry);
1210 ret.push_back(entry);
1214 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1216 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1219 entry.push_back(Pair("account", strSentAccount));
1220 entry.push_back(Pair("address", s.first.ToString()));
1221 entry.push_back(Pair("category", "send"));
1222 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1223 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1225 WalletTxToJSON(wtx, entry);
1226 ret.push_back(entry);
1231 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1232 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1235 if (pwalletMain->mapAddressBook.count(r.first))
1236 account = pwalletMain->mapAddressBook[r.first];
1237 if (fAllAccounts || (account == strAccount))
1240 entry.push_back(Pair("account", account));
1241 entry.push_back(Pair("address", r.first.ToString()));
1242 entry.push_back(Pair("category", "receive"));
1243 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1245 WalletTxToJSON(wtx, entry);
1246 ret.push_back(entry);
1251 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1253 bool fAllAccounts = (strAccount == string("*"));
1255 if (fAllAccounts || acentry.strAccount == strAccount)
1258 entry.push_back(Pair("account", acentry.strAccount));
1259 entry.push_back(Pair("category", "move"));
1260 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1261 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1262 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1263 entry.push_back(Pair("comment", acentry.strComment));
1264 ret.push_back(entry);
1268 Value listtransactions(const Array& params, bool fHelp)
1270 if (fHelp || params.size() > 3)
1271 throw runtime_error(
1272 "listtransactions [account] [count=10] [from=0]\n"
1273 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1275 string strAccount = "*";
1276 if (params.size() > 0)
1277 strAccount = params[0].get_str();
1279 if (params.size() > 1)
1280 nCount = params[1].get_int();
1282 if (params.size() > 2)
1283 nFrom = params[2].get_int();
1286 CWalletDB walletdb(pwalletMain->strWalletFile);
1288 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1289 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1290 typedef multimap<int64, TxPair > TxItems;
1293 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1295 CWalletTx* wtx = &((*it).second);
1296 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1298 list<CAccountingEntry> acentries;
1299 walletdb.ListAccountCreditDebit(strAccount, acentries);
1300 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1302 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1305 // Now: iterate backwards until we have nCount items to return:
1306 TxItems::reverse_iterator it = txByTime.rbegin();
1307 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1308 for (; it != txByTime.rend(); ++it)
1310 CWalletTx *const pwtx = (*it).second.first;
1312 ListTransactions(*pwtx, strAccount, 0, true, ret);
1313 CAccountingEntry *const pacentry = (*it).second.second;
1315 AcentryToJSON(*pacentry, strAccount, ret);
1317 if (ret.size() >= nCount) break;
1319 // ret is now newest to oldest
1321 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1322 if (ret.size() > nCount)
1324 Array::iterator last = ret.begin();
1325 std::advance(last, nCount);
1326 ret.erase(last, ret.end());
1328 std::reverse(ret.begin(), ret.end()); // oldest to newest
1333 Value listaccounts(const Array& params, bool fHelp)
1335 if (fHelp || params.size() > 1)
1336 throw runtime_error(
1337 "listaccounts [minconf=1]\n"
1338 "Returns Object that has account names as keys, account balances as values.");
1341 if (params.size() > 0)
1342 nMinDepth = params[0].get_int();
1344 map<string, int64> mapAccountBalances;
1345 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1346 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1347 mapAccountBalances[entry.second] = 0;
1350 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1352 const CWalletTx& wtx = (*it).second;
1353 int64 nGeneratedImmature, nGeneratedMature, nFee;
1354 string strSentAccount;
1355 list<pair<CBitcoinAddress, int64> > listReceived;
1356 list<pair<CBitcoinAddress, int64> > listSent;
1357 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1358 mapAccountBalances[strSentAccount] -= nFee;
1359 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1360 mapAccountBalances[strSentAccount] -= s.second;
1361 if (wtx.GetDepthInMainChain() >= nMinDepth)
1363 mapAccountBalances[""] += nGeneratedMature;
1364 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1365 if (pwalletMain->mapAddressBook.count(r.first))
1366 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1368 mapAccountBalances[""] += r.second;
1372 list<CAccountingEntry> acentries;
1373 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1374 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1375 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1378 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1379 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1384 Value listsinceblock(const Array& params, bool fHelp)
1387 throw runtime_error(
1388 "listsinceblock [blockid] [target-confirmations]\n"
1389 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1391 CBlockIndex *pindex = NULL;
1392 int target_confirms = 1;
1394 if (params.size() > 0)
1396 uint256 blockId = 0;
1398 blockId.SetHex(params[0].get_str());
1399 pindex = CBlockLocator(blockId).GetBlockIndex();
1402 if (params.size() > 1)
1404 target_confirms = params[1].get_int();
1406 if (target_confirms < 1)
1407 throw JSONRPCError(-8, "Invalid parameter");
1410 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1414 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1416 CWalletTx tx = (*it).second;
1418 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1419 ListTransactions(tx, "*", 0, true, transactions);
1424 if (target_confirms == 1)
1427 lastblock = hashBestChain;
1431 int target_height = pindexBest->nHeight + 1 - target_confirms;
1434 for (block = pindexBest;
1435 block && block->nHeight > target_height;
1436 block = block->pprev) { }
1438 lastblock = block ? block->GetBlockHash() : 0;
1442 ret.push_back(Pair("transactions", transactions));
1443 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1448 Value gettransaction(const Array& params, bool fHelp)
1450 if (fHelp || params.size() != 1)
1451 throw runtime_error(
1452 "gettransaction <txid>\n"
1453 "Get detailed information about <txid>");
1456 hash.SetHex(params[0].get_str());
1460 if (!pwalletMain->mapWallet.count(hash))
1461 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1462 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1464 int64 nCredit = wtx.GetCredit();
1465 int64 nDebit = wtx.GetDebit();
1466 int64 nNet = nCredit - nDebit;
1467 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1469 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1471 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1473 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1476 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1477 entry.push_back(Pair("details", details));
1483 Value backupwallet(const Array& params, bool fHelp)
1485 if (fHelp || params.size() != 1)
1486 throw runtime_error(
1487 "backupwallet <destination>\n"
1488 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1490 string strDest = params[0].get_str();
1491 BackupWallet(*pwalletMain, strDest);
1497 Value keypoolrefill(const Array& params, bool fHelp)
1499 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1500 throw runtime_error(
1502 "Fills the keypool, requires wallet passphrase to be set.");
1503 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1504 throw runtime_error(
1506 "Fills the keypool.");
1508 if (pwalletMain->IsLocked())
1509 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1511 pwalletMain->TopUpKeyPool();
1513 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1514 throw JSONRPCError(-4, "Error refreshing keypool.");
1520 void ThreadTopUpKeyPool(void* parg)
1522 pwalletMain->TopUpKeyPool();
1525 void ThreadCleanWalletPassphrase(void* parg)
1527 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1529 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1531 if (nWalletUnlockTime == 0)
1533 nWalletUnlockTime = nMyWakeTime;
1537 if (nWalletUnlockTime==0)
1539 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1543 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1545 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1549 if (nWalletUnlockTime)
1551 nWalletUnlockTime = 0;
1552 pwalletMain->Lock();
1557 if (nWalletUnlockTime < nMyWakeTime)
1558 nWalletUnlockTime = nMyWakeTime;
1561 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1563 delete (int64*)parg;
1566 Value walletpassphrase(const Array& params, bool fHelp)
1568 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1569 throw runtime_error(
1570 "walletpassphrase <passphrase> <timeout>\n"
1571 "Stores the wallet decryption key in memory for <timeout> seconds.");
1574 if (!pwalletMain->IsCrypted())
1575 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1577 if (!pwalletMain->IsLocked())
1578 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1580 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1581 SecureString strWalletPass;
1582 strWalletPass.reserve(100);
1583 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1584 // Alternately, find a way to make params[0] mlock()'d to begin with.
1585 strWalletPass = params[0].get_str().c_str();
1587 if (strWalletPass.length() > 0)
1589 if (!pwalletMain->Unlock(strWalletPass))
1590 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1593 throw runtime_error(
1594 "walletpassphrase <passphrase> <timeout>\n"
1595 "Stores the wallet decryption key in memory for <timeout> seconds.");
1597 CreateThread(ThreadTopUpKeyPool, NULL);
1598 int64* pnSleepTime = new int64(params[1].get_int64());
1599 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1605 Value walletpassphrasechange(const Array& params, bool fHelp)
1607 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1608 throw runtime_error(
1609 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1610 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1613 if (!pwalletMain->IsCrypted())
1614 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1616 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1617 // Alternately, find a way to make params[0] mlock()'d to begin with.
1618 SecureString strOldWalletPass;
1619 strOldWalletPass.reserve(100);
1620 strOldWalletPass = params[0].get_str().c_str();
1622 SecureString strNewWalletPass;
1623 strNewWalletPass.reserve(100);
1624 strNewWalletPass = params[1].get_str().c_str();
1626 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1627 throw runtime_error(
1628 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1629 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1631 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1632 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1638 Value walletlock(const Array& params, bool fHelp)
1640 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1641 throw runtime_error(
1643 "Removes the wallet encryption key from memory, locking the wallet.\n"
1644 "After calling this method, you will need to call walletpassphrase again\n"
1645 "before being able to call any methods which require the wallet to be unlocked.");
1648 if (!pwalletMain->IsCrypted())
1649 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1651 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1653 pwalletMain->Lock();
1654 nWalletUnlockTime = 0;
1661 Value encryptwallet(const Array& params, bool fHelp)
1663 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1664 throw runtime_error(
1665 "encryptwallet <passphrase>\n"
1666 "Encrypts the wallet with <passphrase>.");
1669 if (pwalletMain->IsCrypted())
1670 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1672 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1673 // Alternately, find a way to make params[0] mlock()'d to begin with.
1674 SecureString strWalletPass;
1675 strWalletPass.reserve(100);
1676 strWalletPass = params[0].get_str().c_str();
1678 if (strWalletPass.length() < 1)
1679 throw runtime_error(
1680 "encryptwallet <passphrase>\n"
1681 "Encrypts the wallet with <passphrase>.");
1683 if (!pwalletMain->EncryptWallet(strWalletPass))
1684 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1686 // BDB seems to have a bad habit of writing old data into
1687 // slack space in .dat files; that is bad if the old data is
1688 // unencrypted private keys. So:
1690 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1694 Value validateaddress(const Array& params, bool fHelp)
1696 if (fHelp || params.size() != 1)
1697 throw runtime_error(
1698 "validateaddress <bitcoinaddress>\n"
1699 "Return information about <bitcoinaddress>.");
1701 CBitcoinAddress address(params[0].get_str());
1702 bool isValid = address.IsValid();
1705 ret.push_back(Pair("isvalid", isValid));
1708 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1709 // version of the address:
1710 string currentAddress = address.ToString();
1711 ret.push_back(Pair("address", currentAddress));
1712 if (pwalletMain->HaveKey(address))
1714 ret.push_back(Pair("ismine", true));
1715 std::vector<unsigned char> vchPubKey;
1716 pwalletMain->GetPubKey(address, vchPubKey);
1717 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1719 key.SetPubKey(vchPubKey);
1720 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1722 else if (pwalletMain->HaveCScript(address.GetHash160()))
1724 ret.push_back(Pair("isscript", true));
1726 pwalletMain->GetCScript(address.GetHash160(), subscript);
1727 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1728 std::vector<CBitcoinAddress> addresses;
1729 txnouttype whichType;
1731 ExtractAddresses(subscript, whichType, addresses, nRequired);
1732 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1734 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1735 a.push_back(addr.ToString());
1736 ret.push_back(Pair("addresses", a));
1737 if (whichType == TX_MULTISIG)
1738 ret.push_back(Pair("sigsrequired", nRequired));
1741 ret.push_back(Pair("ismine", false));
1742 if (pwalletMain->mapAddressBook.count(address))
1743 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1748 Value getwork(const Array& params, bool fHelp)
1750 if (fHelp || params.size() > 1)
1751 throw runtime_error(
1753 "If [data] is not specified, returns formatted hash data to work on:\n"
1754 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1755 " \"data\" : block data\n"
1756 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1757 " \"target\" : little endian hash target\n"
1758 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1761 throw JSONRPCError(-9, "Bitcoin is not connected!");
1763 if (IsInitialBlockDownload())
1764 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1766 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1767 static mapNewBlock_t mapNewBlock;
1768 static vector<CBlock*> vNewBlock;
1769 static CReserveKey reservekey(pwalletMain);
1771 if (params.size() == 0)
1774 static unsigned int nTransactionsUpdatedLast;
1775 static CBlockIndex* pindexPrev;
1776 static int64 nStart;
1777 static CBlock* pblock;
1778 if (pindexPrev != pindexBest ||
1779 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1781 if (pindexPrev != pindexBest)
1783 // Deallocate old blocks since they're obsolete now
1784 mapNewBlock.clear();
1785 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1789 nTransactionsUpdatedLast = nTransactionsUpdated;
1790 pindexPrev = pindexBest;
1794 pblock = CreateNewBlock(reservekey);
1796 throw JSONRPCError(-7, "Out of memory");
1797 vNewBlock.push_back(pblock);
1801 pblock->UpdateTime(pindexPrev);
1804 // Update nExtraNonce
1805 static unsigned int nExtraNonce = 0;
1806 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1809 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1811 // Prebuild hash buffers
1815 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1817 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1820 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1821 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1822 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1823 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1829 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1830 if (vchData.size() != 128)
1831 throw JSONRPCError(-8, "Invalid parameter");
1832 CBlock* pdata = (CBlock*)&vchData[0];
1835 for (int i = 0; i < 128/4; i++)
1836 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1839 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1841 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1843 pblock->nTime = pdata->nTime;
1844 pblock->nNonce = pdata->nNonce;
1845 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1846 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1848 return CheckWork(pblock, *pwalletMain, reservekey);
1853 Value getmemorypool(const Array& params, bool fHelp)
1855 if (fHelp || params.size() > 1)
1856 throw runtime_error(
1857 "getmemorypool [data]\n"
1858 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1859 " \"version\" : block version\n"
1860 " \"previousblockhash\" : hash of current highest block\n"
1861 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1862 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1863 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1864 " \"time\" : timestamp appropriate for next block\n"
1865 " \"mintime\" : minimum timestamp appropriate for next block\n"
1866 " \"curtime\" : current timestamp\n"
1867 " \"bits\" : compressed target of next block\n"
1868 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1870 if (params.size() == 0)
1873 throw JSONRPCError(-9, "Bitcoin is not connected!");
1875 if (IsInitialBlockDownload())
1876 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1878 static CReserveKey reservekey(pwalletMain);
1881 static unsigned int nTransactionsUpdatedLast;
1882 static CBlockIndex* pindexPrev;
1883 static int64 nStart;
1884 static CBlock* pblock;
1885 if (pindexPrev != pindexBest ||
1886 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1888 nTransactionsUpdatedLast = nTransactionsUpdated;
1889 pindexPrev = pindexBest;
1895 pblock = CreateNewBlock(reservekey);
1897 throw JSONRPCError(-7, "Out of memory");
1901 pblock->UpdateTime(pindexPrev);
1905 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1912 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1916 result.push_back(Pair("version", pblock->nVersion));
1917 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1918 result.push_back(Pair("transactions", transactions));
1919 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1920 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1921 result.push_back(Pair("time", (int64_t)pblock->nTime));
1922 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1923 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1924 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1931 CDataStream ssBlock(ParseHex(params[0].get_str()));
1935 return ProcessBlock(NULL, &pblock);
1939 Value getblockhash(const Array& params, bool fHelp)
1941 if (fHelp || params.size() != 1)
1942 throw runtime_error(
1943 "getblockhash <index>\n"
1944 "Returns hash of block in best-block-chain at <index>.");
1946 int nHeight = params[0].get_int();
1947 if (nHeight < 0 || nHeight > nBestHeight)
1948 throw runtime_error("Block number out of range.");
1951 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1952 while (pblockindex->nHeight > nHeight)
1953 pblockindex = pblockindex->pprev;
1954 return pblockindex->phashBlock->GetHex();
1957 Value getblock(const Array& params, bool fHelp)
1959 if (fHelp || params.size() != 1)
1960 throw runtime_error(
1962 "Returns details of a block with given block-hash.");
1964 std::string strHash = params[0].get_str();
1965 uint256 hash(strHash);
1967 if (mapBlockIndex.count(hash) == 0)
1968 throw JSONRPCError(-5, "Block not found");
1971 CBlockIndex* pblockindex = mapBlockIndex[hash];
1972 block.ReadFromDisk(pblockindex, true);
1974 return blockToJSON(block, pblockindex);
1991 pair<string, rpcfn_type> pCallTable[] =
1993 make_pair("help", &help),
1994 make_pair("stop", &stop),
1995 make_pair("getblockcount", &getblockcount),
1996 make_pair("getblocknumber", &getblocknumber),
1997 make_pair("getconnectioncount", &getconnectioncount),
1998 make_pair("getdifficulty", &getdifficulty),
1999 make_pair("getgenerate", &getgenerate),
2000 make_pair("setgenerate", &setgenerate),
2001 make_pair("gethashespersec", &gethashespersec),
2002 make_pair("getinfo", &getinfo),
2003 make_pair("getmininginfo", &getmininginfo),
2004 make_pair("getnewaddress", &getnewaddress),
2005 make_pair("getaccountaddress", &getaccountaddress),
2006 make_pair("setaccount", &setaccount),
2007 make_pair("getaccount", &getaccount),
2008 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2009 make_pair("sendtoaddress", &sendtoaddress),
2010 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2011 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2012 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2013 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2014 make_pair("backupwallet", &backupwallet),
2015 make_pair("keypoolrefill", &keypoolrefill),
2016 make_pair("walletpassphrase", &walletpassphrase),
2017 make_pair("walletpassphrasechange", &walletpassphrasechange),
2018 make_pair("walletlock", &walletlock),
2019 make_pair("encryptwallet", &encryptwallet),
2020 make_pair("validateaddress", &validateaddress),
2021 make_pair("getbalance", &getbalance),
2022 make_pair("move", &movecmd),
2023 make_pair("sendfrom", &sendfrom),
2024 make_pair("sendmany", &sendmany),
2025 make_pair("addmultisigaddress", &addmultisigaddress),
2026 make_pair("getblock", &getblock),
2027 make_pair("getblockhash", &getblockhash),
2028 make_pair("gettransaction", &gettransaction),
2029 make_pair("listtransactions", &listtransactions),
2030 make_pair("signmessage", &signmessage),
2031 make_pair("verifymessage", &verifymessage),
2032 make_pair("getwork", &getwork),
2033 make_pair("listaccounts", &listaccounts),
2034 make_pair("settxfee", &settxfee),
2035 make_pair("getmemorypool", &getmemorypool),
2036 make_pair("listsinceblock", &listsinceblock),
2037 make_pair("dumpprivkey", &dumpprivkey),
2038 make_pair("importprivkey", &importprivkey)
2040 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2042 string pAllowInSafeMode[] =
2047 "getblocknumber", // deprecated
2048 "getconnectioncount",
2056 "getaccountaddress",
2058 "getaddressesbyaccount",
2067 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2075 // This ain't Apache. We're just using HTTP header for the length field
2076 // and to be compatible with other JSON-RPC implementations.
2079 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2082 s << "POST / HTTP/1.1\r\n"
2083 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2084 << "Host: 127.0.0.1\r\n"
2085 << "Content-Type: application/json\r\n"
2086 << "Content-Length: " << strMsg.size() << "\r\n"
2087 << "Connection: close\r\n"
2088 << "Accept: application/json\r\n";
2089 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2090 s << item.first << ": " << item.second << "\r\n";
2091 s << "\r\n" << strMsg;
2096 string rfc1123Time()
2101 struct tm* now_gmt = gmtime(&now);
2102 string locale(setlocale(LC_TIME, NULL));
2103 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2104 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2105 setlocale(LC_TIME, locale.c_str());
2106 return string(buffer);
2109 static string HTTPReply(int nStatus, const string& strMsg)
2112 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2114 "Server: bitcoin-json-rpc/%s\r\n"
2115 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2116 "Content-Type: text/html\r\n"
2117 "Content-Length: 296\r\n"
2119 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2120 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2123 "<TITLE>Error</TITLE>\r\n"
2124 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2126 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2127 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2128 const char *cStatus;
2129 if (nStatus == 200) cStatus = "OK";
2130 else if (nStatus == 400) cStatus = "Bad Request";
2131 else if (nStatus == 403) cStatus = "Forbidden";
2132 else if (nStatus == 404) cStatus = "Not Found";
2133 else if (nStatus == 500) cStatus = "Internal Server Error";
2136 "HTTP/1.1 %d %s\r\n"
2138 "Connection: close\r\n"
2139 "Content-Length: %d\r\n"
2140 "Content-Type: application/json\r\n"
2141 "Server: bitcoin-json-rpc/%s\r\n"
2146 rfc1123Time().c_str(),
2148 FormatFullVersion().c_str(),
2152 int ReadHTTPStatus(std::basic_istream<char>& stream)
2155 getline(stream, str);
2156 vector<string> vWords;
2157 boost::split(vWords, str, boost::is_any_of(" "));
2158 if (vWords.size() < 2)
2160 return atoi(vWords[1].c_str());
2163 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2169 std::getline(stream, str);
2170 if (str.empty() || str == "\r")
2172 string::size_type nColon = str.find(":");
2173 if (nColon != string::npos)
2175 string strHeader = str.substr(0, nColon);
2176 boost::trim(strHeader);
2177 boost::to_lower(strHeader);
2178 string strValue = str.substr(nColon+1);
2179 boost::trim(strValue);
2180 mapHeadersRet[strHeader] = strValue;
2181 if (strHeader == "content-length")
2182 nLen = atoi(strValue.c_str());
2188 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2190 mapHeadersRet.clear();
2194 int nStatus = ReadHTTPStatus(stream);
2197 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2198 if (nLen < 0 || nLen > MAX_SIZE)
2204 vector<char> vch(nLen);
2205 stream.read(&vch[0], nLen);
2206 strMessageRet = string(vch.begin(), vch.end());
2212 bool HTTPAuthorized(map<string, string>& mapHeaders)
2214 string strAuth = mapHeaders["authorization"];
2215 if (strAuth.substr(0,6) != "Basic ")
2217 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2218 string strUserPass = DecodeBase64(strUserPass64);
2219 return strUserPass == strRPCUserColonPass;
2223 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2224 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2225 // unspecified (HTTP errors and contents of 'error').
2227 // 1.0 spec: http://json-rpc.org/wiki/specification
2228 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2229 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2232 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2235 request.push_back(Pair("method", strMethod));
2236 request.push_back(Pair("params", params));
2237 request.push_back(Pair("id", id));
2238 return write_string(Value(request), false) + "\n";
2241 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2244 if (error.type() != null_type)
2245 reply.push_back(Pair("result", Value::null));
2247 reply.push_back(Pair("result", result));
2248 reply.push_back(Pair("error", error));
2249 reply.push_back(Pair("id", id));
2250 return write_string(Value(reply), false) + "\n";
2253 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2255 // Send error reply from json-rpc error object
2257 int code = find_value(objError, "code").get_int();
2258 if (code == -32600) nStatus = 400;
2259 else if (code == -32601) nStatus = 404;
2260 string strReply = JSONRPCReply(Value::null, objError, id);
2261 stream << HTTPReply(nStatus, strReply) << std::flush;
2264 bool ClientAllowed(const string& strAddress)
2266 if (strAddress == asio::ip::address_v4::loopback().to_string())
2268 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2269 BOOST_FOREACH(string strAllow, vAllow)
2270 if (WildcardMatch(strAddress, strAllow))
2276 // IOStream device that speaks SSL but can also speak non-SSL
2278 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2280 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2282 fUseSSL = fUseSSLIn;
2283 fNeedHandshake = fUseSSLIn;
2286 void handshake(ssl::stream_base::handshake_type role)
2288 if (!fNeedHandshake) return;
2289 fNeedHandshake = false;
2290 stream.handshake(role);
2292 std::streamsize read(char* s, std::streamsize n)
2294 handshake(ssl::stream_base::server); // HTTPS servers read first
2295 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2296 return stream.next_layer().read_some(asio::buffer(s, n));
2298 std::streamsize write(const char* s, std::streamsize n)
2300 handshake(ssl::stream_base::client); // HTTPS clients write first
2301 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2302 return asio::write(stream.next_layer(), asio::buffer(s, n));
2304 bool connect(const std::string& server, const std::string& port)
2306 ip::tcp::resolver resolver(stream.get_io_service());
2307 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2308 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2309 ip::tcp::resolver::iterator end;
2310 boost::system::error_code error = asio::error::host_not_found;
2311 while (error && endpoint_iterator != end)
2313 stream.lowest_layer().close();
2314 stream.lowest_layer().connect(*endpoint_iterator++, error);
2322 bool fNeedHandshake;
2327 void ThreadRPCServer(void* parg)
2329 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2332 vnThreadsRunning[THREAD_RPCSERVER]++;
2333 ThreadRPCServer2(parg);
2334 vnThreadsRunning[THREAD_RPCSERVER]--;
2336 catch (std::exception& e) {
2337 vnThreadsRunning[THREAD_RPCSERVER]--;
2338 PrintException(&e, "ThreadRPCServer()");
2340 vnThreadsRunning[THREAD_RPCSERVER]--;
2341 PrintException(NULL, "ThreadRPCServer()");
2343 printf("ThreadRPCServer exiting\n");
2346 void ThreadRPCServer2(void* parg)
2348 printf("ThreadRPCServer started\n");
2350 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2351 if (mapArgs["-rpcpassword"] == "")
2353 unsigned char rand_pwd[32];
2354 RAND_bytes(rand_pwd, 32);
2355 string strWhatAmI = "To use bitcoind";
2356 if (mapArgs.count("-server"))
2357 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2358 else if (mapArgs.count("-daemon"))
2359 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2360 ThreadSafeMessageBox(strprintf(
2361 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2362 "It is recommended you use the following random password:\n"
2363 "rpcuser=bitcoinrpc\n"
2365 "(you do not need to remember this password)\n"
2366 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2368 GetConfigFile().c_str(),
2369 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2370 _("Error"), wxOK | wxMODAL);
2375 bool fUseSSL = GetBoolArg("-rpcssl");
2376 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2378 asio::io_service io_service;
2379 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2380 ip::tcp::acceptor acceptor(io_service);
2383 acceptor.open(endpoint.protocol());
2384 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2385 acceptor.bind(endpoint);
2386 acceptor.listen(socket_base::max_connections);
2388 catch(system::system_error &e)
2390 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2391 _("Error"), wxOK | wxMODAL);
2396 ssl::context context(io_service, ssl::context::sslv23);
2399 context.set_options(ssl::context::no_sslv2);
2400 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2401 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2402 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2403 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2404 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2405 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2406 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2407 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2409 string ciphers = GetArg("-rpcsslciphers",
2410 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2411 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2416 // Accept connection
2417 SSLStream sslStream(io_service, context);
2418 SSLIOStreamDevice d(sslStream, fUseSSL);
2419 iostreams::stream<SSLIOStreamDevice> stream(d);
2421 ip::tcp::endpoint peer;
2422 vnThreadsRunning[THREAD_RPCSERVER]--;
2423 acceptor.accept(sslStream.lowest_layer(), peer);
2424 vnThreadsRunning[4]++;
2428 // Restrict callers by IP
2429 if (!ClientAllowed(peer.address().to_string()))
2431 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2433 stream << HTTPReply(403, "") << std::flush;
2437 map<string, string> mapHeaders;
2440 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2441 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2444 printf("ThreadRPCServer ReadHTTP timeout\n");
2448 // Check authorization
2449 if (mapHeaders.count("authorization") == 0)
2451 stream << HTTPReply(401, "") << std::flush;
2454 if (!HTTPAuthorized(mapHeaders))
2456 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2457 /* Deter brute-forcing short passwords.
2458 If this results in a DOS the user really
2459 shouldn't have their RPC port exposed.*/
2460 if (mapArgs["-rpcpassword"].size() < 20)
2463 stream << HTTPReply(401, "") << std::flush;
2467 Value id = Value::null;
2472 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2473 throw JSONRPCError(-32700, "Parse error");
2474 const Object& request = valRequest.get_obj();
2476 // Parse id now so errors from here on will have the id
2477 id = find_value(request, "id");
2480 Value valMethod = find_value(request, "method");
2481 if (valMethod.type() == null_type)
2482 throw JSONRPCError(-32600, "Missing method");
2483 if (valMethod.type() != str_type)
2484 throw JSONRPCError(-32600, "Method must be a string");
2485 string strMethod = valMethod.get_str();
2486 if (strMethod != "getwork" && strMethod != "getmemorypool")
2487 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2490 Value valParams = find_value(request, "params");
2492 if (valParams.type() == array_type)
2493 params = valParams.get_array();
2494 else if (valParams.type() == null_type)
2497 throw JSONRPCError(-32600, "Params must be an array");
2500 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2501 if (mi == mapCallTable.end())
2502 throw JSONRPCError(-32601, "Method not found");
2504 // Observe safe mode
2505 string strWarning = GetWarnings("rpc");
2506 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2507 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2513 CRITICAL_BLOCK(cs_main)
2514 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2515 result = (*(*mi).second)(params, false);
2518 string strReply = JSONRPCReply(result, Value::null, id);
2519 stream << HTTPReply(200, strReply) << std::flush;
2521 catch (std::exception& e)
2523 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2526 catch (Object& objError)
2528 ErrorReply(stream, objError, id);
2530 catch (std::exception& e)
2532 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2540 Object CallRPC(const string& strMethod, const Array& params)
2542 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2543 throw runtime_error(strprintf(
2544 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2545 "If the file does not exist, create it with owner-readable-only file permissions."),
2546 GetConfigFile().c_str()));
2548 // Connect to localhost
2549 bool fUseSSL = GetBoolArg("-rpcssl");
2550 asio::io_service io_service;
2551 ssl::context context(io_service, ssl::context::sslv23);
2552 context.set_options(ssl::context::no_sslv2);
2553 SSLStream sslStream(io_service, context);
2554 SSLIOStreamDevice d(sslStream, fUseSSL);
2555 iostreams::stream<SSLIOStreamDevice> stream(d);
2556 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2557 throw runtime_error("couldn't connect to server");
2559 // HTTP basic authentication
2560 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2561 map<string, string> mapRequestHeaders;
2562 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2565 string strRequest = JSONRPCRequest(strMethod, params, 1);
2566 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2567 stream << strPost << std::flush;
2570 map<string, string> mapHeaders;
2572 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2574 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2575 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2576 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2577 else if (strReply.empty())
2578 throw runtime_error("no response from server");
2582 if (!read_string(strReply, valReply))
2583 throw runtime_error("couldn't parse reply from server");
2584 const Object& reply = valReply.get_obj();
2586 throw runtime_error("expected reply to have result, error and id properties");
2594 template<typename T>
2595 void ConvertTo(Value& value)
2597 if (value.type() == str_type)
2599 // reinterpret string as unquoted json value
2601 if (!read_string(value.get_str(), value2))
2602 throw runtime_error("type mismatch");
2603 value = value2.get_value<T>();
2607 value = value.get_value<T>();
2611 int CommandLineRPC(int argc, char *argv[])
2618 while (argc > 1 && IsSwitchChar(argv[1][0]))
2626 throw runtime_error("too few parameters");
2627 string strMethod = argv[1];
2629 // Parameters default to strings
2631 for (int i = 2; i < argc; i++)
2632 params.push_back(argv[i]);
2633 int n = params.size();
2636 // Special case non-string parameter types
2638 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2639 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2640 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2641 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2642 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2643 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2644 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2645 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2646 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2647 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2648 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2649 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2650 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2651 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2652 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2653 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2654 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2655 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2656 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2657 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2658 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "sendmany" && n > 1)
2661 string s = params[1].get_str();
2663 if (!read_string(s, v) || v.type() != obj_type)
2664 throw runtime_error("type mismatch");
2665 params[1] = v.get_obj();
2667 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2668 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2669 if (strMethod == "addmultisigaddress" && n > 1)
2671 string s = params[1].get_str();
2673 if (!read_string(s, v) || v.type() != array_type)
2674 throw runtime_error("type mismatch "+s);
2675 params[1] = v.get_array();
2679 Object reply = CallRPC(strMethod, params);
2682 const Value& result = find_value(reply, "result");
2683 const Value& error = find_value(reply, "error");
2685 if (error.type() != null_type)
2688 strPrint = "error: " + write_string(error, false);
2689 int code = find_value(error.get_obj(), "code").get_int();
2695 if (result.type() == null_type)
2697 else if (result.type() == str_type)
2698 strPrint = result.get_str();
2700 strPrint = write_string(result, true);
2703 catch (std::exception& e)
2705 strPrint = string("error: ") + e.what();
2710 PrintException(NULL, "CommandLineRPC()");
2715 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2724 int main(int argc, char *argv[])
2727 // Turn off microsoft heap dump noise
2728 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2729 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2731 setbuf(stdin, NULL);
2732 setbuf(stdout, NULL);
2733 setbuf(stderr, NULL);
2737 if (argc >= 2 && string(argv[1]) == "-server")
2739 printf("server ready\n");
2740 ThreadRPCServer(NULL);
2744 return CommandLineRPC(argc, argv);
2747 catch (std::exception& e) {
2748 PrintException(&e, "main()");
2750 PrintException(NULL, "main()");