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 CWalletDB walletdb(pwalletMain->strWalletFile);
1291 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1292 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1293 typedef multimap<int64, TxPair > TxItems;
1296 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1298 CWalletTx* wtx = &((*it).second);
1299 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1301 list<CAccountingEntry> acentries;
1302 walletdb.ListAccountCreditDebit(strAccount, acentries);
1303 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1305 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1308 // Now: iterate backwards until we have nCount items to return:
1309 TxItems::reverse_iterator it = txByTime.rbegin();
1310 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1311 for (; it != txByTime.rend(); ++it)
1313 CWalletTx *const pwtx = (*it).second.first;
1315 ListTransactions(*pwtx, strAccount, 0, true, ret);
1316 CAccountingEntry *const pacentry = (*it).second.second;
1318 AcentryToJSON(*pacentry, strAccount, ret);
1320 if (ret.size() >= nCount) break;
1322 // ret is now newest to oldest
1324 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1325 if (ret.size() > nCount)
1327 Array::iterator last = ret.begin();
1328 std::advance(last, nCount);
1329 ret.erase(last, ret.end());
1331 std::reverse(ret.begin(), ret.end()); // oldest to newest
1336 Value listaccounts(const Array& params, bool fHelp)
1338 if (fHelp || params.size() > 1)
1339 throw runtime_error(
1340 "listaccounts [minconf=1]\n"
1341 "Returns Object that has account names as keys, account balances as values.");
1344 if (params.size() > 0)
1345 nMinDepth = params[0].get_int();
1347 map<string, int64> mapAccountBalances;
1348 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1349 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1350 mapAccountBalances[entry.second] = 0;
1353 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1355 const CWalletTx& wtx = (*it).second;
1356 int64 nGeneratedImmature, nGeneratedMature, nFee;
1357 string strSentAccount;
1358 list<pair<CBitcoinAddress, int64> > listReceived;
1359 list<pair<CBitcoinAddress, int64> > listSent;
1360 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1361 mapAccountBalances[strSentAccount] -= nFee;
1362 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1363 mapAccountBalances[strSentAccount] -= s.second;
1364 if (wtx.GetDepthInMainChain() >= nMinDepth)
1366 mapAccountBalances[""] += nGeneratedMature;
1367 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1368 if (pwalletMain->mapAddressBook.count(r.first))
1369 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1371 mapAccountBalances[""] += r.second;
1375 list<CAccountingEntry> acentries;
1376 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1377 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1378 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1381 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1382 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1387 Value listsinceblock(const Array& params, bool fHelp)
1390 throw runtime_error(
1391 "listsinceblock [blockid] [target-confirmations]\n"
1392 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1394 CBlockIndex *pindex = NULL;
1395 int target_confirms = 1;
1397 if (params.size() > 0)
1399 uint256 blockId = 0;
1401 blockId.SetHex(params[0].get_str());
1402 pindex = CBlockLocator(blockId).GetBlockIndex();
1405 if (params.size() > 1)
1407 target_confirms = params[1].get_int();
1409 if (target_confirms < 1)
1410 throw JSONRPCError(-8, "Invalid parameter");
1413 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1417 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1419 CWalletTx tx = (*it).second;
1421 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1422 ListTransactions(tx, "*", 0, true, transactions);
1427 if (target_confirms == 1)
1430 lastblock = hashBestChain;
1434 int target_height = pindexBest->nHeight + 1 - target_confirms;
1437 for (block = pindexBest;
1438 block && block->nHeight > target_height;
1439 block = block->pprev) { }
1441 lastblock = block ? block->GetBlockHash() : 0;
1445 ret.push_back(Pair("transactions", transactions));
1446 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1451 Value gettransaction(const Array& params, bool fHelp)
1453 if (fHelp || params.size() != 1)
1454 throw runtime_error(
1455 "gettransaction <txid>\n"
1456 "Get detailed information about <txid>");
1459 hash.SetHex(params[0].get_str());
1463 if (!pwalletMain->mapWallet.count(hash))
1464 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1465 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1467 int64 nCredit = wtx.GetCredit();
1468 int64 nDebit = wtx.GetDebit();
1469 int64 nNet = nCredit - nDebit;
1470 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1472 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1474 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1476 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1479 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1480 entry.push_back(Pair("details", details));
1486 Value backupwallet(const Array& params, bool fHelp)
1488 if (fHelp || params.size() != 1)
1489 throw runtime_error(
1490 "backupwallet <destination>\n"
1491 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1493 string strDest = params[0].get_str();
1494 BackupWallet(*pwalletMain, strDest);
1500 Value keypoolrefill(const Array& params, bool fHelp)
1502 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1503 throw runtime_error(
1505 "Fills the keypool, requires wallet passphrase to be set.");
1506 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1507 throw runtime_error(
1509 "Fills the keypool.");
1511 if (pwalletMain->IsLocked())
1512 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1514 pwalletMain->TopUpKeyPool();
1516 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1517 throw JSONRPCError(-4, "Error refreshing keypool.");
1523 void ThreadTopUpKeyPool(void* parg)
1525 pwalletMain->TopUpKeyPool();
1528 void ThreadCleanWalletPassphrase(void* parg)
1530 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1532 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1534 if (nWalletUnlockTime == 0)
1536 nWalletUnlockTime = nMyWakeTime;
1540 if (nWalletUnlockTime==0)
1542 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1546 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1548 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1552 if (nWalletUnlockTime)
1554 nWalletUnlockTime = 0;
1555 pwalletMain->Lock();
1560 if (nWalletUnlockTime < nMyWakeTime)
1561 nWalletUnlockTime = nMyWakeTime;
1564 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1566 delete (int64*)parg;
1569 Value walletpassphrase(const Array& params, bool fHelp)
1571 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1572 throw runtime_error(
1573 "walletpassphrase <passphrase> <timeout>\n"
1574 "Stores the wallet decryption key in memory for <timeout> seconds.");
1577 if (!pwalletMain->IsCrypted())
1578 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1580 if (!pwalletMain->IsLocked())
1581 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1583 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1584 SecureString strWalletPass;
1585 strWalletPass.reserve(100);
1586 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1587 // Alternately, find a way to make params[0] mlock()'d to begin with.
1588 strWalletPass = params[0].get_str().c_str();
1590 if (strWalletPass.length() > 0)
1592 if (!pwalletMain->Unlock(strWalletPass))
1593 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1596 throw runtime_error(
1597 "walletpassphrase <passphrase> <timeout>\n"
1598 "Stores the wallet decryption key in memory for <timeout> seconds.");
1600 CreateThread(ThreadTopUpKeyPool, NULL);
1601 int64* pnSleepTime = new int64(params[1].get_int64());
1602 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1608 Value walletpassphrasechange(const Array& params, bool fHelp)
1610 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1611 throw runtime_error(
1612 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1613 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1616 if (!pwalletMain->IsCrypted())
1617 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1619 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1620 // Alternately, find a way to make params[0] mlock()'d to begin with.
1621 SecureString strOldWalletPass;
1622 strOldWalletPass.reserve(100);
1623 strOldWalletPass = params[0].get_str().c_str();
1625 SecureString strNewWalletPass;
1626 strNewWalletPass.reserve(100);
1627 strNewWalletPass = params[1].get_str().c_str();
1629 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1630 throw runtime_error(
1631 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1632 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1634 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1635 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1641 Value walletlock(const Array& params, bool fHelp)
1643 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1644 throw runtime_error(
1646 "Removes the wallet encryption key from memory, locking the wallet.\n"
1647 "After calling this method, you will need to call walletpassphrase again\n"
1648 "before being able to call any methods which require the wallet to be unlocked.");
1651 if (!pwalletMain->IsCrypted())
1652 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1654 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1656 pwalletMain->Lock();
1657 nWalletUnlockTime = 0;
1664 Value encryptwallet(const Array& params, bool fHelp)
1666 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1667 throw runtime_error(
1668 "encryptwallet <passphrase>\n"
1669 "Encrypts the wallet with <passphrase>.");
1672 if (pwalletMain->IsCrypted())
1673 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1675 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1676 // Alternately, find a way to make params[0] mlock()'d to begin with.
1677 SecureString strWalletPass;
1678 strWalletPass.reserve(100);
1679 strWalletPass = params[0].get_str().c_str();
1681 if (strWalletPass.length() < 1)
1682 throw runtime_error(
1683 "encryptwallet <passphrase>\n"
1684 "Encrypts the wallet with <passphrase>.");
1686 if (!pwalletMain->EncryptWallet(strWalletPass))
1687 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1689 // BDB seems to have a bad habit of writing old data into
1690 // slack space in .dat files; that is bad if the old data is
1691 // unencrypted private keys. So:
1693 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1697 Value validateaddress(const Array& params, bool fHelp)
1699 if (fHelp || params.size() != 1)
1700 throw runtime_error(
1701 "validateaddress <bitcoinaddress>\n"
1702 "Return information about <bitcoinaddress>.");
1704 CBitcoinAddress address(params[0].get_str());
1705 bool isValid = address.IsValid();
1708 ret.push_back(Pair("isvalid", isValid));
1711 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1712 // version of the address:
1713 string currentAddress = address.ToString();
1714 ret.push_back(Pair("address", currentAddress));
1715 if (pwalletMain->HaveKey(address))
1717 ret.push_back(Pair("ismine", true));
1718 std::vector<unsigned char> vchPubKey;
1719 pwalletMain->GetPubKey(address, vchPubKey);
1720 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1722 key.SetPubKey(vchPubKey);
1723 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1725 else if (pwalletMain->HaveCScript(address.GetHash160()))
1727 ret.push_back(Pair("isscript", true));
1729 pwalletMain->GetCScript(address.GetHash160(), subscript);
1730 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1731 std::vector<CBitcoinAddress> addresses;
1732 txnouttype whichType;
1734 ExtractAddresses(subscript, whichType, addresses, nRequired);
1735 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1737 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1738 a.push_back(addr.ToString());
1739 ret.push_back(Pair("addresses", a));
1740 if (whichType == TX_MULTISIG)
1741 ret.push_back(Pair("sigsrequired", nRequired));
1744 ret.push_back(Pair("ismine", false));
1745 if (pwalletMain->mapAddressBook.count(address))
1746 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1751 Value getwork(const Array& params, bool fHelp)
1753 if (fHelp || params.size() > 1)
1754 throw runtime_error(
1756 "If [data] is not specified, returns formatted hash data to work on:\n"
1757 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1758 " \"data\" : block data\n"
1759 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1760 " \"target\" : little endian hash target\n"
1761 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1764 throw JSONRPCError(-9, "Bitcoin is not connected!");
1766 if (IsInitialBlockDownload())
1767 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1769 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1770 static mapNewBlock_t mapNewBlock;
1771 static vector<CBlock*> vNewBlock;
1772 static CReserveKey reservekey(pwalletMain);
1774 if (params.size() == 0)
1777 static unsigned int nTransactionsUpdatedLast;
1778 static CBlockIndex* pindexPrev;
1779 static int64 nStart;
1780 static CBlock* pblock;
1781 if (pindexPrev != pindexBest ||
1782 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1784 if (pindexPrev != pindexBest)
1786 // Deallocate old blocks since they're obsolete now
1787 mapNewBlock.clear();
1788 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1792 nTransactionsUpdatedLast = nTransactionsUpdated;
1793 pindexPrev = pindexBest;
1797 pblock = CreateNewBlock(reservekey);
1799 throw JSONRPCError(-7, "Out of memory");
1800 vNewBlock.push_back(pblock);
1804 pblock->UpdateTime(pindexPrev);
1807 // Update nExtraNonce
1808 static unsigned int nExtraNonce = 0;
1809 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1812 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1814 // Prebuild hash buffers
1818 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1820 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1823 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1824 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1825 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1826 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1832 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1833 if (vchData.size() != 128)
1834 throw JSONRPCError(-8, "Invalid parameter");
1835 CBlock* pdata = (CBlock*)&vchData[0];
1838 for (int i = 0; i < 128/4; i++)
1839 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1842 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1844 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1846 pblock->nTime = pdata->nTime;
1847 pblock->nNonce = pdata->nNonce;
1848 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1849 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1851 return CheckWork(pblock, *pwalletMain, reservekey);
1856 Value getmemorypool(const Array& params, bool fHelp)
1858 if (fHelp || params.size() > 1)
1859 throw runtime_error(
1860 "getmemorypool [data]\n"
1861 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1862 " \"version\" : block version\n"
1863 " \"previousblockhash\" : hash of current highest block\n"
1864 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1865 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1866 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1867 " \"time\" : timestamp appropriate for next block\n"
1868 " \"mintime\" : minimum timestamp appropriate for next block\n"
1869 " \"curtime\" : current timestamp\n"
1870 " \"bits\" : compressed target of next block\n"
1871 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1873 if (params.size() == 0)
1876 throw JSONRPCError(-9, "Bitcoin is not connected!");
1878 if (IsInitialBlockDownload())
1879 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1881 static CReserveKey reservekey(pwalletMain);
1884 static unsigned int nTransactionsUpdatedLast;
1885 static CBlockIndex* pindexPrev;
1886 static int64 nStart;
1887 static CBlock* pblock;
1888 if (pindexPrev != pindexBest ||
1889 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1891 nTransactionsUpdatedLast = nTransactionsUpdated;
1892 pindexPrev = pindexBest;
1898 pblock = CreateNewBlock(reservekey);
1900 throw JSONRPCError(-7, "Out of memory");
1904 pblock->UpdateTime(pindexPrev);
1908 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1915 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1919 result.push_back(Pair("version", pblock->nVersion));
1920 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1921 result.push_back(Pair("transactions", transactions));
1922 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1923 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1924 result.push_back(Pair("time", (int64_t)pblock->nTime));
1925 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1926 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1927 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1934 CDataStream ssBlock(ParseHex(params[0].get_str()));
1938 return ProcessBlock(NULL, &pblock);
1942 Value getblockhash(const Array& params, bool fHelp)
1944 if (fHelp || params.size() != 1)
1945 throw runtime_error(
1946 "getblockhash <index>\n"
1947 "Returns hash of block in best-block-chain at <index>.");
1949 int nHeight = params[0].get_int();
1950 if (nHeight < 0 || nHeight > nBestHeight)
1951 throw runtime_error("Block number out of range.");
1954 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1955 while (pblockindex->nHeight > nHeight)
1956 pblockindex = pblockindex->pprev;
1957 return pblockindex->phashBlock->GetHex();
1960 Value getblock(const Array& params, bool fHelp)
1962 if (fHelp || params.size() != 1)
1963 throw runtime_error(
1965 "Returns details of a block with given block-hash.");
1967 std::string strHash = params[0].get_str();
1968 uint256 hash(strHash);
1970 if (mapBlockIndex.count(hash) == 0)
1971 throw JSONRPCError(-5, "Block not found");
1974 CBlockIndex* pblockindex = mapBlockIndex[hash];
1975 block.ReadFromDisk(pblockindex, true);
1977 return blockToJSON(block, pblockindex);
1994 pair<string, rpcfn_type> pCallTable[] =
1996 make_pair("help", &help),
1997 make_pair("stop", &stop),
1998 make_pair("getblockcount", &getblockcount),
1999 make_pair("getblocknumber", &getblocknumber),
2000 make_pair("getconnectioncount", &getconnectioncount),
2001 make_pair("getdifficulty", &getdifficulty),
2002 make_pair("getgenerate", &getgenerate),
2003 make_pair("setgenerate", &setgenerate),
2004 make_pair("gethashespersec", &gethashespersec),
2005 make_pair("getinfo", &getinfo),
2006 make_pair("getmininginfo", &getmininginfo),
2007 make_pair("getnewaddress", &getnewaddress),
2008 make_pair("getaccountaddress", &getaccountaddress),
2009 make_pair("setaccount", &setaccount),
2010 make_pair("getaccount", &getaccount),
2011 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2012 make_pair("sendtoaddress", &sendtoaddress),
2013 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2014 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2015 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2016 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2017 make_pair("backupwallet", &backupwallet),
2018 make_pair("keypoolrefill", &keypoolrefill),
2019 make_pair("walletpassphrase", &walletpassphrase),
2020 make_pair("walletpassphrasechange", &walletpassphrasechange),
2021 make_pair("walletlock", &walletlock),
2022 make_pair("encryptwallet", &encryptwallet),
2023 make_pair("validateaddress", &validateaddress),
2024 make_pair("getbalance", &getbalance),
2025 make_pair("move", &movecmd),
2026 make_pair("sendfrom", &sendfrom),
2027 make_pair("sendmany", &sendmany),
2028 make_pair("addmultisigaddress", &addmultisigaddress),
2029 make_pair("getblock", &getblock),
2030 make_pair("getblockhash", &getblockhash),
2031 make_pair("gettransaction", &gettransaction),
2032 make_pair("listtransactions", &listtransactions),
2033 make_pair("signmessage", &signmessage),
2034 make_pair("verifymessage", &verifymessage),
2035 make_pair("getwork", &getwork),
2036 make_pair("listaccounts", &listaccounts),
2037 make_pair("settxfee", &settxfee),
2038 make_pair("getmemorypool", &getmemorypool),
2039 make_pair("listsinceblock", &listsinceblock),
2040 make_pair("dumpprivkey", &dumpprivkey),
2041 make_pair("importprivkey", &importprivkey)
2043 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2045 string pAllowInSafeMode[] =
2050 "getblocknumber", // deprecated
2051 "getconnectioncount",
2059 "getaccountaddress",
2061 "getaddressesbyaccount",
2070 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2078 // This ain't Apache. We're just using HTTP header for the length field
2079 // and to be compatible with other JSON-RPC implementations.
2082 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2085 s << "POST / HTTP/1.1\r\n"
2086 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2087 << "Host: 127.0.0.1\r\n"
2088 << "Content-Type: application/json\r\n"
2089 << "Content-Length: " << strMsg.size() << "\r\n"
2090 << "Connection: close\r\n"
2091 << "Accept: application/json\r\n";
2092 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2093 s << item.first << ": " << item.second << "\r\n";
2094 s << "\r\n" << strMsg;
2099 string rfc1123Time()
2104 struct tm* now_gmt = gmtime(&now);
2105 string locale(setlocale(LC_TIME, NULL));
2106 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2107 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2108 setlocale(LC_TIME, locale.c_str());
2109 return string(buffer);
2112 static string HTTPReply(int nStatus, const string& strMsg)
2115 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2117 "Server: bitcoin-json-rpc/%s\r\n"
2118 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2119 "Content-Type: text/html\r\n"
2120 "Content-Length: 296\r\n"
2122 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2123 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2126 "<TITLE>Error</TITLE>\r\n"
2127 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2129 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2130 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2131 const char *cStatus;
2132 if (nStatus == 200) cStatus = "OK";
2133 else if (nStatus == 400) cStatus = "Bad Request";
2134 else if (nStatus == 403) cStatus = "Forbidden";
2135 else if (nStatus == 404) cStatus = "Not Found";
2136 else if (nStatus == 500) cStatus = "Internal Server Error";
2139 "HTTP/1.1 %d %s\r\n"
2141 "Connection: close\r\n"
2142 "Content-Length: %d\r\n"
2143 "Content-Type: application/json\r\n"
2144 "Server: bitcoin-json-rpc/%s\r\n"
2149 rfc1123Time().c_str(),
2151 FormatFullVersion().c_str(),
2155 int ReadHTTPStatus(std::basic_istream<char>& stream)
2158 getline(stream, str);
2159 vector<string> vWords;
2160 boost::split(vWords, str, boost::is_any_of(" "));
2161 if (vWords.size() < 2)
2163 return atoi(vWords[1].c_str());
2166 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2172 std::getline(stream, str);
2173 if (str.empty() || str == "\r")
2175 string::size_type nColon = str.find(":");
2176 if (nColon != string::npos)
2178 string strHeader = str.substr(0, nColon);
2179 boost::trim(strHeader);
2180 boost::to_lower(strHeader);
2181 string strValue = str.substr(nColon+1);
2182 boost::trim(strValue);
2183 mapHeadersRet[strHeader] = strValue;
2184 if (strHeader == "content-length")
2185 nLen = atoi(strValue.c_str());
2191 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2193 mapHeadersRet.clear();
2197 int nStatus = ReadHTTPStatus(stream);
2200 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2201 if (nLen < 0 || nLen > MAX_SIZE)
2207 vector<char> vch(nLen);
2208 stream.read(&vch[0], nLen);
2209 strMessageRet = string(vch.begin(), vch.end());
2215 bool HTTPAuthorized(map<string, string>& mapHeaders)
2217 string strAuth = mapHeaders["authorization"];
2218 if (strAuth.substr(0,6) != "Basic ")
2220 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2221 string strUserPass = DecodeBase64(strUserPass64);
2222 return strUserPass == strRPCUserColonPass;
2226 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2227 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2228 // unspecified (HTTP errors and contents of 'error').
2230 // 1.0 spec: http://json-rpc.org/wiki/specification
2231 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2232 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2235 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2238 request.push_back(Pair("method", strMethod));
2239 request.push_back(Pair("params", params));
2240 request.push_back(Pair("id", id));
2241 return write_string(Value(request), false) + "\n";
2244 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2247 if (error.type() != null_type)
2248 reply.push_back(Pair("result", Value::null));
2250 reply.push_back(Pair("result", result));
2251 reply.push_back(Pair("error", error));
2252 reply.push_back(Pair("id", id));
2253 return write_string(Value(reply), false) + "\n";
2256 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2258 // Send error reply from json-rpc error object
2260 int code = find_value(objError, "code").get_int();
2261 if (code == -32600) nStatus = 400;
2262 else if (code == -32601) nStatus = 404;
2263 string strReply = JSONRPCReply(Value::null, objError, id);
2264 stream << HTTPReply(nStatus, strReply) << std::flush;
2267 bool ClientAllowed(const string& strAddress)
2269 if (strAddress == asio::ip::address_v4::loopback().to_string())
2271 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2272 BOOST_FOREACH(string strAllow, vAllow)
2273 if (WildcardMatch(strAddress, strAllow))
2280 // IOStream device that speaks SSL but can also speak non-SSL
2282 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2284 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2286 fUseSSL = fUseSSLIn;
2287 fNeedHandshake = fUseSSLIn;
2290 void handshake(ssl::stream_base::handshake_type role)
2292 if (!fNeedHandshake) return;
2293 fNeedHandshake = false;
2294 stream.handshake(role);
2296 std::streamsize read(char* s, std::streamsize n)
2298 handshake(ssl::stream_base::server); // HTTPS servers read first
2299 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2300 return stream.next_layer().read_some(asio::buffer(s, n));
2302 std::streamsize write(const char* s, std::streamsize n)
2304 handshake(ssl::stream_base::client); // HTTPS clients write first
2305 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2306 return asio::write(stream.next_layer(), asio::buffer(s, n));
2308 bool connect(const std::string& server, const std::string& port)
2310 ip::tcp::resolver resolver(stream.get_io_service());
2311 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2312 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2313 ip::tcp::resolver::iterator end;
2314 boost::system::error_code error = asio::error::host_not_found;
2315 while (error && endpoint_iterator != end)
2317 stream.lowest_layer().close();
2318 stream.lowest_layer().connect(*endpoint_iterator++, error);
2326 bool fNeedHandshake;
2332 void ThreadRPCServer(void* parg)
2334 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2337 vnThreadsRunning[THREAD_RPCSERVER]++;
2338 ThreadRPCServer2(parg);
2339 vnThreadsRunning[THREAD_RPCSERVER]--;
2341 catch (std::exception& e) {
2342 vnThreadsRunning[THREAD_RPCSERVER]--;
2343 PrintException(&e, "ThreadRPCServer()");
2345 vnThreadsRunning[THREAD_RPCSERVER]--;
2346 PrintException(NULL, "ThreadRPCServer()");
2348 printf("ThreadRPCServer exiting\n");
2351 void ThreadRPCServer2(void* parg)
2353 printf("ThreadRPCServer started\n");
2355 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2356 if (mapArgs["-rpcpassword"] == "")
2358 unsigned char rand_pwd[32];
2359 RAND_bytes(rand_pwd, 32);
2360 string strWhatAmI = "To use bitcoind";
2361 if (mapArgs.count("-server"))
2362 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2363 else if (mapArgs.count("-daemon"))
2364 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2365 ThreadSafeMessageBox(strprintf(
2366 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2367 "It is recommended you use the following random password:\n"
2368 "rpcuser=bitcoinrpc\n"
2370 "(you do not need to remember this password)\n"
2371 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2373 GetConfigFile().c_str(),
2374 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2375 _("Error"), wxOK | wxMODAL);
2380 bool fUseSSL = GetBoolArg("-rpcssl");
2381 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2383 asio::io_service io_service;
2384 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2385 ip::tcp::acceptor acceptor(io_service, endpoint);
2387 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2390 ssl::context context(io_service, ssl::context::sslv23);
2393 context.set_options(ssl::context::no_sslv2);
2394 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2395 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2396 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2397 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2398 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2399 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2400 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2401 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2403 string ciphers = GetArg("-rpcsslciphers",
2404 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2405 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2409 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2414 // Accept connection
2416 SSLStream sslStream(io_service, context);
2417 SSLIOStreamDevice d(sslStream, fUseSSL);
2418 iostreams::stream<SSLIOStreamDevice> stream(d);
2420 ip::tcp::iostream stream;
2423 ip::tcp::endpoint peer;
2424 vnThreadsRunning[THREAD_RPCSERVER]--;
2426 acceptor.accept(sslStream.lowest_layer(), peer);
2428 acceptor.accept(*stream.rdbuf(), peer);
2430 vnThreadsRunning[4]++;
2434 // Restrict callers by IP
2435 if (!ClientAllowed(peer.address().to_string()))
2437 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2439 stream << HTTPReply(403, "") << std::flush;
2443 map<string, string> mapHeaders;
2446 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2447 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2450 printf("ThreadRPCServer ReadHTTP timeout\n");
2454 // Check authorization
2455 if (mapHeaders.count("authorization") == 0)
2457 stream << HTTPReply(401, "") << std::flush;
2460 if (!HTTPAuthorized(mapHeaders))
2462 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2463 /* Deter brute-forcing short passwords.
2464 If this results in a DOS the user really
2465 shouldn't have their RPC port exposed.*/
2466 if (mapArgs["-rpcpassword"].size() < 20)
2469 stream << HTTPReply(401, "") << std::flush;
2473 Value id = Value::null;
2478 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2479 throw JSONRPCError(-32700, "Parse error");
2480 const Object& request = valRequest.get_obj();
2482 // Parse id now so errors from here on will have the id
2483 id = find_value(request, "id");
2486 Value valMethod = find_value(request, "method");
2487 if (valMethod.type() == null_type)
2488 throw JSONRPCError(-32600, "Missing method");
2489 if (valMethod.type() != str_type)
2490 throw JSONRPCError(-32600, "Method must be a string");
2491 string strMethod = valMethod.get_str();
2492 if (strMethod != "getwork" && strMethod != "getmemorypool")
2493 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2496 Value valParams = find_value(request, "params");
2498 if (valParams.type() == array_type)
2499 params = valParams.get_array();
2500 else if (valParams.type() == null_type)
2503 throw JSONRPCError(-32600, "Params must be an array");
2506 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2507 if (mi == mapCallTable.end())
2508 throw JSONRPCError(-32601, "Method not found");
2510 // Observe safe mode
2511 string strWarning = GetWarnings("rpc");
2512 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2513 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2519 CRITICAL_BLOCK(cs_main)
2520 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2521 result = (*(*mi).second)(params, false);
2524 string strReply = JSONRPCReply(result, Value::null, id);
2525 stream << HTTPReply(200, strReply) << std::flush;
2527 catch (std::exception& e)
2529 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2532 catch (Object& objError)
2534 ErrorReply(stream, objError, id);
2536 catch (std::exception& e)
2538 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2546 Object CallRPC(const string& strMethod, const Array& params)
2548 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2549 throw runtime_error(strprintf(
2550 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2551 "If the file does not exist, create it with owner-readable-only file permissions."),
2552 GetConfigFile().c_str()));
2554 // Connect to localhost
2555 bool fUseSSL = GetBoolArg("-rpcssl");
2557 asio::io_service io_service;
2558 ssl::context context(io_service, ssl::context::sslv23);
2559 context.set_options(ssl::context::no_sslv2);
2560 SSLStream sslStream(io_service, context);
2561 SSLIOStreamDevice d(sslStream, fUseSSL);
2562 iostreams::stream<SSLIOStreamDevice> stream(d);
2563 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2564 throw runtime_error("couldn't connect to server");
2567 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2569 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2571 throw runtime_error("couldn't connect to server");
2575 // HTTP basic authentication
2576 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2577 map<string, string> mapRequestHeaders;
2578 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2581 string strRequest = JSONRPCRequest(strMethod, params, 1);
2582 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2583 stream << strPost << std::flush;
2586 map<string, string> mapHeaders;
2588 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2590 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2591 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2592 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2593 else if (strReply.empty())
2594 throw runtime_error("no response from server");
2598 if (!read_string(strReply, valReply))
2599 throw runtime_error("couldn't parse reply from server");
2600 const Object& reply = valReply.get_obj();
2602 throw runtime_error("expected reply to have result, error and id properties");
2610 template<typename T>
2611 void ConvertTo(Value& value)
2613 if (value.type() == str_type)
2615 // reinterpret string as unquoted json value
2617 if (!read_string(value.get_str(), value2))
2618 throw runtime_error("type mismatch");
2619 value = value2.get_value<T>();
2623 value = value.get_value<T>();
2627 int CommandLineRPC(int argc, char *argv[])
2634 while (argc > 1 && IsSwitchChar(argv[1][0]))
2642 throw runtime_error("too few parameters");
2643 string strMethod = argv[1];
2645 // Parameters default to strings
2647 for (int i = 2; i < argc; i++)
2648 params.push_back(argv[i]);
2649 int n = params.size();
2652 // Special case non-string parameter types
2654 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2655 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2657 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2658 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2660 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2661 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2662 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2663 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2664 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2666 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2667 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2668 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2669 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2670 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2672 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2673 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675 if (strMethod == "sendmany" && n > 1)
2677 string s = params[1].get_str();
2679 if (!read_string(s, v) || v.type() != obj_type)
2680 throw runtime_error("type mismatch");
2681 params[1] = v.get_obj();
2683 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2684 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2685 if (strMethod == "addmultisigaddress" && n > 1)
2687 string s = params[1].get_str();
2689 if (!read_string(s, v) || v.type() != array_type)
2690 throw runtime_error("type mismatch "+s);
2691 params[1] = v.get_array();
2695 Object reply = CallRPC(strMethod, params);
2698 const Value& result = find_value(reply, "result");
2699 const Value& error = find_value(reply, "error");
2701 if (error.type() != null_type)
2704 strPrint = "error: " + write_string(error, false);
2705 int code = find_value(error.get_obj(), "code").get_int();
2711 if (result.type() == null_type)
2713 else if (result.type() == str_type)
2714 strPrint = result.get_str();
2716 strPrint = write_string(result, true);
2719 catch (std::exception& e)
2721 strPrint = string("error: ") + e.what();
2726 PrintException(NULL, "CommandLineRPC()");
2731 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2740 int main(int argc, char *argv[])
2743 // Turn off microsoft heap dump noise
2744 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2745 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2747 setbuf(stdin, NULL);
2748 setbuf(stdout, NULL);
2749 setbuf(stderr, NULL);
2753 if (argc >= 2 && string(argv[1]) == "-server")
2755 printf("server ready\n");
2756 ThreadRPCServer(NULL);
2760 return CommandLineRPC(argc, argv);
2763 catch (std::exception& e) {
2764 PrintException(&e, "main()");
2766 PrintException(NULL, "main()");