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 throw runtime_error("addmultisigaddress available only when running -testnet\n");
992 int nRequired = params[0].get_int();
993 const Array& keys = params[1].get_array();
995 if (params.size() > 2)
996 strAccount = AccountFromValue(params[2]);
998 // Gather public keys
999 if (nRequired < 1 || keys.size() < nRequired)
1000 throw runtime_error(
1001 strprintf("wrong number of keys"
1002 "(got %d, need at least %d)", keys.size(), nRequired));
1003 std::vector<CKey> pubkeys;
1004 pubkeys.resize(keys.size());
1005 for (int i = 0; i < keys.size(); i++)
1007 const std::string& ks = keys[i].get_str();
1009 // Case 1: bitcoin address and we have full public key:
1010 CBitcoinAddress address(ks);
1011 if (address.IsValid())
1013 if (address.IsScript())
1014 throw runtime_error(
1015 strprintf("%s is a pay-to-script address",ks.c_str()));
1016 std::vector<unsigned char> vchPubKey;
1017 if (!pwalletMain->GetPubKey(address, vchPubKey))
1018 throw runtime_error(
1019 strprintf("no full public key for address %s",ks.c_str()));
1020 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1021 throw runtime_error(" Invalid public key: "+ks);
1024 // Case 2: hex public key
1027 vector<unsigned char> vchPubKey = ParseHex(ks);
1028 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1029 throw runtime_error(" Invalid public key: "+ks);
1033 throw runtime_error(" Invalid public key: "+ks);
1037 // Construct using pay-to-script-hash:
1039 inner.SetMultisig(nRequired, pubkeys);
1041 uint160 scriptHash = Hash160(inner);
1042 CScript scriptPubKey;
1043 scriptPubKey.SetPayToScriptHash(inner);
1044 pwalletMain->AddCScript(inner);
1045 CBitcoinAddress address;
1046 address.SetScriptHash160(scriptHash);
1048 pwalletMain->SetAddressBookName(address, strAccount);
1049 return address.ToString();
1060 nConf = std::numeric_limits<int>::max();
1064 Value ListReceived(const Array& params, bool fByAccounts)
1066 // Minimum confirmations
1068 if (params.size() > 0)
1069 nMinDepth = params[0].get_int();
1071 // Whether to include empty accounts
1072 bool fIncludeEmpty = false;
1073 if (params.size() > 1)
1074 fIncludeEmpty = params[1].get_bool();
1077 map<CBitcoinAddress, tallyitem> mapTally;
1078 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1080 const CWalletTx& wtx = (*it).second;
1082 if (wtx.IsCoinBase() || !wtx.IsFinal())
1085 int nDepth = wtx.GetDepthInMainChain();
1086 if (nDepth < nMinDepth)
1089 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1091 CBitcoinAddress address;
1092 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1095 tallyitem& item = mapTally[address];
1096 item.nAmount += txout.nValue;
1097 item.nConf = min(item.nConf, nDepth);
1103 map<string, tallyitem> mapAccountTally;
1104 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1106 const CBitcoinAddress& address = item.first;
1107 const string& strAccount = item.second;
1108 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1109 if (it == mapTally.end() && !fIncludeEmpty)
1113 int nConf = std::numeric_limits<int>::max();
1114 if (it != mapTally.end())
1116 nAmount = (*it).second.nAmount;
1117 nConf = (*it).second.nConf;
1122 tallyitem& item = mapAccountTally[strAccount];
1123 item.nAmount += nAmount;
1124 item.nConf = min(item.nConf, nConf);
1129 obj.push_back(Pair("address", address.ToString()));
1130 obj.push_back(Pair("account", strAccount));
1131 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1132 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1139 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1141 int64 nAmount = (*it).second.nAmount;
1142 int nConf = (*it).second.nConf;
1144 obj.push_back(Pair("account", (*it).first));
1145 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1146 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1154 Value listreceivedbyaddress(const Array& params, bool fHelp)
1156 if (fHelp || params.size() > 2)
1157 throw runtime_error(
1158 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1159 "[minconf] is the minimum number of confirmations before payments are included.\n"
1160 "[includeempty] whether to include addresses that haven't received any payments.\n"
1161 "Returns an array of objects containing:\n"
1162 " \"address\" : receiving address\n"
1163 " \"account\" : the account of the receiving address\n"
1164 " \"amount\" : total amount received by the address\n"
1165 " \"confirmations\" : number of confirmations of the most recent transaction included");
1167 return ListReceived(params, false);
1170 Value listreceivedbyaccount(const Array& params, bool fHelp)
1172 if (fHelp || params.size() > 2)
1173 throw runtime_error(
1174 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1175 "[minconf] is the minimum number of confirmations before payments are included.\n"
1176 "[includeempty] whether to include accounts that haven't received any payments.\n"
1177 "Returns an array of objects containing:\n"
1178 " \"account\" : the account of the receiving addresses\n"
1179 " \"amount\" : total amount received by addresses with this account\n"
1180 " \"confirmations\" : number of confirmations of the most recent transaction included");
1182 return ListReceived(params, true);
1185 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1187 int64 nGeneratedImmature, nGeneratedMature, nFee;
1188 string strSentAccount;
1189 list<pair<CBitcoinAddress, int64> > listReceived;
1190 list<pair<CBitcoinAddress, int64> > listSent;
1192 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1194 bool fAllAccounts = (strAccount == string("*"));
1196 // Generated blocks assigned to account ""
1197 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1200 entry.push_back(Pair("account", string("")));
1201 if (nGeneratedImmature)
1203 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1204 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1208 entry.push_back(Pair("category", "generate"));
1209 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1212 WalletTxToJSON(wtx, entry);
1213 ret.push_back(entry);
1217 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1219 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1222 entry.push_back(Pair("account", strSentAccount));
1223 entry.push_back(Pair("address", s.first.ToString()));
1224 entry.push_back(Pair("category", "send"));
1225 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1226 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1228 WalletTxToJSON(wtx, entry);
1229 ret.push_back(entry);
1234 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1235 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1238 if (pwalletMain->mapAddressBook.count(r.first))
1239 account = pwalletMain->mapAddressBook[r.first];
1240 if (fAllAccounts || (account == strAccount))
1243 entry.push_back(Pair("account", account));
1244 entry.push_back(Pair("address", r.first.ToString()));
1245 entry.push_back(Pair("category", "receive"));
1246 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1248 WalletTxToJSON(wtx, entry);
1249 ret.push_back(entry);
1254 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1256 bool fAllAccounts = (strAccount == string("*"));
1258 if (fAllAccounts || acentry.strAccount == strAccount)
1261 entry.push_back(Pair("account", acentry.strAccount));
1262 entry.push_back(Pair("category", "move"));
1263 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1264 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1265 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1266 entry.push_back(Pair("comment", acentry.strComment));
1267 ret.push_back(entry);
1271 Value listtransactions(const Array& params, bool fHelp)
1273 if (fHelp || params.size() > 3)
1274 throw runtime_error(
1275 "listtransactions [account] [count=10] [from=0]\n"
1276 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1278 string strAccount = "*";
1279 if (params.size() > 0)
1280 strAccount = params[0].get_str();
1282 if (params.size() > 1)
1283 nCount = params[1].get_int();
1285 if (params.size() > 2)
1286 nFrom = params[2].get_int();
1289 throw JSONRPCError(-8, "Negative count");
1291 throw JSONRPCError(-8, "Negative from");
1294 CWalletDB walletdb(pwalletMain->strWalletFile);
1296 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1297 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1298 typedef multimap<int64, TxPair > TxItems;
1301 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1302 // would make this much faster for applications that do this a lot.
1303 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1305 CWalletTx* wtx = &((*it).second);
1306 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1308 list<CAccountingEntry> acentries;
1309 walletdb.ListAccountCreditDebit(strAccount, acentries);
1310 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1312 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1315 // iterate backwards until we have nCount items to return:
1316 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1318 CWalletTx *const pwtx = (*it).second.first;
1320 ListTransactions(*pwtx, strAccount, 0, true, ret);
1321 CAccountingEntry *const pacentry = (*it).second.second;
1323 AcentryToJSON(*pacentry, strAccount, ret);
1325 if (ret.size() >= (nCount+nFrom)) break;
1327 // ret is newest to oldest
1329 if (nFrom > ret.size()) nFrom = ret.size();
1330 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1331 Array::iterator first = ret.begin();
1332 std::advance(first, nFrom);
1333 Array::iterator last = ret.begin();
1334 std::advance(last, nFrom+nCount);
1336 if (last != ret.end()) ret.erase(last, ret.end());
1337 if (first != ret.begin()) ret.erase(ret.begin(), first);
1339 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1344 Value listaccounts(const Array& params, bool fHelp)
1346 if (fHelp || params.size() > 1)
1347 throw runtime_error(
1348 "listaccounts [minconf=1]\n"
1349 "Returns Object that has account names as keys, account balances as values.");
1352 if (params.size() > 0)
1353 nMinDepth = params[0].get_int();
1355 map<string, int64> mapAccountBalances;
1356 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1357 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1358 mapAccountBalances[entry.second] = 0;
1361 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1363 const CWalletTx& wtx = (*it).second;
1364 int64 nGeneratedImmature, nGeneratedMature, nFee;
1365 string strSentAccount;
1366 list<pair<CBitcoinAddress, int64> > listReceived;
1367 list<pair<CBitcoinAddress, int64> > listSent;
1368 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1369 mapAccountBalances[strSentAccount] -= nFee;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1371 mapAccountBalances[strSentAccount] -= s.second;
1372 if (wtx.GetDepthInMainChain() >= nMinDepth)
1374 mapAccountBalances[""] += nGeneratedMature;
1375 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1376 if (pwalletMain->mapAddressBook.count(r.first))
1377 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1379 mapAccountBalances[""] += r.second;
1383 list<CAccountingEntry> acentries;
1384 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1385 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1386 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1389 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1390 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1395 Value listsinceblock(const Array& params, bool fHelp)
1398 throw runtime_error(
1399 "listsinceblock [blockid] [target-confirmations]\n"
1400 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1402 CBlockIndex *pindex = NULL;
1403 int target_confirms = 1;
1405 if (params.size() > 0)
1407 uint256 blockId = 0;
1409 blockId.SetHex(params[0].get_str());
1410 pindex = CBlockLocator(blockId).GetBlockIndex();
1413 if (params.size() > 1)
1415 target_confirms = params[1].get_int();
1417 if (target_confirms < 1)
1418 throw JSONRPCError(-8, "Invalid parameter");
1421 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1425 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1427 CWalletTx tx = (*it).second;
1429 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1430 ListTransactions(tx, "*", 0, true, transactions);
1435 if (target_confirms == 1)
1438 lastblock = hashBestChain;
1442 int target_height = pindexBest->nHeight + 1 - target_confirms;
1445 for (block = pindexBest;
1446 block && block->nHeight > target_height;
1447 block = block->pprev) { }
1449 lastblock = block ? block->GetBlockHash() : 0;
1453 ret.push_back(Pair("transactions", transactions));
1454 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1459 Value gettransaction(const Array& params, bool fHelp)
1461 if (fHelp || params.size() != 1)
1462 throw runtime_error(
1463 "gettransaction <txid>\n"
1464 "Get detailed information about <txid>");
1467 hash.SetHex(params[0].get_str());
1471 if (!pwalletMain->mapWallet.count(hash))
1472 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1473 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1475 int64 nCredit = wtx.GetCredit();
1476 int64 nDebit = wtx.GetDebit();
1477 int64 nNet = nCredit - nDebit;
1478 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1480 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1482 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1484 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1487 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1488 entry.push_back(Pair("details", details));
1494 Value backupwallet(const Array& params, bool fHelp)
1496 if (fHelp || params.size() != 1)
1497 throw runtime_error(
1498 "backupwallet <destination>\n"
1499 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1501 string strDest = params[0].get_str();
1502 BackupWallet(*pwalletMain, strDest);
1508 Value keypoolrefill(const Array& params, bool fHelp)
1510 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511 throw runtime_error(
1513 "Fills the keypool, requires wallet passphrase to be set.");
1514 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1515 throw runtime_error(
1517 "Fills the keypool.");
1519 if (pwalletMain->IsLocked())
1520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1522 pwalletMain->TopUpKeyPool();
1524 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1525 throw JSONRPCError(-4, "Error refreshing keypool.");
1531 void ThreadTopUpKeyPool(void* parg)
1533 pwalletMain->TopUpKeyPool();
1536 void ThreadCleanWalletPassphrase(void* parg)
1538 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1540 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1542 if (nWalletUnlockTime == 0)
1544 nWalletUnlockTime = nMyWakeTime;
1548 if (nWalletUnlockTime==0)
1550 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1554 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1560 if (nWalletUnlockTime)
1562 nWalletUnlockTime = 0;
1563 pwalletMain->Lock();
1568 if (nWalletUnlockTime < nMyWakeTime)
1569 nWalletUnlockTime = nMyWakeTime;
1572 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1574 delete (int64*)parg;
1577 Value walletpassphrase(const Array& params, bool fHelp)
1579 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1580 throw runtime_error(
1581 "walletpassphrase <passphrase> <timeout>\n"
1582 "Stores the wallet decryption key in memory for <timeout> seconds.");
1585 if (!pwalletMain->IsCrypted())
1586 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1588 if (!pwalletMain->IsLocked())
1589 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1591 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1592 SecureString strWalletPass;
1593 strWalletPass.reserve(100);
1594 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1595 // Alternately, find a way to make params[0] mlock()'d to begin with.
1596 strWalletPass = params[0].get_str().c_str();
1598 if (strWalletPass.length() > 0)
1600 if (!pwalletMain->Unlock(strWalletPass))
1601 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1604 throw runtime_error(
1605 "walletpassphrase <passphrase> <timeout>\n"
1606 "Stores the wallet decryption key in memory for <timeout> seconds.");
1608 CreateThread(ThreadTopUpKeyPool, NULL);
1609 int64* pnSleepTime = new int64(params[1].get_int64());
1610 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1616 Value walletpassphrasechange(const Array& params, bool fHelp)
1618 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1619 throw runtime_error(
1620 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1621 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1624 if (!pwalletMain->IsCrypted())
1625 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1627 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1628 // Alternately, find a way to make params[0] mlock()'d to begin with.
1629 SecureString strOldWalletPass;
1630 strOldWalletPass.reserve(100);
1631 strOldWalletPass = params[0].get_str().c_str();
1633 SecureString strNewWalletPass;
1634 strNewWalletPass.reserve(100);
1635 strNewWalletPass = params[1].get_str().c_str();
1637 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1638 throw runtime_error(
1639 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1640 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1642 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1643 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1649 Value walletlock(const Array& params, bool fHelp)
1651 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1652 throw runtime_error(
1654 "Removes the wallet encryption key from memory, locking the wallet.\n"
1655 "After calling this method, you will need to call walletpassphrase again\n"
1656 "before being able to call any methods which require the wallet to be unlocked.");
1659 if (!pwalletMain->IsCrypted())
1660 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1662 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1664 pwalletMain->Lock();
1665 nWalletUnlockTime = 0;
1672 Value encryptwallet(const Array& params, bool fHelp)
1674 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1675 throw runtime_error(
1676 "encryptwallet <passphrase>\n"
1677 "Encrypts the wallet with <passphrase>.");
1680 if (pwalletMain->IsCrypted())
1681 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1683 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1684 // Alternately, find a way to make params[0] mlock()'d to begin with.
1685 SecureString strWalletPass;
1686 strWalletPass.reserve(100);
1687 strWalletPass = params[0].get_str().c_str();
1689 if (strWalletPass.length() < 1)
1690 throw runtime_error(
1691 "encryptwallet <passphrase>\n"
1692 "Encrypts the wallet with <passphrase>.");
1694 if (!pwalletMain->EncryptWallet(strWalletPass))
1695 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1697 // BDB seems to have a bad habit of writing old data into
1698 // slack space in .dat files; that is bad if the old data is
1699 // unencrypted private keys. So:
1701 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1705 Value validateaddress(const Array& params, bool fHelp)
1707 if (fHelp || params.size() != 1)
1708 throw runtime_error(
1709 "validateaddress <bitcoinaddress>\n"
1710 "Return information about <bitcoinaddress>.");
1712 CBitcoinAddress address(params[0].get_str());
1713 bool isValid = address.IsValid();
1716 ret.push_back(Pair("isvalid", isValid));
1719 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1720 // version of the address:
1721 string currentAddress = address.ToString();
1722 ret.push_back(Pair("address", currentAddress));
1723 if (pwalletMain->HaveKey(address))
1725 ret.push_back(Pair("ismine", true));
1726 std::vector<unsigned char> vchPubKey;
1727 pwalletMain->GetPubKey(address, vchPubKey);
1728 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1730 key.SetPubKey(vchPubKey);
1731 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1733 else if (pwalletMain->HaveCScript(address.GetHash160()))
1735 ret.push_back(Pair("isscript", true));
1737 pwalletMain->GetCScript(address.GetHash160(), subscript);
1738 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1739 std::vector<CBitcoinAddress> addresses;
1740 txnouttype whichType;
1742 ExtractAddresses(subscript, whichType, addresses, nRequired);
1743 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1745 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1746 a.push_back(addr.ToString());
1747 ret.push_back(Pair("addresses", a));
1748 if (whichType == TX_MULTISIG)
1749 ret.push_back(Pair("sigsrequired", nRequired));
1752 ret.push_back(Pair("ismine", false));
1753 if (pwalletMain->mapAddressBook.count(address))
1754 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1759 Value getwork(const Array& params, bool fHelp)
1761 if (fHelp || params.size() > 1)
1762 throw runtime_error(
1764 "If [data] is not specified, returns formatted hash data to work on:\n"
1765 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1766 " \"data\" : block data\n"
1767 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1768 " \"target\" : little endian hash target\n"
1769 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1772 throw JSONRPCError(-9, "Bitcoin is not connected!");
1774 if (IsInitialBlockDownload())
1775 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1777 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1778 static mapNewBlock_t mapNewBlock;
1779 static vector<CBlock*> vNewBlock;
1780 static CReserveKey reservekey(pwalletMain);
1782 if (params.size() == 0)
1785 static unsigned int nTransactionsUpdatedLast;
1786 static CBlockIndex* pindexPrev;
1787 static int64 nStart;
1788 static CBlock* pblock;
1789 if (pindexPrev != pindexBest ||
1790 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1792 if (pindexPrev != pindexBest)
1794 // Deallocate old blocks since they're obsolete now
1795 mapNewBlock.clear();
1796 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1800 nTransactionsUpdatedLast = nTransactionsUpdated;
1801 pindexPrev = pindexBest;
1805 pblock = CreateNewBlock(reservekey);
1807 throw JSONRPCError(-7, "Out of memory");
1808 vNewBlock.push_back(pblock);
1812 pblock->UpdateTime(pindexPrev);
1815 // Update nExtraNonce
1816 static unsigned int nExtraNonce = 0;
1817 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1820 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1822 // Prebuild hash buffers
1826 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1828 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1831 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1832 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1833 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1834 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1840 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1841 if (vchData.size() != 128)
1842 throw JSONRPCError(-8, "Invalid parameter");
1843 CBlock* pdata = (CBlock*)&vchData[0];
1846 for (int i = 0; i < 128/4; i++)
1847 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1850 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1852 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1854 pblock->nTime = pdata->nTime;
1855 pblock->nNonce = pdata->nNonce;
1856 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1857 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1859 return CheckWork(pblock, *pwalletMain, reservekey);
1864 Value getmemorypool(const Array& params, bool fHelp)
1866 if (fHelp || params.size() > 1)
1867 throw runtime_error(
1868 "getmemorypool [data]\n"
1869 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1870 " \"version\" : block version\n"
1871 " \"previousblockhash\" : hash of current highest block\n"
1872 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1873 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1874 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1875 " \"time\" : timestamp appropriate for next block\n"
1876 " \"mintime\" : minimum timestamp appropriate for next block\n"
1877 " \"curtime\" : current timestamp\n"
1878 " \"bits\" : compressed target of next block\n"
1879 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1881 if (params.size() == 0)
1884 throw JSONRPCError(-9, "Bitcoin is not connected!");
1886 if (IsInitialBlockDownload())
1887 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1889 static CReserveKey reservekey(pwalletMain);
1892 static unsigned int nTransactionsUpdatedLast;
1893 static CBlockIndex* pindexPrev;
1894 static int64 nStart;
1895 static CBlock* pblock;
1896 if (pindexPrev != pindexBest ||
1897 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1899 nTransactionsUpdatedLast = nTransactionsUpdated;
1900 pindexPrev = pindexBest;
1906 pblock = CreateNewBlock(reservekey);
1908 throw JSONRPCError(-7, "Out of memory");
1912 pblock->UpdateTime(pindexPrev);
1916 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1923 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1927 result.push_back(Pair("version", pblock->nVersion));
1928 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1929 result.push_back(Pair("transactions", transactions));
1930 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1931 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1932 result.push_back(Pair("time", (int64_t)pblock->nTime));
1933 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1934 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1935 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1942 CDataStream ssBlock(ParseHex(params[0].get_str()));
1946 return ProcessBlock(NULL, &pblock);
1950 Value getblockhash(const Array& params, bool fHelp)
1952 if (fHelp || params.size() != 1)
1953 throw runtime_error(
1954 "getblockhash <index>\n"
1955 "Returns hash of block in best-block-chain at <index>.");
1957 int nHeight = params[0].get_int();
1958 if (nHeight < 0 || nHeight > nBestHeight)
1959 throw runtime_error("Block number out of range.");
1962 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1963 while (pblockindex->nHeight > nHeight)
1964 pblockindex = pblockindex->pprev;
1965 return pblockindex->phashBlock->GetHex();
1968 Value getblock(const Array& params, bool fHelp)
1970 if (fHelp || params.size() != 1)
1971 throw runtime_error(
1973 "Returns details of a block with given block-hash.");
1975 std::string strHash = params[0].get_str();
1976 uint256 hash(strHash);
1978 if (mapBlockIndex.count(hash) == 0)
1979 throw JSONRPCError(-5, "Block not found");
1982 CBlockIndex* pblockindex = mapBlockIndex[hash];
1983 block.ReadFromDisk(pblockindex, true);
1985 return blockToJSON(block, pblockindex);
2002 pair<string, rpcfn_type> pCallTable[] =
2004 make_pair("help", &help),
2005 make_pair("stop", &stop),
2006 make_pair("getblockcount", &getblockcount),
2007 make_pair("getblocknumber", &getblocknumber),
2008 make_pair("getconnectioncount", &getconnectioncount),
2009 make_pair("getdifficulty", &getdifficulty),
2010 make_pair("getgenerate", &getgenerate),
2011 make_pair("setgenerate", &setgenerate),
2012 make_pair("gethashespersec", &gethashespersec),
2013 make_pair("getinfo", &getinfo),
2014 make_pair("getmininginfo", &getmininginfo),
2015 make_pair("getnewaddress", &getnewaddress),
2016 make_pair("getaccountaddress", &getaccountaddress),
2017 make_pair("setaccount", &setaccount),
2018 make_pair("getaccount", &getaccount),
2019 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2020 make_pair("sendtoaddress", &sendtoaddress),
2021 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2022 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2023 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2024 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2025 make_pair("backupwallet", &backupwallet),
2026 make_pair("keypoolrefill", &keypoolrefill),
2027 make_pair("walletpassphrase", &walletpassphrase),
2028 make_pair("walletpassphrasechange", &walletpassphrasechange),
2029 make_pair("walletlock", &walletlock),
2030 make_pair("encryptwallet", &encryptwallet),
2031 make_pair("validateaddress", &validateaddress),
2032 make_pair("getbalance", &getbalance),
2033 make_pair("move", &movecmd),
2034 make_pair("sendfrom", &sendfrom),
2035 make_pair("sendmany", &sendmany),
2036 make_pair("addmultisigaddress", &addmultisigaddress),
2037 make_pair("getblock", &getblock),
2038 make_pair("getblockhash", &getblockhash),
2039 make_pair("gettransaction", &gettransaction),
2040 make_pair("listtransactions", &listtransactions),
2041 make_pair("signmessage", &signmessage),
2042 make_pair("verifymessage", &verifymessage),
2043 make_pair("getwork", &getwork),
2044 make_pair("listaccounts", &listaccounts),
2045 make_pair("settxfee", &settxfee),
2046 make_pair("getmemorypool", &getmemorypool),
2047 make_pair("listsinceblock", &listsinceblock),
2048 make_pair("dumpprivkey", &dumpprivkey),
2049 make_pair("importprivkey", &importprivkey)
2051 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2053 string pAllowInSafeMode[] =
2058 "getblocknumber", // deprecated
2059 "getconnectioncount",
2067 "getaccountaddress",
2069 "getaddressesbyaccount",
2078 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2086 // This ain't Apache. We're just using HTTP header for the length field
2087 // and to be compatible with other JSON-RPC implementations.
2090 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2093 s << "POST / HTTP/1.1\r\n"
2094 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2095 << "Host: 127.0.0.1\r\n"
2096 << "Content-Type: application/json\r\n"
2097 << "Content-Length: " << strMsg.size() << "\r\n"
2098 << "Connection: close\r\n"
2099 << "Accept: application/json\r\n";
2100 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2101 s << item.first << ": " << item.second << "\r\n";
2102 s << "\r\n" << strMsg;
2107 string rfc1123Time()
2112 struct tm* now_gmt = gmtime(&now);
2113 string locale(setlocale(LC_TIME, NULL));
2114 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2115 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2116 setlocale(LC_TIME, locale.c_str());
2117 return string(buffer);
2120 static string HTTPReply(int nStatus, const string& strMsg)
2123 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2125 "Server: bitcoin-json-rpc/%s\r\n"
2126 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2127 "Content-Type: text/html\r\n"
2128 "Content-Length: 296\r\n"
2130 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2131 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2134 "<TITLE>Error</TITLE>\r\n"
2135 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2137 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2138 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2139 const char *cStatus;
2140 if (nStatus == 200) cStatus = "OK";
2141 else if (nStatus == 400) cStatus = "Bad Request";
2142 else if (nStatus == 403) cStatus = "Forbidden";
2143 else if (nStatus == 404) cStatus = "Not Found";
2144 else if (nStatus == 500) cStatus = "Internal Server Error";
2147 "HTTP/1.1 %d %s\r\n"
2149 "Connection: close\r\n"
2150 "Content-Length: %d\r\n"
2151 "Content-Type: application/json\r\n"
2152 "Server: bitcoin-json-rpc/%s\r\n"
2157 rfc1123Time().c_str(),
2159 FormatFullVersion().c_str(),
2163 int ReadHTTPStatus(std::basic_istream<char>& stream)
2166 getline(stream, str);
2167 vector<string> vWords;
2168 boost::split(vWords, str, boost::is_any_of(" "));
2169 if (vWords.size() < 2)
2171 return atoi(vWords[1].c_str());
2174 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2180 std::getline(stream, str);
2181 if (str.empty() || str == "\r")
2183 string::size_type nColon = str.find(":");
2184 if (nColon != string::npos)
2186 string strHeader = str.substr(0, nColon);
2187 boost::trim(strHeader);
2188 boost::to_lower(strHeader);
2189 string strValue = str.substr(nColon+1);
2190 boost::trim(strValue);
2191 mapHeadersRet[strHeader] = strValue;
2192 if (strHeader == "content-length")
2193 nLen = atoi(strValue.c_str());
2199 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2201 mapHeadersRet.clear();
2205 int nStatus = ReadHTTPStatus(stream);
2208 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2209 if (nLen < 0 || nLen > MAX_SIZE)
2215 vector<char> vch(nLen);
2216 stream.read(&vch[0], nLen);
2217 strMessageRet = string(vch.begin(), vch.end());
2223 bool HTTPAuthorized(map<string, string>& mapHeaders)
2225 string strAuth = mapHeaders["authorization"];
2226 if (strAuth.substr(0,6) != "Basic ")
2228 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2229 string strUserPass = DecodeBase64(strUserPass64);
2230 return strUserPass == strRPCUserColonPass;
2234 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2235 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2236 // unspecified (HTTP errors and contents of 'error').
2238 // 1.0 spec: http://json-rpc.org/wiki/specification
2239 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2240 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2243 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2246 request.push_back(Pair("method", strMethod));
2247 request.push_back(Pair("params", params));
2248 request.push_back(Pair("id", id));
2249 return write_string(Value(request), false) + "\n";
2252 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2255 if (error.type() != null_type)
2256 reply.push_back(Pair("result", Value::null));
2258 reply.push_back(Pair("result", result));
2259 reply.push_back(Pair("error", error));
2260 reply.push_back(Pair("id", id));
2261 return write_string(Value(reply), false) + "\n";
2264 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2266 // Send error reply from json-rpc error object
2268 int code = find_value(objError, "code").get_int();
2269 if (code == -32600) nStatus = 400;
2270 else if (code == -32601) nStatus = 404;
2271 string strReply = JSONRPCReply(Value::null, objError, id);
2272 stream << HTTPReply(nStatus, strReply) << std::flush;
2275 bool ClientAllowed(const string& strAddress)
2277 if (strAddress == asio::ip::address_v4::loopback().to_string())
2279 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2280 BOOST_FOREACH(string strAllow, vAllow)
2281 if (WildcardMatch(strAddress, strAllow))
2288 // IOStream device that speaks SSL but can also speak non-SSL
2290 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2292 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2294 fUseSSL = fUseSSLIn;
2295 fNeedHandshake = fUseSSLIn;
2298 void handshake(ssl::stream_base::handshake_type role)
2300 if (!fNeedHandshake) return;
2301 fNeedHandshake = false;
2302 stream.handshake(role);
2304 std::streamsize read(char* s, std::streamsize n)
2306 handshake(ssl::stream_base::server); // HTTPS servers read first
2307 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2308 return stream.next_layer().read_some(asio::buffer(s, n));
2310 std::streamsize write(const char* s, std::streamsize n)
2312 handshake(ssl::stream_base::client); // HTTPS clients write first
2313 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2314 return asio::write(stream.next_layer(), asio::buffer(s, n));
2316 bool connect(const std::string& server, const std::string& port)
2318 ip::tcp::resolver resolver(stream.get_io_service());
2319 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2320 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2321 ip::tcp::resolver::iterator end;
2322 boost::system::error_code error = asio::error::host_not_found;
2323 while (error && endpoint_iterator != end)
2325 stream.lowest_layer().close();
2326 stream.lowest_layer().connect(*endpoint_iterator++, error);
2334 bool fNeedHandshake;
2340 void ThreadRPCServer(void* parg)
2342 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2345 vnThreadsRunning[THREAD_RPCSERVER]++;
2346 ThreadRPCServer2(parg);
2347 vnThreadsRunning[THREAD_RPCSERVER]--;
2349 catch (std::exception& e) {
2350 vnThreadsRunning[THREAD_RPCSERVER]--;
2351 PrintException(&e, "ThreadRPCServer()");
2353 vnThreadsRunning[THREAD_RPCSERVER]--;
2354 PrintException(NULL, "ThreadRPCServer()");
2356 printf("ThreadRPCServer exiting\n");
2359 void ThreadRPCServer2(void* parg)
2361 printf("ThreadRPCServer started\n");
2363 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2364 if (mapArgs["-rpcpassword"] == "")
2366 unsigned char rand_pwd[32];
2367 RAND_bytes(rand_pwd, 32);
2368 string strWhatAmI = "To use bitcoind";
2369 if (mapArgs.count("-server"))
2370 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2371 else if (mapArgs.count("-daemon"))
2372 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2373 ThreadSafeMessageBox(strprintf(
2374 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2375 "It is recommended you use the following random password:\n"
2376 "rpcuser=bitcoinrpc\n"
2378 "(you do not need to remember this password)\n"
2379 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2381 GetConfigFile().c_str(),
2382 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2383 _("Error"), wxOK | wxMODAL);
2388 bool fUseSSL = GetBoolArg("-rpcssl");
2389 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2391 asio::io_service io_service;
2392 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2393 ip::tcp::acceptor acceptor(io_service, endpoint);
2395 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2398 ssl::context context(io_service, ssl::context::sslv23);
2401 context.set_options(ssl::context::no_sslv2);
2402 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2403 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2404 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2405 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2406 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2407 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2408 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2409 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2411 string ciphers = GetArg("-rpcsslciphers",
2412 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2413 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2417 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2422 // Accept connection
2424 SSLStream sslStream(io_service, context);
2425 SSLIOStreamDevice d(sslStream, fUseSSL);
2426 iostreams::stream<SSLIOStreamDevice> stream(d);
2428 ip::tcp::iostream stream;
2431 ip::tcp::endpoint peer;
2432 vnThreadsRunning[THREAD_RPCSERVER]--;
2434 acceptor.accept(sslStream.lowest_layer(), peer);
2436 acceptor.accept(*stream.rdbuf(), peer);
2438 vnThreadsRunning[4]++;
2442 // Restrict callers by IP
2443 if (!ClientAllowed(peer.address().to_string()))
2445 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2447 stream << HTTPReply(403, "") << std::flush;
2451 map<string, string> mapHeaders;
2454 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2455 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2458 printf("ThreadRPCServer ReadHTTP timeout\n");
2462 // Check authorization
2463 if (mapHeaders.count("authorization") == 0)
2465 stream << HTTPReply(401, "") << std::flush;
2468 if (!HTTPAuthorized(mapHeaders))
2470 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2471 /* Deter brute-forcing short passwords.
2472 If this results in a DOS the user really
2473 shouldn't have their RPC port exposed.*/
2474 if (mapArgs["-rpcpassword"].size() < 20)
2477 stream << HTTPReply(401, "") << std::flush;
2481 Value id = Value::null;
2486 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2487 throw JSONRPCError(-32700, "Parse error");
2488 const Object& request = valRequest.get_obj();
2490 // Parse id now so errors from here on will have the id
2491 id = find_value(request, "id");
2494 Value valMethod = find_value(request, "method");
2495 if (valMethod.type() == null_type)
2496 throw JSONRPCError(-32600, "Missing method");
2497 if (valMethod.type() != str_type)
2498 throw JSONRPCError(-32600, "Method must be a string");
2499 string strMethod = valMethod.get_str();
2500 if (strMethod != "getwork" && strMethod != "getmemorypool")
2501 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2504 Value valParams = find_value(request, "params");
2506 if (valParams.type() == array_type)
2507 params = valParams.get_array();
2508 else if (valParams.type() == null_type)
2511 throw JSONRPCError(-32600, "Params must be an array");
2514 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2515 if (mi == mapCallTable.end())
2516 throw JSONRPCError(-32601, "Method not found");
2518 // Observe safe mode
2519 string strWarning = GetWarnings("rpc");
2520 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2521 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2527 CRITICAL_BLOCK(cs_main)
2528 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2529 result = (*(*mi).second)(params, false);
2532 string strReply = JSONRPCReply(result, Value::null, id);
2533 stream << HTTPReply(200, strReply) << std::flush;
2535 catch (std::exception& e)
2537 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2540 catch (Object& objError)
2542 ErrorReply(stream, objError, id);
2544 catch (std::exception& e)
2546 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2554 Object CallRPC(const string& strMethod, const Array& params)
2556 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2557 throw runtime_error(strprintf(
2558 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2559 "If the file does not exist, create it with owner-readable-only file permissions."),
2560 GetConfigFile().c_str()));
2562 // Connect to localhost
2563 bool fUseSSL = GetBoolArg("-rpcssl");
2565 asio::io_service io_service;
2566 ssl::context context(io_service, ssl::context::sslv23);
2567 context.set_options(ssl::context::no_sslv2);
2568 SSLStream sslStream(io_service, context);
2569 SSLIOStreamDevice d(sslStream, fUseSSL);
2570 iostreams::stream<SSLIOStreamDevice> stream(d);
2571 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2572 throw runtime_error("couldn't connect to server");
2575 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2577 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2579 throw runtime_error("couldn't connect to server");
2583 // HTTP basic authentication
2584 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2585 map<string, string> mapRequestHeaders;
2586 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2589 string strRequest = JSONRPCRequest(strMethod, params, 1);
2590 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2591 stream << strPost << std::flush;
2594 map<string, string> mapHeaders;
2596 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2598 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2599 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2600 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2601 else if (strReply.empty())
2602 throw runtime_error("no response from server");
2606 if (!read_string(strReply, valReply))
2607 throw runtime_error("couldn't parse reply from server");
2608 const Object& reply = valReply.get_obj();
2610 throw runtime_error("expected reply to have result, error and id properties");
2618 template<typename T>
2619 void ConvertTo(Value& value)
2621 if (value.type() == str_type)
2623 // reinterpret string as unquoted json value
2625 if (!read_string(value.get_str(), value2))
2626 throw runtime_error("type mismatch");
2627 value = value2.get_value<T>();
2631 value = value.get_value<T>();
2635 int CommandLineRPC(int argc, char *argv[])
2642 while (argc > 1 && IsSwitchChar(argv[1][0]))
2650 throw runtime_error("too few parameters");
2651 string strMethod = argv[1];
2653 // Parameters default to strings
2655 for (int i = 2; i < argc; i++)
2656 params.push_back(argv[i]);
2657 int n = params.size();
2660 // Special case non-string parameter types
2662 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2663 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2664 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2665 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2666 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2667 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2669 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2670 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2671 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2672 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2673 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2674 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2675 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2676 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2677 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2678 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2679 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2680 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2681 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2682 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2683 if (strMethod == "sendmany" && n > 1)
2685 string s = params[1].get_str();
2687 if (!read_string(s, v) || v.type() != obj_type)
2688 throw runtime_error("type mismatch");
2689 params[1] = v.get_obj();
2691 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2692 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2693 if (strMethod == "addmultisigaddress" && n > 1)
2695 string s = params[1].get_str();
2697 if (!read_string(s, v) || v.type() != array_type)
2698 throw runtime_error("type mismatch "+s);
2699 params[1] = v.get_array();
2703 Object reply = CallRPC(strMethod, params);
2706 const Value& result = find_value(reply, "result");
2707 const Value& error = find_value(reply, "error");
2709 if (error.type() != null_type)
2712 strPrint = "error: " + write_string(error, false);
2713 int code = find_value(error.get_obj(), "code").get_int();
2719 if (result.type() == null_type)
2721 else if (result.type() == str_type)
2722 strPrint = result.get_str();
2724 strPrint = write_string(result, true);
2727 catch (std::exception& e)
2729 strPrint = string("error: ") + e.what();
2734 PrintException(NULL, "CommandLineRPC()");
2739 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2748 int main(int argc, char *argv[])
2751 // Turn off microsoft heap dump noise
2752 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2753 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2755 setbuf(stdin, NULL);
2756 setbuf(stdout, NULL);
2757 setbuf(stderr, NULL);
2761 if (argc >= 2 && string(argv[1]) == "-server")
2763 printf("server ready\n");
2764 ThreadRPCServer(NULL);
2768 return CommandLineRPC(argc, argv);
2771 catch (std::exception& e) {
2772 PrintException(&e, "main()");
2774 PrintException(NULL, "main()");