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.
12 #include "ui_interface.h"
13 #include "bitcoinrpc.h"
16 #include <boost/asio.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/iostreams/concepts.hpp>
19 #include <boost/iostreams/stream.hpp>
20 #include <boost/algorithm/string.hpp>
21 #include <boost/lexical_cast.hpp>
22 #include <boost/asio/ssl.hpp>
23 #include <boost/filesystem/fstream.hpp>
24 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
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);
39 static std::string strRPCUserColonPass;
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
44 extern Value dumpprivkey(const Array& params, bool fHelp);
45 extern Value importprivkey(const Array& params, bool fHelp);
47 Object JSONRPCError(int code, const string& message)
50 error.push_back(Pair("code", code));
51 error.push_back(Pair("message", message));
55 double GetDifficulty(const CBlockIndex* blockindex = NULL)
57 // Floating point number that is a multiple of the minimum difficulty,
58 // minimum difficulty = 1.0.
59 if (blockindex == NULL)
61 if (pindexBest == NULL)
64 blockindex = pindexBest;
67 int nShift = (blockindex->nBits >> 24) & 0xff;
70 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
87 int64 AmountFromValue(const Value& value)
89 double dAmount = value.get_real();
90 if (dAmount <= 0.0 || dAmount > 21000000.0)
91 throw JSONRPCError(-3, "Invalid amount");
92 int64 nAmount = roundint64(dAmount * COIN);
93 if (!MoneyRange(nAmount))
94 throw JSONRPCError(-3, "Invalid amount");
98 Value ValueFromAmount(int64 amount)
100 return (double)amount / (double)COIN;
104 HexBits(unsigned int nBits)
110 uBits.nBits = htonl((int32_t)nBits);
111 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
114 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
116 int confirms = wtx.GetDepthInMainChain();
117 entry.push_back(Pair("confirmations", confirms));
120 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
121 entry.push_back(Pair("blockindex", wtx.nIndex));
123 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
124 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
125 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
126 entry.push_back(Pair(item.first, item.second));
129 string AccountFromValue(const Value& value)
131 string strAccount = value.get_str();
132 if (strAccount == "*")
133 throw JSONRPCError(-11, "Invalid account name");
137 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
140 result.push_back(Pair("hash", block.GetHash().GetHex()));
141 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
142 result.push_back(Pair("height", blockindex->nHeight));
143 result.push_back(Pair("version", block.nVersion));
144 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
145 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
146 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
147 result.push_back(Pair("bits", HexBits(block.nBits)));
148 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
150 BOOST_FOREACH (const CTransaction&tx, block.vtx)
151 txhashes.push_back(tx.GetHash().GetHex());
152 result.push_back(Pair("tx", txhashes));
154 if (blockindex->pprev)
155 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
156 if (blockindex->pnext)
157 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
164 /// Note: This interface may still be subject to change.
167 string CRPCTable::help(string strCommand) const
170 set<rpcfn_type> setDone;
171 for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
173 const CRPCCommand *pcmd = mi->second;
174 string strMethod = mi->first;
175 // We already filter duplicates, but these deprecated screw up the sort order
176 if (strMethod == "getamountreceived" ||
177 strMethod == "getallreceived" ||
178 strMethod == "getblocknumber" || // deprecated
179 (strMethod.find("label") != string::npos))
181 if (strCommand != "" && strMethod != strCommand)
186 rpcfn_type pfn = pcmd->actor;
187 if (setDone.insert(pfn).second)
188 (*pfn)(params, true);
190 catch (std::exception& e)
192 // Help text is returned in an exception
193 string strHelp = string(e.what());
194 if (strCommand == "")
195 if (strHelp.find('\n') != string::npos)
196 strHelp = strHelp.substr(0, strHelp.find('\n'));
197 strRet += strHelp + "\n";
201 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
202 strRet = strRet.substr(0,strRet.size()-1);
206 Value help(const Array& params, bool fHelp)
208 if (fHelp || params.size() > 1)
211 "List commands, or get help for a command.");
214 if (params.size() > 0)
215 strCommand = params[0].get_str();
217 return tableRPC.help(strCommand);
221 Value stop(const Array& params, bool fHelp)
223 if (fHelp || params.size() != 0)
226 "Stop bitcoin server.");
227 // Shutdown will take long enough that the response should get back
229 return "bitcoin server stopping";
233 Value getblockcount(const Array& params, bool fHelp)
235 if (fHelp || params.size() != 0)
238 "Returns the number of blocks in the longest block chain.");
245 Value getblocknumber(const Array& params, bool fHelp)
247 if (fHelp || params.size() != 0)
250 "Deprecated. Use getblockcount.");
256 Value getconnectioncount(const Array& params, bool fHelp)
258 if (fHelp || params.size() != 0)
260 "getconnectioncount\n"
261 "Returns the number of connections to other nodes.");
263 return (int)vNodes.size();
267 Value getdifficulty(const Array& params, bool fHelp)
269 if (fHelp || params.size() != 0)
272 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
274 return GetDifficulty();
278 Value getgenerate(const Array& params, bool fHelp)
280 if (fHelp || params.size() != 0)
283 "Returns true or false.");
285 return GetBoolArg("-gen");
289 Value setgenerate(const Array& params, bool fHelp)
291 if (fHelp || params.size() < 1 || params.size() > 2)
293 "setgenerate <generate> [genproclimit]\n"
294 "<generate> is true or false to turn generation on or off.\n"
295 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
297 bool fGenerate = true;
298 if (params.size() > 0)
299 fGenerate = params[0].get_bool();
301 if (params.size() > 1)
303 int nGenProcLimit = params[1].get_int();
304 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
305 if (nGenProcLimit == 0)
308 mapArgs["-gen"] = (fGenerate ? "1" : "0");
310 GenerateBitcoins(fGenerate, pwalletMain);
315 Value gethashespersec(const Array& params, bool fHelp)
317 if (fHelp || params.size() != 0)
320 "Returns a recent hashes per second performance measurement while generating.");
322 if (GetTimeMillis() - nHPSTimerStart > 8000)
323 return (boost::int64_t)0;
324 return (boost::int64_t)dHashesPerSec;
328 Value getinfo(const Array& params, bool fHelp)
330 if (fHelp || params.size() != 0)
333 "Returns an object containing various state info.");
336 obj.push_back(Pair("version", (int)CLIENT_VERSION));
337 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
338 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
339 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
340 obj.push_back(Pair("blocks", (int)nBestHeight));
341 obj.push_back(Pair("connections", (int)vNodes.size()));
342 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
343 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
344 obj.push_back(Pair("testnet", fTestNet));
345 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
346 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
347 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
348 if (pwalletMain->IsCrypted())
349 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
350 obj.push_back(Pair("errors", GetWarnings("statusbar")));
355 Value getmininginfo(const Array& params, bool fHelp)
357 if (fHelp || params.size() != 0)
360 "Returns an object containing mining-related information.");
363 obj.push_back(Pair("blocks", (int)nBestHeight));
364 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
365 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
366 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
367 obj.push_back(Pair("errors", GetWarnings("statusbar")));
368 obj.push_back(Pair("generate", GetBoolArg("-gen")));
369 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
370 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
371 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
372 obj.push_back(Pair("testnet", fTestNet));
377 Value getnewaddress(const Array& params, bool fHelp)
379 if (fHelp || params.size() > 1)
381 "getnewaddress [account]\n"
382 "Returns a new bitcoin address for receiving payments. "
383 "If [account] is specified (recommended), it is added to the address book "
384 "so payments received with the address will be credited to [account].");
386 // Parse the account first so we don't generate a key if there's an error
388 if (params.size() > 0)
389 strAccount = AccountFromValue(params[0]);
391 if (!pwalletMain->IsLocked())
392 pwalletMain->TopUpKeyPool();
394 // Generate a new key that is added to wallet
395 std::vector<unsigned char> newKey;
396 if (!pwalletMain->GetKeyFromPool(newKey, false))
397 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
398 CBitcoinAddress address(newKey);
400 pwalletMain->SetAddressBookName(address, strAccount);
402 return address.ToString();
406 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
408 CWalletDB walletdb(pwalletMain->strWalletFile);
411 walletdb.ReadAccount(strAccount, account);
413 bool bKeyUsed = false;
415 // Check if the current key has been used
416 if (!account.vchPubKey.empty())
418 CScript scriptPubKey;
419 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
420 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
421 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
424 const CWalletTx& wtx = (*it).second;
425 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
426 if (txout.scriptPubKey == scriptPubKey)
431 // Generate a new key
432 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
434 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
435 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
437 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
438 walletdb.WriteAccount(strAccount, account);
441 return CBitcoinAddress(account.vchPubKey);
444 Value getaccountaddress(const Array& params, bool fHelp)
446 if (fHelp || params.size() != 1)
448 "getaccountaddress <account>\n"
449 "Returns the current bitcoin address for receiving payments to this account.");
451 // Parse the account first so we don't generate a key if there's an error
452 string strAccount = AccountFromValue(params[0]);
456 ret = GetAccountAddress(strAccount).ToString();
463 Value setaccount(const Array& params, bool fHelp)
465 if (fHelp || params.size() < 1 || params.size() > 2)
467 "setaccount <bitcoinaddress> <account>\n"
468 "Sets the account associated with the given address.");
470 CBitcoinAddress address(params[0].get_str());
471 if (!address.IsValid())
472 throw JSONRPCError(-5, "Invalid bitcoin address");
476 if (params.size() > 1)
477 strAccount = AccountFromValue(params[1]);
479 // Detect when changing the account of an address that is the 'unused current key' of another account:
480 if (pwalletMain->mapAddressBook.count(address))
482 string strOldAccount = pwalletMain->mapAddressBook[address];
483 if (address == GetAccountAddress(strOldAccount))
484 GetAccountAddress(strOldAccount, true);
487 pwalletMain->SetAddressBookName(address, strAccount);
493 Value getaccount(const Array& params, bool fHelp)
495 if (fHelp || params.size() != 1)
497 "getaccount <bitcoinaddress>\n"
498 "Returns the account associated with the given address.");
500 CBitcoinAddress address(params[0].get_str());
501 if (!address.IsValid())
502 throw JSONRPCError(-5, "Invalid bitcoin address");
505 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
506 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
507 strAccount = (*mi).second;
512 Value getaddressesbyaccount(const Array& params, bool fHelp)
514 if (fHelp || params.size() != 1)
516 "getaddressesbyaccount <account>\n"
517 "Returns the list of addresses for the given account.");
519 string strAccount = AccountFromValue(params[0]);
521 // Find all addresses that have the given account
523 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
525 const CBitcoinAddress& address = item.first;
526 const string& strName = item.second;
527 if (strName == strAccount)
528 ret.push_back(address.ToString());
533 Value settxfee(const Array& params, bool fHelp)
535 if (fHelp || params.size() < 1 || params.size() > 1)
537 "settxfee <amount>\n"
538 "<amount> is a real and is rounded to the nearest 0.00000001");
542 if (params[0].get_real() != 0.0)
543 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
545 nTransactionFee = nAmount;
549 Value sendtoaddress(const Array& params, bool fHelp)
551 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
553 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
554 "<amount> is a real and is rounded to the nearest 0.00000001\n"
555 "requires wallet passphrase to be set with walletpassphrase first");
556 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
558 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
559 "<amount> is a real and is rounded to the nearest 0.00000001");
561 CBitcoinAddress address(params[0].get_str());
562 if (!address.IsValid())
563 throw JSONRPCError(-5, "Invalid bitcoin address");
566 int64 nAmount = AmountFromValue(params[1]);
570 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
571 wtx.mapValue["comment"] = params[2].get_str();
572 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
573 wtx.mapValue["to"] = params[3].get_str();
575 if (pwalletMain->IsLocked())
576 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
578 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
580 throw JSONRPCError(-4, strError);
582 return wtx.GetHash().GetHex();
585 Value signmessage(const Array& params, bool fHelp)
587 if (fHelp || params.size() != 2)
589 "signmessage <bitcoinaddress> <message>\n"
590 "Sign a message with the private key of an address");
592 if (pwalletMain->IsLocked())
593 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
595 string strAddress = params[0].get_str();
596 string strMessage = params[1].get_str();
598 CBitcoinAddress addr(strAddress);
600 throw JSONRPCError(-3, "Invalid address");
603 if (!pwalletMain->GetKey(addr, key))
604 throw JSONRPCError(-4, "Private key not available");
606 CDataStream ss(SER_GETHASH, 0);
607 ss << strMessageMagic;
610 vector<unsigned char> vchSig;
611 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
612 throw JSONRPCError(-5, "Sign failed");
614 return EncodeBase64(&vchSig[0], vchSig.size());
617 Value verifymessage(const Array& params, bool fHelp)
619 if (fHelp || params.size() != 3)
621 "verifymessage <bitcoinaddress> <signature> <message>\n"
622 "Verify a signed message");
624 string strAddress = params[0].get_str();
625 string strSign = params[1].get_str();
626 string strMessage = params[2].get_str();
628 CBitcoinAddress addr(strAddress);
630 throw JSONRPCError(-3, "Invalid address");
632 bool fInvalid = false;
633 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
636 throw JSONRPCError(-5, "Malformed base64 encoding");
638 CDataStream ss(SER_GETHASH, 0);
639 ss << strMessageMagic;
643 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
646 return (CBitcoinAddress(key.GetPubKey()) == addr);
650 Value getreceivedbyaddress(const Array& params, bool fHelp)
652 if (fHelp || params.size() < 1 || params.size() > 2)
654 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
655 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
658 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
659 CScript scriptPubKey;
660 if (!address.IsValid())
661 throw JSONRPCError(-5, "Invalid bitcoin address");
662 scriptPubKey.SetBitcoinAddress(address);
663 if (!IsMine(*pwalletMain,scriptPubKey))
666 // Minimum confirmations
668 if (params.size() > 1)
669 nMinDepth = params[1].get_int();
673 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
675 const CWalletTx& wtx = (*it).second;
676 if (wtx.IsCoinBase() || !wtx.IsFinal())
679 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
680 if (txout.scriptPubKey == scriptPubKey)
681 if (wtx.GetDepthInMainChain() >= nMinDepth)
682 nAmount += txout.nValue;
685 return ValueFromAmount(nAmount);
689 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
691 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
693 const CBitcoinAddress& address = item.first;
694 const string& strName = item.second;
695 if (strName == strAccount)
696 setAddress.insert(address);
701 Value getreceivedbyaccount(const Array& params, bool fHelp)
703 if (fHelp || params.size() < 1 || params.size() > 2)
705 "getreceivedbyaccount <account> [minconf=1]\n"
706 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
708 // Minimum confirmations
710 if (params.size() > 1)
711 nMinDepth = params[1].get_int();
713 // Get the set of pub keys assigned to account
714 string strAccount = AccountFromValue(params[0]);
715 set<CBitcoinAddress> setAddress;
716 GetAccountAddresses(strAccount, setAddress);
720 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
722 const CWalletTx& wtx = (*it).second;
723 if (wtx.IsCoinBase() || !wtx.IsFinal())
726 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
728 CBitcoinAddress address;
729 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
730 if (wtx.GetDepthInMainChain() >= nMinDepth)
731 nAmount += txout.nValue;
735 return (double)nAmount / (double)COIN;
739 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
743 // Tally wallet transactions
744 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
746 const CWalletTx& wtx = (*it).second;
750 int64 nGenerated, nReceived, nSent, nFee;
751 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
753 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
754 nBalance += nReceived;
755 nBalance += nGenerated - nSent - nFee;
758 // Tally internal accounting entries
759 nBalance += walletdb.GetAccountCreditDebit(strAccount);
764 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
766 CWalletDB walletdb(pwalletMain->strWalletFile);
767 return GetAccountBalance(walletdb, strAccount, nMinDepth);
771 Value getbalance(const Array& params, bool fHelp)
773 if (fHelp || params.size() > 2)
775 "getbalance [account] [minconf=1]\n"
776 "If [account] is not specified, returns the server's total available balance.\n"
777 "If [account] is specified, returns the balance in the account.");
779 if (params.size() == 0)
780 return ValueFromAmount(pwalletMain->GetBalance());
783 if (params.size() > 1)
784 nMinDepth = params[1].get_int();
786 if (params[0].get_str() == "*") {
787 // Calculate total balance a different way from GetBalance()
788 // (GetBalance() sums up all unspent TxOuts)
789 // getbalance and getbalance '*' should always return the same number.
791 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
793 const CWalletTx& wtx = (*it).second;
797 int64 allGeneratedImmature, allGeneratedMature, allFee;
798 allGeneratedImmature = allGeneratedMature = allFee = 0;
799 string strSentAccount;
800 list<pair<CBitcoinAddress, int64> > listReceived;
801 list<pair<CBitcoinAddress, int64> > listSent;
802 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
803 if (wtx.GetDepthInMainChain() >= nMinDepth)
805 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
806 nBalance += r.second;
808 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
809 nBalance -= r.second;
811 nBalance += allGeneratedMature;
813 return ValueFromAmount(nBalance);
816 string strAccount = AccountFromValue(params[0]);
818 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
820 return ValueFromAmount(nBalance);
824 Value movecmd(const Array& params, bool fHelp)
826 if (fHelp || params.size() < 3 || params.size() > 5)
828 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
829 "Move from one account in your wallet to another.");
831 string strFrom = AccountFromValue(params[0]);
832 string strTo = AccountFromValue(params[1]);
833 int64 nAmount = AmountFromValue(params[2]);
834 if (params.size() > 3)
835 // unused parameter, used to be nMinDepth, keep type-checking it though
836 (void)params[3].get_int();
838 if (params.size() > 4)
839 strComment = params[4].get_str();
841 CWalletDB walletdb(pwalletMain->strWalletFile);
842 if (!walletdb.TxnBegin())
843 throw JSONRPCError(-20, "database error");
845 int64 nNow = GetAdjustedTime();
848 CAccountingEntry debit;
849 debit.strAccount = strFrom;
850 debit.nCreditDebit = -nAmount;
852 debit.strOtherAccount = strTo;
853 debit.strComment = strComment;
854 walletdb.WriteAccountingEntry(debit);
857 CAccountingEntry credit;
858 credit.strAccount = strTo;
859 credit.nCreditDebit = nAmount;
861 credit.strOtherAccount = strFrom;
862 credit.strComment = strComment;
863 walletdb.WriteAccountingEntry(credit);
865 if (!walletdb.TxnCommit())
866 throw JSONRPCError(-20, "database error");
872 Value sendfrom(const Array& params, bool fHelp)
874 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
876 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
877 "<amount> is a real and is rounded to the nearest 0.00000001\n"
878 "requires wallet passphrase to be set with walletpassphrase first");
879 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
881 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
882 "<amount> is a real and is rounded to the nearest 0.00000001");
884 string strAccount = AccountFromValue(params[0]);
885 CBitcoinAddress address(params[1].get_str());
886 if (!address.IsValid())
887 throw JSONRPCError(-5, "Invalid bitcoin address");
888 int64 nAmount = AmountFromValue(params[2]);
890 if (params.size() > 3)
891 nMinDepth = params[3].get_int();
894 wtx.strFromAccount = strAccount;
895 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
896 wtx.mapValue["comment"] = params[4].get_str();
897 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
898 wtx.mapValue["to"] = params[5].get_str();
900 if (pwalletMain->IsLocked())
901 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
904 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
905 if (nAmount > nBalance)
906 throw JSONRPCError(-6, "Account has insufficient funds");
909 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
911 throw JSONRPCError(-4, strError);
913 return wtx.GetHash().GetHex();
917 Value sendmany(const Array& params, bool fHelp)
919 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
921 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
922 "amounts are double-precision floating point numbers\n"
923 "requires wallet passphrase to be set with walletpassphrase first");
924 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
926 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
927 "amounts are double-precision floating point numbers");
929 string strAccount = AccountFromValue(params[0]);
930 Object sendTo = params[1].get_obj();
932 if (params.size() > 2)
933 nMinDepth = params[2].get_int();
936 wtx.strFromAccount = strAccount;
937 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
938 wtx.mapValue["comment"] = params[3].get_str();
940 set<CBitcoinAddress> setAddress;
941 vector<pair<CScript, int64> > vecSend;
943 int64 totalAmount = 0;
944 BOOST_FOREACH(const Pair& s, sendTo)
946 CBitcoinAddress address(s.name_);
947 if (!address.IsValid())
948 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
950 if (setAddress.count(address))
951 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
952 setAddress.insert(address);
954 CScript scriptPubKey;
955 scriptPubKey.SetBitcoinAddress(address);
956 int64 nAmount = AmountFromValue(s.value_);
957 totalAmount += nAmount;
959 vecSend.push_back(make_pair(scriptPubKey, nAmount));
962 if (pwalletMain->IsLocked())
963 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
966 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
967 if (totalAmount > nBalance)
968 throw JSONRPCError(-6, "Account has insufficient funds");
971 CReserveKey keyChange(pwalletMain);
972 int64 nFeeRequired = 0;
973 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
976 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
977 throw JSONRPCError(-6, "Insufficient funds");
978 throw JSONRPCError(-4, "Transaction creation failed");
980 if (!pwalletMain->CommitTransaction(wtx, keyChange))
981 throw JSONRPCError(-4, "Transaction commit failed");
983 return wtx.GetHash().GetHex();
986 Value addmultisigaddress(const Array& params, bool fHelp)
988 if (fHelp || params.size() < 2 || params.size() > 3)
990 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
991 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
992 "each key is a bitcoin address or hex-encoded public key\n"
993 "If [account] is specified, assign address to [account].";
994 throw runtime_error(msg);
997 int nRequired = params[0].get_int();
998 const Array& keys = params[1].get_array();
1000 if (params.size() > 2)
1001 strAccount = AccountFromValue(params[2]);
1003 // Gather public keys
1005 throw runtime_error("a multisignature address must require at least one key to redeem");
1006 if ((int)keys.size() < nRequired)
1007 throw runtime_error(
1008 strprintf("not enough keys supplied "
1009 "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1010 std::vector<CKey> pubkeys;
1011 pubkeys.resize(keys.size());
1012 for (unsigned int i = 0; i < keys.size(); i++)
1014 const std::string& ks = keys[i].get_str();
1016 // Case 1: bitcoin address and we have full public key:
1017 CBitcoinAddress address(ks);
1018 if (address.IsValid())
1020 if (address.IsScript())
1021 throw runtime_error(
1022 strprintf("%s is a pay-to-script address",ks.c_str()));
1023 std::vector<unsigned char> vchPubKey;
1024 if (!pwalletMain->GetPubKey(address, vchPubKey))
1025 throw runtime_error(
1026 strprintf("no full public key for address %s",ks.c_str()));
1027 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1028 throw runtime_error(" Invalid public key: "+ks);
1031 // Case 2: hex public key
1034 vector<unsigned char> vchPubKey = ParseHex(ks);
1035 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1036 throw runtime_error(" Invalid public key: "+ks);
1040 throw runtime_error(" Invalid public key: "+ks);
1044 // Construct using pay-to-script-hash:
1046 inner.SetMultisig(nRequired, pubkeys);
1048 uint160 scriptHash = Hash160(inner);
1049 CScript scriptPubKey;
1050 scriptPubKey.SetPayToScriptHash(inner);
1051 pwalletMain->AddCScript(inner);
1052 CBitcoinAddress address;
1053 address.SetScriptHash160(scriptHash);
1055 pwalletMain->SetAddressBookName(address, strAccount);
1056 return address.ToString();
1067 nConf = std::numeric_limits<int>::max();
1071 Value ListReceived(const Array& params, bool fByAccounts)
1073 // Minimum confirmations
1075 if (params.size() > 0)
1076 nMinDepth = params[0].get_int();
1078 // Whether to include empty accounts
1079 bool fIncludeEmpty = false;
1080 if (params.size() > 1)
1081 fIncludeEmpty = params[1].get_bool();
1084 map<CBitcoinAddress, tallyitem> mapTally;
1085 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1087 const CWalletTx& wtx = (*it).second;
1089 if (wtx.IsCoinBase() || !wtx.IsFinal())
1092 int nDepth = wtx.GetDepthInMainChain();
1093 if (nDepth < nMinDepth)
1096 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1098 CBitcoinAddress address;
1099 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1102 tallyitem& item = mapTally[address];
1103 item.nAmount += txout.nValue;
1104 item.nConf = min(item.nConf, nDepth);
1110 map<string, tallyitem> mapAccountTally;
1111 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1113 const CBitcoinAddress& address = item.first;
1114 const string& strAccount = item.second;
1115 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1116 if (it == mapTally.end() && !fIncludeEmpty)
1120 int nConf = std::numeric_limits<int>::max();
1121 if (it != mapTally.end())
1123 nAmount = (*it).second.nAmount;
1124 nConf = (*it).second.nConf;
1129 tallyitem& item = mapAccountTally[strAccount];
1130 item.nAmount += nAmount;
1131 item.nConf = min(item.nConf, nConf);
1136 obj.push_back(Pair("address", address.ToString()));
1137 obj.push_back(Pair("account", strAccount));
1138 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1139 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1146 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1148 int64 nAmount = (*it).second.nAmount;
1149 int nConf = (*it).second.nConf;
1151 obj.push_back(Pair("account", (*it).first));
1152 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1153 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1161 Value listreceivedbyaddress(const Array& params, bool fHelp)
1163 if (fHelp || params.size() > 2)
1164 throw runtime_error(
1165 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1166 "[minconf] is the minimum number of confirmations before payments are included.\n"
1167 "[includeempty] whether to include addresses that haven't received any payments.\n"
1168 "Returns an array of objects containing:\n"
1169 " \"address\" : receiving address\n"
1170 " \"account\" : the account of the receiving address\n"
1171 " \"amount\" : total amount received by the address\n"
1172 " \"confirmations\" : number of confirmations of the most recent transaction included");
1174 return ListReceived(params, false);
1177 Value listreceivedbyaccount(const Array& params, bool fHelp)
1179 if (fHelp || params.size() > 2)
1180 throw runtime_error(
1181 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1182 "[minconf] is the minimum number of confirmations before payments are included.\n"
1183 "[includeempty] whether to include accounts that haven't received any payments.\n"
1184 "Returns an array of objects containing:\n"
1185 " \"account\" : the account of the receiving addresses\n"
1186 " \"amount\" : total amount received by addresses with this account\n"
1187 " \"confirmations\" : number of confirmations of the most recent transaction included");
1189 return ListReceived(params, true);
1192 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1194 int64 nGeneratedImmature, nGeneratedMature, nFee;
1195 string strSentAccount;
1196 list<pair<CBitcoinAddress, int64> > listReceived;
1197 list<pair<CBitcoinAddress, int64> > listSent;
1199 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1201 bool fAllAccounts = (strAccount == string("*"));
1203 // Generated blocks assigned to account ""
1204 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1207 entry.push_back(Pair("account", string("")));
1208 if (nGeneratedImmature)
1210 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1211 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1215 entry.push_back(Pair("category", "generate"));
1216 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1219 WalletTxToJSON(wtx, entry);
1220 ret.push_back(entry);
1224 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1226 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1229 entry.push_back(Pair("account", strSentAccount));
1230 entry.push_back(Pair("address", s.first.ToString()));
1231 entry.push_back(Pair("category", "send"));
1232 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1233 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1235 WalletTxToJSON(wtx, entry);
1236 ret.push_back(entry);
1241 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1243 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1246 if (pwalletMain->mapAddressBook.count(r.first))
1247 account = pwalletMain->mapAddressBook[r.first];
1248 if (fAllAccounts || (account == strAccount))
1251 entry.push_back(Pair("account", account));
1252 entry.push_back(Pair("address", r.first.ToString()));
1253 entry.push_back(Pair("category", "receive"));
1254 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1256 WalletTxToJSON(wtx, entry);
1257 ret.push_back(entry);
1263 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1265 bool fAllAccounts = (strAccount == string("*"));
1267 if (fAllAccounts || acentry.strAccount == strAccount)
1270 entry.push_back(Pair("account", acentry.strAccount));
1271 entry.push_back(Pair("category", "move"));
1272 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1273 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1274 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1275 entry.push_back(Pair("comment", acentry.strComment));
1276 ret.push_back(entry);
1280 Value listtransactions(const Array& params, bool fHelp)
1282 if (fHelp || params.size() > 3)
1283 throw runtime_error(
1284 "listtransactions [account] [count=10] [from=0]\n"
1285 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1287 string strAccount = "*";
1288 if (params.size() > 0)
1289 strAccount = params[0].get_str();
1291 if (params.size() > 1)
1292 nCount = params[1].get_int();
1294 if (params.size() > 2)
1295 nFrom = params[2].get_int();
1298 throw JSONRPCError(-8, "Negative count");
1300 throw JSONRPCError(-8, "Negative from");
1303 CWalletDB walletdb(pwalletMain->strWalletFile);
1305 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1306 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1307 typedef multimap<int64, TxPair > TxItems;
1310 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1311 // would make this much faster for applications that do this a lot.
1312 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1314 CWalletTx* wtx = &((*it).second);
1315 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1317 list<CAccountingEntry> acentries;
1318 walletdb.ListAccountCreditDebit(strAccount, acentries);
1319 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1321 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1324 // iterate backwards until we have nCount items to return:
1325 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1327 CWalletTx *const pwtx = (*it).second.first;
1329 ListTransactions(*pwtx, strAccount, 0, true, ret);
1330 CAccountingEntry *const pacentry = (*it).second.second;
1332 AcentryToJSON(*pacentry, strAccount, ret);
1334 if (ret.size() >= (nCount+nFrom)) break;
1336 // ret is newest to oldest
1338 if (nFrom > (int)ret.size())
1340 if ((nFrom + nCount) > (int)ret.size())
1341 nCount = ret.size() - nFrom;
1342 Array::iterator first = ret.begin();
1343 std::advance(first, nFrom);
1344 Array::iterator last = ret.begin();
1345 std::advance(last, nFrom+nCount);
1347 if (last != ret.end()) ret.erase(last, ret.end());
1348 if (first != ret.begin()) ret.erase(ret.begin(), first);
1350 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1355 Value listaccounts(const Array& params, bool fHelp)
1357 if (fHelp || params.size() > 1)
1358 throw runtime_error(
1359 "listaccounts [minconf=1]\n"
1360 "Returns Object that has account names as keys, account balances as values.");
1363 if (params.size() > 0)
1364 nMinDepth = params[0].get_int();
1366 map<string, int64> mapAccountBalances;
1367 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1368 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1369 mapAccountBalances[entry.second] = 0;
1372 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1374 const CWalletTx& wtx = (*it).second;
1375 int64 nGeneratedImmature, nGeneratedMature, nFee;
1376 string strSentAccount;
1377 list<pair<CBitcoinAddress, int64> > listReceived;
1378 list<pair<CBitcoinAddress, int64> > listSent;
1379 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1380 mapAccountBalances[strSentAccount] -= nFee;
1381 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1382 mapAccountBalances[strSentAccount] -= s.second;
1383 if (wtx.GetDepthInMainChain() >= nMinDepth)
1385 mapAccountBalances[""] += nGeneratedMature;
1386 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1387 if (pwalletMain->mapAddressBook.count(r.first))
1388 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1390 mapAccountBalances[""] += r.second;
1394 list<CAccountingEntry> acentries;
1395 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1396 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1397 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1400 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1401 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1406 Value listsinceblock(const Array& params, bool fHelp)
1409 throw runtime_error(
1410 "listsinceblock [blockhash] [target-confirmations]\n"
1411 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1413 CBlockIndex *pindex = NULL;
1414 int target_confirms = 1;
1416 if (params.size() > 0)
1418 uint256 blockId = 0;
1420 blockId.SetHex(params[0].get_str());
1421 pindex = CBlockLocator(blockId).GetBlockIndex();
1424 if (params.size() > 1)
1426 target_confirms = params[1].get_int();
1428 if (target_confirms < 1)
1429 throw JSONRPCError(-8, "Invalid parameter");
1432 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1436 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1438 CWalletTx tx = (*it).second;
1440 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1441 ListTransactions(tx, "*", 0, true, transactions);
1446 if (target_confirms == 1)
1448 lastblock = hashBestChain;
1452 int target_height = pindexBest->nHeight + 1 - target_confirms;
1455 for (block = pindexBest;
1456 block && block->nHeight > target_height;
1457 block = block->pprev) { }
1459 lastblock = block ? block->GetBlockHash() : 0;
1463 ret.push_back(Pair("transactions", transactions));
1464 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1469 Value gettransaction(const Array& params, bool fHelp)
1471 if (fHelp || params.size() != 1)
1472 throw runtime_error(
1473 "gettransaction <txid>\n"
1474 "Get detailed information about <txid>");
1477 hash.SetHex(params[0].get_str());
1481 if (!pwalletMain->mapWallet.count(hash))
1482 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1483 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1485 int64 nCredit = wtx.GetCredit();
1486 int64 nDebit = wtx.GetDebit();
1487 int64 nNet = nCredit - nDebit;
1488 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1490 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1492 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1494 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1497 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1498 entry.push_back(Pair("details", details));
1504 Value backupwallet(const Array& params, bool fHelp)
1506 if (fHelp || params.size() != 1)
1507 throw runtime_error(
1508 "backupwallet <destination>\n"
1509 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1511 string strDest = params[0].get_str();
1512 BackupWallet(*pwalletMain, strDest);
1518 Value keypoolrefill(const Array& params, bool fHelp)
1520 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1521 throw runtime_error(
1523 "Fills the keypool, requires wallet passphrase to be set.");
1524 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1525 throw runtime_error(
1527 "Fills the keypool.");
1529 if (pwalletMain->IsLocked())
1530 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1532 pwalletMain->TopUpKeyPool();
1534 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1535 throw JSONRPCError(-4, "Error refreshing keypool.");
1541 void ThreadTopUpKeyPool(void* parg)
1543 pwalletMain->TopUpKeyPool();
1546 void ThreadCleanWalletPassphrase(void* parg)
1548 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1550 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1552 if (nWalletUnlockTime == 0)
1554 nWalletUnlockTime = nMyWakeTime;
1558 if (nWalletUnlockTime==0)
1560 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1564 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1566 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1570 if (nWalletUnlockTime)
1572 nWalletUnlockTime = 0;
1573 pwalletMain->Lock();
1578 if (nWalletUnlockTime < nMyWakeTime)
1579 nWalletUnlockTime = nMyWakeTime;
1582 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1584 delete (int64*)parg;
1587 Value walletpassphrase(const Array& params, bool fHelp)
1589 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1590 throw runtime_error(
1591 "walletpassphrase <passphrase> <timeout>\n"
1592 "Stores the wallet decryption key in memory for <timeout> seconds.");
1595 if (!pwalletMain->IsCrypted())
1596 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1598 if (!pwalletMain->IsLocked())
1599 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1601 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1602 SecureString strWalletPass;
1603 strWalletPass.reserve(100);
1604 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1605 // Alternately, find a way to make params[0] mlock()'d to begin with.
1606 strWalletPass = params[0].get_str().c_str();
1608 if (strWalletPass.length() > 0)
1610 if (!pwalletMain->Unlock(strWalletPass))
1611 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1614 throw runtime_error(
1615 "walletpassphrase <passphrase> <timeout>\n"
1616 "Stores the wallet decryption key in memory for <timeout> seconds.");
1618 CreateThread(ThreadTopUpKeyPool, NULL);
1619 int64* pnSleepTime = new int64(params[1].get_int64());
1620 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1626 Value walletpassphrasechange(const Array& params, bool fHelp)
1628 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1629 throw runtime_error(
1630 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1631 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1634 if (!pwalletMain->IsCrypted())
1635 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1637 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1638 // Alternately, find a way to make params[0] mlock()'d to begin with.
1639 SecureString strOldWalletPass;
1640 strOldWalletPass.reserve(100);
1641 strOldWalletPass = params[0].get_str().c_str();
1643 SecureString strNewWalletPass;
1644 strNewWalletPass.reserve(100);
1645 strNewWalletPass = params[1].get_str().c_str();
1647 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1648 throw runtime_error(
1649 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1650 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1652 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1653 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1659 Value walletlock(const Array& params, bool fHelp)
1661 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1662 throw runtime_error(
1664 "Removes the wallet encryption key from memory, locking the wallet.\n"
1665 "After calling this method, you will need to call walletpassphrase again\n"
1666 "before being able to call any methods which require the wallet to be unlocked.");
1669 if (!pwalletMain->IsCrypted())
1670 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1673 LOCK(cs_nWalletUnlockTime);
1674 pwalletMain->Lock();
1675 nWalletUnlockTime = 0;
1682 Value encryptwallet(const Array& params, bool fHelp)
1684 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1685 throw runtime_error(
1686 "encryptwallet <passphrase>\n"
1687 "Encrypts the wallet with <passphrase>.");
1690 if (pwalletMain->IsCrypted())
1691 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1693 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1694 // Alternately, find a way to make params[0] mlock()'d to begin with.
1695 SecureString strWalletPass;
1696 strWalletPass.reserve(100);
1697 strWalletPass = params[0].get_str().c_str();
1699 if (strWalletPass.length() < 1)
1700 throw runtime_error(
1701 "encryptwallet <passphrase>\n"
1702 "Encrypts the wallet with <passphrase>.");
1704 if (!pwalletMain->EncryptWallet(strWalletPass))
1705 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1707 // BDB seems to have a bad habit of writing old data into
1708 // slack space in .dat files; that is bad if the old data is
1709 // unencrypted private keys. So:
1711 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1715 Value validateaddress(const Array& params, bool fHelp)
1717 if (fHelp || params.size() != 1)
1718 throw runtime_error(
1719 "validateaddress <bitcoinaddress>\n"
1720 "Return information about <bitcoinaddress>.");
1722 CBitcoinAddress address(params[0].get_str());
1723 bool isValid = address.IsValid();
1726 ret.push_back(Pair("isvalid", isValid));
1729 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1730 // version of the address:
1731 string currentAddress = address.ToString();
1732 ret.push_back(Pair("address", currentAddress));
1733 if (pwalletMain->HaveKey(address))
1735 ret.push_back(Pair("ismine", true));
1736 std::vector<unsigned char> vchPubKey;
1737 pwalletMain->GetPubKey(address, vchPubKey);
1738 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1740 key.SetPubKey(vchPubKey);
1741 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1743 else if (pwalletMain->HaveCScript(address.GetHash160()))
1745 ret.push_back(Pair("isscript", true));
1747 pwalletMain->GetCScript(address.GetHash160(), subscript);
1748 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1749 std::vector<CBitcoinAddress> addresses;
1750 txnouttype whichType;
1752 ExtractAddresses(subscript, whichType, addresses, nRequired);
1753 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1755 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1756 a.push_back(addr.ToString());
1757 ret.push_back(Pair("addresses", a));
1758 if (whichType == TX_MULTISIG)
1759 ret.push_back(Pair("sigsrequired", nRequired));
1762 ret.push_back(Pair("ismine", false));
1763 if (pwalletMain->mapAddressBook.count(address))
1764 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1769 Value getwork(const Array& params, bool fHelp)
1771 if (fHelp || params.size() > 1)
1772 throw runtime_error(
1774 "If [data] is not specified, returns formatted hash data to work on:\n"
1775 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1776 " \"data\" : block data\n"
1777 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1778 " \"target\" : little endian hash target\n"
1779 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1782 throw JSONRPCError(-9, "Bitcoin is not connected!");
1784 if (IsInitialBlockDownload())
1785 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1787 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1788 static mapNewBlock_t mapNewBlock;
1789 static vector<CBlock*> vNewBlock;
1790 static CReserveKey reservekey(pwalletMain);
1792 if (params.size() == 0)
1795 static unsigned int nTransactionsUpdatedLast;
1796 static CBlockIndex* pindexPrev;
1797 static int64 nStart;
1798 static CBlock* pblock;
1799 if (pindexPrev != pindexBest ||
1800 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1802 if (pindexPrev != pindexBest)
1804 // Deallocate old blocks since they're obsolete now
1805 mapNewBlock.clear();
1806 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1810 nTransactionsUpdatedLast = nTransactionsUpdated;
1811 pindexPrev = pindexBest;
1815 pblock = CreateNewBlock(reservekey);
1817 throw JSONRPCError(-7, "Out of memory");
1818 vNewBlock.push_back(pblock);
1822 pblock->UpdateTime(pindexPrev);
1825 // Update nExtraNonce
1826 static unsigned int nExtraNonce = 0;
1827 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1830 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1832 // Prebuild hash buffers
1836 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1838 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1841 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1842 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1843 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1844 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1850 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1851 if (vchData.size() != 128)
1852 throw JSONRPCError(-8, "Invalid parameter");
1853 CBlock* pdata = (CBlock*)&vchData[0];
1856 for (int i = 0; i < 128/4; i++)
1857 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1860 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1862 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1864 pblock->nTime = pdata->nTime;
1865 pblock->nNonce = pdata->nNonce;
1866 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1867 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1869 return CheckWork(pblock, *pwalletMain, reservekey);
1874 Value getmemorypool(const Array& params, bool fHelp)
1876 if (fHelp || params.size() > 1)
1877 throw runtime_error(
1878 "getmemorypool [data]\n"
1879 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1880 " \"version\" : block version\n"
1881 " \"previousblockhash\" : hash of current highest block\n"
1882 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1883 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1884 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1885 " \"time\" : timestamp appropriate for next block\n"
1886 " \"mintime\" : minimum timestamp appropriate for next block\n"
1887 " \"curtime\" : current timestamp\n"
1888 " \"bits\" : compressed target of next block\n"
1889 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1891 if (params.size() == 0)
1894 throw JSONRPCError(-9, "Bitcoin is not connected!");
1896 if (IsInitialBlockDownload())
1897 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1899 static CReserveKey reservekey(pwalletMain);
1902 static unsigned int nTransactionsUpdatedLast;
1903 static CBlockIndex* pindexPrev;
1904 static int64 nStart;
1905 static CBlock* pblock;
1906 if (pindexPrev != pindexBest ||
1907 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1909 nTransactionsUpdatedLast = nTransactionsUpdated;
1910 pindexPrev = pindexBest;
1916 pblock = CreateNewBlock(reservekey);
1918 throw JSONRPCError(-7, "Out of memory");
1922 pblock->UpdateTime(pindexPrev);
1926 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1930 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1933 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1937 result.push_back(Pair("version", pblock->nVersion));
1938 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1939 result.push_back(Pair("transactions", transactions));
1940 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1941 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1942 result.push_back(Pair("time", (int64_t)pblock->nTime));
1943 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1944 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1945 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1952 CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
1956 return ProcessBlock(NULL, &pblock);
1960 Value getblockhash(const Array& params, bool fHelp)
1962 if (fHelp || params.size() != 1)
1963 throw runtime_error(
1964 "getblockhash <index>\n"
1965 "Returns hash of block in best-block-chain at <index>.");
1967 int nHeight = params[0].get_int();
1968 if (nHeight < 0 || nHeight > nBestHeight)
1969 throw runtime_error("Block number out of range.");
1972 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1973 while (pblockindex->nHeight > nHeight)
1974 pblockindex = pblockindex->pprev;
1975 return pblockindex->phashBlock->GetHex();
1978 Value getblock(const Array& params, bool fHelp)
1980 if (fHelp || params.size() != 1)
1981 throw runtime_error(
1983 "Returns details of a block with given block-hash.");
1985 std::string strHash = params[0].get_str();
1986 uint256 hash(strHash);
1988 if (mapBlockIndex.count(hash) == 0)
1989 throw JSONRPCError(-5, "Block not found");
1992 CBlockIndex* pblockindex = mapBlockIndex[hash];
1993 block.ReadFromDisk(pblockindex, true);
1995 return blockToJSON(block, pblockindex);
2013 static const CRPCCommand vRPCCommands[] =
2014 { // name function safe mode?
2015 // ------------------------ ----------------------- ----------
2016 { "help", &help, true },
2017 { "stop", &stop, true },
2018 { "getblockcount", &getblockcount, true },
2019 { "getblocknumber", &getblocknumber, true },
2020 { "getconnectioncount", &getconnectioncount, true },
2021 { "getdifficulty", &getdifficulty, true },
2022 { "getgenerate", &getgenerate, true },
2023 { "setgenerate", &setgenerate, true },
2024 { "gethashespersec", &gethashespersec, true },
2025 { "getinfo", &getinfo, true },
2026 { "getmininginfo", &getmininginfo, true },
2027 { "getnewaddress", &getnewaddress, true },
2028 { "getaccountaddress", &getaccountaddress, true },
2029 { "setaccount", &setaccount, true },
2030 { "getaccount", &getaccount, false },
2031 { "getaddressesbyaccount", &getaddressesbyaccount, true },
2032 { "sendtoaddress", &sendtoaddress, false },
2033 { "getreceivedbyaddress", &getreceivedbyaddress, false },
2034 { "getreceivedbyaccount", &getreceivedbyaccount, false },
2035 { "listreceivedbyaddress", &listreceivedbyaddress, false },
2036 { "listreceivedbyaccount", &listreceivedbyaccount, false },
2037 { "backupwallet", &backupwallet, true },
2038 { "keypoolrefill", &keypoolrefill, true },
2039 { "walletpassphrase", &walletpassphrase, true },
2040 { "walletpassphrasechange", &walletpassphrasechange, false },
2041 { "walletlock", &walletlock, true },
2042 { "encryptwallet", &encryptwallet, false },
2043 { "validateaddress", &validateaddress, true },
2044 { "getbalance", &getbalance, false },
2045 { "move", &movecmd, false },
2046 { "sendfrom", &sendfrom, false },
2047 { "sendmany", &sendmany, false },
2048 { "addmultisigaddress", &addmultisigaddress, false },
2049 { "getblock", &getblock, false },
2050 { "getblockhash", &getblockhash, false },
2051 { "gettransaction", &gettransaction, false },
2052 { "listtransactions", &listtransactions, false },
2053 { "signmessage", &signmessage, false },
2054 { "verifymessage", &verifymessage, false },
2055 { "getwork", &getwork, true },
2056 { "listaccounts", &listaccounts, false },
2057 { "settxfee", &settxfee, false },
2058 { "getmemorypool", &getmemorypool, true },
2059 { "listsinceblock", &listsinceblock, false },
2060 { "dumpprivkey", &dumpprivkey, false },
2061 { "importprivkey", &importprivkey, false },
2064 CRPCTable::CRPCTable()
2067 for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
2069 const CRPCCommand *pcmd;
2071 pcmd = &vRPCCommands[vcidx];
2072 mapCommands[pcmd->name] = pcmd;
2076 const CRPCCommand *CRPCTable::operator[](string name) const
2078 map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
2079 if (it == mapCommands.end())
2081 return (*it).second;
2087 // This ain't Apache. We're just using HTTP header for the length field
2088 // and to be compatible with other JSON-RPC implementations.
2091 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2094 s << "POST / HTTP/1.1\r\n"
2095 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2096 << "Host: 127.0.0.1\r\n"
2097 << "Content-Type: application/json\r\n"
2098 << "Content-Length: " << strMsg.size() << "\r\n"
2099 << "Connection: close\r\n"
2100 << "Accept: application/json\r\n";
2101 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2102 s << item.first << ": " << item.second << "\r\n";
2103 s << "\r\n" << strMsg;
2108 string rfc1123Time()
2113 struct tm* now_gmt = gmtime(&now);
2114 string locale(setlocale(LC_TIME, NULL));
2115 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2116 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2117 setlocale(LC_TIME, locale.c_str());
2118 return string(buffer);
2121 static string HTTPReply(int nStatus, const string& strMsg)
2124 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2126 "Server: bitcoin-json-rpc/%s\r\n"
2127 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2128 "Content-Type: text/html\r\n"
2129 "Content-Length: 296\r\n"
2131 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2132 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2135 "<TITLE>Error</TITLE>\r\n"
2136 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2138 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2139 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2140 const char *cStatus;
2141 if (nStatus == 200) cStatus = "OK";
2142 else if (nStatus == 400) cStatus = "Bad Request";
2143 else if (nStatus == 403) cStatus = "Forbidden";
2144 else if (nStatus == 404) cStatus = "Not Found";
2145 else if (nStatus == 500) cStatus = "Internal Server Error";
2148 "HTTP/1.1 %d %s\r\n"
2150 "Connection: close\r\n"
2151 "Content-Length: %d\r\n"
2152 "Content-Type: application/json\r\n"
2153 "Server: bitcoin-json-rpc/%s\r\n"
2158 rfc1123Time().c_str(),
2160 FormatFullVersion().c_str(),
2164 int ReadHTTPStatus(std::basic_istream<char>& stream)
2167 getline(stream, str);
2168 vector<string> vWords;
2169 boost::split(vWords, str, boost::is_any_of(" "));
2170 if (vWords.size() < 2)
2172 return atoi(vWords[1].c_str());
2175 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2181 std::getline(stream, str);
2182 if (str.empty() || str == "\r")
2184 string::size_type nColon = str.find(":");
2185 if (nColon != string::npos)
2187 string strHeader = str.substr(0, nColon);
2188 boost::trim(strHeader);
2189 boost::to_lower(strHeader);
2190 string strValue = str.substr(nColon+1);
2191 boost::trim(strValue);
2192 mapHeadersRet[strHeader] = strValue;
2193 if (strHeader == "content-length")
2194 nLen = atoi(strValue.c_str());
2200 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2202 mapHeadersRet.clear();
2206 int nStatus = ReadHTTPStatus(stream);
2209 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2210 if (nLen < 0 || nLen > (int)MAX_SIZE)
2216 vector<char> vch(nLen);
2217 stream.read(&vch[0], nLen);
2218 strMessageRet = string(vch.begin(), vch.end());
2224 bool HTTPAuthorized(map<string, string>& mapHeaders)
2226 string strAuth = mapHeaders["authorization"];
2227 if (strAuth.substr(0,6) != "Basic ")
2229 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2230 string strUserPass = DecodeBase64(strUserPass64);
2231 return strUserPass == strRPCUserColonPass;
2235 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2236 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2237 // unspecified (HTTP errors and contents of 'error').
2239 // 1.0 spec: http://json-rpc.org/wiki/specification
2240 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2241 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2244 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2247 request.push_back(Pair("method", strMethod));
2248 request.push_back(Pair("params", params));
2249 request.push_back(Pair("id", id));
2250 return write_string(Value(request), false) + "\n";
2253 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2256 if (error.type() != null_type)
2257 reply.push_back(Pair("result", Value::null));
2259 reply.push_back(Pair("result", result));
2260 reply.push_back(Pair("error", error));
2261 reply.push_back(Pair("id", id));
2262 return write_string(Value(reply), false) + "\n";
2265 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2267 // Send error reply from json-rpc error object
2269 int code = find_value(objError, "code").get_int();
2270 if (code == -32600) nStatus = 400;
2271 else if (code == -32601) nStatus = 404;
2272 string strReply = JSONRPCReply(Value::null, objError, id);
2273 stream << HTTPReply(nStatus, strReply) << std::flush;
2276 bool ClientAllowed(const string& strAddress)
2278 if (strAddress == asio::ip::address_v4::loopback().to_string())
2280 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2281 BOOST_FOREACH(string strAllow, vAllow)
2282 if (WildcardMatch(strAddress, strAllow))
2288 // IOStream device that speaks SSL but can also speak non-SSL
2290 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2292 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2294 fUseSSL = fUseSSLIn;
2295 fNeedHandshake = fUseSSLIn;
2298 void handshake(ssl::stream_base::handshake_type role)
2300 if (!fNeedHandshake) return;
2301 fNeedHandshake = false;
2302 stream.handshake(role);
2304 std::streamsize read(char* s, std::streamsize n)
2306 handshake(ssl::stream_base::server); // HTTPS servers read first
2307 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2308 return stream.next_layer().read_some(asio::buffer(s, n));
2310 std::streamsize write(const char* s, std::streamsize n)
2312 handshake(ssl::stream_base::client); // HTTPS clients write first
2313 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2314 return asio::write(stream.next_layer(), asio::buffer(s, n));
2316 bool connect(const std::string& server, const std::string& port)
2318 ip::tcp::resolver resolver(stream.get_io_service());
2319 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2320 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2321 ip::tcp::resolver::iterator end;
2322 boost::system::error_code error = asio::error::host_not_found;
2323 while (error && endpoint_iterator != end)
2325 stream.lowest_layer().close();
2326 stream.lowest_layer().connect(*endpoint_iterator++, error);
2334 bool fNeedHandshake;
2339 void ThreadRPCServer(void* parg)
2341 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2344 vnThreadsRunning[THREAD_RPCSERVER]++;
2345 ThreadRPCServer2(parg);
2346 vnThreadsRunning[THREAD_RPCSERVER]--;
2348 catch (std::exception& e) {
2349 vnThreadsRunning[THREAD_RPCSERVER]--;
2350 PrintException(&e, "ThreadRPCServer()");
2352 vnThreadsRunning[THREAD_RPCSERVER]--;
2353 PrintException(NULL, "ThreadRPCServer()");
2355 printf("ThreadRPCServer exiting\n");
2358 void ThreadRPCServer2(void* parg)
2360 printf("ThreadRPCServer started\n");
2362 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2363 if (mapArgs["-rpcpassword"] == "")
2365 unsigned char rand_pwd[32];
2366 RAND_bytes(rand_pwd, 32);
2367 string strWhatAmI = "To use bitcoind";
2368 if (mapArgs.count("-server"))
2369 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2370 else if (mapArgs.count("-daemon"))
2371 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2372 ThreadSafeMessageBox(strprintf(
2373 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2374 "It is recommended you use the following random password:\n"
2375 "rpcuser=bitcoinrpc\n"
2377 "(you do not need to remember this password)\n"
2378 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2380 GetConfigFile().string().c_str(),
2381 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2382 _("Error"), wxOK | wxMODAL);
2387 bool fUseSSL = GetBoolArg("-rpcssl");
2388 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2390 asio::io_service io_service;
2391 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2392 ip::tcp::acceptor acceptor(io_service);
2395 acceptor.open(endpoint.protocol());
2396 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2397 acceptor.bind(endpoint);
2398 acceptor.listen(socket_base::max_connections);
2400 catch(boost::system::system_error &e)
2402 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2403 _("Error"), wxOK | wxMODAL);
2408 ssl::context context(io_service, ssl::context::sslv23);
2411 context.set_options(ssl::context::no_sslv2);
2413 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2414 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2415 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2416 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2418 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2419 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2420 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2421 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2423 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2424 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2429 // Accept connection
2430 SSLStream sslStream(io_service, context);
2431 SSLIOStreamDevice d(sslStream, fUseSSL);
2432 iostreams::stream<SSLIOStreamDevice> stream(d);
2434 ip::tcp::endpoint peer;
2435 vnThreadsRunning[THREAD_RPCSERVER]--;
2436 acceptor.accept(sslStream.lowest_layer(), peer);
2437 vnThreadsRunning[4]++;
2441 // Restrict callers by IP
2442 if (!ClientAllowed(peer.address().to_string()))
2444 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2446 stream << HTTPReply(403, "") << std::flush;
2450 map<string, string> mapHeaders;
2453 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2454 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2457 printf("ThreadRPCServer ReadHTTP timeout\n");
2461 // Check authorization
2462 if (mapHeaders.count("authorization") == 0)
2464 stream << HTTPReply(401, "") << std::flush;
2467 if (!HTTPAuthorized(mapHeaders))
2469 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2470 /* Deter brute-forcing short passwords.
2471 If this results in a DOS the user really
2472 shouldn't have their RPC port exposed.*/
2473 if (mapArgs["-rpcpassword"].size() < 20)
2476 stream << HTTPReply(401, "") << std::flush;
2480 Value id = Value::null;
2485 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2486 throw JSONRPCError(-32700, "Parse error");
2487 const Object& request = valRequest.get_obj();
2489 // Parse id now so errors from here on will have the id
2490 id = find_value(request, "id");
2493 Value valMethod = find_value(request, "method");
2494 if (valMethod.type() == null_type)
2495 throw JSONRPCError(-32600, "Missing method");
2496 if (valMethod.type() != str_type)
2497 throw JSONRPCError(-32600, "Method must be a string");
2498 string strMethod = valMethod.get_str();
2499 if (strMethod != "getwork" && strMethod != "getmemorypool")
2500 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2503 Value valParams = find_value(request, "params");
2505 if (valParams.type() == array_type)
2506 params = valParams.get_array();
2507 else if (valParams.type() == null_type)
2510 throw JSONRPCError(-32600, "Params must be an array");
2513 const CRPCCommand *pcmd = tableRPC[strMethod];
2515 throw JSONRPCError(-32601, "Method not found");
2517 // Observe safe mode
2518 string strWarning = GetWarnings("rpc");
2519 if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
2521 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2528 LOCK2(cs_main, pwalletMain->cs_wallet);
2529 result = pcmd->actor(params, false);
2533 string strReply = JSONRPCReply(result, Value::null, id);
2534 stream << HTTPReply(200, strReply) << std::flush;
2536 catch (std::exception& e)
2538 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2541 catch (Object& objError)
2543 ErrorReply(stream, objError, id);
2545 catch (std::exception& e)
2547 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2555 Object CallRPC(const string& strMethod, const Array& params)
2557 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2558 throw runtime_error(strprintf(
2559 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2560 "If the file does not exist, create it with owner-readable-only file permissions."),
2561 GetConfigFile().string().c_str()));
2563 // Connect to localhost
2564 bool fUseSSL = GetBoolArg("-rpcssl");
2565 asio::io_service io_service;
2566 ssl::context context(io_service, ssl::context::sslv23);
2567 context.set_options(ssl::context::no_sslv2);
2568 SSLStream sslStream(io_service, context);
2569 SSLIOStreamDevice d(sslStream, fUseSSL);
2570 iostreams::stream<SSLIOStreamDevice> stream(d);
2571 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2572 throw runtime_error("couldn't connect to server");
2574 // HTTP basic authentication
2575 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2576 map<string, string> mapRequestHeaders;
2577 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2580 string strRequest = JSONRPCRequest(strMethod, params, 1);
2581 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2582 stream << strPost << std::flush;
2585 map<string, string> mapHeaders;
2587 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2589 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2590 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2591 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2592 else if (strReply.empty())
2593 throw runtime_error("no response from server");
2597 if (!read_string(strReply, valReply))
2598 throw runtime_error("couldn't parse reply from server");
2599 const Object& reply = valReply.get_obj();
2601 throw runtime_error("expected reply to have result, error and id properties");
2609 template<typename T>
2610 void ConvertTo(Value& value)
2612 if (value.type() == str_type)
2614 // reinterpret string as unquoted json value
2616 if (!read_string(value.get_str(), value2))
2617 throw runtime_error("type mismatch");
2618 value = value2.get_value<T>();
2622 value = value.get_value<T>();
2626 int CommandLineRPC(int argc, char *argv[])
2633 while (argc > 1 && IsSwitchChar(argv[1][0]))
2641 throw runtime_error("too few parameters");
2642 string strMethod = argv[1];
2644 // Parameters default to strings
2646 for (int i = 2; i < argc; i++)
2647 params.push_back(argv[i]);
2648 int n = params.size();
2651 // Special case non-string parameter types
2653 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2654 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2655 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2656 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2657 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2658 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2661 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2662 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2663 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2664 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2665 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2666 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2667 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2668 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2669 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2670 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2671 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2672 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2673 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674 if (strMethod == "sendmany" && n > 1)
2676 string s = params[1].get_str();
2678 if (!read_string(s, v) || v.type() != obj_type)
2679 throw runtime_error("type mismatch");
2680 params[1] = v.get_obj();
2682 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2683 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2684 if (strMethod == "addmultisigaddress" && n > 1)
2686 string s = params[1].get_str();
2688 if (!read_string(s, v) || v.type() != array_type)
2689 throw runtime_error("type mismatch "+s);
2690 params[1] = v.get_array();
2694 Object reply = CallRPC(strMethod, params);
2697 const Value& result = find_value(reply, "result");
2698 const Value& error = find_value(reply, "error");
2700 if (error.type() != null_type)
2703 strPrint = "error: " + write_string(error, false);
2704 int code = find_value(error.get_obj(), "code").get_int();
2710 if (result.type() == null_type)
2712 else if (result.type() == str_type)
2713 strPrint = result.get_str();
2715 strPrint = write_string(result, true);
2718 catch (std::exception& e)
2720 strPrint = string("error: ") + e.what();
2725 PrintException(NULL, "CommandLineRPC()");
2730 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2739 int main(int argc, char *argv[])
2742 // Turn off microsoft heap dump noise
2743 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2744 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2746 setbuf(stdin, NULL);
2747 setbuf(stdout, NULL);
2748 setbuf(stderr, NULL);
2752 if (argc >= 2 && string(argv[1]) == "-server")
2754 printf("server ready\n");
2755 ThreadRPCServer(NULL);
2759 return CommandLineRPC(argc, argv);
2762 catch (std::exception& e) {
2763 PrintException(&e, "main()");
2765 PrintException(NULL, "main()");
2771 const CRPCTable tableRPC;