1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static std::string strRPCUserColonPass;
42 static int64 nWalletUnlockTime;
43 static CCriticalSection cs_nWalletUnlockTime;
45 extern Value dumpprivkey(const Array& params, bool fHelp);
46 extern Value importprivkey(const Array& params, bool fHelp);
48 Object JSONRPCError(int code, const string& message)
51 error.push_back(Pair("code", code));
52 error.push_back(Pair("message", message));
56 double GetDifficulty(const CBlockIndex* blockindex = NULL)
58 // Floating point number that is a multiple of the minimum difficulty,
59 // minimum difficulty = 1.0.
60 if (blockindex == NULL)
62 if (pindexBest == NULL)
65 blockindex = pindexBest;
68 int nShift = (blockindex->nBits >> 24) & 0xff;
71 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
88 int64 AmountFromValue(const Value& value)
90 double dAmount = value.get_real();
91 if (dAmount <= 0.0 || dAmount > 21000000.0)
92 throw JSONRPCError(-3, "Invalid amount");
93 int64 nAmount = roundint64(dAmount * COIN);
94 if (!MoneyRange(nAmount))
95 throw JSONRPCError(-3, "Invalid amount");
99 Value ValueFromAmount(int64 amount)
101 return (double)amount / (double)COIN;
105 HexBits(unsigned int nBits)
111 uBits.nBits = htonl((int32_t)nBits);
112 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
115 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
117 int confirms = wtx.GetDepthInMainChain();
118 entry.push_back(Pair("confirmations", confirms));
121 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
122 entry.push_back(Pair("blockindex", wtx.nIndex));
124 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
125 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
126 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
127 entry.push_back(Pair(item.first, item.second));
130 string AccountFromValue(const Value& value)
132 string strAccount = value.get_str();
133 if (strAccount == "*")
134 throw JSONRPCError(-11, "Invalid account name");
138 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
141 result.push_back(Pair("hash", block.GetHash().GetHex()));
142 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
143 result.push_back(Pair("height", blockindex->nHeight));
144 result.push_back(Pair("version", block.nVersion));
145 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
146 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
147 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
148 result.push_back(Pair("bits", HexBits(block.nBits)));
149 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
151 BOOST_FOREACH (const CTransaction&tx, block.vtx)
152 txhashes.push_back(tx.GetHash().GetHex());
153 result.push_back(Pair("tx", txhashes));
155 if (blockindex->pprev)
156 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
157 if (blockindex->pnext)
158 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
165 /// Note: This interface may still be subject to change.
169 Value help(const Array& params, bool fHelp)
171 if (fHelp || params.size() > 1)
174 "List commands, or get help for a command.");
177 if (params.size() > 0)
178 strCommand = params[0].get_str();
181 set<rpcfn_type> setDone;
182 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
184 string strMethod = (*mi).first;
185 // We already filter duplicates, but these deprecated screw up the sort order
186 if (strMethod == "getamountreceived" ||
187 strMethod == "getallreceived" ||
188 strMethod == "getblocknumber" || // deprecated
189 (strMethod.find("label") != string::npos))
191 if (strCommand != "" && strMethod != strCommand)
196 rpcfn_type pfn = (*mi).second;
197 if (setDone.insert(pfn).second)
198 (*pfn)(params, true);
200 catch (std::exception& e)
202 // Help text is returned in an exception
203 string strHelp = string(e.what());
204 if (strCommand == "")
205 if (strHelp.find('\n') != -1)
206 strHelp = strHelp.substr(0, strHelp.find('\n'));
207 strRet += strHelp + "\n";
211 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
212 strRet = strRet.substr(0,strRet.size()-1);
217 Value stop(const Array& params, bool fHelp)
219 if (fHelp || params.size() != 0)
222 "Stop bitcoin server.");
223 // Shutdown will take long enough that the response should get back
225 return "bitcoin server stopping";
229 Value getblockcount(const Array& params, bool fHelp)
231 if (fHelp || params.size() != 0)
234 "Returns the number of blocks in the longest block chain.");
241 Value getblocknumber(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Deprecated. Use getblockcount.");
252 Value getconnectioncount(const Array& params, bool fHelp)
254 if (fHelp || params.size() != 0)
256 "getconnectioncount\n"
257 "Returns the number of connections to other nodes.");
259 return (int)vNodes.size();
263 Value getdifficulty(const Array& params, bool fHelp)
265 if (fHelp || params.size() != 0)
268 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
270 return GetDifficulty();
274 Value getgenerate(const Array& params, bool fHelp)
276 if (fHelp || params.size() != 0)
279 "Returns true or false.");
281 return GetBoolArg("-gen");
285 Value setgenerate(const Array& params, bool fHelp)
287 if (fHelp || params.size() < 1 || params.size() > 2)
289 "setgenerate <generate> [genproclimit]\n"
290 "<generate> is true or false to turn generation on or off.\n"
291 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
293 bool fGenerate = true;
294 if (params.size() > 0)
295 fGenerate = params[0].get_bool();
297 if (params.size() > 1)
299 int nGenProcLimit = params[1].get_int();
300 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
301 if (nGenProcLimit == 0)
304 mapArgs["-gen"] = (fGenerate ? "1" : "0");
306 GenerateBitcoins(fGenerate, pwalletMain);
311 Value gethashespersec(const Array& params, bool fHelp)
313 if (fHelp || params.size() != 0)
316 "Returns a recent hashes per second performance measurement while generating.");
318 if (GetTimeMillis() - nHPSTimerStart > 8000)
319 return (boost::int64_t)0;
320 return (boost::int64_t)dHashesPerSec;
324 Value getinfo(const Array& params, bool fHelp)
326 if (fHelp || params.size() != 0)
329 "Returns an object containing various state info.");
332 obj.push_back(Pair("version", (int)CLIENT_VERSION));
333 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
334 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
335 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
336 obj.push_back(Pair("blocks", (int)nBestHeight));
337 obj.push_back(Pair("connections", (int)vNodes.size()));
338 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
339 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
340 obj.push_back(Pair("testnet", fTestNet));
341 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
342 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
343 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
344 if (pwalletMain->IsCrypted())
345 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
346 obj.push_back(Pair("errors", GetWarnings("statusbar")));
351 Value getmininginfo(const Array& params, bool fHelp)
353 if (fHelp || params.size() != 0)
356 "Returns an object containing mining-related information.");
359 obj.push_back(Pair("blocks", (int)nBestHeight));
360 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
361 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
362 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
363 obj.push_back(Pair("errors", GetWarnings("statusbar")));
364 obj.push_back(Pair("generate", GetBoolArg("-gen")));
365 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
366 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
367 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
368 obj.push_back(Pair("testnet", fTestNet));
373 Value getnewaddress(const Array& params, bool fHelp)
375 if (fHelp || params.size() > 1)
377 "getnewaddress [account]\n"
378 "Returns a new bitcoin address for receiving payments. "
379 "If [account] is specified (recommended), it is added to the address book "
380 "so payments received with the address will be credited to [account].");
382 // Parse the account first so we don't generate a key if there's an error
384 if (params.size() > 0)
385 strAccount = AccountFromValue(params[0]);
387 if (!pwalletMain->IsLocked())
388 pwalletMain->TopUpKeyPool();
390 // Generate a new key that is added to wallet
391 std::vector<unsigned char> newKey;
392 if (!pwalletMain->GetKeyFromPool(newKey, false))
393 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
394 CBitcoinAddress address(newKey);
396 pwalletMain->SetAddressBookName(address, strAccount);
398 return address.ToString();
402 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
404 CWalletDB walletdb(pwalletMain->strWalletFile);
407 walletdb.ReadAccount(strAccount, account);
409 bool bKeyUsed = false;
411 // Check if the current key has been used
412 if (!account.vchPubKey.empty())
414 CScript scriptPubKey;
415 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
416 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
417 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
420 const CWalletTx& wtx = (*it).second;
421 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
422 if (txout.scriptPubKey == scriptPubKey)
427 // Generate a new key
428 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
430 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
431 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
433 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
434 walletdb.WriteAccount(strAccount, account);
437 return CBitcoinAddress(account.vchPubKey);
440 Value getaccountaddress(const Array& params, bool fHelp)
442 if (fHelp || params.size() != 1)
444 "getaccountaddress <account>\n"
445 "Returns the current bitcoin address for receiving payments to this account.");
447 // Parse the account first so we don't generate a key if there's an error
448 string strAccount = AccountFromValue(params[0]);
452 ret = GetAccountAddress(strAccount).ToString();
459 Value setaccount(const Array& params, bool fHelp)
461 if (fHelp || params.size() < 1 || params.size() > 2)
463 "setaccount <bitcoinaddress> <account>\n"
464 "Sets the account associated with the given address.");
466 CBitcoinAddress address(params[0].get_str());
467 if (!address.IsValid())
468 throw JSONRPCError(-5, "Invalid bitcoin address");
472 if (params.size() > 1)
473 strAccount = AccountFromValue(params[1]);
475 // Detect when changing the account of an address that is the 'unused current key' of another account:
476 if (pwalletMain->mapAddressBook.count(address))
478 string strOldAccount = pwalletMain->mapAddressBook[address];
479 if (address == GetAccountAddress(strOldAccount))
480 GetAccountAddress(strOldAccount, true);
483 pwalletMain->SetAddressBookName(address, strAccount);
489 Value getaccount(const Array& params, bool fHelp)
491 if (fHelp || params.size() != 1)
493 "getaccount <bitcoinaddress>\n"
494 "Returns the account associated with the given address.");
496 CBitcoinAddress address(params[0].get_str());
497 if (!address.IsValid())
498 throw JSONRPCError(-5, "Invalid bitcoin address");
501 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
502 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
503 strAccount = (*mi).second;
508 Value getaddressesbyaccount(const Array& params, bool fHelp)
510 if (fHelp || params.size() != 1)
512 "getaddressesbyaccount <account>\n"
513 "Returns the list of addresses for the given account.");
515 string strAccount = AccountFromValue(params[0]);
517 // Find all addresses that have the given account
519 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
521 const CBitcoinAddress& address = item.first;
522 const string& strName = item.second;
523 if (strName == strAccount)
524 ret.push_back(address.ToString());
529 Value settxfee(const Array& params, bool fHelp)
531 if (fHelp || params.size() < 1 || params.size() > 1)
533 "settxfee <amount>\n"
534 "<amount> is a real and is rounded to the nearest 0.00000001");
538 if (params[0].get_real() != 0.0)
539 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
541 nTransactionFee = nAmount;
545 Value sendtoaddress(const Array& params, bool fHelp)
547 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
549 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
550 "<amount> is a real and is rounded to the nearest 0.00000001\n"
551 "requires wallet passphrase to be set with walletpassphrase first");
552 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
554 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
555 "<amount> is a real and is rounded to the nearest 0.00000001");
557 CBitcoinAddress address(params[0].get_str());
558 if (!address.IsValid())
559 throw JSONRPCError(-5, "Invalid bitcoin address");
562 int64 nAmount = AmountFromValue(params[1]);
566 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
567 wtx.mapValue["comment"] = params[2].get_str();
568 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
569 wtx.mapValue["to"] = params[3].get_str();
571 if (pwalletMain->IsLocked())
572 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
574 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
576 throw JSONRPCError(-4, strError);
578 return wtx.GetHash().GetHex();
581 Value signmessage(const Array& params, bool fHelp)
583 if (fHelp || params.size() != 2)
585 "signmessage <bitcoinaddress> <message>\n"
586 "Sign a message with the private key of an address");
588 if (pwalletMain->IsLocked())
589 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
591 string strAddress = params[0].get_str();
592 string strMessage = params[1].get_str();
594 CBitcoinAddress addr(strAddress);
596 throw JSONRPCError(-3, "Invalid address");
599 if (!pwalletMain->GetKey(addr, key))
600 throw JSONRPCError(-4, "Private key not available");
602 CDataStream ss(SER_GETHASH);
603 ss << strMessageMagic;
606 vector<unsigned char> vchSig;
607 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
608 throw JSONRPCError(-5, "Sign failed");
610 return EncodeBase64(&vchSig[0], vchSig.size());
613 Value verifymessage(const Array& params, bool fHelp)
615 if (fHelp || params.size() != 3)
617 "verifymessage <bitcoinaddress> <signature> <message>\n"
618 "Verify a signed message");
620 string strAddress = params[0].get_str();
621 string strSign = params[1].get_str();
622 string strMessage = params[2].get_str();
624 CBitcoinAddress addr(strAddress);
626 throw JSONRPCError(-3, "Invalid address");
628 bool fInvalid = false;
629 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
632 throw JSONRPCError(-5, "Malformed base64 encoding");
634 CDataStream ss(SER_GETHASH);
635 ss << strMessageMagic;
639 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
642 return (CBitcoinAddress(key.GetPubKey()) == addr);
646 Value getreceivedbyaddress(const Array& params, bool fHelp)
648 if (fHelp || params.size() < 1 || params.size() > 2)
650 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
651 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
654 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
655 CScript scriptPubKey;
656 if (!address.IsValid())
657 throw JSONRPCError(-5, "Invalid bitcoin address");
658 scriptPubKey.SetBitcoinAddress(address);
659 if (!IsMine(*pwalletMain,scriptPubKey))
662 // Minimum confirmations
664 if (params.size() > 1)
665 nMinDepth = params[1].get_int();
669 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
671 const CWalletTx& wtx = (*it).second;
672 if (wtx.IsCoinBase() || !wtx.IsFinal())
675 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
676 if (txout.scriptPubKey == scriptPubKey)
677 if (wtx.GetDepthInMainChain() >= nMinDepth)
678 nAmount += txout.nValue;
681 return ValueFromAmount(nAmount);
685 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
687 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
689 const CBitcoinAddress& address = item.first;
690 const string& strName = item.second;
691 if (strName == strAccount)
692 setAddress.insert(address);
697 Value getreceivedbyaccount(const Array& params, bool fHelp)
699 if (fHelp || params.size() < 1 || params.size() > 2)
701 "getreceivedbyaccount <account> [minconf=1]\n"
702 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
704 // Minimum confirmations
706 if (params.size() > 1)
707 nMinDepth = params[1].get_int();
709 // Get the set of pub keys assigned to account
710 string strAccount = AccountFromValue(params[0]);
711 set<CBitcoinAddress> setAddress;
712 GetAccountAddresses(strAccount, setAddress);
716 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
718 const CWalletTx& wtx = (*it).second;
719 if (wtx.IsCoinBase() || !wtx.IsFinal())
722 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
724 CBitcoinAddress address;
725 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
726 if (wtx.GetDepthInMainChain() >= nMinDepth)
727 nAmount += txout.nValue;
731 return (double)nAmount / (double)COIN;
735 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
739 // Tally wallet transactions
740 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
742 const CWalletTx& wtx = (*it).second;
746 int64 nGenerated, nReceived, nSent, nFee;
747 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
749 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
750 nBalance += nReceived;
751 nBalance += nGenerated - nSent - nFee;
754 // Tally internal accounting entries
755 nBalance += walletdb.GetAccountCreditDebit(strAccount);
760 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
762 CWalletDB walletdb(pwalletMain->strWalletFile);
763 return GetAccountBalance(walletdb, strAccount, nMinDepth);
767 Value getbalance(const Array& params, bool fHelp)
769 if (fHelp || params.size() > 2)
771 "getbalance [account] [minconf=1]\n"
772 "If [account] is not specified, returns the server's total available balance.\n"
773 "If [account] is specified, returns the balance in the account.");
775 if (params.size() == 0)
776 return ValueFromAmount(pwalletMain->GetBalance());
779 if (params.size() > 1)
780 nMinDepth = params[1].get_int();
782 if (params[0].get_str() == "*") {
783 // Calculate total balance a different way from GetBalance()
784 // (GetBalance() sums up all unspent TxOuts)
785 // getbalance and getbalance '*' should always return the same number.
787 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
789 const CWalletTx& wtx = (*it).second;
793 int64 allGeneratedImmature, allGeneratedMature, allFee;
794 allGeneratedImmature = allGeneratedMature = allFee = 0;
795 string strSentAccount;
796 list<pair<CBitcoinAddress, int64> > listReceived;
797 list<pair<CBitcoinAddress, int64> > listSent;
798 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
799 if (wtx.GetDepthInMainChain() >= nMinDepth)
800 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
801 nBalance += r.second;
802 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
803 nBalance -= r.second;
805 nBalance += allGeneratedMature;
807 return ValueFromAmount(nBalance);
810 string strAccount = AccountFromValue(params[0]);
812 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
814 return ValueFromAmount(nBalance);
818 Value movecmd(const Array& params, bool fHelp)
820 if (fHelp || params.size() < 3 || params.size() > 5)
822 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
823 "Move from one account in your wallet to another.");
825 string strFrom = AccountFromValue(params[0]);
826 string strTo = AccountFromValue(params[1]);
827 int64 nAmount = AmountFromValue(params[2]);
828 if (params.size() > 3)
829 // unused parameter, used to be nMinDepth, keep type-checking it though
830 (void)params[3].get_int();
832 if (params.size() > 4)
833 strComment = params[4].get_str();
835 CWalletDB walletdb(pwalletMain->strWalletFile);
838 int64 nNow = GetAdjustedTime();
841 CAccountingEntry debit;
842 debit.strAccount = strFrom;
843 debit.nCreditDebit = -nAmount;
845 debit.strOtherAccount = strTo;
846 debit.strComment = strComment;
847 walletdb.WriteAccountingEntry(debit);
850 CAccountingEntry credit;
851 credit.strAccount = strTo;
852 credit.nCreditDebit = nAmount;
854 credit.strOtherAccount = strFrom;
855 credit.strComment = strComment;
856 walletdb.WriteAccountingEntry(credit);
858 walletdb.TxnCommit();
864 Value sendfrom(const Array& params, bool fHelp)
866 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
868 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
869 "<amount> is a real and is rounded to the nearest 0.00000001\n"
870 "requires wallet passphrase to be set with walletpassphrase first");
871 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
873 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
874 "<amount> is a real and is rounded to the nearest 0.00000001");
876 string strAccount = AccountFromValue(params[0]);
877 CBitcoinAddress address(params[1].get_str());
878 if (!address.IsValid())
879 throw JSONRPCError(-5, "Invalid bitcoin address");
880 int64 nAmount = AmountFromValue(params[2]);
882 if (params.size() > 3)
883 nMinDepth = params[3].get_int();
886 wtx.strFromAccount = strAccount;
887 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
888 wtx.mapValue["comment"] = params[4].get_str();
889 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
890 wtx.mapValue["to"] = params[5].get_str();
892 if (pwalletMain->IsLocked())
893 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
896 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
897 if (nAmount > nBalance)
898 throw JSONRPCError(-6, "Account has insufficient funds");
901 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
903 throw JSONRPCError(-4, strError);
905 return wtx.GetHash().GetHex();
909 Value sendmany(const Array& params, bool fHelp)
911 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
913 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
914 "amounts are double-precision floating point numbers\n"
915 "requires wallet passphrase to be set with walletpassphrase first");
916 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
918 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
919 "amounts are double-precision floating point numbers");
921 string strAccount = AccountFromValue(params[0]);
922 Object sendTo = params[1].get_obj();
924 if (params.size() > 2)
925 nMinDepth = params[2].get_int();
928 wtx.strFromAccount = strAccount;
929 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
930 wtx.mapValue["comment"] = params[3].get_str();
932 set<CBitcoinAddress> setAddress;
933 vector<pair<CScript, int64> > vecSend;
935 int64 totalAmount = 0;
936 BOOST_FOREACH(const Pair& s, sendTo)
938 CBitcoinAddress address(s.name_);
939 if (!address.IsValid())
940 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
942 if (setAddress.count(address))
943 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
944 setAddress.insert(address);
946 CScript scriptPubKey;
947 scriptPubKey.SetBitcoinAddress(address);
948 int64 nAmount = AmountFromValue(s.value_);
949 totalAmount += nAmount;
951 vecSend.push_back(make_pair(scriptPubKey, nAmount));
954 if (pwalletMain->IsLocked())
955 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
958 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
959 if (totalAmount > nBalance)
960 throw JSONRPCError(-6, "Account has insufficient funds");
963 CReserveKey keyChange(pwalletMain);
964 int64 nFeeRequired = 0;
965 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
968 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
969 throw JSONRPCError(-6, "Insufficient funds");
970 throw JSONRPCError(-4, "Transaction creation failed");
972 if (!pwalletMain->CommitTransaction(wtx, keyChange))
973 throw JSONRPCError(-4, "Transaction commit failed");
975 return wtx.GetHash().GetHex();
978 Value addmultisigaddress(const Array& params, bool fHelp)
980 if (fHelp || params.size() < 2 || params.size() > 3)
982 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
983 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
984 "each key is a bitcoin address or hex-encoded public key\n"
985 "If [account] is specified, assign address to [account].";
986 throw runtime_error(msg);
989 throw runtime_error("addmultisigaddress available only when running -testnet\n");
991 int nRequired = params[0].get_int();
992 const Array& keys = params[1].get_array();
994 if (params.size() > 2)
995 strAccount = AccountFromValue(params[2]);
997 // Gather public keys
998 if (nRequired < 1 || keys.size() < nRequired)
1000 strprintf("wrong number of keys"
1001 "(got %d, need at least %d)", keys.size(), nRequired));
1002 std::vector<CKey> pubkeys;
1003 pubkeys.resize(keys.size());
1004 for (int i = 0; i < keys.size(); i++)
1006 const std::string& ks = keys[i].get_str();
1008 // Case 1: bitcoin address and we have full public key:
1009 CBitcoinAddress address(ks);
1010 if (address.IsValid())
1012 if (address.IsScript())
1013 throw runtime_error(
1014 strprintf("%s is a pay-to-script address",ks.c_str()));
1015 std::vector<unsigned char> vchPubKey;
1016 if (!pwalletMain->GetPubKey(address, vchPubKey))
1017 throw runtime_error(
1018 strprintf("no full public key for address %s",ks.c_str()));
1019 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1020 throw runtime_error(" Invalid public key: "+ks);
1023 // Case 2: hex public key
1026 vector<unsigned char> vchPubKey = ParseHex(ks);
1027 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1028 throw runtime_error(" Invalid public key: "+ks);
1032 throw runtime_error(" Invalid public key: "+ks);
1036 // Construct using pay-to-script-hash:
1038 inner.SetMultisig(nRequired, pubkeys);
1040 uint160 scriptHash = Hash160(inner);
1041 CScript scriptPubKey;
1042 scriptPubKey.SetPayToScriptHash(inner);
1043 pwalletMain->AddCScript(inner);
1044 CBitcoinAddress address;
1045 address.SetScriptHash160(scriptHash);
1047 pwalletMain->SetAddressBookName(address, strAccount);
1048 return address.ToString();
1059 nConf = std::numeric_limits<int>::max();
1063 Value ListReceived(const Array& params, bool fByAccounts)
1065 // Minimum confirmations
1067 if (params.size() > 0)
1068 nMinDepth = params[0].get_int();
1070 // Whether to include empty accounts
1071 bool fIncludeEmpty = false;
1072 if (params.size() > 1)
1073 fIncludeEmpty = params[1].get_bool();
1076 map<CBitcoinAddress, tallyitem> mapTally;
1077 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1079 const CWalletTx& wtx = (*it).second;
1081 if (wtx.IsCoinBase() || !wtx.IsFinal())
1084 int nDepth = wtx.GetDepthInMainChain();
1085 if (nDepth < nMinDepth)
1088 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1090 CBitcoinAddress address;
1091 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1094 tallyitem& item = mapTally[address];
1095 item.nAmount += txout.nValue;
1096 item.nConf = min(item.nConf, nDepth);
1102 map<string, tallyitem> mapAccountTally;
1103 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1105 const CBitcoinAddress& address = item.first;
1106 const string& strAccount = item.second;
1107 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1108 if (it == mapTally.end() && !fIncludeEmpty)
1112 int nConf = std::numeric_limits<int>::max();
1113 if (it != mapTally.end())
1115 nAmount = (*it).second.nAmount;
1116 nConf = (*it).second.nConf;
1121 tallyitem& item = mapAccountTally[strAccount];
1122 item.nAmount += nAmount;
1123 item.nConf = min(item.nConf, nConf);
1128 obj.push_back(Pair("address", address.ToString()));
1129 obj.push_back(Pair("account", strAccount));
1130 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1131 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1138 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1140 int64 nAmount = (*it).second.nAmount;
1141 int nConf = (*it).second.nConf;
1143 obj.push_back(Pair("account", (*it).first));
1144 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1145 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1153 Value listreceivedbyaddress(const Array& params, bool fHelp)
1155 if (fHelp || params.size() > 2)
1156 throw runtime_error(
1157 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1158 "[minconf] is the minimum number of confirmations before payments are included.\n"
1159 "[includeempty] whether to include addresses that haven't received any payments.\n"
1160 "Returns an array of objects containing:\n"
1161 " \"address\" : receiving address\n"
1162 " \"account\" : the account of the receiving address\n"
1163 " \"amount\" : total amount received by the address\n"
1164 " \"confirmations\" : number of confirmations of the most recent transaction included");
1166 return ListReceived(params, false);
1169 Value listreceivedbyaccount(const Array& params, bool fHelp)
1171 if (fHelp || params.size() > 2)
1172 throw runtime_error(
1173 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1174 "[minconf] is the minimum number of confirmations before payments are included.\n"
1175 "[includeempty] whether to include accounts that haven't received any payments.\n"
1176 "Returns an array of objects containing:\n"
1177 " \"account\" : the account of the receiving addresses\n"
1178 " \"amount\" : total amount received by addresses with this account\n"
1179 " \"confirmations\" : number of confirmations of the most recent transaction included");
1181 return ListReceived(params, true);
1184 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1186 int64 nGeneratedImmature, nGeneratedMature, nFee;
1187 string strSentAccount;
1188 list<pair<CBitcoinAddress, int64> > listReceived;
1189 list<pair<CBitcoinAddress, int64> > listSent;
1191 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1193 bool fAllAccounts = (strAccount == string("*"));
1195 // Generated blocks assigned to account ""
1196 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1199 entry.push_back(Pair("account", string("")));
1200 if (nGeneratedImmature)
1202 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1203 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1207 entry.push_back(Pair("category", "generate"));
1208 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1211 WalletTxToJSON(wtx, entry);
1212 ret.push_back(entry);
1216 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1218 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1221 entry.push_back(Pair("account", strSentAccount));
1222 entry.push_back(Pair("address", s.first.ToString()));
1223 entry.push_back(Pair("category", "send"));
1224 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1225 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1227 WalletTxToJSON(wtx, entry);
1228 ret.push_back(entry);
1233 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1234 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1237 if (pwalletMain->mapAddressBook.count(r.first))
1238 account = pwalletMain->mapAddressBook[r.first];
1239 if (fAllAccounts || (account == strAccount))
1242 entry.push_back(Pair("account", account));
1243 entry.push_back(Pair("address", r.first.ToString()));
1244 entry.push_back(Pair("category", "receive"));
1245 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1247 WalletTxToJSON(wtx, entry);
1248 ret.push_back(entry);
1253 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1255 bool fAllAccounts = (strAccount == string("*"));
1257 if (fAllAccounts || acentry.strAccount == strAccount)
1260 entry.push_back(Pair("account", acentry.strAccount));
1261 entry.push_back(Pair("category", "move"));
1262 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1263 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1264 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1265 entry.push_back(Pair("comment", acentry.strComment));
1266 ret.push_back(entry);
1270 Value listtransactions(const Array& params, bool fHelp)
1272 if (fHelp || params.size() > 3)
1273 throw runtime_error(
1274 "listtransactions [account] [count=10] [from=0]\n"
1275 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1277 string strAccount = "*";
1278 if (params.size() > 0)
1279 strAccount = params[0].get_str();
1281 if (params.size() > 1)
1282 nCount = params[1].get_int();
1284 if (params.size() > 2)
1285 nFrom = params[2].get_int();
1288 CWalletDB walletdb(pwalletMain->strWalletFile);
1290 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1291 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1292 typedef multimap<int64, TxPair > TxItems;
1295 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1297 CWalletTx* wtx = &((*it).second);
1298 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1300 list<CAccountingEntry> acentries;
1301 walletdb.ListAccountCreditDebit(strAccount, acentries);
1302 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1304 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1307 // Now: iterate backwards until we have nCount items to return:
1308 TxItems::reverse_iterator it = txByTime.rbegin();
1309 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1310 for (; it != txByTime.rend(); ++it)
1312 CWalletTx *const pwtx = (*it).second.first;
1314 ListTransactions(*pwtx, strAccount, 0, true, ret);
1315 CAccountingEntry *const pacentry = (*it).second.second;
1317 AcentryToJSON(*pacentry, strAccount, ret);
1319 if (ret.size() >= nCount) break;
1321 // ret is now newest to oldest
1323 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1324 if (ret.size() > nCount)
1326 Array::iterator last = ret.begin();
1327 std::advance(last, nCount);
1328 ret.erase(last, ret.end());
1330 std::reverse(ret.begin(), ret.end()); // oldest to newest
1335 Value listaccounts(const Array& params, bool fHelp)
1337 if (fHelp || params.size() > 1)
1338 throw runtime_error(
1339 "listaccounts [minconf=1]\n"
1340 "Returns Object that has account names as keys, account balances as values.");
1343 if (params.size() > 0)
1344 nMinDepth = params[0].get_int();
1346 map<string, int64> mapAccountBalances;
1347 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1348 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1349 mapAccountBalances[entry.second] = 0;
1352 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1354 const CWalletTx& wtx = (*it).second;
1355 int64 nGeneratedImmature, nGeneratedMature, nFee;
1356 string strSentAccount;
1357 list<pair<CBitcoinAddress, int64> > listReceived;
1358 list<pair<CBitcoinAddress, int64> > listSent;
1359 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1360 mapAccountBalances[strSentAccount] -= nFee;
1361 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1362 mapAccountBalances[strSentAccount] -= s.second;
1363 if (wtx.GetDepthInMainChain() >= nMinDepth)
1365 mapAccountBalances[""] += nGeneratedMature;
1366 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1367 if (pwalletMain->mapAddressBook.count(r.first))
1368 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1370 mapAccountBalances[""] += r.second;
1374 list<CAccountingEntry> acentries;
1375 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1376 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1377 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1380 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1381 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1386 Value listsinceblock(const Array& params, bool fHelp)
1389 throw runtime_error(
1390 "listsinceblock [blockid] [target-confirmations]\n"
1391 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1393 CBlockIndex *pindex = NULL;
1394 int target_confirms = 1;
1396 if (params.size() > 0)
1398 uint256 blockId = 0;
1400 blockId.SetHex(params[0].get_str());
1401 pindex = CBlockLocator(blockId).GetBlockIndex();
1404 if (params.size() > 1)
1406 target_confirms = params[1].get_int();
1408 if (target_confirms < 1)
1409 throw JSONRPCError(-8, "Invalid parameter");
1412 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1416 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1418 CWalletTx tx = (*it).second;
1420 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1421 ListTransactions(tx, "*", 0, true, transactions);
1426 if (target_confirms == 1)
1429 lastblock = hashBestChain;
1433 int target_height = pindexBest->nHeight + 1 - target_confirms;
1436 for (block = pindexBest;
1437 block && block->nHeight > target_height;
1438 block = block->pprev) { }
1440 lastblock = block ? block->GetBlockHash() : 0;
1444 ret.push_back(Pair("transactions", transactions));
1445 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1450 Value gettransaction(const Array& params, bool fHelp)
1452 if (fHelp || params.size() != 1)
1453 throw runtime_error(
1454 "gettransaction <txid>\n"
1455 "Get detailed information about <txid>");
1458 hash.SetHex(params[0].get_str());
1462 if (!pwalletMain->mapWallet.count(hash))
1463 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1464 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1466 int64 nCredit = wtx.GetCredit();
1467 int64 nDebit = wtx.GetDebit();
1468 int64 nNet = nCredit - nDebit;
1469 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1471 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1473 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1475 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1478 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1479 entry.push_back(Pair("details", details));
1485 Value backupwallet(const Array& params, bool fHelp)
1487 if (fHelp || params.size() != 1)
1488 throw runtime_error(
1489 "backupwallet <destination>\n"
1490 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1492 string strDest = params[0].get_str();
1493 BackupWallet(*pwalletMain, strDest);
1499 Value keypoolrefill(const Array& params, bool fHelp)
1501 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1502 throw runtime_error(
1504 "Fills the keypool, requires wallet passphrase to be set.");
1505 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1506 throw runtime_error(
1508 "Fills the keypool.");
1510 if (pwalletMain->IsLocked())
1511 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1513 pwalletMain->TopUpKeyPool();
1515 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1516 throw JSONRPCError(-4, "Error refreshing keypool.");
1522 void ThreadTopUpKeyPool(void* parg)
1524 pwalletMain->TopUpKeyPool();
1527 void ThreadCleanWalletPassphrase(void* parg)
1529 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1531 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1533 if (nWalletUnlockTime == 0)
1535 nWalletUnlockTime = nMyWakeTime;
1539 if (nWalletUnlockTime==0)
1541 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1545 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1547 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1551 if (nWalletUnlockTime)
1553 nWalletUnlockTime = 0;
1554 pwalletMain->Lock();
1559 if (nWalletUnlockTime < nMyWakeTime)
1560 nWalletUnlockTime = nMyWakeTime;
1563 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1565 delete (int64*)parg;
1568 Value walletpassphrase(const Array& params, bool fHelp)
1570 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1571 throw runtime_error(
1572 "walletpassphrase <passphrase> <timeout>\n"
1573 "Stores the wallet decryption key in memory for <timeout> seconds.");
1576 if (!pwalletMain->IsCrypted())
1577 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1579 if (!pwalletMain->IsLocked())
1580 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1582 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1583 SecureString strWalletPass;
1584 strWalletPass.reserve(100);
1585 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1586 // Alternately, find a way to make params[0] mlock()'d to begin with.
1587 strWalletPass = params[0].get_str().c_str();
1589 if (strWalletPass.length() > 0)
1591 if (!pwalletMain->Unlock(strWalletPass))
1592 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1595 throw runtime_error(
1596 "walletpassphrase <passphrase> <timeout>\n"
1597 "Stores the wallet decryption key in memory for <timeout> seconds.");
1599 CreateThread(ThreadTopUpKeyPool, NULL);
1600 int64* pnSleepTime = new int64(params[1].get_int64());
1601 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1607 Value walletpassphrasechange(const Array& params, bool fHelp)
1609 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1610 throw runtime_error(
1611 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1612 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1615 if (!pwalletMain->IsCrypted())
1616 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1618 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1619 // Alternately, find a way to make params[0] mlock()'d to begin with.
1620 SecureString strOldWalletPass;
1621 strOldWalletPass.reserve(100);
1622 strOldWalletPass = params[0].get_str().c_str();
1624 SecureString strNewWalletPass;
1625 strNewWalletPass.reserve(100);
1626 strNewWalletPass = params[1].get_str().c_str();
1628 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1629 throw runtime_error(
1630 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1631 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1633 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1634 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1640 Value walletlock(const Array& params, bool fHelp)
1642 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1643 throw runtime_error(
1645 "Removes the wallet encryption key from memory, locking the wallet.\n"
1646 "After calling this method, you will need to call walletpassphrase again\n"
1647 "before being able to call any methods which require the wallet to be unlocked.");
1650 if (!pwalletMain->IsCrypted())
1651 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1653 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1655 pwalletMain->Lock();
1656 nWalletUnlockTime = 0;
1663 Value encryptwallet(const Array& params, bool fHelp)
1665 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1666 throw runtime_error(
1667 "encryptwallet <passphrase>\n"
1668 "Encrypts the wallet with <passphrase>.");
1671 if (pwalletMain->IsCrypted())
1672 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1674 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1675 // Alternately, find a way to make params[0] mlock()'d to begin with.
1676 SecureString strWalletPass;
1677 strWalletPass.reserve(100);
1678 strWalletPass = params[0].get_str().c_str();
1680 if (strWalletPass.length() < 1)
1681 throw runtime_error(
1682 "encryptwallet <passphrase>\n"
1683 "Encrypts the wallet with <passphrase>.");
1685 if (!pwalletMain->EncryptWallet(strWalletPass))
1686 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1688 // BDB seems to have a bad habit of writing old data into
1689 // slack space in .dat files; that is bad if the old data is
1690 // unencrypted private keys. So:
1692 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1696 Value validateaddress(const Array& params, bool fHelp)
1698 if (fHelp || params.size() != 1)
1699 throw runtime_error(
1700 "validateaddress <bitcoinaddress>\n"
1701 "Return information about <bitcoinaddress>.");
1703 CBitcoinAddress address(params[0].get_str());
1704 bool isValid = address.IsValid();
1707 ret.push_back(Pair("isvalid", isValid));
1710 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1711 // version of the address:
1712 string currentAddress = address.ToString();
1713 ret.push_back(Pair("address", currentAddress));
1714 if (pwalletMain->HaveKey(address))
1716 ret.push_back(Pair("ismine", true));
1717 std::vector<unsigned char> vchPubKey;
1718 pwalletMain->GetPubKey(address, vchPubKey);
1719 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1721 key.SetPubKey(vchPubKey);
1722 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1724 else if (pwalletMain->HaveCScript(address.GetHash160()))
1726 ret.push_back(Pair("isscript", true));
1728 pwalletMain->GetCScript(address.GetHash160(), subscript);
1729 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1730 std::vector<CBitcoinAddress> addresses;
1731 txnouttype whichType;
1733 ExtractAddresses(subscript, whichType, addresses, nRequired);
1734 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1736 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1737 a.push_back(addr.ToString());
1738 ret.push_back(Pair("addresses", a));
1739 if (whichType == TX_MULTISIG)
1740 ret.push_back(Pair("sigsrequired", nRequired));
1743 ret.push_back(Pair("ismine", false));
1744 if (pwalletMain->mapAddressBook.count(address))
1745 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1750 Value getwork(const Array& params, bool fHelp)
1752 if (fHelp || params.size() > 1)
1753 throw runtime_error(
1755 "If [data] is not specified, returns formatted hash data to work on:\n"
1756 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1757 " \"data\" : block data\n"
1758 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1759 " \"target\" : little endian hash target\n"
1760 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1763 throw JSONRPCError(-9, "Bitcoin is not connected!");
1765 if (IsInitialBlockDownload())
1766 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1768 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1769 static mapNewBlock_t mapNewBlock;
1770 static vector<CBlock*> vNewBlock;
1771 static CReserveKey reservekey(pwalletMain);
1773 if (params.size() == 0)
1776 static unsigned int nTransactionsUpdatedLast;
1777 static CBlockIndex* pindexPrev;
1778 static int64 nStart;
1779 static CBlock* pblock;
1780 if (pindexPrev != pindexBest ||
1781 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1783 if (pindexPrev != pindexBest)
1785 // Deallocate old blocks since they're obsolete now
1786 mapNewBlock.clear();
1787 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1791 nTransactionsUpdatedLast = nTransactionsUpdated;
1792 pindexPrev = pindexBest;
1796 pblock = CreateNewBlock(reservekey);
1798 throw JSONRPCError(-7, "Out of memory");
1799 vNewBlock.push_back(pblock);
1803 pblock->UpdateTime(pindexPrev);
1806 // Update nExtraNonce
1807 static unsigned int nExtraNonce = 0;
1808 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1811 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1813 // Prebuild hash buffers
1817 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1819 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1822 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1823 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1824 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1825 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1831 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1832 if (vchData.size() != 128)
1833 throw JSONRPCError(-8, "Invalid parameter");
1834 CBlock* pdata = (CBlock*)&vchData[0];
1837 for (int i = 0; i < 128/4; i++)
1838 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1841 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1843 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1845 pblock->nTime = pdata->nTime;
1846 pblock->nNonce = pdata->nNonce;
1847 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1848 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1850 return CheckWork(pblock, *pwalletMain, reservekey);
1855 Value getmemorypool(const Array& params, bool fHelp)
1857 if (fHelp || params.size() > 1)
1858 throw runtime_error(
1859 "getmemorypool [data]\n"
1860 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1861 " \"version\" : block version\n"
1862 " \"previousblockhash\" : hash of current highest block\n"
1863 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1864 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1865 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1866 " \"time\" : timestamp appropriate for next block\n"
1867 " \"mintime\" : minimum timestamp appropriate for next block\n"
1868 " \"curtime\" : current timestamp\n"
1869 " \"bits\" : compressed target of next block\n"
1870 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1872 if (params.size() == 0)
1875 throw JSONRPCError(-9, "Bitcoin is not connected!");
1877 if (IsInitialBlockDownload())
1878 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1880 static CReserveKey reservekey(pwalletMain);
1883 static unsigned int nTransactionsUpdatedLast;
1884 static CBlockIndex* pindexPrev;
1885 static int64 nStart;
1886 static CBlock* pblock;
1887 if (pindexPrev != pindexBest ||
1888 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1890 nTransactionsUpdatedLast = nTransactionsUpdated;
1891 pindexPrev = pindexBest;
1897 pblock = CreateNewBlock(reservekey);
1899 throw JSONRPCError(-7, "Out of memory");
1903 pblock->UpdateTime(pindexPrev);
1907 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1914 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1918 result.push_back(Pair("version", pblock->nVersion));
1919 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1920 result.push_back(Pair("transactions", transactions));
1921 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1922 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1923 result.push_back(Pair("time", (int64_t)pblock->nTime));
1924 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1925 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1926 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1933 CDataStream ssBlock(ParseHex(params[0].get_str()));
1937 return ProcessBlock(NULL, &pblock);
1941 Value getblockhash(const Array& params, bool fHelp)
1943 if (fHelp || params.size() != 1)
1944 throw runtime_error(
1945 "getblockhash <index>\n"
1946 "Returns hash of block in best-block-chain at <index>.");
1948 int nHeight = params[0].get_int();
1949 if (nHeight < 0 || nHeight > nBestHeight)
1950 throw runtime_error("Block number out of range.");
1953 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1954 while (pblockindex->nHeight > nHeight)
1955 pblockindex = pblockindex->pprev;
1956 return pblockindex->phashBlock->GetHex();
1959 Value getblock(const Array& params, bool fHelp)
1961 if (fHelp || params.size() != 1)
1962 throw runtime_error(
1964 "Returns details of a block with given block-hash.");
1966 std::string strHash = params[0].get_str();
1967 uint256 hash(strHash);
1969 if (mapBlockIndex.count(hash) == 0)
1970 throw JSONRPCError(-5, "Block not found");
1973 CBlockIndex* pblockindex = mapBlockIndex[hash];
1974 block.ReadFromDisk(pblockindex, true);
1976 return blockToJSON(block, pblockindex);
1993 pair<string, rpcfn_type> pCallTable[] =
1995 make_pair("help", &help),
1996 make_pair("stop", &stop),
1997 make_pair("getblockcount", &getblockcount),
1998 make_pair("getblocknumber", &getblocknumber),
1999 make_pair("getconnectioncount", &getconnectioncount),
2000 make_pair("getdifficulty", &getdifficulty),
2001 make_pair("getgenerate", &getgenerate),
2002 make_pair("setgenerate", &setgenerate),
2003 make_pair("gethashespersec", &gethashespersec),
2004 make_pair("getinfo", &getinfo),
2005 make_pair("getmininginfo", &getmininginfo),
2006 make_pair("getnewaddress", &getnewaddress),
2007 make_pair("getaccountaddress", &getaccountaddress),
2008 make_pair("setaccount", &setaccount),
2009 make_pair("getaccount", &getaccount),
2010 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2011 make_pair("sendtoaddress", &sendtoaddress),
2012 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2013 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2014 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2015 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2016 make_pair("backupwallet", &backupwallet),
2017 make_pair("keypoolrefill", &keypoolrefill),
2018 make_pair("walletpassphrase", &walletpassphrase),
2019 make_pair("walletpassphrasechange", &walletpassphrasechange),
2020 make_pair("walletlock", &walletlock),
2021 make_pair("encryptwallet", &encryptwallet),
2022 make_pair("validateaddress", &validateaddress),
2023 make_pair("getbalance", &getbalance),
2024 make_pair("move", &movecmd),
2025 make_pair("sendfrom", &sendfrom),
2026 make_pair("sendmany", &sendmany),
2027 make_pair("addmultisigaddress", &addmultisigaddress),
2028 make_pair("getblock", &getblock),
2029 make_pair("getblockhash", &getblockhash),
2030 make_pair("gettransaction", &gettransaction),
2031 make_pair("listtransactions", &listtransactions),
2032 make_pair("signmessage", &signmessage),
2033 make_pair("verifymessage", &verifymessage),
2034 make_pair("getwork", &getwork),
2035 make_pair("listaccounts", &listaccounts),
2036 make_pair("settxfee", &settxfee),
2037 make_pair("getmemorypool", &getmemorypool),
2038 make_pair("listsinceblock", &listsinceblock),
2039 make_pair("dumpprivkey", &dumpprivkey),
2040 make_pair("importprivkey", &importprivkey)
2042 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2044 string pAllowInSafeMode[] =
2049 "getblocknumber", // deprecated
2050 "getconnectioncount",
2058 "getaccountaddress",
2060 "getaddressesbyaccount",
2069 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2077 // This ain't Apache. We're just using HTTP header for the length field
2078 // and to be compatible with other JSON-RPC implementations.
2081 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2084 s << "POST / HTTP/1.1\r\n"
2085 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2086 << "Host: 127.0.0.1\r\n"
2087 << "Content-Type: application/json\r\n"
2088 << "Content-Length: " << strMsg.size() << "\r\n"
2089 << "Connection: close\r\n"
2090 << "Accept: application/json\r\n";
2091 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2092 s << item.first << ": " << item.second << "\r\n";
2093 s << "\r\n" << strMsg;
2098 string rfc1123Time()
2103 struct tm* now_gmt = gmtime(&now);
2104 string locale(setlocale(LC_TIME, NULL));
2105 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2106 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2107 setlocale(LC_TIME, locale.c_str());
2108 return string(buffer);
2111 static string HTTPReply(int nStatus, const string& strMsg)
2114 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2116 "Server: bitcoin-json-rpc/%s\r\n"
2117 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2118 "Content-Type: text/html\r\n"
2119 "Content-Length: 296\r\n"
2121 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2122 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2125 "<TITLE>Error</TITLE>\r\n"
2126 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2128 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2129 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2130 const char *cStatus;
2131 if (nStatus == 200) cStatus = "OK";
2132 else if (nStatus == 400) cStatus = "Bad Request";
2133 else if (nStatus == 403) cStatus = "Forbidden";
2134 else if (nStatus == 404) cStatus = "Not Found";
2135 else if (nStatus == 500) cStatus = "Internal Server Error";
2138 "HTTP/1.1 %d %s\r\n"
2140 "Connection: close\r\n"
2141 "Content-Length: %d\r\n"
2142 "Content-Type: application/json\r\n"
2143 "Server: bitcoin-json-rpc/%s\r\n"
2148 rfc1123Time().c_str(),
2150 FormatFullVersion().c_str(),
2154 int ReadHTTPStatus(std::basic_istream<char>& stream)
2157 getline(stream, str);
2158 vector<string> vWords;
2159 boost::split(vWords, str, boost::is_any_of(" "));
2160 if (vWords.size() < 2)
2162 return atoi(vWords[1].c_str());
2165 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2171 std::getline(stream, str);
2172 if (str.empty() || str == "\r")
2174 string::size_type nColon = str.find(":");
2175 if (nColon != string::npos)
2177 string strHeader = str.substr(0, nColon);
2178 boost::trim(strHeader);
2179 boost::to_lower(strHeader);
2180 string strValue = str.substr(nColon+1);
2181 boost::trim(strValue);
2182 mapHeadersRet[strHeader] = strValue;
2183 if (strHeader == "content-length")
2184 nLen = atoi(strValue.c_str());
2190 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2192 mapHeadersRet.clear();
2196 int nStatus = ReadHTTPStatus(stream);
2199 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2200 if (nLen < 0 || nLen > MAX_SIZE)
2206 vector<char> vch(nLen);
2207 stream.read(&vch[0], nLen);
2208 strMessageRet = string(vch.begin(), vch.end());
2214 bool HTTPAuthorized(map<string, string>& mapHeaders)
2216 string strAuth = mapHeaders["authorization"];
2217 if (strAuth.substr(0,6) != "Basic ")
2219 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2220 string strUserPass = DecodeBase64(strUserPass64);
2221 return strUserPass == strRPCUserColonPass;
2225 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2226 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2227 // unspecified (HTTP errors and contents of 'error').
2229 // 1.0 spec: http://json-rpc.org/wiki/specification
2230 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2231 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2234 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2237 request.push_back(Pair("method", strMethod));
2238 request.push_back(Pair("params", params));
2239 request.push_back(Pair("id", id));
2240 return write_string(Value(request), false) + "\n";
2243 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2246 if (error.type() != null_type)
2247 reply.push_back(Pair("result", Value::null));
2249 reply.push_back(Pair("result", result));
2250 reply.push_back(Pair("error", error));
2251 reply.push_back(Pair("id", id));
2252 return write_string(Value(reply), false) + "\n";
2255 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2257 // Send error reply from json-rpc error object
2259 int code = find_value(objError, "code").get_int();
2260 if (code == -32600) nStatus = 400;
2261 else if (code == -32601) nStatus = 404;
2262 string strReply = JSONRPCReply(Value::null, objError, id);
2263 stream << HTTPReply(nStatus, strReply) << std::flush;
2266 bool ClientAllowed(const string& strAddress)
2268 if (strAddress == asio::ip::address_v4::loopback().to_string())
2270 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2271 BOOST_FOREACH(string strAllow, vAllow)
2272 if (WildcardMatch(strAddress, strAllow))
2278 // IOStream device that speaks SSL but can also speak non-SSL
2280 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2282 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2284 fUseSSL = fUseSSLIn;
2285 fNeedHandshake = fUseSSLIn;
2288 void handshake(ssl::stream_base::handshake_type role)
2290 if (!fNeedHandshake) return;
2291 fNeedHandshake = false;
2292 stream.handshake(role);
2294 std::streamsize read(char* s, std::streamsize n)
2296 handshake(ssl::stream_base::server); // HTTPS servers read first
2297 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2298 return stream.next_layer().read_some(asio::buffer(s, n));
2300 std::streamsize write(const char* s, std::streamsize n)
2302 handshake(ssl::stream_base::client); // HTTPS clients write first
2303 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2304 return asio::write(stream.next_layer(), asio::buffer(s, n));
2306 bool connect(const std::string& server, const std::string& port)
2308 ip::tcp::resolver resolver(stream.get_io_service());
2309 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2310 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2311 ip::tcp::resolver::iterator end;
2312 boost::system::error_code error = asio::error::host_not_found;
2313 while (error && endpoint_iterator != end)
2315 stream.lowest_layer().close();
2316 stream.lowest_layer().connect(*endpoint_iterator++, error);
2324 bool fNeedHandshake;
2329 void ThreadRPCServer(void* parg)
2331 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2334 vnThreadsRunning[THREAD_RPCSERVER]++;
2335 ThreadRPCServer2(parg);
2336 vnThreadsRunning[THREAD_RPCSERVER]--;
2338 catch (std::exception& e) {
2339 vnThreadsRunning[THREAD_RPCSERVER]--;
2340 PrintException(&e, "ThreadRPCServer()");
2342 vnThreadsRunning[THREAD_RPCSERVER]--;
2343 PrintException(NULL, "ThreadRPCServer()");
2345 printf("ThreadRPCServer exiting\n");
2348 void ThreadRPCServer2(void* parg)
2350 printf("ThreadRPCServer started\n");
2352 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2353 if (mapArgs["-rpcpassword"] == "")
2355 unsigned char rand_pwd[32];
2356 RAND_bytes(rand_pwd, 32);
2357 string strWhatAmI = "To use bitcoind";
2358 if (mapArgs.count("-server"))
2359 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2360 else if (mapArgs.count("-daemon"))
2361 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2362 ThreadSafeMessageBox(strprintf(
2363 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2364 "It is recommended you use the following random password:\n"
2365 "rpcuser=bitcoinrpc\n"
2367 "(you do not need to remember this password)\n"
2368 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2370 GetConfigFile().c_str(),
2371 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2372 _("Error"), wxOK | wxMODAL);
2377 bool fUseSSL = GetBoolArg("-rpcssl");
2378 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2380 asio::io_service io_service;
2381 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2382 ip::tcp::acceptor acceptor(io_service, endpoint);
2384 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2386 ssl::context context(io_service, ssl::context::sslv23);
2389 context.set_options(ssl::context::no_sslv2);
2390 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2391 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2392 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2393 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2394 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2395 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2396 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2397 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2399 string ciphers = GetArg("-rpcsslciphers",
2400 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2401 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2406 // Accept connection
2407 SSLStream sslStream(io_service, context);
2408 SSLIOStreamDevice d(sslStream, fUseSSL);
2409 iostreams::stream<SSLIOStreamDevice> stream(d);
2411 ip::tcp::endpoint peer;
2412 vnThreadsRunning[THREAD_RPCSERVER]--;
2413 acceptor.accept(sslStream.lowest_layer(), peer);
2414 vnThreadsRunning[4]++;
2418 // Restrict callers by IP
2419 if (!ClientAllowed(peer.address().to_string()))
2421 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2423 stream << HTTPReply(403, "") << std::flush;
2427 map<string, string> mapHeaders;
2430 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2431 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2434 printf("ThreadRPCServer ReadHTTP timeout\n");
2438 // Check authorization
2439 if (mapHeaders.count("authorization") == 0)
2441 stream << HTTPReply(401, "") << std::flush;
2444 if (!HTTPAuthorized(mapHeaders))
2446 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2447 /* Deter brute-forcing short passwords.
2448 If this results in a DOS the user really
2449 shouldn't have their RPC port exposed.*/
2450 if (mapArgs["-rpcpassword"].size() < 20)
2453 stream << HTTPReply(401, "") << std::flush;
2457 Value id = Value::null;
2462 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2463 throw JSONRPCError(-32700, "Parse error");
2464 const Object& request = valRequest.get_obj();
2466 // Parse id now so errors from here on will have the id
2467 id = find_value(request, "id");
2470 Value valMethod = find_value(request, "method");
2471 if (valMethod.type() == null_type)
2472 throw JSONRPCError(-32600, "Missing method");
2473 if (valMethod.type() != str_type)
2474 throw JSONRPCError(-32600, "Method must be a string");
2475 string strMethod = valMethod.get_str();
2476 if (strMethod != "getwork" && strMethod != "getmemorypool")
2477 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2480 Value valParams = find_value(request, "params");
2482 if (valParams.type() == array_type)
2483 params = valParams.get_array();
2484 else if (valParams.type() == null_type)
2487 throw JSONRPCError(-32600, "Params must be an array");
2490 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2491 if (mi == mapCallTable.end())
2492 throw JSONRPCError(-32601, "Method not found");
2494 // Observe safe mode
2495 string strWarning = GetWarnings("rpc");
2496 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2497 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2503 CRITICAL_BLOCK(cs_main)
2504 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2505 result = (*(*mi).second)(params, false);
2508 string strReply = JSONRPCReply(result, Value::null, id);
2509 stream << HTTPReply(200, strReply) << std::flush;
2511 catch (std::exception& e)
2513 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2516 catch (Object& objError)
2518 ErrorReply(stream, objError, id);
2520 catch (std::exception& e)
2522 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2530 Object CallRPC(const string& strMethod, const Array& params)
2532 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2533 throw runtime_error(strprintf(
2534 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2535 "If the file does not exist, create it with owner-readable-only file permissions."),
2536 GetConfigFile().c_str()));
2538 // Connect to localhost
2539 bool fUseSSL = GetBoolArg("-rpcssl");
2540 asio::io_service io_service;
2541 ssl::context context(io_service, ssl::context::sslv23);
2542 context.set_options(ssl::context::no_sslv2);
2543 SSLStream sslStream(io_service, context);
2544 SSLIOStreamDevice d(sslStream, fUseSSL);
2545 iostreams::stream<SSLIOStreamDevice> stream(d);
2546 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2547 throw runtime_error("couldn't connect to server");
2549 // HTTP basic authentication
2550 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2551 map<string, string> mapRequestHeaders;
2552 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2555 string strRequest = JSONRPCRequest(strMethod, params, 1);
2556 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2557 stream << strPost << std::flush;
2560 map<string, string> mapHeaders;
2562 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2564 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2565 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2566 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2567 else if (strReply.empty())
2568 throw runtime_error("no response from server");
2572 if (!read_string(strReply, valReply))
2573 throw runtime_error("couldn't parse reply from server");
2574 const Object& reply = valReply.get_obj();
2576 throw runtime_error("expected reply to have result, error and id properties");
2584 template<typename T>
2585 void ConvertTo(Value& value)
2587 if (value.type() == str_type)
2589 // reinterpret string as unquoted json value
2591 if (!read_string(value.get_str(), value2))
2592 throw runtime_error("type mismatch");
2593 value = value2.get_value<T>();
2597 value = value.get_value<T>();
2601 int CommandLineRPC(int argc, char *argv[])
2608 while (argc > 1 && IsSwitchChar(argv[1][0]))
2616 throw runtime_error("too few parameters");
2617 string strMethod = argv[1];
2619 // Parameters default to strings
2621 for (int i = 2; i < argc; i++)
2622 params.push_back(argv[i]);
2623 int n = params.size();
2626 // Special case non-string parameter types
2628 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2629 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2630 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2631 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2632 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2633 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2634 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2635 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2636 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2637 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2638 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2639 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2640 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2641 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2642 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2643 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2644 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2645 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2646 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2647 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2648 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2649 if (strMethod == "sendmany" && n > 1)
2651 string s = params[1].get_str();
2653 if (!read_string(s, v) || v.type() != obj_type)
2654 throw runtime_error("type mismatch");
2655 params[1] = v.get_obj();
2657 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2658 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2659 if (strMethod == "addmultisigaddress" && n > 1)
2661 string s = params[1].get_str();
2663 if (!read_string(s, v) || v.type() != array_type)
2664 throw runtime_error("type mismatch "+s);
2665 params[1] = v.get_array();
2669 Object reply = CallRPC(strMethod, params);
2672 const Value& result = find_value(reply, "result");
2673 const Value& error = find_value(reply, "error");
2675 if (error.type() != null_type)
2678 strPrint = "error: " + write_string(error, false);
2679 int code = find_value(error.get_obj(), "code").get_int();
2685 if (result.type() == null_type)
2687 else if (result.type() == str_type)
2688 strPrint = result.get_str();
2690 strPrint = write_string(result, true);
2693 catch (std::exception& e)
2695 strPrint = string("error: ") + e.what();
2700 PrintException(NULL, "CommandLineRPC()");
2705 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2714 int main(int argc, char *argv[])
2717 // Turn off microsoft heap dump noise
2718 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2719 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2721 setbuf(stdin, NULL);
2722 setbuf(stdout, NULL);
2723 setbuf(stderr, NULL);
2727 if (argc >= 2 && string(argv[1]) == "-server")
2729 printf("server ready\n");
2730 ThreadRPCServer(NULL);
2734 return CommandLineRPC(argc, argv);
2737 catch (std::exception& e) {
2738 PrintException(&e, "main()");
2740 PrintException(NULL, "main()");