1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
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);
844 int64 nNow = GetAdjustedTime();
847 CAccountingEntry debit;
848 debit.strAccount = strFrom;
849 debit.nCreditDebit = -nAmount;
851 debit.strOtherAccount = strTo;
852 debit.strComment = strComment;
853 walletdb.WriteAccountingEntry(debit);
856 CAccountingEntry credit;
857 credit.strAccount = strTo;
858 credit.nCreditDebit = nAmount;
860 credit.strOtherAccount = strFrom;
861 credit.strComment = strComment;
862 walletdb.WriteAccountingEntry(credit);
864 walletdb.TxnCommit();
870 Value sendfrom(const Array& params, bool fHelp)
872 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
874 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
875 "<amount> is a real and is rounded to the nearest 0.00000001\n"
876 "requires wallet passphrase to be set with walletpassphrase first");
877 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
879 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
880 "<amount> is a real and is rounded to the nearest 0.00000001");
882 string strAccount = AccountFromValue(params[0]);
883 CBitcoinAddress address(params[1].get_str());
884 if (!address.IsValid())
885 throw JSONRPCError(-5, "Invalid bitcoin address");
886 int64 nAmount = AmountFromValue(params[2]);
888 if (params.size() > 3)
889 nMinDepth = params[3].get_int();
892 wtx.strFromAccount = strAccount;
893 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
894 wtx.mapValue["comment"] = params[4].get_str();
895 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
896 wtx.mapValue["to"] = params[5].get_str();
898 if (pwalletMain->IsLocked())
899 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
902 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
903 if (nAmount > nBalance)
904 throw JSONRPCError(-6, "Account has insufficient funds");
907 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
909 throw JSONRPCError(-4, strError);
911 return wtx.GetHash().GetHex();
915 Value sendmany(const Array& params, bool fHelp)
917 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
919 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
920 "amounts are double-precision floating point numbers\n"
921 "requires wallet passphrase to be set with walletpassphrase first");
922 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
924 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
925 "amounts are double-precision floating point numbers");
927 string strAccount = AccountFromValue(params[0]);
928 Object sendTo = params[1].get_obj();
930 if (params.size() > 2)
931 nMinDepth = params[2].get_int();
934 wtx.strFromAccount = strAccount;
935 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
936 wtx.mapValue["comment"] = params[3].get_str();
938 set<CBitcoinAddress> setAddress;
939 vector<pair<CScript, int64> > vecSend;
941 int64 totalAmount = 0;
942 BOOST_FOREACH(const Pair& s, sendTo)
944 CBitcoinAddress address(s.name_);
945 if (!address.IsValid())
946 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
948 if (setAddress.count(address))
949 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
950 setAddress.insert(address);
952 CScript scriptPubKey;
953 scriptPubKey.SetBitcoinAddress(address);
954 int64 nAmount = AmountFromValue(s.value_);
955 totalAmount += nAmount;
957 vecSend.push_back(make_pair(scriptPubKey, nAmount));
960 if (pwalletMain->IsLocked())
961 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
964 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
965 if (totalAmount > nBalance)
966 throw JSONRPCError(-6, "Account has insufficient funds");
969 CReserveKey keyChange(pwalletMain);
970 int64 nFeeRequired = 0;
971 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
974 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
975 throw JSONRPCError(-6, "Insufficient funds");
976 throw JSONRPCError(-4, "Transaction creation failed");
978 if (!pwalletMain->CommitTransaction(wtx, keyChange))
979 throw JSONRPCError(-4, "Transaction commit failed");
981 return wtx.GetHash().GetHex();
984 Value addmultisigaddress(const Array& params, bool fHelp)
986 if (fHelp || params.size() < 2 || params.size() > 3)
988 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
989 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
990 "each key is a bitcoin address or hex-encoded public key\n"
991 "If [account] is specified, assign address to [account].";
992 throw runtime_error(msg);
995 int nRequired = params[0].get_int();
996 const Array& keys = params[1].get_array();
998 if (params.size() > 2)
999 strAccount = AccountFromValue(params[2]);
1001 // Gather public keys
1002 if (nRequired < 1 || keys.size() < nRequired)
1003 throw runtime_error(
1004 strprintf("wrong number of keys"
1005 "(got %d, need at least %d)", keys.size(), nRequired));
1006 std::vector<CKey> pubkeys;
1007 pubkeys.resize(keys.size());
1008 for (unsigned int i = 0; i < keys.size(); i++)
1010 const std::string& ks = keys[i].get_str();
1012 // Case 1: bitcoin address and we have full public key:
1013 CBitcoinAddress address(ks);
1014 if (address.IsValid())
1016 if (address.IsScript())
1017 throw runtime_error(
1018 strprintf("%s is a pay-to-script address",ks.c_str()));
1019 std::vector<unsigned char> vchPubKey;
1020 if (!pwalletMain->GetPubKey(address, vchPubKey))
1021 throw runtime_error(
1022 strprintf("no full public key for address %s",ks.c_str()));
1023 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1024 throw runtime_error(" Invalid public key: "+ks);
1027 // Case 2: hex public key
1030 vector<unsigned char> vchPubKey = ParseHex(ks);
1031 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1032 throw runtime_error(" Invalid public key: "+ks);
1036 throw runtime_error(" Invalid public key: "+ks);
1040 // Construct using pay-to-script-hash:
1042 inner.SetMultisig(nRequired, pubkeys);
1044 uint160 scriptHash = Hash160(inner);
1045 CScript scriptPubKey;
1046 scriptPubKey.SetPayToScriptHash(inner);
1047 pwalletMain->AddCScript(inner);
1048 CBitcoinAddress address;
1049 address.SetScriptHash160(scriptHash);
1051 pwalletMain->SetAddressBookName(address, strAccount);
1052 return address.ToString();
1063 nConf = std::numeric_limits<int>::max();
1067 Value ListReceived(const Array& params, bool fByAccounts)
1069 // Minimum confirmations
1071 if (params.size() > 0)
1072 nMinDepth = params[0].get_int();
1074 // Whether to include empty accounts
1075 bool fIncludeEmpty = false;
1076 if (params.size() > 1)
1077 fIncludeEmpty = params[1].get_bool();
1080 map<CBitcoinAddress, tallyitem> mapTally;
1081 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1083 const CWalletTx& wtx = (*it).second;
1085 if (wtx.IsCoinBase() || !wtx.IsFinal())
1088 int nDepth = wtx.GetDepthInMainChain();
1089 if (nDepth < nMinDepth)
1092 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1094 CBitcoinAddress address;
1095 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1098 tallyitem& item = mapTally[address];
1099 item.nAmount += txout.nValue;
1100 item.nConf = min(item.nConf, nDepth);
1106 map<string, tallyitem> mapAccountTally;
1107 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1109 const CBitcoinAddress& address = item.first;
1110 const string& strAccount = item.second;
1111 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1112 if (it == mapTally.end() && !fIncludeEmpty)
1116 int nConf = std::numeric_limits<int>::max();
1117 if (it != mapTally.end())
1119 nAmount = (*it).second.nAmount;
1120 nConf = (*it).second.nConf;
1125 tallyitem& item = mapAccountTally[strAccount];
1126 item.nAmount += nAmount;
1127 item.nConf = min(item.nConf, nConf);
1132 obj.push_back(Pair("address", address.ToString()));
1133 obj.push_back(Pair("account", strAccount));
1134 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1135 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1142 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1144 int64 nAmount = (*it).second.nAmount;
1145 int nConf = (*it).second.nConf;
1147 obj.push_back(Pair("account", (*it).first));
1148 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1149 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1157 Value listreceivedbyaddress(const Array& params, bool fHelp)
1159 if (fHelp || params.size() > 2)
1160 throw runtime_error(
1161 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1162 "[minconf] is the minimum number of confirmations before payments are included.\n"
1163 "[includeempty] whether to include addresses that haven't received any payments.\n"
1164 "Returns an array of objects containing:\n"
1165 " \"address\" : receiving address\n"
1166 " \"account\" : the account of the receiving address\n"
1167 " \"amount\" : total amount received by the address\n"
1168 " \"confirmations\" : number of confirmations of the most recent transaction included");
1170 return ListReceived(params, false);
1173 Value listreceivedbyaccount(const Array& params, bool fHelp)
1175 if (fHelp || params.size() > 2)
1176 throw runtime_error(
1177 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1178 "[minconf] is the minimum number of confirmations before payments are included.\n"
1179 "[includeempty] whether to include accounts that haven't received any payments.\n"
1180 "Returns an array of objects containing:\n"
1181 " \"account\" : the account of the receiving addresses\n"
1182 " \"amount\" : total amount received by addresses with this account\n"
1183 " \"confirmations\" : number of confirmations of the most recent transaction included");
1185 return ListReceived(params, true);
1188 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1190 int64 nGeneratedImmature, nGeneratedMature, nFee;
1191 string strSentAccount;
1192 list<pair<CBitcoinAddress, int64> > listReceived;
1193 list<pair<CBitcoinAddress, int64> > listSent;
1195 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1197 bool fAllAccounts = (strAccount == string("*"));
1199 // Generated blocks assigned to account ""
1200 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1203 entry.push_back(Pair("account", string("")));
1204 if (nGeneratedImmature)
1206 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1207 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1211 entry.push_back(Pair("category", "generate"));
1212 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1215 WalletTxToJSON(wtx, entry);
1216 ret.push_back(entry);
1220 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1222 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1225 entry.push_back(Pair("account", strSentAccount));
1226 entry.push_back(Pair("address", s.first.ToString()));
1227 entry.push_back(Pair("category", "send"));
1228 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1229 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1231 WalletTxToJSON(wtx, entry);
1232 ret.push_back(entry);
1237 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1239 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1242 if (pwalletMain->mapAddressBook.count(r.first))
1243 account = pwalletMain->mapAddressBook[r.first];
1244 if (fAllAccounts || (account == strAccount))
1247 entry.push_back(Pair("account", account));
1248 entry.push_back(Pair("address", r.first.ToString()));
1249 entry.push_back(Pair("category", "receive"));
1250 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1252 WalletTxToJSON(wtx, entry);
1253 ret.push_back(entry);
1259 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1261 bool fAllAccounts = (strAccount == string("*"));
1263 if (fAllAccounts || acentry.strAccount == strAccount)
1266 entry.push_back(Pair("account", acentry.strAccount));
1267 entry.push_back(Pair("category", "move"));
1268 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1269 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1270 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1271 entry.push_back(Pair("comment", acentry.strComment));
1272 ret.push_back(entry);
1276 Value listtransactions(const Array& params, bool fHelp)
1278 if (fHelp || params.size() > 3)
1279 throw runtime_error(
1280 "listtransactions [account] [count=10] [from=0]\n"
1281 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1283 string strAccount = "*";
1284 if (params.size() > 0)
1285 strAccount = params[0].get_str();
1287 if (params.size() > 1)
1288 nCount = params[1].get_int();
1290 if (params.size() > 2)
1291 nFrom = params[2].get_int();
1294 throw JSONRPCError(-8, "Negative count");
1296 throw JSONRPCError(-8, "Negative from");
1299 CWalletDB walletdb(pwalletMain->strWalletFile);
1301 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1302 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1303 typedef multimap<int64, TxPair > TxItems;
1306 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1307 // would make this much faster for applications that do this a lot.
1308 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1310 CWalletTx* wtx = &((*it).second);
1311 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1313 list<CAccountingEntry> acentries;
1314 walletdb.ListAccountCreditDebit(strAccount, acentries);
1315 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1317 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1320 // iterate backwards until we have nCount items to return:
1321 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1323 CWalletTx *const pwtx = (*it).second.first;
1325 ListTransactions(*pwtx, strAccount, 0, true, ret);
1326 CAccountingEntry *const pacentry = (*it).second.second;
1328 AcentryToJSON(*pacentry, strAccount, ret);
1330 if (ret.size() >= (nCount+nFrom)) break;
1332 // ret is newest to oldest
1334 if (nFrom > ret.size()) nFrom = ret.size();
1335 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1336 Array::iterator first = ret.begin();
1337 std::advance(first, nFrom);
1338 Array::iterator last = ret.begin();
1339 std::advance(last, nFrom+nCount);
1341 if (last != ret.end()) ret.erase(last, ret.end());
1342 if (first != ret.begin()) ret.erase(ret.begin(), first);
1344 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1349 Value listaccounts(const Array& params, bool fHelp)
1351 if (fHelp || params.size() > 1)
1352 throw runtime_error(
1353 "listaccounts [minconf=1]\n"
1354 "Returns Object that has account names as keys, account balances as values.");
1357 if (params.size() > 0)
1358 nMinDepth = params[0].get_int();
1360 map<string, int64> mapAccountBalances;
1361 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1362 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1363 mapAccountBalances[entry.second] = 0;
1366 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1368 const CWalletTx& wtx = (*it).second;
1369 int64 nGeneratedImmature, nGeneratedMature, nFee;
1370 string strSentAccount;
1371 list<pair<CBitcoinAddress, int64> > listReceived;
1372 list<pair<CBitcoinAddress, int64> > listSent;
1373 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1374 mapAccountBalances[strSentAccount] -= nFee;
1375 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1376 mapAccountBalances[strSentAccount] -= s.second;
1377 if (wtx.GetDepthInMainChain() >= nMinDepth)
1379 mapAccountBalances[""] += nGeneratedMature;
1380 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1381 if (pwalletMain->mapAddressBook.count(r.first))
1382 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1384 mapAccountBalances[""] += r.second;
1388 list<CAccountingEntry> acentries;
1389 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1390 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1391 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1394 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1395 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1400 Value listsinceblock(const Array& params, bool fHelp)
1403 throw runtime_error(
1404 "listsinceblock [blockid] [target-confirmations]\n"
1405 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1407 CBlockIndex *pindex = NULL;
1408 int target_confirms = 1;
1410 if (params.size() > 0)
1412 uint256 blockId = 0;
1414 blockId.SetHex(params[0].get_str());
1415 pindex = CBlockLocator(blockId).GetBlockIndex();
1418 if (params.size() > 1)
1420 target_confirms = params[1].get_int();
1422 if (target_confirms < 1)
1423 throw JSONRPCError(-8, "Invalid parameter");
1426 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1430 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1432 CWalletTx tx = (*it).second;
1434 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1435 ListTransactions(tx, "*", 0, true, transactions);
1440 if (target_confirms == 1)
1443 lastblock = hashBestChain;
1447 int target_height = pindexBest->nHeight + 1 - target_confirms;
1450 for (block = pindexBest;
1451 block && block->nHeight > target_height;
1452 block = block->pprev) { }
1454 lastblock = block ? block->GetBlockHash() : 0;
1458 ret.push_back(Pair("transactions", transactions));
1459 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1464 Value gettransaction(const Array& params, bool fHelp)
1466 if (fHelp || params.size() != 1)
1467 throw runtime_error(
1468 "gettransaction <txid>\n"
1469 "Get detailed information about <txid>");
1472 hash.SetHex(params[0].get_str());
1476 if (!pwalletMain->mapWallet.count(hash))
1477 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1478 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1480 int64 nCredit = wtx.GetCredit();
1481 int64 nDebit = wtx.GetDebit();
1482 int64 nNet = nCredit - nDebit;
1483 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1485 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1487 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1489 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1492 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1493 entry.push_back(Pair("details", details));
1499 Value backupwallet(const Array& params, bool fHelp)
1501 if (fHelp || params.size() != 1)
1502 throw runtime_error(
1503 "backupwallet <destination>\n"
1504 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1506 string strDest = params[0].get_str();
1507 BackupWallet(*pwalletMain, strDest);
1513 Value keypoolrefill(const Array& params, bool fHelp)
1515 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1516 throw runtime_error(
1518 "Fills the keypool, requires wallet passphrase to be set.");
1519 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1520 throw runtime_error(
1522 "Fills the keypool.");
1524 if (pwalletMain->IsLocked())
1525 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1527 pwalletMain->TopUpKeyPool();
1529 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1530 throw JSONRPCError(-4, "Error refreshing keypool.");
1536 void ThreadTopUpKeyPool(void* parg)
1538 pwalletMain->TopUpKeyPool();
1541 void ThreadCleanWalletPassphrase(void* parg)
1543 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1545 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1547 if (nWalletUnlockTime == 0)
1549 nWalletUnlockTime = nMyWakeTime;
1553 if (nWalletUnlockTime==0)
1555 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1559 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1561 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1565 if (nWalletUnlockTime)
1567 nWalletUnlockTime = 0;
1568 pwalletMain->Lock();
1573 if (nWalletUnlockTime < nMyWakeTime)
1574 nWalletUnlockTime = nMyWakeTime;
1577 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1579 delete (int64*)parg;
1582 Value walletpassphrase(const Array& params, bool fHelp)
1584 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1585 throw runtime_error(
1586 "walletpassphrase <passphrase> <timeout>\n"
1587 "Stores the wallet decryption key in memory for <timeout> seconds.");
1590 if (!pwalletMain->IsCrypted())
1591 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1593 if (!pwalletMain->IsLocked())
1594 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1596 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1597 SecureString strWalletPass;
1598 strWalletPass.reserve(100);
1599 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1600 // Alternately, find a way to make params[0] mlock()'d to begin with.
1601 strWalletPass = params[0].get_str().c_str();
1603 if (strWalletPass.length() > 0)
1605 if (!pwalletMain->Unlock(strWalletPass))
1606 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1609 throw runtime_error(
1610 "walletpassphrase <passphrase> <timeout>\n"
1611 "Stores the wallet decryption key in memory for <timeout> seconds.");
1613 CreateThread(ThreadTopUpKeyPool, NULL);
1614 int64* pnSleepTime = new int64(params[1].get_int64());
1615 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1621 Value walletpassphrasechange(const Array& params, bool fHelp)
1623 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1624 throw runtime_error(
1625 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1626 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1629 if (!pwalletMain->IsCrypted())
1630 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1632 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1633 // Alternately, find a way to make params[0] mlock()'d to begin with.
1634 SecureString strOldWalletPass;
1635 strOldWalletPass.reserve(100);
1636 strOldWalletPass = params[0].get_str().c_str();
1638 SecureString strNewWalletPass;
1639 strNewWalletPass.reserve(100);
1640 strNewWalletPass = params[1].get_str().c_str();
1642 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1643 throw runtime_error(
1644 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1645 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1647 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1648 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1654 Value walletlock(const Array& params, bool fHelp)
1656 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1657 throw runtime_error(
1659 "Removes the wallet encryption key from memory, locking the wallet.\n"
1660 "After calling this method, you will need to call walletpassphrase again\n"
1661 "before being able to call any methods which require the wallet to be unlocked.");
1664 if (!pwalletMain->IsCrypted())
1665 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1668 LOCK(cs_nWalletUnlockTime);
1669 pwalletMain->Lock();
1670 nWalletUnlockTime = 0;
1677 Value encryptwallet(const Array& params, bool fHelp)
1679 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1680 throw runtime_error(
1681 "encryptwallet <passphrase>\n"
1682 "Encrypts the wallet with <passphrase>.");
1685 if (pwalletMain->IsCrypted())
1686 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1688 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1689 // Alternately, find a way to make params[0] mlock()'d to begin with.
1690 SecureString strWalletPass;
1691 strWalletPass.reserve(100);
1692 strWalletPass = params[0].get_str().c_str();
1694 if (strWalletPass.length() < 1)
1695 throw runtime_error(
1696 "encryptwallet <passphrase>\n"
1697 "Encrypts the wallet with <passphrase>.");
1699 if (!pwalletMain->EncryptWallet(strWalletPass))
1700 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1702 // BDB seems to have a bad habit of writing old data into
1703 // slack space in .dat files; that is bad if the old data is
1704 // unencrypted private keys. So:
1706 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1710 Value validateaddress(const Array& params, bool fHelp)
1712 if (fHelp || params.size() != 1)
1713 throw runtime_error(
1714 "validateaddress <bitcoinaddress>\n"
1715 "Return information about <bitcoinaddress>.");
1717 CBitcoinAddress address(params[0].get_str());
1718 bool isValid = address.IsValid();
1721 ret.push_back(Pair("isvalid", isValid));
1724 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1725 // version of the address:
1726 string currentAddress = address.ToString();
1727 ret.push_back(Pair("address", currentAddress));
1728 if (pwalletMain->HaveKey(address))
1730 ret.push_back(Pair("ismine", true));
1731 std::vector<unsigned char> vchPubKey;
1732 pwalletMain->GetPubKey(address, vchPubKey);
1733 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1735 key.SetPubKey(vchPubKey);
1736 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1738 else if (pwalletMain->HaveCScript(address.GetHash160()))
1740 ret.push_back(Pair("isscript", true));
1742 pwalletMain->GetCScript(address.GetHash160(), subscript);
1743 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1744 std::vector<CBitcoinAddress> addresses;
1745 txnouttype whichType;
1747 ExtractAddresses(subscript, whichType, addresses, nRequired);
1748 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1750 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1751 a.push_back(addr.ToString());
1752 ret.push_back(Pair("addresses", a));
1753 if (whichType == TX_MULTISIG)
1754 ret.push_back(Pair("sigsrequired", nRequired));
1757 ret.push_back(Pair("ismine", false));
1758 if (pwalletMain->mapAddressBook.count(address))
1759 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1764 Value getwork(const Array& params, bool fHelp)
1766 if (fHelp || params.size() > 1)
1767 throw runtime_error(
1769 "If [data] is not specified, returns formatted hash data to work on:\n"
1770 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1771 " \"data\" : block data\n"
1772 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1773 " \"target\" : little endian hash target\n"
1774 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1777 throw JSONRPCError(-9, "Bitcoin is not connected!");
1779 if (IsInitialBlockDownload())
1780 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1782 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1783 static mapNewBlock_t mapNewBlock;
1784 static vector<CBlock*> vNewBlock;
1785 static CReserveKey reservekey(pwalletMain);
1787 if (params.size() == 0)
1790 static unsigned int nTransactionsUpdatedLast;
1791 static CBlockIndex* pindexPrev;
1792 static int64 nStart;
1793 static CBlock* pblock;
1794 if (pindexPrev != pindexBest ||
1795 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1797 if (pindexPrev != pindexBest)
1799 // Deallocate old blocks since they're obsolete now
1800 mapNewBlock.clear();
1801 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1805 nTransactionsUpdatedLast = nTransactionsUpdated;
1806 pindexPrev = pindexBest;
1810 pblock = CreateNewBlock(reservekey);
1812 throw JSONRPCError(-7, "Out of memory");
1813 vNewBlock.push_back(pblock);
1817 pblock->UpdateTime(pindexPrev);
1820 // Update nExtraNonce
1821 static unsigned int nExtraNonce = 0;
1822 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1825 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1827 // Prebuild hash buffers
1831 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1833 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1836 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1837 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1838 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1839 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1845 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1846 if (vchData.size() != 128)
1847 throw JSONRPCError(-8, "Invalid parameter");
1848 CBlock* pdata = (CBlock*)&vchData[0];
1851 for (int i = 0; i < 128/4; i++)
1852 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1855 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1857 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1859 pblock->nTime = pdata->nTime;
1860 pblock->nNonce = pdata->nNonce;
1861 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1862 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1864 return CheckWork(pblock, *pwalletMain, reservekey);
1869 Value getmemorypool(const Array& params, bool fHelp)
1871 if (fHelp || params.size() > 1)
1872 throw runtime_error(
1873 "getmemorypool [data]\n"
1874 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1875 " \"version\" : block version\n"
1876 " \"previousblockhash\" : hash of current highest block\n"
1877 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1878 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1879 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1880 " \"time\" : timestamp appropriate for next block\n"
1881 " \"mintime\" : minimum timestamp appropriate for next block\n"
1882 " \"curtime\" : current timestamp\n"
1883 " \"bits\" : compressed target of next block\n"
1884 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1886 if (params.size() == 0)
1889 throw JSONRPCError(-9, "Bitcoin is not connected!");
1891 if (IsInitialBlockDownload())
1892 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1894 static CReserveKey reservekey(pwalletMain);
1897 static unsigned int nTransactionsUpdatedLast;
1898 static CBlockIndex* pindexPrev;
1899 static int64 nStart;
1900 static CBlock* pblock;
1901 if (pindexPrev != pindexBest ||
1902 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1904 nTransactionsUpdatedLast = nTransactionsUpdated;
1905 pindexPrev = pindexBest;
1911 pblock = CreateNewBlock(reservekey);
1913 throw JSONRPCError(-7, "Out of memory");
1917 pblock->UpdateTime(pindexPrev);
1921 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1925 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1928 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1932 result.push_back(Pair("version", pblock->nVersion));
1933 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1934 result.push_back(Pair("transactions", transactions));
1935 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1936 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1937 result.push_back(Pair("time", (int64_t)pblock->nTime));
1938 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1939 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1940 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1947 CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
1951 return ProcessBlock(NULL, &pblock);
1955 Value getblockhash(const Array& params, bool fHelp)
1957 if (fHelp || params.size() != 1)
1958 throw runtime_error(
1959 "getblockhash <index>\n"
1960 "Returns hash of block in best-block-chain at <index>.");
1962 int nHeight = params[0].get_int();
1963 if (nHeight < 0 || nHeight > nBestHeight)
1964 throw runtime_error("Block number out of range.");
1967 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1968 while (pblockindex->nHeight > nHeight)
1969 pblockindex = pblockindex->pprev;
1970 return pblockindex->phashBlock->GetHex();
1973 Value getblock(const Array& params, bool fHelp)
1975 if (fHelp || params.size() != 1)
1976 throw runtime_error(
1978 "Returns details of a block with given block-hash.");
1980 std::string strHash = params[0].get_str();
1981 uint256 hash(strHash);
1983 if (mapBlockIndex.count(hash) == 0)
1984 throw JSONRPCError(-5, "Block not found");
1987 CBlockIndex* pblockindex = mapBlockIndex[hash];
1988 block.ReadFromDisk(pblockindex, true);
1990 return blockToJSON(block, pblockindex);
2008 static const CRPCCommand vRPCCommands[] =
2009 { // name function safe mode?
2010 // ------------------------ ----------------------- ----------
2011 { "help", &help, true },
2012 { "stop", &stop, true },
2013 { "getblockcount", &getblockcount, true },
2014 { "getblocknumber", &getblocknumber, true },
2015 { "getconnectioncount", &getconnectioncount, true },
2016 { "getdifficulty", &getdifficulty, true },
2017 { "getgenerate", &getgenerate, true },
2018 { "setgenerate", &setgenerate, true },
2019 { "gethashespersec", &gethashespersec, true },
2020 { "getinfo", &getinfo, true },
2021 { "getmininginfo", &getmininginfo, true },
2022 { "getnewaddress", &getnewaddress, true },
2023 { "getaccountaddress", &getaccountaddress, true },
2024 { "setaccount", &setaccount, true },
2025 { "getaccount", &getaccount, false },
2026 { "getaddressesbyaccount", &getaddressesbyaccount, true },
2027 { "sendtoaddress", &sendtoaddress, false },
2028 { "getreceivedbyaddress", &getreceivedbyaddress, false },
2029 { "getreceivedbyaccount", &getreceivedbyaccount, false },
2030 { "listreceivedbyaddress", &listreceivedbyaddress, false },
2031 { "listreceivedbyaccount", &listreceivedbyaccount, false },
2032 { "backupwallet", &backupwallet, true },
2033 { "keypoolrefill", &keypoolrefill, true },
2034 { "walletpassphrase", &walletpassphrase, true },
2035 { "walletpassphrasechange", &walletpassphrasechange, false },
2036 { "walletlock", &walletlock, true },
2037 { "encryptwallet", &encryptwallet, false },
2038 { "validateaddress", &validateaddress, true },
2039 { "getbalance", &getbalance, false },
2040 { "move", &movecmd, false },
2041 { "sendfrom", &sendfrom, false },
2042 { "sendmany", &sendmany, false },
2043 { "addmultisigaddress", &addmultisigaddress, false },
2044 { "getblock", &getblock, false },
2045 { "getblockhash", &getblockhash, false },
2046 { "gettransaction", &gettransaction, false },
2047 { "listtransactions", &listtransactions, false },
2048 { "signmessage", &signmessage, false },
2049 { "verifymessage", &verifymessage, false },
2050 { "getwork", &getwork, true },
2051 { "listaccounts", &listaccounts, false },
2052 { "settxfee", &settxfee, false },
2053 { "getmemorypool", &getmemorypool, true },
2054 { "listsinceblock", &listsinceblock, false },
2055 { "dumpprivkey", &dumpprivkey, false },
2056 { "importprivkey", &importprivkey, false },
2059 CRPCTable::CRPCTable()
2062 for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
2064 const CRPCCommand *pcmd;
2066 pcmd = &vRPCCommands[vcidx];
2067 mapCommands[pcmd->name] = pcmd;
2071 const CRPCCommand *CRPCTable::operator[](string name) const
2073 map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
2074 if (it == mapCommands.end())
2076 return (*it).second;
2082 // This ain't Apache. We're just using HTTP header for the length field
2083 // and to be compatible with other JSON-RPC implementations.
2086 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2089 s << "POST / HTTP/1.1\r\n"
2090 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2091 << "Host: 127.0.0.1\r\n"
2092 << "Content-Type: application/json\r\n"
2093 << "Content-Length: " << strMsg.size() << "\r\n"
2094 << "Connection: close\r\n"
2095 << "Accept: application/json\r\n";
2096 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2097 s << item.first << ": " << item.second << "\r\n";
2098 s << "\r\n" << strMsg;
2103 string rfc1123Time()
2108 struct tm* now_gmt = gmtime(&now);
2109 string locale(setlocale(LC_TIME, NULL));
2110 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2111 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2112 setlocale(LC_TIME, locale.c_str());
2113 return string(buffer);
2116 static string HTTPReply(int nStatus, const string& strMsg)
2119 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2121 "Server: bitcoin-json-rpc/%s\r\n"
2122 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2123 "Content-Type: text/html\r\n"
2124 "Content-Length: 296\r\n"
2126 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2127 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2130 "<TITLE>Error</TITLE>\r\n"
2131 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2133 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2134 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2135 const char *cStatus;
2136 if (nStatus == 200) cStatus = "OK";
2137 else if (nStatus == 400) cStatus = "Bad Request";
2138 else if (nStatus == 403) cStatus = "Forbidden";
2139 else if (nStatus == 404) cStatus = "Not Found";
2140 else if (nStatus == 500) cStatus = "Internal Server Error";
2143 "HTTP/1.1 %d %s\r\n"
2145 "Connection: close\r\n"
2146 "Content-Length: %d\r\n"
2147 "Content-Type: application/json\r\n"
2148 "Server: bitcoin-json-rpc/%s\r\n"
2153 rfc1123Time().c_str(),
2155 FormatFullVersion().c_str(),
2159 int ReadHTTPStatus(std::basic_istream<char>& stream)
2162 getline(stream, str);
2163 vector<string> vWords;
2164 boost::split(vWords, str, boost::is_any_of(" "));
2165 if (vWords.size() < 2)
2167 return atoi(vWords[1].c_str());
2170 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2176 std::getline(stream, str);
2177 if (str.empty() || str == "\r")
2179 string::size_type nColon = str.find(":");
2180 if (nColon != string::npos)
2182 string strHeader = str.substr(0, nColon);
2183 boost::trim(strHeader);
2184 boost::to_lower(strHeader);
2185 string strValue = str.substr(nColon+1);
2186 boost::trim(strValue);
2187 mapHeadersRet[strHeader] = strValue;
2188 if (strHeader == "content-length")
2189 nLen = atoi(strValue.c_str());
2195 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2197 mapHeadersRet.clear();
2201 int nStatus = ReadHTTPStatus(stream);
2204 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2205 if (nLen < 0 || nLen > MAX_SIZE)
2211 vector<char> vch(nLen);
2212 stream.read(&vch[0], nLen);
2213 strMessageRet = string(vch.begin(), vch.end());
2219 bool HTTPAuthorized(map<string, string>& mapHeaders)
2221 string strAuth = mapHeaders["authorization"];
2222 if (strAuth.substr(0,6) != "Basic ")
2224 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2225 string strUserPass = DecodeBase64(strUserPass64);
2226 return strUserPass == strRPCUserColonPass;
2230 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2231 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2232 // unspecified (HTTP errors and contents of 'error').
2234 // 1.0 spec: http://json-rpc.org/wiki/specification
2235 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2236 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2239 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2242 request.push_back(Pair("method", strMethod));
2243 request.push_back(Pair("params", params));
2244 request.push_back(Pair("id", id));
2245 return write_string(Value(request), false) + "\n";
2248 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2251 if (error.type() != null_type)
2252 reply.push_back(Pair("result", Value::null));
2254 reply.push_back(Pair("result", result));
2255 reply.push_back(Pair("error", error));
2256 reply.push_back(Pair("id", id));
2257 return write_string(Value(reply), false) + "\n";
2260 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2262 // Send error reply from json-rpc error object
2264 int code = find_value(objError, "code").get_int();
2265 if (code == -32600) nStatus = 400;
2266 else if (code == -32601) nStatus = 404;
2267 string strReply = JSONRPCReply(Value::null, objError, id);
2268 stream << HTTPReply(nStatus, strReply) << std::flush;
2271 bool ClientAllowed(const string& strAddress)
2273 if (strAddress == asio::ip::address_v4::loopback().to_string())
2275 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2276 BOOST_FOREACH(string strAllow, vAllow)
2277 if (WildcardMatch(strAddress, strAllow))
2283 // IOStream device that speaks SSL but can also speak non-SSL
2285 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2287 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2289 fUseSSL = fUseSSLIn;
2290 fNeedHandshake = fUseSSLIn;
2293 void handshake(ssl::stream_base::handshake_type role)
2295 if (!fNeedHandshake) return;
2296 fNeedHandshake = false;
2297 stream.handshake(role);
2299 std::streamsize read(char* s, std::streamsize n)
2301 handshake(ssl::stream_base::server); // HTTPS servers read first
2302 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2303 return stream.next_layer().read_some(asio::buffer(s, n));
2305 std::streamsize write(const char* s, std::streamsize n)
2307 handshake(ssl::stream_base::client); // HTTPS clients write first
2308 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2309 return asio::write(stream.next_layer(), asio::buffer(s, n));
2311 bool connect(const std::string& server, const std::string& port)
2313 ip::tcp::resolver resolver(stream.get_io_service());
2314 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2315 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2316 ip::tcp::resolver::iterator end;
2317 boost::system::error_code error = asio::error::host_not_found;
2318 while (error && endpoint_iterator != end)
2320 stream.lowest_layer().close();
2321 stream.lowest_layer().connect(*endpoint_iterator++, error);
2329 bool fNeedHandshake;
2334 void ThreadRPCServer(void* parg)
2336 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2339 vnThreadsRunning[THREAD_RPCSERVER]++;
2340 ThreadRPCServer2(parg);
2341 vnThreadsRunning[THREAD_RPCSERVER]--;
2343 catch (std::exception& e) {
2344 vnThreadsRunning[THREAD_RPCSERVER]--;
2345 PrintException(&e, "ThreadRPCServer()");
2347 vnThreadsRunning[THREAD_RPCSERVER]--;
2348 PrintException(NULL, "ThreadRPCServer()");
2350 printf("ThreadRPCServer exiting\n");
2353 void ThreadRPCServer2(void* parg)
2355 printf("ThreadRPCServer started\n");
2357 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2358 if (mapArgs["-rpcpassword"] == "")
2360 unsigned char rand_pwd[32];
2361 RAND_bytes(rand_pwd, 32);
2362 string strWhatAmI = "To use bitcoind";
2363 if (mapArgs.count("-server"))
2364 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2365 else if (mapArgs.count("-daemon"))
2366 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2367 ThreadSafeMessageBox(strprintf(
2368 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2369 "It is recommended you use the following random password:\n"
2370 "rpcuser=bitcoinrpc\n"
2372 "(you do not need to remember this password)\n"
2373 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2375 GetConfigFile().string().c_str(),
2376 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2377 _("Error"), wxOK | wxMODAL);
2382 bool fUseSSL = GetBoolArg("-rpcssl");
2383 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2385 asio::io_service io_service;
2386 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2387 ip::tcp::acceptor acceptor(io_service);
2390 acceptor.open(endpoint.protocol());
2391 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2392 acceptor.bind(endpoint);
2393 acceptor.listen(socket_base::max_connections);
2395 catch(boost::system::system_error &e)
2397 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2398 _("Error"), wxOK | wxMODAL);
2403 ssl::context context(io_service, ssl::context::sslv23);
2406 context.set_options(ssl::context::no_sslv2);
2408 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2409 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2410 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2411 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2413 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2414 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2415 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2416 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2418 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2419 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2424 // Accept connection
2425 SSLStream sslStream(io_service, context);
2426 SSLIOStreamDevice d(sslStream, fUseSSL);
2427 iostreams::stream<SSLIOStreamDevice> stream(d);
2429 ip::tcp::endpoint peer;
2430 vnThreadsRunning[THREAD_RPCSERVER]--;
2431 acceptor.accept(sslStream.lowest_layer(), peer);
2432 vnThreadsRunning[4]++;
2436 // Restrict callers by IP
2437 if (!ClientAllowed(peer.address().to_string()))
2439 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2441 stream << HTTPReply(403, "") << std::flush;
2445 map<string, string> mapHeaders;
2448 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2449 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2452 printf("ThreadRPCServer ReadHTTP timeout\n");
2456 // Check authorization
2457 if (mapHeaders.count("authorization") == 0)
2459 stream << HTTPReply(401, "") << std::flush;
2462 if (!HTTPAuthorized(mapHeaders))
2464 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2465 /* Deter brute-forcing short passwords.
2466 If this results in a DOS the user really
2467 shouldn't have their RPC port exposed.*/
2468 if (mapArgs["-rpcpassword"].size() < 20)
2471 stream << HTTPReply(401, "") << std::flush;
2475 Value id = Value::null;
2480 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2481 throw JSONRPCError(-32700, "Parse error");
2482 const Object& request = valRequest.get_obj();
2484 // Parse id now so errors from here on will have the id
2485 id = find_value(request, "id");
2488 Value valMethod = find_value(request, "method");
2489 if (valMethod.type() == null_type)
2490 throw JSONRPCError(-32600, "Missing method");
2491 if (valMethod.type() != str_type)
2492 throw JSONRPCError(-32600, "Method must be a string");
2493 string strMethod = valMethod.get_str();
2494 if (strMethod != "getwork" && strMethod != "getmemorypool")
2495 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2498 Value valParams = find_value(request, "params");
2500 if (valParams.type() == array_type)
2501 params = valParams.get_array();
2502 else if (valParams.type() == null_type)
2505 throw JSONRPCError(-32600, "Params must be an array");
2508 const CRPCCommand *pcmd = tableRPC[strMethod];
2510 throw JSONRPCError(-32601, "Method not found");
2512 // Observe safe mode
2513 string strWarning = GetWarnings("rpc");
2514 if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
2516 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2523 LOCK2(cs_main, pwalletMain->cs_wallet);
2524 result = pcmd->actor(params, false);
2528 string strReply = JSONRPCReply(result, Value::null, id);
2529 stream << HTTPReply(200, strReply) << std::flush;
2531 catch (std::exception& e)
2533 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2536 catch (Object& objError)
2538 ErrorReply(stream, objError, id);
2540 catch (std::exception& e)
2542 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2550 Object CallRPC(const string& strMethod, const Array& params)
2552 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2553 throw runtime_error(strprintf(
2554 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2555 "If the file does not exist, create it with owner-readable-only file permissions."),
2556 GetConfigFile().string().c_str()));
2558 // Connect to localhost
2559 bool fUseSSL = GetBoolArg("-rpcssl");
2560 asio::io_service io_service;
2561 ssl::context context(io_service, ssl::context::sslv23);
2562 context.set_options(ssl::context::no_sslv2);
2563 SSLStream sslStream(io_service, context);
2564 SSLIOStreamDevice d(sslStream, fUseSSL);
2565 iostreams::stream<SSLIOStreamDevice> stream(d);
2566 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2567 throw runtime_error("couldn't connect to server");
2569 // HTTP basic authentication
2570 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2571 map<string, string> mapRequestHeaders;
2572 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2575 string strRequest = JSONRPCRequest(strMethod, params, 1);
2576 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2577 stream << strPost << std::flush;
2580 map<string, string> mapHeaders;
2582 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2584 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2585 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2586 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2587 else if (strReply.empty())
2588 throw runtime_error("no response from server");
2592 if (!read_string(strReply, valReply))
2593 throw runtime_error("couldn't parse reply from server");
2594 const Object& reply = valReply.get_obj();
2596 throw runtime_error("expected reply to have result, error and id properties");
2604 template<typename T>
2605 void ConvertTo(Value& value)
2607 if (value.type() == str_type)
2609 // reinterpret string as unquoted json value
2611 if (!read_string(value.get_str(), value2))
2612 throw runtime_error("type mismatch");
2613 value = value2.get_value<T>();
2617 value = value.get_value<T>();
2621 int CommandLineRPC(int argc, char *argv[])
2628 while (argc > 1 && IsSwitchChar(argv[1][0]))
2636 throw runtime_error("too few parameters");
2637 string strMethod = argv[1];
2639 // Parameters default to strings
2641 for (int i = 2; i < argc; i++)
2642 params.push_back(argv[i]);
2643 int n = params.size();
2646 // Special case non-string parameter types
2648 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2649 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2650 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2651 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2652 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2654 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2655 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2656 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2657 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2658 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2661 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2662 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2663 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2664 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2666 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2669 if (strMethod == "sendmany" && n > 1)
2671 string s = params[1].get_str();
2673 if (!read_string(s, v) || v.type() != obj_type)
2674 throw runtime_error("type mismatch");
2675 params[1] = v.get_obj();
2677 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2678 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679 if (strMethod == "addmultisigaddress" && n > 1)
2681 string s = params[1].get_str();
2683 if (!read_string(s, v) || v.type() != array_type)
2684 throw runtime_error("type mismatch "+s);
2685 params[1] = v.get_array();
2689 Object reply = CallRPC(strMethod, params);
2692 const Value& result = find_value(reply, "result");
2693 const Value& error = find_value(reply, "error");
2695 if (error.type() != null_type)
2698 strPrint = "error: " + write_string(error, false);
2699 int code = find_value(error.get_obj(), "code").get_int();
2705 if (result.type() == null_type)
2707 else if (result.type() == str_type)
2708 strPrint = result.get_str();
2710 strPrint = write_string(result, true);
2713 catch (std::exception& e)
2715 strPrint = string("error: ") + e.what();
2720 PrintException(NULL, "CommandLineRPC()");
2725 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2734 int main(int argc, char *argv[])
2737 // Turn off microsoft heap dump noise
2738 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2739 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2741 setbuf(stdin, NULL);
2742 setbuf(stdout, NULL);
2743 setbuf(stderr, NULL);
2747 if (argc >= 2 && string(argv[1]) == "-server")
2749 printf("server ready\n");
2750 ThreadRPCServer(NULL);
2754 return CommandLineRPC(argc, argv);
2757 catch (std::exception& e) {
2758 PrintException(&e, "main()");
2760 PrintException(NULL, "main()");
2766 const CRPCTable tableRPC;