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 COPYING 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') != string::npos)
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.");
225 // Shutdown will take long enough that the response should get back
226 // NOTE: This should actually work with Bitcoin-Qt too now, but 0.6.0 didn't allow it
228 return "bitcoin server stopping";
230 throw runtime_error("NYI: cannot shut down GUI with RPC command");
235 Value getblockcount(const Array& params, bool fHelp)
237 if (fHelp || params.size() != 0)
240 "Returns the number of blocks in the longest block chain.");
247 Value getblocknumber(const Array& params, bool fHelp)
249 if (fHelp || params.size() != 0)
252 "Deprecated. Use getblockcount.");
258 Value getconnectioncount(const Array& params, bool fHelp)
260 if (fHelp || params.size() != 0)
262 "getconnectioncount\n"
263 "Returns the number of connections to other nodes.");
265 return (int)vNodes.size();
269 Value getdifficulty(const Array& params, bool fHelp)
271 if (fHelp || params.size() != 0)
274 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
276 return GetDifficulty();
280 Value getgenerate(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 0)
285 "Returns true or false.");
287 return GetBoolArg("-gen");
291 Value setgenerate(const Array& params, bool fHelp)
293 if (fHelp || params.size() < 1 || params.size() > 2)
295 "setgenerate <generate> [genproclimit]\n"
296 "<generate> is true or false to turn generation on or off.\n"
297 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
299 bool fGenerate = true;
300 if (params.size() > 0)
301 fGenerate = params[0].get_bool();
303 if (params.size() > 1)
305 int nGenProcLimit = params[1].get_int();
306 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
307 if (nGenProcLimit == 0)
310 mapArgs["-gen"] = (fGenerate ? "1" : "0");
312 GenerateBitcoins(fGenerate, pwalletMain);
317 Value gethashespersec(const Array& params, bool fHelp)
319 if (fHelp || params.size() != 0)
322 "Returns a recent hashes per second performance measurement while generating.");
324 if (GetTimeMillis() - nHPSTimerStart > 8000)
325 return (boost::int64_t)0;
326 return (boost::int64_t)dHashesPerSec;
330 Value getinfo(const Array& params, bool fHelp)
332 if (fHelp || params.size() != 0)
335 "Returns an object containing various state info.");
338 obj.push_back(Pair("version", (int)CLIENT_VERSION));
339 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
340 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
341 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
342 obj.push_back(Pair("blocks", (int)nBestHeight));
343 obj.push_back(Pair("connections", (int)vNodes.size()));
344 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
345 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
346 obj.push_back(Pair("testnet", fTestNet));
347 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
348 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
349 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
350 if (pwalletMain->IsCrypted())
351 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
352 obj.push_back(Pair("errors", GetWarnings("statusbar")));
357 Value getmininginfo(const Array& params, bool fHelp)
359 if (fHelp || params.size() != 0)
362 "Returns an object containing mining-related information.");
365 obj.push_back(Pair("blocks", (int)nBestHeight));
366 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
367 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
368 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
369 obj.push_back(Pair("errors", GetWarnings("statusbar")));
370 obj.push_back(Pair("generate", GetBoolArg("-gen")));
371 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
372 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
373 obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
374 obj.push_back(Pair("testnet", fTestNet));
379 Value getnewaddress(const Array& params, bool fHelp)
381 if (fHelp || params.size() > 1)
383 "getnewaddress [account]\n"
384 "Returns a new bitcoin address for receiving payments. "
385 "If [account] is specified (recommended), it is added to the address book "
386 "so payments received with the address will be credited to [account].");
388 // Parse the account first so we don't generate a key if there's an error
390 if (params.size() > 0)
391 strAccount = AccountFromValue(params[0]);
393 if (!pwalletMain->IsLocked())
394 pwalletMain->TopUpKeyPool();
396 // Generate a new key that is added to wallet
397 std::vector<unsigned char> newKey;
398 if (!pwalletMain->GetKeyFromPool(newKey, false))
399 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
400 CBitcoinAddress address(newKey);
402 pwalletMain->SetAddressBookName(address, strAccount);
404 return address.ToString();
408 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
410 CWalletDB walletdb(pwalletMain->strWalletFile);
413 walletdb.ReadAccount(strAccount, account);
415 bool bKeyUsed = false;
417 // Check if the current key has been used
418 if (!account.vchPubKey.empty())
420 CScript scriptPubKey;
421 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
422 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
423 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
426 const CWalletTx& wtx = (*it).second;
427 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
428 if (txout.scriptPubKey == scriptPubKey)
433 // Generate a new key
434 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
436 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
437 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
439 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
440 walletdb.WriteAccount(strAccount, account);
443 return CBitcoinAddress(account.vchPubKey);
446 Value getaccountaddress(const Array& params, bool fHelp)
448 if (fHelp || params.size() != 1)
450 "getaccountaddress <account>\n"
451 "Returns the current bitcoin address for receiving payments to this account.");
453 // Parse the account first so we don't generate a key if there's an error
454 string strAccount = AccountFromValue(params[0]);
458 ret = GetAccountAddress(strAccount).ToString();
465 Value setaccount(const Array& params, bool fHelp)
467 if (fHelp || params.size() < 1 || params.size() > 2)
469 "setaccount <bitcoinaddress> <account>\n"
470 "Sets the account associated with the given address.");
472 CBitcoinAddress address(params[0].get_str());
473 if (!address.IsValid())
474 throw JSONRPCError(-5, "Invalid bitcoin address");
478 if (params.size() > 1)
479 strAccount = AccountFromValue(params[1]);
481 // Detect when changing the account of an address that is the 'unused current key' of another account:
482 if (pwalletMain->mapAddressBook.count(address))
484 string strOldAccount = pwalletMain->mapAddressBook[address];
485 if (address == GetAccountAddress(strOldAccount))
486 GetAccountAddress(strOldAccount, true);
489 pwalletMain->SetAddressBookName(address, strAccount);
495 Value getaccount(const Array& params, bool fHelp)
497 if (fHelp || params.size() != 1)
499 "getaccount <bitcoinaddress>\n"
500 "Returns the account associated with the given address.");
502 CBitcoinAddress address(params[0].get_str());
503 if (!address.IsValid())
504 throw JSONRPCError(-5, "Invalid bitcoin address");
507 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
508 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
509 strAccount = (*mi).second;
514 Value getaddressesbyaccount(const Array& params, bool fHelp)
516 if (fHelp || params.size() != 1)
518 "getaddressesbyaccount <account>\n"
519 "Returns the list of addresses for the given account.");
521 string strAccount = AccountFromValue(params[0]);
523 // Find all addresses that have the given account
525 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
527 const CBitcoinAddress& address = item.first;
528 const string& strName = item.second;
529 if (strName == strAccount)
530 ret.push_back(address.ToString());
535 Value settxfee(const Array& params, bool fHelp)
537 if (fHelp || params.size() < 1 || params.size() > 1)
539 "settxfee <amount>\n"
540 "<amount> is a real and is rounded to the nearest 0.00000001");
544 if (params[0].get_real() != 0.0)
545 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
547 nTransactionFee = nAmount;
551 Value sendtoaddress(const Array& params, bool fHelp)
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\n"
557 "requires wallet passphrase to be set with walletpassphrase first");
558 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
560 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
561 "<amount> is a real and is rounded to the nearest 0.00000001");
563 CBitcoinAddress address(params[0].get_str());
564 if (!address.IsValid())
565 throw JSONRPCError(-5, "Invalid bitcoin address");
568 int64 nAmount = AmountFromValue(params[1]);
572 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
573 wtx.mapValue["comment"] = params[2].get_str();
574 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
575 wtx.mapValue["to"] = params[3].get_str();
577 if (pwalletMain->IsLocked())
578 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
580 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
582 throw JSONRPCError(-4, strError);
584 return wtx.GetHash().GetHex();
587 Value signmessage(const Array& params, bool fHelp)
589 if (fHelp || params.size() != 2)
591 "signmessage <bitcoinaddress> <message>\n"
592 "Sign a message with the private key of an address");
594 if (pwalletMain->IsLocked())
595 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
597 string strAddress = params[0].get_str();
598 string strMessage = params[1].get_str();
600 CBitcoinAddress addr(strAddress);
602 throw JSONRPCError(-3, "Invalid address");
605 if (!pwalletMain->GetKey(addr, key))
606 throw JSONRPCError(-4, "Private key not available");
608 CDataStream ss(SER_GETHASH);
609 ss << strMessageMagic;
612 vector<unsigned char> vchSig;
613 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
614 throw JSONRPCError(-5, "Sign failed");
616 return EncodeBase64(&vchSig[0], vchSig.size());
619 Value verifymessage(const Array& params, bool fHelp)
621 if (fHelp || params.size() != 3)
623 "verifymessage <bitcoinaddress> <signature> <message>\n"
624 "Verify a signed message");
626 string strAddress = params[0].get_str();
627 string strSign = params[1].get_str();
628 string strMessage = params[2].get_str();
630 CBitcoinAddress addr(strAddress);
632 throw JSONRPCError(-3, "Invalid address");
634 bool fInvalid = false;
635 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
638 throw JSONRPCError(-5, "Malformed base64 encoding");
640 CDataStream ss(SER_GETHASH);
641 ss << strMessageMagic;
645 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
648 return (CBitcoinAddress(key.GetPubKey()) == addr);
652 Value getreceivedbyaddress(const Array& params, bool fHelp)
654 if (fHelp || params.size() < 1 || params.size() > 2)
656 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
657 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
660 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
661 CScript scriptPubKey;
662 if (!address.IsValid())
663 throw JSONRPCError(-5, "Invalid bitcoin address");
664 scriptPubKey.SetBitcoinAddress(address);
665 if (!IsMine(*pwalletMain,scriptPubKey))
668 // Minimum confirmations
670 if (params.size() > 1)
671 nMinDepth = params[1].get_int();
675 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
677 const CWalletTx& wtx = (*it).second;
678 if (wtx.IsCoinBase() || !wtx.IsFinal())
681 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
682 if (txout.scriptPubKey == scriptPubKey)
683 if (wtx.GetDepthInMainChain() >= nMinDepth)
684 nAmount += txout.nValue;
687 return ValueFromAmount(nAmount);
691 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
693 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
695 const CBitcoinAddress& address = item.first;
696 const string& strName = item.second;
697 if (strName == strAccount)
698 setAddress.insert(address);
703 Value getreceivedbyaccount(const Array& params, bool fHelp)
705 if (fHelp || params.size() < 1 || params.size() > 2)
707 "getreceivedbyaccount <account> [minconf=1]\n"
708 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
710 // Minimum confirmations
712 if (params.size() > 1)
713 nMinDepth = params[1].get_int();
715 // Get the set of pub keys assigned to account
716 string strAccount = AccountFromValue(params[0]);
717 set<CBitcoinAddress> setAddress;
718 GetAccountAddresses(strAccount, setAddress);
722 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
724 const CWalletTx& wtx = (*it).second;
725 if (wtx.IsCoinBase() || !wtx.IsFinal())
728 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
730 CBitcoinAddress address;
731 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
732 if (wtx.GetDepthInMainChain() >= nMinDepth)
733 nAmount += txout.nValue;
737 return (double)nAmount / (double)COIN;
741 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
745 // Tally wallet transactions
746 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
748 const CWalletTx& wtx = (*it).second;
752 int64 nGenerated, nReceived, nSent, nFee;
753 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
755 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
756 nBalance += nReceived;
757 nBalance += nGenerated - nSent - nFee;
760 // Tally internal accounting entries
761 nBalance += walletdb.GetAccountCreditDebit(strAccount);
766 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
768 CWalletDB walletdb(pwalletMain->strWalletFile);
769 return GetAccountBalance(walletdb, strAccount, nMinDepth);
773 Value getbalance(const Array& params, bool fHelp)
775 if (fHelp || params.size() > 2)
777 "getbalance [account] [minconf=1]\n"
778 "If [account] is not specified, returns the server's total available balance.\n"
779 "If [account] is specified, returns the balance in the account.");
781 if (params.size() == 0)
782 return ValueFromAmount(pwalletMain->GetBalance());
785 if (params.size() > 1)
786 nMinDepth = params[1].get_int();
788 if (params[0].get_str() == "*") {
789 // Calculate total balance a different way from GetBalance()
790 // (GetBalance() sums up all unspent TxOuts)
791 // getbalance and getbalance '*' should always return the same number.
793 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
795 const CWalletTx& wtx = (*it).second;
799 int64 allGeneratedImmature, allGeneratedMature, allFee;
800 allGeneratedImmature = allGeneratedMature = allFee = 0;
801 string strSentAccount;
802 list<pair<CBitcoinAddress, int64> > listReceived;
803 list<pair<CBitcoinAddress, int64> > listSent;
804 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
805 if (wtx.GetDepthInMainChain() >= nMinDepth)
807 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
808 nBalance += r.second;
810 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
811 nBalance -= r.second;
813 nBalance += allGeneratedMature;
815 return ValueFromAmount(nBalance);
818 string strAccount = AccountFromValue(params[0]);
820 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
822 return ValueFromAmount(nBalance);
826 Value movecmd(const Array& params, bool fHelp)
828 if (fHelp || params.size() < 3 || params.size() > 5)
830 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
831 "Move from one account in your wallet to another.");
833 string strFrom = AccountFromValue(params[0]);
834 string strTo = AccountFromValue(params[1]);
835 int64 nAmount = AmountFromValue(params[2]);
836 if (params.size() > 3)
837 // unused parameter, used to be nMinDepth, keep type-checking it though
838 (void)params[3].get_int();
840 if (params.size() > 4)
841 strComment = params[4].get_str();
843 CWalletDB walletdb(pwalletMain->strWalletFile);
844 if (!walletdb.TxnBegin())
845 throw JSONRPCError(-20, "database error");
847 int64 nNow = GetAdjustedTime();
850 CAccountingEntry debit;
851 debit.strAccount = strFrom;
852 debit.nCreditDebit = -nAmount;
854 debit.strOtherAccount = strTo;
855 debit.strComment = strComment;
856 walletdb.WriteAccountingEntry(debit);
859 CAccountingEntry credit;
860 credit.strAccount = strTo;
861 credit.nCreditDebit = nAmount;
863 credit.strOtherAccount = strFrom;
864 credit.strComment = strComment;
865 walletdb.WriteAccountingEntry(credit);
867 if (!walletdb.TxnCommit())
868 throw JSONRPCError(-20, "database error");
874 Value sendfrom(const Array& params, bool fHelp)
876 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
878 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
879 "<amount> is a real and is rounded to the nearest 0.00000001\n"
880 "requires wallet passphrase to be set with walletpassphrase first");
881 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
883 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
884 "<amount> is a real and is rounded to the nearest 0.00000001");
886 string strAccount = AccountFromValue(params[0]);
887 CBitcoinAddress address(params[1].get_str());
888 if (!address.IsValid())
889 throw JSONRPCError(-5, "Invalid bitcoin address");
890 int64 nAmount = AmountFromValue(params[2]);
892 if (params.size() > 3)
893 nMinDepth = params[3].get_int();
896 wtx.strFromAccount = strAccount;
897 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
898 wtx.mapValue["comment"] = params[4].get_str();
899 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
900 wtx.mapValue["to"] = params[5].get_str();
902 if (pwalletMain->IsLocked())
903 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
906 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
907 if (nAmount > nBalance)
908 throw JSONRPCError(-6, "Account has insufficient funds");
911 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
913 throw JSONRPCError(-4, strError);
915 return wtx.GetHash().GetHex();
919 Value sendmany(const Array& params, bool fHelp)
921 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
923 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
924 "amounts are double-precision floating point numbers\n"
925 "requires wallet passphrase to be set with walletpassphrase first");
926 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
928 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
929 "amounts are double-precision floating point numbers");
931 string strAccount = AccountFromValue(params[0]);
932 Object sendTo = params[1].get_obj();
934 if (params.size() > 2)
935 nMinDepth = params[2].get_int();
938 wtx.strFromAccount = strAccount;
939 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
940 wtx.mapValue["comment"] = params[3].get_str();
942 set<CBitcoinAddress> setAddress;
943 vector<pair<CScript, int64> > vecSend;
945 int64 totalAmount = 0;
946 BOOST_FOREACH(const Pair& s, sendTo)
948 CBitcoinAddress address(s.name_);
949 if (!address.IsValid())
950 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
952 if (setAddress.count(address))
953 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
954 setAddress.insert(address);
956 CScript scriptPubKey;
957 scriptPubKey.SetBitcoinAddress(address);
958 int64 nAmount = AmountFromValue(s.value_);
959 totalAmount += nAmount;
961 vecSend.push_back(make_pair(scriptPubKey, nAmount));
964 if (pwalletMain->IsLocked())
965 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
968 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
969 if (totalAmount > nBalance)
970 throw JSONRPCError(-6, "Account has insufficient funds");
973 CReserveKey keyChange(pwalletMain);
974 int64 nFeeRequired = 0;
975 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
978 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
979 throw JSONRPCError(-6, "Insufficient funds");
980 throw JSONRPCError(-4, "Transaction creation failed");
982 if (!pwalletMain->CommitTransaction(wtx, keyChange))
983 throw JSONRPCError(-4, "Transaction commit failed");
985 return wtx.GetHash().GetHex();
988 Value addmultisigaddress(const Array& params, bool fHelp)
990 if (fHelp || params.size() < 2 || params.size() > 3)
992 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
993 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
994 "each key is a bitcoin address or hex-encoded public key\n"
995 "If [account] is specified, assign address to [account].";
996 throw runtime_error(msg);
999 throw runtime_error("addmultisigaddress available only when running -testnet\n");
1001 int nRequired = params[0].get_int();
1002 const Array& keys = params[1].get_array();
1004 if (params.size() > 2)
1005 strAccount = AccountFromValue(params[2]);
1007 // Gather public keys
1009 throw runtime_error("a multisignature address must require at least one key to redeem");
1010 if (keys.size() < nRequired)
1011 throw runtime_error(
1012 strprintf("not enough keys supplied "
1013 "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1014 std::vector<CKey> pubkeys;
1015 pubkeys.resize(keys.size());
1016 for (unsigned int i = 0; i < keys.size(); i++)
1018 const std::string& ks = keys[i].get_str();
1020 // Case 1: bitcoin address and we have full public key:
1021 CBitcoinAddress address(ks);
1022 if (address.IsValid())
1024 if (address.IsScript())
1025 throw runtime_error(
1026 strprintf("%s is a pay-to-script address",ks.c_str()));
1027 std::vector<unsigned char> vchPubKey;
1028 if (!pwalletMain->GetPubKey(address, vchPubKey))
1029 throw runtime_error(
1030 strprintf("no full public key for address %s",ks.c_str()));
1031 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1032 throw runtime_error(" Invalid public key: "+ks);
1035 // Case 2: hex public key
1038 vector<unsigned char> vchPubKey = ParseHex(ks);
1039 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1040 throw runtime_error(" Invalid public key: "+ks);
1044 throw runtime_error(" Invalid public key: "+ks);
1048 // Construct using pay-to-script-hash:
1050 inner.SetMultisig(nRequired, pubkeys);
1052 uint160 scriptHash = Hash160(inner);
1053 CScript scriptPubKey;
1054 scriptPubKey.SetPayToScriptHash(inner);
1055 pwalletMain->AddCScript(inner);
1056 CBitcoinAddress address;
1057 address.SetScriptHash160(scriptHash);
1059 pwalletMain->SetAddressBookName(address, strAccount);
1060 return address.ToString();
1071 nConf = std::numeric_limits<int>::max();
1075 Value ListReceived(const Array& params, bool fByAccounts)
1077 // Minimum confirmations
1079 if (params.size() > 0)
1080 nMinDepth = params[0].get_int();
1082 // Whether to include empty accounts
1083 bool fIncludeEmpty = false;
1084 if (params.size() > 1)
1085 fIncludeEmpty = params[1].get_bool();
1088 map<CBitcoinAddress, tallyitem> mapTally;
1089 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1091 const CWalletTx& wtx = (*it).second;
1093 if (wtx.IsCoinBase() || !wtx.IsFinal())
1096 int nDepth = wtx.GetDepthInMainChain();
1097 if (nDepth < nMinDepth)
1100 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1102 CBitcoinAddress address;
1103 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1106 tallyitem& item = mapTally[address];
1107 item.nAmount += txout.nValue;
1108 item.nConf = min(item.nConf, nDepth);
1114 map<string, tallyitem> mapAccountTally;
1115 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1117 const CBitcoinAddress& address = item.first;
1118 const string& strAccount = item.second;
1119 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1120 if (it == mapTally.end() && !fIncludeEmpty)
1124 int nConf = std::numeric_limits<int>::max();
1125 if (it != mapTally.end())
1127 nAmount = (*it).second.nAmount;
1128 nConf = (*it).second.nConf;
1133 tallyitem& item = mapAccountTally[strAccount];
1134 item.nAmount += nAmount;
1135 item.nConf = min(item.nConf, nConf);
1140 obj.push_back(Pair("address", address.ToString()));
1141 obj.push_back(Pair("account", strAccount));
1142 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1143 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1150 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1152 int64 nAmount = (*it).second.nAmount;
1153 int nConf = (*it).second.nConf;
1155 obj.push_back(Pair("account", (*it).first));
1156 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1157 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1165 Value listreceivedbyaddress(const Array& params, bool fHelp)
1167 if (fHelp || params.size() > 2)
1168 throw runtime_error(
1169 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1170 "[minconf] is the minimum number of confirmations before payments are included.\n"
1171 "[includeempty] whether to include addresses that haven't received any payments.\n"
1172 "Returns an array of objects containing:\n"
1173 " \"address\" : receiving address\n"
1174 " \"account\" : the account of the receiving address\n"
1175 " \"amount\" : total amount received by the address\n"
1176 " \"confirmations\" : number of confirmations of the most recent transaction included");
1178 return ListReceived(params, false);
1181 Value listreceivedbyaccount(const Array& params, bool fHelp)
1183 if (fHelp || params.size() > 2)
1184 throw runtime_error(
1185 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1186 "[minconf] is the minimum number of confirmations before payments are included.\n"
1187 "[includeempty] whether to include accounts that haven't received any payments.\n"
1188 "Returns an array of objects containing:\n"
1189 " \"account\" : the account of the receiving addresses\n"
1190 " \"amount\" : total amount received by addresses with this account\n"
1191 " \"confirmations\" : number of confirmations of the most recent transaction included");
1193 return ListReceived(params, true);
1196 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1198 int64 nGeneratedImmature, nGeneratedMature, nFee;
1199 string strSentAccount;
1200 list<pair<CBitcoinAddress, int64> > listReceived;
1201 list<pair<CBitcoinAddress, int64> > listSent;
1203 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1205 bool fAllAccounts = (strAccount == string("*"));
1207 // Generated blocks assigned to account ""
1208 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1211 entry.push_back(Pair("account", string("")));
1212 if (nGeneratedImmature)
1214 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1215 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1219 entry.push_back(Pair("category", "generate"));
1220 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1223 WalletTxToJSON(wtx, entry);
1224 ret.push_back(entry);
1228 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1230 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1233 entry.push_back(Pair("account", strSentAccount));
1234 entry.push_back(Pair("address", s.first.ToString()));
1235 entry.push_back(Pair("category", "send"));
1236 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1237 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1239 WalletTxToJSON(wtx, entry);
1240 ret.push_back(entry);
1245 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1247 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1250 if (pwalletMain->mapAddressBook.count(r.first))
1251 account = pwalletMain->mapAddressBook[r.first];
1252 if (fAllAccounts || (account == strAccount))
1255 entry.push_back(Pair("account", account));
1256 entry.push_back(Pair("address", r.first.ToString()));
1257 entry.push_back(Pair("category", "receive"));
1258 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1260 WalletTxToJSON(wtx, entry);
1261 ret.push_back(entry);
1267 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1269 bool fAllAccounts = (strAccount == string("*"));
1271 if (fAllAccounts || acentry.strAccount == strAccount)
1274 entry.push_back(Pair("account", acentry.strAccount));
1275 entry.push_back(Pair("category", "move"));
1276 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1277 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1278 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1279 entry.push_back(Pair("comment", acentry.strComment));
1280 ret.push_back(entry);
1284 Value listtransactions(const Array& params, bool fHelp)
1286 if (fHelp || params.size() > 3)
1287 throw runtime_error(
1288 "listtransactions [account] [count=10] [from=0]\n"
1289 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1291 string strAccount = "*";
1292 if (params.size() > 0)
1293 strAccount = params[0].get_str();
1295 if (params.size() > 1)
1296 nCount = params[1].get_int();
1298 if (params.size() > 2)
1299 nFrom = params[2].get_int();
1302 throw JSONRPCError(-8, "Negative count");
1304 throw JSONRPCError(-8, "Negative from");
1307 CWalletDB walletdb(pwalletMain->strWalletFile);
1309 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1310 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1311 typedef multimap<int64, TxPair > TxItems;
1314 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1315 // would make this much faster for applications that do this a lot.
1316 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1318 CWalletTx* wtx = &((*it).second);
1319 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1321 list<CAccountingEntry> acentries;
1322 walletdb.ListAccountCreditDebit(strAccount, acentries);
1323 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1325 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1328 // iterate backwards until we have nCount items to return:
1329 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1331 CWalletTx *const pwtx = (*it).second.first;
1333 ListTransactions(*pwtx, strAccount, 0, true, ret);
1334 CAccountingEntry *const pacentry = (*it).second.second;
1336 AcentryToJSON(*pacentry, strAccount, ret);
1338 if (ret.size() >= (nCount+nFrom)) break;
1340 // ret is newest to oldest
1342 if (nFrom > ret.size()) nFrom = ret.size();
1343 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1344 Array::iterator first = ret.begin();
1345 std::advance(first, nFrom);
1346 Array::iterator last = ret.begin();
1347 std::advance(last, nFrom+nCount);
1349 if (last != ret.end()) ret.erase(last, ret.end());
1350 if (first != ret.begin()) ret.erase(ret.begin(), first);
1352 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1357 Value listaccounts(const Array& params, bool fHelp)
1359 if (fHelp || params.size() > 1)
1360 throw runtime_error(
1361 "listaccounts [minconf=1]\n"
1362 "Returns Object that has account names as keys, account balances as values.");
1365 if (params.size() > 0)
1366 nMinDepth = params[0].get_int();
1368 map<string, int64> mapAccountBalances;
1369 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1370 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1371 mapAccountBalances[entry.second] = 0;
1374 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1376 const CWalletTx& wtx = (*it).second;
1377 int64 nGeneratedImmature, nGeneratedMature, nFee;
1378 string strSentAccount;
1379 list<pair<CBitcoinAddress, int64> > listReceived;
1380 list<pair<CBitcoinAddress, int64> > listSent;
1381 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1382 mapAccountBalances[strSentAccount] -= nFee;
1383 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1384 mapAccountBalances[strSentAccount] -= s.second;
1385 if (wtx.GetDepthInMainChain() >= nMinDepth)
1387 mapAccountBalances[""] += nGeneratedMature;
1388 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1389 if (pwalletMain->mapAddressBook.count(r.first))
1390 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1392 mapAccountBalances[""] += r.second;
1396 list<CAccountingEntry> acentries;
1397 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1398 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1399 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1402 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1403 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1408 Value listsinceblock(const Array& params, bool fHelp)
1411 throw runtime_error(
1412 "listsinceblock [blockhash] [target-confirmations]\n"
1413 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1415 CBlockIndex *pindex = NULL;
1416 int target_confirms = 1;
1418 if (params.size() > 0)
1420 uint256 blockId = 0;
1422 blockId.SetHex(params[0].get_str());
1423 pindex = CBlockLocator(blockId).GetBlockIndex();
1426 if (params.size() > 1)
1428 target_confirms = params[1].get_int();
1430 if (target_confirms < 1)
1431 throw JSONRPCError(-8, "Invalid parameter");
1434 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1438 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1440 CWalletTx tx = (*it).second;
1442 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1443 ListTransactions(tx, "*", 0, true, transactions);
1448 if (target_confirms == 1)
1450 lastblock = hashBestChain;
1454 int target_height = pindexBest->nHeight + 1 - target_confirms;
1457 for (block = pindexBest;
1458 block && block->nHeight > target_height;
1459 block = block->pprev) { }
1461 lastblock = block ? block->GetBlockHash() : 0;
1465 ret.push_back(Pair("transactions", transactions));
1466 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1471 Value gettransaction(const Array& params, bool fHelp)
1473 if (fHelp || params.size() != 1)
1474 throw runtime_error(
1475 "gettransaction <txid>\n"
1476 "Get detailed information about <txid>");
1479 hash.SetHex(params[0].get_str());
1483 if (!pwalletMain->mapWallet.count(hash))
1484 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1485 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1487 int64 nCredit = wtx.GetCredit();
1488 int64 nDebit = wtx.GetDebit();
1489 int64 nNet = nCredit - nDebit;
1490 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1492 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1494 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1496 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1499 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1500 entry.push_back(Pair("details", details));
1506 Value backupwallet(const Array& params, bool fHelp)
1508 if (fHelp || params.size() != 1)
1509 throw runtime_error(
1510 "backupwallet <destination>\n"
1511 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1513 string strDest = params[0].get_str();
1514 BackupWallet(*pwalletMain, strDest);
1520 Value keypoolrefill(const Array& params, bool fHelp)
1522 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1523 throw runtime_error(
1525 "Fills the keypool, requires wallet passphrase to be set.");
1526 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1527 throw runtime_error(
1529 "Fills the keypool.");
1531 if (pwalletMain->IsLocked())
1532 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1534 pwalletMain->TopUpKeyPool();
1536 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1537 throw JSONRPCError(-4, "Error refreshing keypool.");
1543 void ThreadTopUpKeyPool(void* parg)
1545 pwalletMain->TopUpKeyPool();
1548 void ThreadCleanWalletPassphrase(void* parg)
1550 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1552 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1554 if (nWalletUnlockTime == 0)
1556 nWalletUnlockTime = nMyWakeTime;
1560 if (nWalletUnlockTime==0)
1562 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1566 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1568 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1572 if (nWalletUnlockTime)
1574 nWalletUnlockTime = 0;
1575 pwalletMain->Lock();
1580 if (nWalletUnlockTime < nMyWakeTime)
1581 nWalletUnlockTime = nMyWakeTime;
1584 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1586 delete (int64*)parg;
1589 Value walletpassphrase(const Array& params, bool fHelp)
1591 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1592 throw runtime_error(
1593 "walletpassphrase <passphrase> <timeout>\n"
1594 "Stores the wallet decryption key in memory for <timeout> seconds.");
1597 if (!pwalletMain->IsCrypted())
1598 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1600 if (!pwalletMain->IsLocked())
1601 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1603 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1604 SecureString strWalletPass;
1605 strWalletPass.reserve(100);
1606 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1607 // Alternately, find a way to make params[0] mlock()'d to begin with.
1608 strWalletPass = params[0].get_str().c_str();
1610 if (strWalletPass.length() > 0)
1612 if (!pwalletMain->Unlock(strWalletPass))
1613 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1616 throw runtime_error(
1617 "walletpassphrase <passphrase> <timeout>\n"
1618 "Stores the wallet decryption key in memory for <timeout> seconds.");
1620 CreateThread(ThreadTopUpKeyPool, NULL);
1621 int64* pnSleepTime = new int64(params[1].get_int64());
1622 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1628 Value walletpassphrasechange(const Array& params, bool fHelp)
1630 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1631 throw runtime_error(
1632 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1633 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1636 if (!pwalletMain->IsCrypted())
1637 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1639 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1640 // Alternately, find a way to make params[0] mlock()'d to begin with.
1641 SecureString strOldWalletPass;
1642 strOldWalletPass.reserve(100);
1643 strOldWalletPass = params[0].get_str().c_str();
1645 SecureString strNewWalletPass;
1646 strNewWalletPass.reserve(100);
1647 strNewWalletPass = params[1].get_str().c_str();
1649 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1650 throw runtime_error(
1651 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1652 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1654 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1655 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1661 Value walletlock(const Array& params, bool fHelp)
1663 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1664 throw runtime_error(
1666 "Removes the wallet encryption key from memory, locking the wallet.\n"
1667 "After calling this method, you will need to call walletpassphrase again\n"
1668 "before being able to call any methods which require the wallet to be unlocked.");
1671 if (!pwalletMain->IsCrypted())
1672 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1674 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1676 pwalletMain->Lock();
1677 nWalletUnlockTime = 0;
1684 Value encryptwallet(const Array& params, bool fHelp)
1686 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1687 throw runtime_error(
1688 "encryptwallet <passphrase>\n"
1689 "Encrypts the wallet with <passphrase>.");
1692 if (pwalletMain->IsCrypted())
1693 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1696 // shutting down via RPC while the GUI is running does not work (yet):
1697 throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1700 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1701 // Alternately, find a way to make params[0] mlock()'d to begin with.
1702 SecureString strWalletPass;
1703 strWalletPass.reserve(100);
1704 strWalletPass = params[0].get_str().c_str();
1706 if (strWalletPass.length() < 1)
1707 throw runtime_error(
1708 "encryptwallet <passphrase>\n"
1709 "Encrypts the wallet with <passphrase>.");
1711 if (!pwalletMain->EncryptWallet(strWalletPass))
1712 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1714 // BDB seems to have a bad habit of writing old data into
1715 // slack space in .dat files; that is bad if the old data is
1716 // unencrypted private keys. So:
1718 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1722 Value validateaddress(const Array& params, bool fHelp)
1724 if (fHelp || params.size() != 1)
1725 throw runtime_error(
1726 "validateaddress <bitcoinaddress>\n"
1727 "Return information about <bitcoinaddress>.");
1729 CBitcoinAddress address(params[0].get_str());
1730 bool isValid = address.IsValid();
1733 ret.push_back(Pair("isvalid", isValid));
1736 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1737 // version of the address:
1738 string currentAddress = address.ToString();
1739 ret.push_back(Pair("address", currentAddress));
1740 if (pwalletMain->HaveKey(address))
1742 ret.push_back(Pair("ismine", true));
1743 std::vector<unsigned char> vchPubKey;
1744 pwalletMain->GetPubKey(address, vchPubKey);
1745 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1747 key.SetPubKey(vchPubKey);
1748 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1750 else if (pwalletMain->HaveCScript(address.GetHash160()))
1752 ret.push_back(Pair("isscript", true));
1754 pwalletMain->GetCScript(address.GetHash160(), subscript);
1755 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1756 std::vector<CBitcoinAddress> addresses;
1757 txnouttype whichType;
1759 ExtractAddresses(subscript, whichType, addresses, nRequired);
1760 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1762 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1763 a.push_back(addr.ToString());
1764 ret.push_back(Pair("addresses", a));
1765 if (whichType == TX_MULTISIG)
1766 ret.push_back(Pair("sigsrequired", nRequired));
1769 ret.push_back(Pair("ismine", false));
1770 if (pwalletMain->mapAddressBook.count(address))
1771 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1776 Value getwork(const Array& params, bool fHelp)
1778 if (fHelp || params.size() > 1)
1779 throw runtime_error(
1781 "If [data] is not specified, returns formatted hash data to work on:\n"
1782 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1783 " \"data\" : block data\n"
1784 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1785 " \"target\" : little endian hash target\n"
1786 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1789 throw JSONRPCError(-9, "Bitcoin is not connected!");
1791 if (IsInitialBlockDownload())
1792 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1794 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1795 static mapNewBlock_t mapNewBlock;
1796 static vector<CBlock*> vNewBlock;
1797 static CReserveKey reservekey(pwalletMain);
1799 if (params.size() == 0)
1802 static unsigned int nTransactionsUpdatedLast;
1803 static CBlockIndex* pindexPrev;
1804 static int64 nStart;
1805 static CBlock* pblock;
1806 if (pindexPrev != pindexBest ||
1807 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1809 if (pindexPrev != pindexBest)
1811 // Deallocate old blocks since they're obsolete now
1812 mapNewBlock.clear();
1813 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1817 nTransactionsUpdatedLast = nTransactionsUpdated;
1818 pindexPrev = pindexBest;
1822 pblock = CreateNewBlock(reservekey);
1824 throw JSONRPCError(-7, "Out of memory");
1825 vNewBlock.push_back(pblock);
1829 pblock->UpdateTime(pindexPrev);
1832 // Update nExtraNonce
1833 static unsigned int nExtraNonce = 0;
1834 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1837 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1839 // Prebuild hash buffers
1843 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1845 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1848 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1849 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1850 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1851 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1857 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1858 if (vchData.size() != 128)
1859 throw JSONRPCError(-8, "Invalid parameter");
1860 CBlock* pdata = (CBlock*)&vchData[0];
1863 for (int i = 0; i < 128/4; i++)
1864 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1867 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1869 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1871 pblock->nTime = pdata->nTime;
1872 pblock->nNonce = pdata->nNonce;
1873 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1874 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1876 return CheckWork(pblock, *pwalletMain, reservekey);
1881 Value getmemorypool(const Array& params, bool fHelp)
1883 if (fHelp || params.size() > 1)
1884 throw runtime_error(
1885 "getmemorypool [data]\n"
1886 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1887 " \"version\" : block version\n"
1888 " \"previousblockhash\" : hash of current highest block\n"
1889 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1890 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1891 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1892 " \"time\" : timestamp appropriate for next block\n"
1893 " \"mintime\" : minimum timestamp appropriate for next block\n"
1894 " \"curtime\" : current timestamp\n"
1895 " \"bits\" : compressed target of next block\n"
1896 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1898 if (params.size() == 0)
1901 throw JSONRPCError(-9, "Bitcoin is not connected!");
1903 if (IsInitialBlockDownload())
1904 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1906 static CReserveKey reservekey(pwalletMain);
1909 static unsigned int nTransactionsUpdatedLast;
1910 static CBlockIndex* pindexPrev;
1911 static int64 nStart;
1912 static CBlock* pblock;
1913 if (pindexPrev != pindexBest ||
1914 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1916 nTransactionsUpdatedLast = nTransactionsUpdated;
1917 pindexPrev = pindexBest;
1923 pblock = CreateNewBlock(reservekey);
1925 throw JSONRPCError(-7, "Out of memory");
1929 pblock->UpdateTime(pindexPrev);
1933 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1940 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1944 result.push_back(Pair("version", pblock->nVersion));
1945 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1946 result.push_back(Pair("transactions", transactions));
1947 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1948 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1949 result.push_back(Pair("time", (int64_t)pblock->nTime));
1950 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1951 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1952 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1959 CDataStream ssBlock(ParseHex(params[0].get_str()));
1963 return ProcessBlock(NULL, &pblock);
1967 Value getblockhash(const Array& params, bool fHelp)
1969 if (fHelp || params.size() != 1)
1970 throw runtime_error(
1971 "getblockhash <index>\n"
1972 "Returns hash of block in best-block-chain at <index>.");
1974 int nHeight = params[0].get_int();
1975 if (nHeight < 0 || nHeight > nBestHeight)
1976 throw runtime_error("Block number out of range.");
1979 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1980 while (pblockindex->nHeight > nHeight)
1981 pblockindex = pblockindex->pprev;
1982 return pblockindex->phashBlock->GetHex();
1985 Value getblock(const Array& params, bool fHelp)
1987 if (fHelp || params.size() != 1)
1988 throw runtime_error(
1990 "Returns details of a block with given block-hash.");
1992 std::string strHash = params[0].get_str();
1993 uint256 hash(strHash);
1995 if (mapBlockIndex.count(hash) == 0)
1996 throw JSONRPCError(-5, "Block not found");
1999 CBlockIndex* pblockindex = mapBlockIndex[hash];
2000 block.ReadFromDisk(pblockindex, true);
2002 return blockToJSON(block, pblockindex);
2019 pair<string, rpcfn_type> pCallTable[] =
2021 make_pair("help", &help),
2022 make_pair("stop", &stop),
2023 make_pair("getblockcount", &getblockcount),
2024 make_pair("getblocknumber", &getblocknumber),
2025 make_pair("getconnectioncount", &getconnectioncount),
2026 make_pair("getdifficulty", &getdifficulty),
2027 make_pair("getgenerate", &getgenerate),
2028 make_pair("setgenerate", &setgenerate),
2029 make_pair("gethashespersec", &gethashespersec),
2030 make_pair("getinfo", &getinfo),
2031 make_pair("getmininginfo", &getmininginfo),
2032 make_pair("getnewaddress", &getnewaddress),
2033 make_pair("getaccountaddress", &getaccountaddress),
2034 make_pair("setaccount", &setaccount),
2035 make_pair("getaccount", &getaccount),
2036 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
2037 make_pair("sendtoaddress", &sendtoaddress),
2038 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
2039 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
2040 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
2041 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
2042 make_pair("backupwallet", &backupwallet),
2043 make_pair("keypoolrefill", &keypoolrefill),
2044 make_pair("walletpassphrase", &walletpassphrase),
2045 make_pair("walletpassphrasechange", &walletpassphrasechange),
2046 make_pair("walletlock", &walletlock),
2047 make_pair("encryptwallet", &encryptwallet),
2048 make_pair("validateaddress", &validateaddress),
2049 make_pair("getbalance", &getbalance),
2050 make_pair("move", &movecmd),
2051 make_pair("sendfrom", &sendfrom),
2052 make_pair("sendmany", &sendmany),
2053 make_pair("addmultisigaddress", &addmultisigaddress),
2054 make_pair("getblock", &getblock),
2055 make_pair("getblockhash", &getblockhash),
2056 make_pair("gettransaction", &gettransaction),
2057 make_pair("listtransactions", &listtransactions),
2058 make_pair("signmessage", &signmessage),
2059 make_pair("verifymessage", &verifymessage),
2060 make_pair("getwork", &getwork),
2061 make_pair("listaccounts", &listaccounts),
2062 make_pair("settxfee", &settxfee),
2063 make_pair("getmemorypool", &getmemorypool),
2064 make_pair("listsinceblock", &listsinceblock),
2065 make_pair("dumpprivkey", &dumpprivkey),
2066 make_pair("importprivkey", &importprivkey)
2068 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2070 string pAllowInSafeMode[] =
2075 "getblocknumber", // deprecated
2076 "getconnectioncount",
2084 "getaccountaddress",
2086 "getaddressesbyaccount",
2095 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2103 // This ain't Apache. We're just using HTTP header for the length field
2104 // and to be compatible with other JSON-RPC implementations.
2107 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2110 s << "POST / HTTP/1.1\r\n"
2111 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2112 << "Host: 127.0.0.1\r\n"
2113 << "Content-Type: application/json\r\n"
2114 << "Content-Length: " << strMsg.size() << "\r\n"
2115 << "Connection: close\r\n"
2116 << "Accept: application/json\r\n";
2117 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2118 s << item.first << ": " << item.second << "\r\n";
2119 s << "\r\n" << strMsg;
2124 string rfc1123Time()
2129 struct tm* now_gmt = gmtime(&now);
2130 string locale(setlocale(LC_TIME, NULL));
2131 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2132 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2133 setlocale(LC_TIME, locale.c_str());
2134 return string(buffer);
2137 static string HTTPReply(int nStatus, const string& strMsg)
2140 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2142 "Server: bitcoin-json-rpc/%s\r\n"
2143 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2144 "Content-Type: text/html\r\n"
2145 "Content-Length: 296\r\n"
2147 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2148 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2151 "<TITLE>Error</TITLE>\r\n"
2152 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2154 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2155 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2156 const char *cStatus;
2157 if (nStatus == 200) cStatus = "OK";
2158 else if (nStatus == 400) cStatus = "Bad Request";
2159 else if (nStatus == 403) cStatus = "Forbidden";
2160 else if (nStatus == 404) cStatus = "Not Found";
2161 else if (nStatus == 500) cStatus = "Internal Server Error";
2164 "HTTP/1.1 %d %s\r\n"
2166 "Connection: close\r\n"
2167 "Content-Length: %d\r\n"
2168 "Content-Type: application/json\r\n"
2169 "Server: bitcoin-json-rpc/%s\r\n"
2174 rfc1123Time().c_str(),
2176 FormatFullVersion().c_str(),
2180 int ReadHTTPStatus(std::basic_istream<char>& stream)
2183 getline(stream, str);
2184 vector<string> vWords;
2185 boost::split(vWords, str, boost::is_any_of(" "));
2186 if (vWords.size() < 2)
2188 return atoi(vWords[1].c_str());
2191 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2197 std::getline(stream, str);
2198 if (str.empty() || str == "\r")
2200 string::size_type nColon = str.find(":");
2201 if (nColon != string::npos)
2203 string strHeader = str.substr(0, nColon);
2204 boost::trim(strHeader);
2205 boost::to_lower(strHeader);
2206 string strValue = str.substr(nColon+1);
2207 boost::trim(strValue);
2208 mapHeadersRet[strHeader] = strValue;
2209 if (strHeader == "content-length")
2210 nLen = atoi(strValue.c_str());
2216 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2218 mapHeadersRet.clear();
2222 int nStatus = ReadHTTPStatus(stream);
2225 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2226 if (nLen < 0 || nLen > MAX_SIZE)
2232 vector<char> vch(nLen);
2233 stream.read(&vch[0], nLen);
2234 strMessageRet = string(vch.begin(), vch.end());
2240 bool HTTPAuthorized(map<string, string>& mapHeaders)
2242 string strAuth = mapHeaders["authorization"];
2243 if (strAuth.substr(0,6) != "Basic ")
2245 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2246 string strUserPass = DecodeBase64(strUserPass64);
2247 return strUserPass == strRPCUserColonPass;
2251 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2252 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2253 // unspecified (HTTP errors and contents of 'error').
2255 // 1.0 spec: http://json-rpc.org/wiki/specification
2256 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2257 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2260 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2263 request.push_back(Pair("method", strMethod));
2264 request.push_back(Pair("params", params));
2265 request.push_back(Pair("id", id));
2266 return write_string(Value(request), false) + "\n";
2269 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2272 if (error.type() != null_type)
2273 reply.push_back(Pair("result", Value::null));
2275 reply.push_back(Pair("result", result));
2276 reply.push_back(Pair("error", error));
2277 reply.push_back(Pair("id", id));
2278 return write_string(Value(reply), false) + "\n";
2281 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2283 // Send error reply from json-rpc error object
2285 int code = find_value(objError, "code").get_int();
2286 if (code == -32600) nStatus = 400;
2287 else if (code == -32601) nStatus = 404;
2288 string strReply = JSONRPCReply(Value::null, objError, id);
2289 stream << HTTPReply(nStatus, strReply) << std::flush;
2292 bool ClientAllowed(const string& strAddress)
2294 if (strAddress == asio::ip::address_v4::loopback().to_string())
2296 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2297 BOOST_FOREACH(string strAllow, vAllow)
2298 if (WildcardMatch(strAddress, strAllow))
2305 // IOStream device that speaks SSL but can also speak non-SSL
2307 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2309 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2311 fUseSSL = fUseSSLIn;
2312 fNeedHandshake = fUseSSLIn;
2315 void handshake(ssl::stream_base::handshake_type role)
2317 if (!fNeedHandshake) return;
2318 fNeedHandshake = false;
2319 stream.handshake(role);
2321 std::streamsize read(char* s, std::streamsize n)
2323 handshake(ssl::stream_base::server); // HTTPS servers read first
2324 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2325 return stream.next_layer().read_some(asio::buffer(s, n));
2327 std::streamsize write(const char* s, std::streamsize n)
2329 handshake(ssl::stream_base::client); // HTTPS clients write first
2330 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2331 return asio::write(stream.next_layer(), asio::buffer(s, n));
2333 bool connect(const std::string& server, const std::string& port)
2335 ip::tcp::resolver resolver(stream.get_io_service());
2336 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2337 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2338 ip::tcp::resolver::iterator end;
2339 boost::system::error_code error = asio::error::host_not_found;
2340 while (error && endpoint_iterator != end)
2342 stream.lowest_layer().close();
2343 stream.lowest_layer().connect(*endpoint_iterator++, error);
2351 bool fNeedHandshake;
2357 void ThreadRPCServer(void* parg)
2359 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2362 vnThreadsRunning[THREAD_RPCSERVER]++;
2363 ThreadRPCServer2(parg);
2364 vnThreadsRunning[THREAD_RPCSERVER]--;
2366 catch (std::exception& e) {
2367 vnThreadsRunning[THREAD_RPCSERVER]--;
2368 PrintException(&e, "ThreadRPCServer()");
2370 vnThreadsRunning[THREAD_RPCSERVER]--;
2371 PrintException(NULL, "ThreadRPCServer()");
2373 printf("ThreadRPCServer exiting\n");
2376 void ThreadRPCServer2(void* parg)
2378 printf("ThreadRPCServer started\n");
2380 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2381 if (mapArgs["-rpcpassword"] == "")
2383 unsigned char rand_pwd[32];
2384 RAND_bytes(rand_pwd, 32);
2385 string strWhatAmI = "To use bitcoind";
2386 if (mapArgs.count("-server"))
2387 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2388 else if (mapArgs.count("-daemon"))
2389 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2390 ThreadSafeMessageBox(strprintf(
2391 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2392 "It is recommended you use the following random password:\n"
2393 "rpcuser=bitcoinrpc\n"
2395 "(you do not need to remember this password)\n"
2396 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2398 GetConfigFile().c_str(),
2399 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2400 _("Error"), wxOK | wxMODAL);
2407 bool fUseSSL = GetBoolArg("-rpcssl");
2408 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2410 asio::io_service io_service;
2411 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2413 ip::tcp::acceptor acceptor(io_service, endpoint);
2415 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2417 ip::tcp::acceptor acceptor(io_service);
2420 acceptor.open(endpoint.protocol());
2421 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2422 acceptor.bind(endpoint);
2423 acceptor.listen(socket_base::max_connections);
2425 catch(boost::system::system_error &e)
2427 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2428 _("Error"), wxOK | wxMODAL);
2435 ssl::context context(io_service, ssl::context::sslv23);
2438 context.set_options(ssl::context::no_sslv2);
2439 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2440 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2441 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2442 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2443 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2444 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2445 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2446 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2448 string ciphers = GetArg("-rpcsslciphers",
2449 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2450 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2454 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2459 // Accept connection
2461 SSLStream sslStream(io_service, context);
2462 SSLIOStreamDevice d(sslStream, fUseSSL);
2463 iostreams::stream<SSLIOStreamDevice> stream(d);
2465 ip::tcp::iostream stream;
2468 ip::tcp::endpoint peer;
2469 vnThreadsRunning[THREAD_RPCSERVER]--;
2471 acceptor.accept(sslStream.lowest_layer(), peer);
2473 acceptor.accept(*stream.rdbuf(), peer);
2475 vnThreadsRunning[4]++;
2479 // Restrict callers by IP
2480 if (!ClientAllowed(peer.address().to_string()))
2482 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2484 stream << HTTPReply(403, "") << std::flush;
2488 map<string, string> mapHeaders;
2491 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2492 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2495 printf("ThreadRPCServer ReadHTTP timeout\n");
2499 // Check authorization
2500 if (mapHeaders.count("authorization") == 0)
2502 stream << HTTPReply(401, "") << std::flush;
2505 if (!HTTPAuthorized(mapHeaders))
2507 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2508 /* Deter brute-forcing short passwords.
2509 If this results in a DOS the user really
2510 shouldn't have their RPC port exposed.*/
2511 if (mapArgs["-rpcpassword"].size() < 20)
2514 stream << HTTPReply(401, "") << std::flush;
2518 Value id = Value::null;
2523 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2524 throw JSONRPCError(-32700, "Parse error");
2525 const Object& request = valRequest.get_obj();
2527 // Parse id now so errors from here on will have the id
2528 id = find_value(request, "id");
2531 Value valMethod = find_value(request, "method");
2532 if (valMethod.type() == null_type)
2533 throw JSONRPCError(-32600, "Missing method");
2534 if (valMethod.type() != str_type)
2535 throw JSONRPCError(-32600, "Method must be a string");
2536 string strMethod = valMethod.get_str();
2537 if (strMethod != "getwork" && strMethod != "getmemorypool")
2538 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2541 Value valParams = find_value(request, "params");
2543 if (valParams.type() == array_type)
2544 params = valParams.get_array();
2545 else if (valParams.type() == null_type)
2548 throw JSONRPCError(-32600, "Params must be an array");
2551 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2552 if (mi == mapCallTable.end())
2553 throw JSONRPCError(-32601, "Method not found");
2555 // Observe safe mode
2556 string strWarning = GetWarnings("rpc");
2557 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2558 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2564 CRITICAL_BLOCK(cs_main)
2565 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2566 result = (*(*mi).second)(params, false);
2569 string strReply = JSONRPCReply(result, Value::null, id);
2570 stream << HTTPReply(200, strReply) << std::flush;
2572 catch (std::exception& e)
2574 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2577 catch (Object& objError)
2579 ErrorReply(stream, objError, id);
2581 catch (std::exception& e)
2583 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2591 Object CallRPC(const string& strMethod, const Array& params)
2593 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2594 throw runtime_error(strprintf(
2595 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2596 "If the file does not exist, create it with owner-readable-only file permissions."),
2597 GetConfigFile().c_str()));
2599 // Connect to localhost
2600 bool fUseSSL = GetBoolArg("-rpcssl");
2602 asio::io_service io_service;
2603 ssl::context context(io_service, ssl::context::sslv23);
2604 context.set_options(ssl::context::no_sslv2);
2605 SSLStream sslStream(io_service, context);
2606 SSLIOStreamDevice d(sslStream, fUseSSL);
2607 iostreams::stream<SSLIOStreamDevice> stream(d);
2608 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2609 throw runtime_error("couldn't connect to server");
2612 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2614 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2616 throw runtime_error("couldn't connect to server");
2620 // HTTP basic authentication
2621 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2622 map<string, string> mapRequestHeaders;
2623 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2626 string strRequest = JSONRPCRequest(strMethod, params, 1);
2627 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2628 stream << strPost << std::flush;
2631 map<string, string> mapHeaders;
2633 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2635 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2636 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2637 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2638 else if (strReply.empty())
2639 throw runtime_error("no response from server");
2643 if (!read_string(strReply, valReply))
2644 throw runtime_error("couldn't parse reply from server");
2645 const Object& reply = valReply.get_obj();
2647 throw runtime_error("expected reply to have result, error and id properties");
2655 template<typename T>
2656 void ConvertTo(Value& value)
2658 if (value.type() == str_type)
2660 // reinterpret string as unquoted json value
2662 if (!read_string(value.get_str(), value2))
2663 throw runtime_error("type mismatch");
2664 value = value2.get_value<T>();
2668 value = value.get_value<T>();
2672 int CommandLineRPC(int argc, char *argv[])
2679 while (argc > 1 && IsSwitchChar(argv[1][0]))
2687 throw runtime_error("too few parameters");
2688 string strMethod = argv[1];
2690 // Parameters default to strings
2692 for (int i = 2; i < argc; i++)
2693 params.push_back(argv[i]);
2694 int n = params.size();
2697 // Special case non-string parameter types
2699 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2700 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2701 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2702 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2703 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2704 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2705 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2706 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2707 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2708 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2709 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2710 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2711 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2712 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2713 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2714 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2715 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2716 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2717 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2718 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2719 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2720 if (strMethod == "sendmany" && n > 1)
2722 string s = params[1].get_str();
2724 if (!read_string(s, v) || v.type() != obj_type)
2725 throw runtime_error("type mismatch");
2726 params[1] = v.get_obj();
2728 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2729 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2730 if (strMethod == "addmultisigaddress" && n > 1)
2732 string s = params[1].get_str();
2734 if (!read_string(s, v) || v.type() != array_type)
2735 throw runtime_error("type mismatch "+s);
2736 params[1] = v.get_array();
2740 Object reply = CallRPC(strMethod, params);
2743 const Value& result = find_value(reply, "result");
2744 const Value& error = find_value(reply, "error");
2746 if (error.type() != null_type)
2749 strPrint = "error: " + write_string(error, false);
2750 int code = find_value(error.get_obj(), "code").get_int();
2756 if (result.type() == null_type)
2758 else if (result.type() == str_type)
2759 strPrint = result.get_str();
2761 strPrint = write_string(result, true);
2764 catch (std::exception& e)
2766 strPrint = string("error: ") + e.what();
2771 PrintException(NULL, "CommandLineRPC()");
2776 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2785 int main(int argc, char *argv[])
2788 // Turn off microsoft heap dump noise
2789 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2790 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2792 setbuf(stdin, NULL);
2793 setbuf(stdout, NULL);
2794 setbuf(stderr, NULL);
2798 if (argc >= 2 && string(argv[1]) == "-server")
2800 printf("server ready\n");
2801 ThreadRPCServer(NULL);
2805 return CommandLineRPC(argc, argv);
2808 catch (std::exception& e) {
2809 PrintException(&e, "main()");
2811 PrintException(NULL, "main()");