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"
15 #include <boost/asio.hpp>
16 #include <boost/filesystem.hpp>
17 #include <boost/iostreams/concepts.hpp>
18 #include <boost/iostreams/stream.hpp>
19 #include <boost/algorithm/string.hpp>
20 #include <boost/lexical_cast.hpp>
21 #include <boost/asio/ssl.hpp>
22 #include <boost/filesystem/fstream.hpp>
23 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
25 #include "json/json_spirit_reader_template.h"
26 #include "json/json_spirit_writer_template.h"
27 #include "json/json_spirit_utils.h"
28 #define printf OutputDebugStringF
29 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
30 // precompiled in headers.h. The problem might be when the pch file goes over
31 // a certain size around 145MB. If we need access to json_spirit outside this
32 // file, we could use the compiled json_spirit option.
35 using namespace boost;
36 using namespace boost::asio;
37 using namespace json_spirit;
39 void ThreadRPCServer2(void* parg);
40 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
50 extern map<string, CRPCCommand*> mapCommands;
52 static std::string strRPCUserColonPass;
54 static int64 nWalletUnlockTime;
55 static CCriticalSection cs_nWalletUnlockTime;
57 extern Value dumpprivkey(const Array& params, bool fHelp);
58 extern Value importprivkey(const Array& params, bool fHelp);
60 Object JSONRPCError(int code, const string& message)
63 error.push_back(Pair("code", code));
64 error.push_back(Pair("message", message));
68 double GetDifficulty(const CBlockIndex* blockindex = NULL)
70 // Floating point number that is a multiple of the minimum difficulty,
71 // minimum difficulty = 1.0.
72 if (blockindex == NULL)
74 if (pindexBest == NULL)
77 blockindex = pindexBest;
80 int nShift = (blockindex->nBits >> 24) & 0xff;
83 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
100 int64 AmountFromValue(const Value& value)
102 double dAmount = value.get_real();
103 if (dAmount <= 0.0 || dAmount > 21000000.0)
104 throw JSONRPCError(-3, "Invalid amount");
105 int64 nAmount = roundint64(dAmount * COIN);
106 if (!MoneyRange(nAmount))
107 throw JSONRPCError(-3, "Invalid amount");
111 Value ValueFromAmount(int64 amount)
113 return (double)amount / (double)COIN;
117 HexBits(unsigned int nBits)
123 uBits.nBits = htonl((int32_t)nBits);
124 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
127 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
129 int confirms = wtx.GetDepthInMainChain();
130 entry.push_back(Pair("confirmations", confirms));
133 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
134 entry.push_back(Pair("blockindex", wtx.nIndex));
136 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
137 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
138 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
139 entry.push_back(Pair(item.first, item.second));
142 string AccountFromValue(const Value& value)
144 string strAccount = value.get_str();
145 if (strAccount == "*")
146 throw JSONRPCError(-11, "Invalid account name");
150 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
153 result.push_back(Pair("hash", block.GetHash().GetHex()));
154 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
155 result.push_back(Pair("height", blockindex->nHeight));
156 result.push_back(Pair("version", block.nVersion));
157 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
158 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
159 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
160 result.push_back(Pair("bits", HexBits(block.nBits)));
161 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
163 BOOST_FOREACH (const CTransaction&tx, block.vtx)
164 txhashes.push_back(tx.GetHash().GetHex());
165 result.push_back(Pair("tx", txhashes));
167 if (blockindex->pprev)
168 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
169 if (blockindex->pnext)
170 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
177 /// Note: This interface may still be subject to change.
181 Value help(const Array& params, bool fHelp)
183 if (fHelp || params.size() > 1)
186 "List commands, or get help for a command.");
189 if (params.size() > 0)
190 strCommand = params[0].get_str();
193 set<rpcfn_type> setDone;
194 for (map<string, CRPCCommand*>::iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
196 CRPCCommand *pcmd = mi->second;
197 string strMethod = mi->first;
198 // We already filter duplicates, but these deprecated screw up the sort order
199 if (strMethod == "getamountreceived" ||
200 strMethod == "getallreceived" ||
201 strMethod == "getblocknumber" || // deprecated
202 (strMethod.find("label") != string::npos))
204 if (strCommand != "" && strMethod != strCommand)
209 rpcfn_type pfn = pcmd->actor;
210 if (setDone.insert(pfn).second)
211 (*pfn)(params, true);
213 catch (std::exception& e)
215 // Help text is returned in an exception
216 string strHelp = string(e.what());
217 if (strCommand == "")
218 if (strHelp.find('\n') != string::npos)
219 strHelp = strHelp.substr(0, strHelp.find('\n'));
220 strRet += strHelp + "\n";
224 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
225 strRet = strRet.substr(0,strRet.size()-1);
230 Value stop(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Stop bitcoin server.");
236 // Shutdown will take long enough that the response should get back
238 return "bitcoin server stopping";
242 Value getblockcount(const Array& params, bool fHelp)
244 if (fHelp || params.size() != 0)
247 "Returns the number of blocks in the longest block chain.");
254 Value getblocknumber(const Array& params, bool fHelp)
256 if (fHelp || params.size() != 0)
259 "Deprecated. Use getblockcount.");
265 Value getconnectioncount(const Array& params, bool fHelp)
267 if (fHelp || params.size() != 0)
269 "getconnectioncount\n"
270 "Returns the number of connections to other nodes.");
272 return (int)vNodes.size();
276 Value getdifficulty(const Array& params, bool fHelp)
278 if (fHelp || params.size() != 0)
281 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
283 return GetDifficulty();
287 Value getgenerate(const Array& params, bool fHelp)
289 if (fHelp || params.size() != 0)
292 "Returns true or false.");
294 return GetBoolArg("-gen");
298 Value setgenerate(const Array& params, bool fHelp)
300 if (fHelp || params.size() < 1 || params.size() > 2)
302 "setgenerate <generate> [genproclimit]\n"
303 "<generate> is true or false to turn generation on or off.\n"
304 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
306 bool fGenerate = true;
307 if (params.size() > 0)
308 fGenerate = params[0].get_bool();
310 if (params.size() > 1)
312 int nGenProcLimit = params[1].get_int();
313 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
314 if (nGenProcLimit == 0)
317 mapArgs["-gen"] = (fGenerate ? "1" : "0");
319 GenerateBitcoins(fGenerate, pwalletMain);
324 Value gethashespersec(const Array& params, bool fHelp)
326 if (fHelp || params.size() != 0)
329 "Returns a recent hashes per second performance measurement while generating.");
331 if (GetTimeMillis() - nHPSTimerStart > 8000)
332 return (boost::int64_t)0;
333 return (boost::int64_t)dHashesPerSec;
337 Value getinfo(const Array& params, bool fHelp)
339 if (fHelp || params.size() != 0)
342 "Returns an object containing various state info.");
345 obj.push_back(Pair("version", (int)CLIENT_VERSION));
346 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
347 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
348 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
349 obj.push_back(Pair("blocks", (int)nBestHeight));
350 obj.push_back(Pair("connections", (int)vNodes.size()));
351 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
352 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
353 obj.push_back(Pair("testnet", fTestNet));
354 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
355 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
356 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
357 if (pwalletMain->IsCrypted())
358 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
359 obj.push_back(Pair("errors", GetWarnings("statusbar")));
364 Value getmininginfo(const Array& params, bool fHelp)
366 if (fHelp || params.size() != 0)
369 "Returns an object containing mining-related information.");
372 obj.push_back(Pair("blocks", (int)nBestHeight));
373 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
374 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
375 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
376 obj.push_back(Pair("errors", GetWarnings("statusbar")));
377 obj.push_back(Pair("generate", GetBoolArg("-gen")));
378 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
379 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
380 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
381 obj.push_back(Pair("testnet", fTestNet));
386 Value getnewaddress(const Array& params, bool fHelp)
388 if (fHelp || params.size() > 1)
390 "getnewaddress [account]\n"
391 "Returns a new bitcoin address for receiving payments. "
392 "If [account] is specified (recommended), it is added to the address book "
393 "so payments received with the address will be credited to [account].");
395 // Parse the account first so we don't generate a key if there's an error
397 if (params.size() > 0)
398 strAccount = AccountFromValue(params[0]);
400 if (!pwalletMain->IsLocked())
401 pwalletMain->TopUpKeyPool();
403 // Generate a new key that is added to wallet
404 std::vector<unsigned char> newKey;
405 if (!pwalletMain->GetKeyFromPool(newKey, false))
406 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
407 CBitcoinAddress address(newKey);
409 pwalletMain->SetAddressBookName(address, strAccount);
411 return address.ToString();
415 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
417 CWalletDB walletdb(pwalletMain->strWalletFile);
420 walletdb.ReadAccount(strAccount, account);
422 bool bKeyUsed = false;
424 // Check if the current key has been used
425 if (!account.vchPubKey.empty())
427 CScript scriptPubKey;
428 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
429 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
430 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
433 const CWalletTx& wtx = (*it).second;
434 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
435 if (txout.scriptPubKey == scriptPubKey)
440 // Generate a new key
441 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
443 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
444 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
446 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
447 walletdb.WriteAccount(strAccount, account);
450 return CBitcoinAddress(account.vchPubKey);
453 Value getaccountaddress(const Array& params, bool fHelp)
455 if (fHelp || params.size() != 1)
457 "getaccountaddress <account>\n"
458 "Returns the current bitcoin address for receiving payments to this account.");
460 // Parse the account first so we don't generate a key if there's an error
461 string strAccount = AccountFromValue(params[0]);
465 ret = GetAccountAddress(strAccount).ToString();
472 Value setaccount(const Array& params, bool fHelp)
474 if (fHelp || params.size() < 1 || params.size() > 2)
476 "setaccount <bitcoinaddress> <account>\n"
477 "Sets the account associated with the given address.");
479 CBitcoinAddress address(params[0].get_str());
480 if (!address.IsValid())
481 throw JSONRPCError(-5, "Invalid bitcoin address");
485 if (params.size() > 1)
486 strAccount = AccountFromValue(params[1]);
488 // Detect when changing the account of an address that is the 'unused current key' of another account:
489 if (pwalletMain->mapAddressBook.count(address))
491 string strOldAccount = pwalletMain->mapAddressBook[address];
492 if (address == GetAccountAddress(strOldAccount))
493 GetAccountAddress(strOldAccount, true);
496 pwalletMain->SetAddressBookName(address, strAccount);
502 Value getaccount(const Array& params, bool fHelp)
504 if (fHelp || params.size() != 1)
506 "getaccount <bitcoinaddress>\n"
507 "Returns the account associated with the given address.");
509 CBitcoinAddress address(params[0].get_str());
510 if (!address.IsValid())
511 throw JSONRPCError(-5, "Invalid bitcoin address");
514 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
515 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
516 strAccount = (*mi).second;
521 Value getaddressesbyaccount(const Array& params, bool fHelp)
523 if (fHelp || params.size() != 1)
525 "getaddressesbyaccount <account>\n"
526 "Returns the list of addresses for the given account.");
528 string strAccount = AccountFromValue(params[0]);
530 // Find all addresses that have the given account
532 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
534 const CBitcoinAddress& address = item.first;
535 const string& strName = item.second;
536 if (strName == strAccount)
537 ret.push_back(address.ToString());
542 Value settxfee(const Array& params, bool fHelp)
544 if (fHelp || params.size() < 1 || params.size() > 1)
546 "settxfee <amount>\n"
547 "<amount> is a real and is rounded to the nearest 0.00000001");
551 if (params[0].get_real() != 0.0)
552 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
554 nTransactionFee = nAmount;
558 Value sendtoaddress(const Array& params, bool fHelp)
560 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
562 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
563 "<amount> is a real and is rounded to the nearest 0.00000001\n"
564 "requires wallet passphrase to be set with walletpassphrase first");
565 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
567 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
568 "<amount> is a real and is rounded to the nearest 0.00000001");
570 CBitcoinAddress address(params[0].get_str());
571 if (!address.IsValid())
572 throw JSONRPCError(-5, "Invalid bitcoin address");
575 int64 nAmount = AmountFromValue(params[1]);
579 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
580 wtx.mapValue["comment"] = params[2].get_str();
581 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
582 wtx.mapValue["to"] = params[3].get_str();
584 if (pwalletMain->IsLocked())
585 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
587 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
589 throw JSONRPCError(-4, strError);
591 return wtx.GetHash().GetHex();
594 Value signmessage(const Array& params, bool fHelp)
596 if (fHelp || params.size() != 2)
598 "signmessage <bitcoinaddress> <message>\n"
599 "Sign a message with the private key of an address");
601 if (pwalletMain->IsLocked())
602 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
604 string strAddress = params[0].get_str();
605 string strMessage = params[1].get_str();
607 CBitcoinAddress addr(strAddress);
609 throw JSONRPCError(-3, "Invalid address");
612 if (!pwalletMain->GetKey(addr, key))
613 throw JSONRPCError(-4, "Private key not available");
615 CDataStream ss(SER_GETHASH, 0);
616 ss << strMessageMagic;
619 vector<unsigned char> vchSig;
620 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
621 throw JSONRPCError(-5, "Sign failed");
623 return EncodeBase64(&vchSig[0], vchSig.size());
626 Value verifymessage(const Array& params, bool fHelp)
628 if (fHelp || params.size() != 3)
630 "verifymessage <bitcoinaddress> <signature> <message>\n"
631 "Verify a signed message");
633 string strAddress = params[0].get_str();
634 string strSign = params[1].get_str();
635 string strMessage = params[2].get_str();
637 CBitcoinAddress addr(strAddress);
639 throw JSONRPCError(-3, "Invalid address");
641 bool fInvalid = false;
642 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
645 throw JSONRPCError(-5, "Malformed base64 encoding");
647 CDataStream ss(SER_GETHASH, 0);
648 ss << strMessageMagic;
652 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
655 return (CBitcoinAddress(key.GetPubKey()) == addr);
659 Value getreceivedbyaddress(const Array& params, bool fHelp)
661 if (fHelp || params.size() < 1 || params.size() > 2)
663 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
664 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
667 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
668 CScript scriptPubKey;
669 if (!address.IsValid())
670 throw JSONRPCError(-5, "Invalid bitcoin address");
671 scriptPubKey.SetBitcoinAddress(address);
672 if (!IsMine(*pwalletMain,scriptPubKey))
675 // Minimum confirmations
677 if (params.size() > 1)
678 nMinDepth = params[1].get_int();
682 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
684 const CWalletTx& wtx = (*it).second;
685 if (wtx.IsCoinBase() || !wtx.IsFinal())
688 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
689 if (txout.scriptPubKey == scriptPubKey)
690 if (wtx.GetDepthInMainChain() >= nMinDepth)
691 nAmount += txout.nValue;
694 return ValueFromAmount(nAmount);
698 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
700 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
702 const CBitcoinAddress& address = item.first;
703 const string& strName = item.second;
704 if (strName == strAccount)
705 setAddress.insert(address);
710 Value getreceivedbyaccount(const Array& params, bool fHelp)
712 if (fHelp || params.size() < 1 || params.size() > 2)
714 "getreceivedbyaccount <account> [minconf=1]\n"
715 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
717 // Minimum confirmations
719 if (params.size() > 1)
720 nMinDepth = params[1].get_int();
722 // Get the set of pub keys assigned to account
723 string strAccount = AccountFromValue(params[0]);
724 set<CBitcoinAddress> setAddress;
725 GetAccountAddresses(strAccount, setAddress);
729 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
731 const CWalletTx& wtx = (*it).second;
732 if (wtx.IsCoinBase() || !wtx.IsFinal())
735 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
737 CBitcoinAddress address;
738 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
739 if (wtx.GetDepthInMainChain() >= nMinDepth)
740 nAmount += txout.nValue;
744 return (double)nAmount / (double)COIN;
748 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
752 // Tally wallet transactions
753 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
755 const CWalletTx& wtx = (*it).second;
759 int64 nGenerated, nReceived, nSent, nFee;
760 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
762 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
763 nBalance += nReceived;
764 nBalance += nGenerated - nSent - nFee;
767 // Tally internal accounting entries
768 nBalance += walletdb.GetAccountCreditDebit(strAccount);
773 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
775 CWalletDB walletdb(pwalletMain->strWalletFile);
776 return GetAccountBalance(walletdb, strAccount, nMinDepth);
780 Value getbalance(const Array& params, bool fHelp)
782 if (fHelp || params.size() > 2)
784 "getbalance [account] [minconf=1]\n"
785 "If [account] is not specified, returns the server's total available balance.\n"
786 "If [account] is specified, returns the balance in the account.");
788 if (params.size() == 0)
789 return ValueFromAmount(pwalletMain->GetBalance());
792 if (params.size() > 1)
793 nMinDepth = params[1].get_int();
795 if (params[0].get_str() == "*") {
796 // Calculate total balance a different way from GetBalance()
797 // (GetBalance() sums up all unspent TxOuts)
798 // getbalance and getbalance '*' should always return the same number.
800 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
802 const CWalletTx& wtx = (*it).second;
806 int64 allGeneratedImmature, allGeneratedMature, allFee;
807 allGeneratedImmature = allGeneratedMature = allFee = 0;
808 string strSentAccount;
809 list<pair<CBitcoinAddress, int64> > listReceived;
810 list<pair<CBitcoinAddress, int64> > listSent;
811 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
812 if (wtx.GetDepthInMainChain() >= nMinDepth)
814 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
815 nBalance += r.second;
817 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
818 nBalance -= r.second;
820 nBalance += allGeneratedMature;
822 return ValueFromAmount(nBalance);
825 string strAccount = AccountFromValue(params[0]);
827 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
829 return ValueFromAmount(nBalance);
833 Value movecmd(const Array& params, bool fHelp)
835 if (fHelp || params.size() < 3 || params.size() > 5)
837 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
838 "Move from one account in your wallet to another.");
840 string strFrom = AccountFromValue(params[0]);
841 string strTo = AccountFromValue(params[1]);
842 int64 nAmount = AmountFromValue(params[2]);
843 if (params.size() > 3)
844 // unused parameter, used to be nMinDepth, keep type-checking it though
845 (void)params[3].get_int();
847 if (params.size() > 4)
848 strComment = params[4].get_str();
850 CWalletDB walletdb(pwalletMain->strWalletFile);
853 int64 nNow = GetAdjustedTime();
856 CAccountingEntry debit;
857 debit.strAccount = strFrom;
858 debit.nCreditDebit = -nAmount;
860 debit.strOtherAccount = strTo;
861 debit.strComment = strComment;
862 walletdb.WriteAccountingEntry(debit);
865 CAccountingEntry credit;
866 credit.strAccount = strTo;
867 credit.nCreditDebit = nAmount;
869 credit.strOtherAccount = strFrom;
870 credit.strComment = strComment;
871 walletdb.WriteAccountingEntry(credit);
873 walletdb.TxnCommit();
879 Value sendfrom(const Array& params, bool fHelp)
881 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
883 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
884 "<amount> is a real and is rounded to the nearest 0.00000001\n"
885 "requires wallet passphrase to be set with walletpassphrase first");
886 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
888 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
889 "<amount> is a real and is rounded to the nearest 0.00000001");
891 string strAccount = AccountFromValue(params[0]);
892 CBitcoinAddress address(params[1].get_str());
893 if (!address.IsValid())
894 throw JSONRPCError(-5, "Invalid bitcoin address");
895 int64 nAmount = AmountFromValue(params[2]);
897 if (params.size() > 3)
898 nMinDepth = params[3].get_int();
901 wtx.strFromAccount = strAccount;
902 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
903 wtx.mapValue["comment"] = params[4].get_str();
904 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
905 wtx.mapValue["to"] = params[5].get_str();
907 if (pwalletMain->IsLocked())
908 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
911 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
912 if (nAmount > nBalance)
913 throw JSONRPCError(-6, "Account has insufficient funds");
916 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
918 throw JSONRPCError(-4, strError);
920 return wtx.GetHash().GetHex();
924 Value sendmany(const Array& params, bool fHelp)
926 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
928 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
929 "amounts are double-precision floating point numbers\n"
930 "requires wallet passphrase to be set with walletpassphrase first");
931 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
933 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
934 "amounts are double-precision floating point numbers");
936 string strAccount = AccountFromValue(params[0]);
937 Object sendTo = params[1].get_obj();
939 if (params.size() > 2)
940 nMinDepth = params[2].get_int();
943 wtx.strFromAccount = strAccount;
944 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
945 wtx.mapValue["comment"] = params[3].get_str();
947 set<CBitcoinAddress> setAddress;
948 vector<pair<CScript, int64> > vecSend;
950 int64 totalAmount = 0;
951 BOOST_FOREACH(const Pair& s, sendTo)
953 CBitcoinAddress address(s.name_);
954 if (!address.IsValid())
955 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
957 if (setAddress.count(address))
958 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
959 setAddress.insert(address);
961 CScript scriptPubKey;
962 scriptPubKey.SetBitcoinAddress(address);
963 int64 nAmount = AmountFromValue(s.value_);
964 totalAmount += nAmount;
966 vecSend.push_back(make_pair(scriptPubKey, nAmount));
969 if (pwalletMain->IsLocked())
970 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
973 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
974 if (totalAmount > nBalance)
975 throw JSONRPCError(-6, "Account has insufficient funds");
978 CReserveKey keyChange(pwalletMain);
979 int64 nFeeRequired = 0;
980 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
983 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
984 throw JSONRPCError(-6, "Insufficient funds");
985 throw JSONRPCError(-4, "Transaction creation failed");
987 if (!pwalletMain->CommitTransaction(wtx, keyChange))
988 throw JSONRPCError(-4, "Transaction commit failed");
990 return wtx.GetHash().GetHex();
993 Value addmultisigaddress(const Array& params, bool fHelp)
995 if (fHelp || params.size() < 2 || params.size() > 3)
997 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
998 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
999 "each key is a bitcoin address or hex-encoded public key\n"
1000 "If [account] is specified, assign address to [account].";
1001 throw runtime_error(msg);
1004 int nRequired = params[0].get_int();
1005 const Array& keys = params[1].get_array();
1007 if (params.size() > 2)
1008 strAccount = AccountFromValue(params[2]);
1010 // Gather public keys
1011 if (nRequired < 1 || keys.size() < nRequired)
1012 throw runtime_error(
1013 strprintf("wrong number of keys"
1014 "(got %d, need at least %d)", keys.size(), nRequired));
1015 std::vector<CKey> pubkeys;
1016 pubkeys.resize(keys.size());
1017 for (unsigned int i = 0; i < keys.size(); i++)
1019 const std::string& ks = keys[i].get_str();
1021 // Case 1: bitcoin address and we have full public key:
1022 CBitcoinAddress address(ks);
1023 if (address.IsValid())
1025 if (address.IsScript())
1026 throw runtime_error(
1027 strprintf("%s is a pay-to-script address",ks.c_str()));
1028 std::vector<unsigned char> vchPubKey;
1029 if (!pwalletMain->GetPubKey(address, vchPubKey))
1030 throw runtime_error(
1031 strprintf("no full public key for address %s",ks.c_str()));
1032 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1033 throw runtime_error(" Invalid public key: "+ks);
1036 // Case 2: hex public key
1039 vector<unsigned char> vchPubKey = ParseHex(ks);
1040 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1041 throw runtime_error(" Invalid public key: "+ks);
1045 throw runtime_error(" Invalid public key: "+ks);
1049 // Construct using pay-to-script-hash:
1051 inner.SetMultisig(nRequired, pubkeys);
1053 uint160 scriptHash = Hash160(inner);
1054 CScript scriptPubKey;
1055 scriptPubKey.SetPayToScriptHash(inner);
1056 pwalletMain->AddCScript(inner);
1057 CBitcoinAddress address;
1058 address.SetScriptHash160(scriptHash);
1060 pwalletMain->SetAddressBookName(address, strAccount);
1061 return address.ToString();
1072 nConf = std::numeric_limits<int>::max();
1076 Value ListReceived(const Array& params, bool fByAccounts)
1078 // Minimum confirmations
1080 if (params.size() > 0)
1081 nMinDepth = params[0].get_int();
1083 // Whether to include empty accounts
1084 bool fIncludeEmpty = false;
1085 if (params.size() > 1)
1086 fIncludeEmpty = params[1].get_bool();
1089 map<CBitcoinAddress, tallyitem> mapTally;
1090 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1092 const CWalletTx& wtx = (*it).second;
1094 if (wtx.IsCoinBase() || !wtx.IsFinal())
1097 int nDepth = wtx.GetDepthInMainChain();
1098 if (nDepth < nMinDepth)
1101 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1103 CBitcoinAddress address;
1104 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1107 tallyitem& item = mapTally[address];
1108 item.nAmount += txout.nValue;
1109 item.nConf = min(item.nConf, nDepth);
1115 map<string, tallyitem> mapAccountTally;
1116 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1118 const CBitcoinAddress& address = item.first;
1119 const string& strAccount = item.second;
1120 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1121 if (it == mapTally.end() && !fIncludeEmpty)
1125 int nConf = std::numeric_limits<int>::max();
1126 if (it != mapTally.end())
1128 nAmount = (*it).second.nAmount;
1129 nConf = (*it).second.nConf;
1134 tallyitem& item = mapAccountTally[strAccount];
1135 item.nAmount += nAmount;
1136 item.nConf = min(item.nConf, nConf);
1141 obj.push_back(Pair("address", address.ToString()));
1142 obj.push_back(Pair("account", strAccount));
1143 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1144 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1151 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1153 int64 nAmount = (*it).second.nAmount;
1154 int nConf = (*it).second.nConf;
1156 obj.push_back(Pair("account", (*it).first));
1157 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1158 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1166 Value listreceivedbyaddress(const Array& params, bool fHelp)
1168 if (fHelp || params.size() > 2)
1169 throw runtime_error(
1170 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1171 "[minconf] is the minimum number of confirmations before payments are included.\n"
1172 "[includeempty] whether to include addresses that haven't received any payments.\n"
1173 "Returns an array of objects containing:\n"
1174 " \"address\" : receiving address\n"
1175 " \"account\" : the account of the receiving address\n"
1176 " \"amount\" : total amount received by the address\n"
1177 " \"confirmations\" : number of confirmations of the most recent transaction included");
1179 return ListReceived(params, false);
1182 Value listreceivedbyaccount(const Array& params, bool fHelp)
1184 if (fHelp || params.size() > 2)
1185 throw runtime_error(
1186 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1187 "[minconf] is the minimum number of confirmations before payments are included.\n"
1188 "[includeempty] whether to include accounts that haven't received any payments.\n"
1189 "Returns an array of objects containing:\n"
1190 " \"account\" : the account of the receiving addresses\n"
1191 " \"amount\" : total amount received by addresses with this account\n"
1192 " \"confirmations\" : number of confirmations of the most recent transaction included");
1194 return ListReceived(params, true);
1197 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1199 int64 nGeneratedImmature, nGeneratedMature, nFee;
1200 string strSentAccount;
1201 list<pair<CBitcoinAddress, int64> > listReceived;
1202 list<pair<CBitcoinAddress, int64> > listSent;
1204 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1206 bool fAllAccounts = (strAccount == string("*"));
1208 // Generated blocks assigned to account ""
1209 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1212 entry.push_back(Pair("account", string("")));
1213 if (nGeneratedImmature)
1215 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1216 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1220 entry.push_back(Pair("category", "generate"));
1221 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1224 WalletTxToJSON(wtx, entry);
1225 ret.push_back(entry);
1229 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1231 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1234 entry.push_back(Pair("account", strSentAccount));
1235 entry.push_back(Pair("address", s.first.ToString()));
1236 entry.push_back(Pair("category", "send"));
1237 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1238 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1240 WalletTxToJSON(wtx, entry);
1241 ret.push_back(entry);
1246 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1248 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1251 if (pwalletMain->mapAddressBook.count(r.first))
1252 account = pwalletMain->mapAddressBook[r.first];
1253 if (fAllAccounts || (account == strAccount))
1256 entry.push_back(Pair("account", account));
1257 entry.push_back(Pair("address", r.first.ToString()));
1258 entry.push_back(Pair("category", "receive"));
1259 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1261 WalletTxToJSON(wtx, entry);
1262 ret.push_back(entry);
1268 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1270 bool fAllAccounts = (strAccount == string("*"));
1272 if (fAllAccounts || acentry.strAccount == strAccount)
1275 entry.push_back(Pair("account", acentry.strAccount));
1276 entry.push_back(Pair("category", "move"));
1277 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1278 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1279 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1280 entry.push_back(Pair("comment", acentry.strComment));
1281 ret.push_back(entry);
1285 Value listtransactions(const Array& params, bool fHelp)
1287 if (fHelp || params.size() > 3)
1288 throw runtime_error(
1289 "listtransactions [account] [count=10] [from=0]\n"
1290 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1292 string strAccount = "*";
1293 if (params.size() > 0)
1294 strAccount = params[0].get_str();
1296 if (params.size() > 1)
1297 nCount = params[1].get_int();
1299 if (params.size() > 2)
1300 nFrom = params[2].get_int();
1303 throw JSONRPCError(-8, "Negative count");
1305 throw JSONRPCError(-8, "Negative from");
1308 CWalletDB walletdb(pwalletMain->strWalletFile);
1310 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1311 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1312 typedef multimap<int64, TxPair > TxItems;
1315 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1316 // would make this much faster for applications that do this a lot.
1317 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1319 CWalletTx* wtx = &((*it).second);
1320 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1322 list<CAccountingEntry> acentries;
1323 walletdb.ListAccountCreditDebit(strAccount, acentries);
1324 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1326 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1329 // iterate backwards until we have nCount items to return:
1330 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1332 CWalletTx *const pwtx = (*it).second.first;
1334 ListTransactions(*pwtx, strAccount, 0, true, ret);
1335 CAccountingEntry *const pacentry = (*it).second.second;
1337 AcentryToJSON(*pacentry, strAccount, ret);
1339 if (ret.size() >= (nCount+nFrom)) break;
1341 // ret is newest to oldest
1343 if (nFrom > ret.size()) nFrom = ret.size();
1344 if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1345 Array::iterator first = ret.begin();
1346 std::advance(first, nFrom);
1347 Array::iterator last = ret.begin();
1348 std::advance(last, nFrom+nCount);
1350 if (last != ret.end()) ret.erase(last, ret.end());
1351 if (first != ret.begin()) ret.erase(ret.begin(), first);
1353 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1358 Value listaccounts(const Array& params, bool fHelp)
1360 if (fHelp || params.size() > 1)
1361 throw runtime_error(
1362 "listaccounts [minconf=1]\n"
1363 "Returns Object that has account names as keys, account balances as values.");
1366 if (params.size() > 0)
1367 nMinDepth = params[0].get_int();
1369 map<string, int64> mapAccountBalances;
1370 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1371 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1372 mapAccountBalances[entry.second] = 0;
1375 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1377 const CWalletTx& wtx = (*it).second;
1378 int64 nGeneratedImmature, nGeneratedMature, nFee;
1379 string strSentAccount;
1380 list<pair<CBitcoinAddress, int64> > listReceived;
1381 list<pair<CBitcoinAddress, int64> > listSent;
1382 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1383 mapAccountBalances[strSentAccount] -= nFee;
1384 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1385 mapAccountBalances[strSentAccount] -= s.second;
1386 if (wtx.GetDepthInMainChain() >= nMinDepth)
1388 mapAccountBalances[""] += nGeneratedMature;
1389 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1390 if (pwalletMain->mapAddressBook.count(r.first))
1391 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1393 mapAccountBalances[""] += r.second;
1397 list<CAccountingEntry> acentries;
1398 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1399 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1400 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1403 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1404 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1409 Value listsinceblock(const Array& params, bool fHelp)
1412 throw runtime_error(
1413 "listsinceblock [blockid] [target-confirmations]\n"
1414 "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1416 CBlockIndex *pindex = NULL;
1417 int target_confirms = 1;
1419 if (params.size() > 0)
1421 uint256 blockId = 0;
1423 blockId.SetHex(params[0].get_str());
1424 pindex = CBlockLocator(blockId).GetBlockIndex();
1427 if (params.size() > 1)
1429 target_confirms = params[1].get_int();
1431 if (target_confirms < 1)
1432 throw JSONRPCError(-8, "Invalid parameter");
1435 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1439 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1441 CWalletTx tx = (*it).second;
1443 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1444 ListTransactions(tx, "*", 0, true, transactions);
1449 if (target_confirms == 1)
1452 lastblock = hashBestChain;
1456 int target_height = pindexBest->nHeight + 1 - target_confirms;
1459 for (block = pindexBest;
1460 block && block->nHeight > target_height;
1461 block = block->pprev) { }
1463 lastblock = block ? block->GetBlockHash() : 0;
1467 ret.push_back(Pair("transactions", transactions));
1468 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1473 Value gettransaction(const Array& params, bool fHelp)
1475 if (fHelp || params.size() != 1)
1476 throw runtime_error(
1477 "gettransaction <txid>\n"
1478 "Get detailed information about <txid>");
1481 hash.SetHex(params[0].get_str());
1485 if (!pwalletMain->mapWallet.count(hash))
1486 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1487 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1489 int64 nCredit = wtx.GetCredit();
1490 int64 nDebit = wtx.GetDebit();
1491 int64 nNet = nCredit - nDebit;
1492 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1494 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1496 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1498 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1501 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1502 entry.push_back(Pair("details", details));
1508 Value backupwallet(const Array& params, bool fHelp)
1510 if (fHelp || params.size() != 1)
1511 throw runtime_error(
1512 "backupwallet <destination>\n"
1513 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1515 string strDest = params[0].get_str();
1516 BackupWallet(*pwalletMain, strDest);
1522 Value keypoolrefill(const Array& params, bool fHelp)
1524 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1525 throw runtime_error(
1527 "Fills the keypool, requires wallet passphrase to be set.");
1528 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1529 throw runtime_error(
1531 "Fills the keypool.");
1533 if (pwalletMain->IsLocked())
1534 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1536 pwalletMain->TopUpKeyPool();
1538 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1539 throw JSONRPCError(-4, "Error refreshing keypool.");
1545 void ThreadTopUpKeyPool(void* parg)
1547 pwalletMain->TopUpKeyPool();
1550 void ThreadCleanWalletPassphrase(void* parg)
1552 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1554 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1556 if (nWalletUnlockTime == 0)
1558 nWalletUnlockTime = nMyWakeTime;
1562 if (nWalletUnlockTime==0)
1564 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1568 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1570 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1574 if (nWalletUnlockTime)
1576 nWalletUnlockTime = 0;
1577 pwalletMain->Lock();
1582 if (nWalletUnlockTime < nMyWakeTime)
1583 nWalletUnlockTime = nMyWakeTime;
1586 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1588 delete (int64*)parg;
1591 Value walletpassphrase(const Array& params, bool fHelp)
1593 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1594 throw runtime_error(
1595 "walletpassphrase <passphrase> <timeout>\n"
1596 "Stores the wallet decryption key in memory for <timeout> seconds.");
1599 if (!pwalletMain->IsCrypted())
1600 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1602 if (!pwalletMain->IsLocked())
1603 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1605 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1606 SecureString strWalletPass;
1607 strWalletPass.reserve(100);
1608 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1609 // Alternately, find a way to make params[0] mlock()'d to begin with.
1610 strWalletPass = params[0].get_str().c_str();
1612 if (strWalletPass.length() > 0)
1614 if (!pwalletMain->Unlock(strWalletPass))
1615 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1618 throw runtime_error(
1619 "walletpassphrase <passphrase> <timeout>\n"
1620 "Stores the wallet decryption key in memory for <timeout> seconds.");
1622 CreateThread(ThreadTopUpKeyPool, NULL);
1623 int64* pnSleepTime = new int64(params[1].get_int64());
1624 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1630 Value walletpassphrasechange(const Array& params, bool fHelp)
1632 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1633 throw runtime_error(
1634 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1635 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1638 if (!pwalletMain->IsCrypted())
1639 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1641 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1642 // Alternately, find a way to make params[0] mlock()'d to begin with.
1643 SecureString strOldWalletPass;
1644 strOldWalletPass.reserve(100);
1645 strOldWalletPass = params[0].get_str().c_str();
1647 SecureString strNewWalletPass;
1648 strNewWalletPass.reserve(100);
1649 strNewWalletPass = params[1].get_str().c_str();
1651 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1652 throw runtime_error(
1653 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1654 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1656 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1657 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1663 Value walletlock(const Array& params, bool fHelp)
1665 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1666 throw runtime_error(
1668 "Removes the wallet encryption key from memory, locking the wallet.\n"
1669 "After calling this method, you will need to call walletpassphrase again\n"
1670 "before being able to call any methods which require the wallet to be unlocked.");
1673 if (!pwalletMain->IsCrypted())
1674 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1677 LOCK(cs_nWalletUnlockTime);
1678 pwalletMain->Lock();
1679 nWalletUnlockTime = 0;
1686 Value encryptwallet(const Array& params, bool fHelp)
1688 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1689 throw runtime_error(
1690 "encryptwallet <passphrase>\n"
1691 "Encrypts the wallet with <passphrase>.");
1694 if (pwalletMain->IsCrypted())
1695 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1697 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1698 // Alternately, find a way to make params[0] mlock()'d to begin with.
1699 SecureString strWalletPass;
1700 strWalletPass.reserve(100);
1701 strWalletPass = params[0].get_str().c_str();
1703 if (strWalletPass.length() < 1)
1704 throw runtime_error(
1705 "encryptwallet <passphrase>\n"
1706 "Encrypts the wallet with <passphrase>.");
1708 if (!pwalletMain->EncryptWallet(strWalletPass))
1709 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1711 // BDB seems to have a bad habit of writing old data into
1712 // slack space in .dat files; that is bad if the old data is
1713 // unencrypted private keys. So:
1715 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1719 Value validateaddress(const Array& params, bool fHelp)
1721 if (fHelp || params.size() != 1)
1722 throw runtime_error(
1723 "validateaddress <bitcoinaddress>\n"
1724 "Return information about <bitcoinaddress>.");
1726 CBitcoinAddress address(params[0].get_str());
1727 bool isValid = address.IsValid();
1730 ret.push_back(Pair("isvalid", isValid));
1733 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1734 // version of the address:
1735 string currentAddress = address.ToString();
1736 ret.push_back(Pair("address", currentAddress));
1737 if (pwalletMain->HaveKey(address))
1739 ret.push_back(Pair("ismine", true));
1740 std::vector<unsigned char> vchPubKey;
1741 pwalletMain->GetPubKey(address, vchPubKey);
1742 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1744 key.SetPubKey(vchPubKey);
1745 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1747 else if (pwalletMain->HaveCScript(address.GetHash160()))
1749 ret.push_back(Pair("isscript", true));
1751 pwalletMain->GetCScript(address.GetHash160(), subscript);
1752 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1753 std::vector<CBitcoinAddress> addresses;
1754 txnouttype whichType;
1756 ExtractAddresses(subscript, whichType, addresses, nRequired);
1757 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1759 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1760 a.push_back(addr.ToString());
1761 ret.push_back(Pair("addresses", a));
1762 if (whichType == TX_MULTISIG)
1763 ret.push_back(Pair("sigsrequired", nRequired));
1766 ret.push_back(Pair("ismine", false));
1767 if (pwalletMain->mapAddressBook.count(address))
1768 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1773 Value getwork(const Array& params, bool fHelp)
1775 if (fHelp || params.size() > 1)
1776 throw runtime_error(
1778 "If [data] is not specified, returns formatted hash data to work on:\n"
1779 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1780 " \"data\" : block data\n"
1781 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1782 " \"target\" : little endian hash target\n"
1783 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1786 throw JSONRPCError(-9, "Bitcoin is not connected!");
1788 if (IsInitialBlockDownload())
1789 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1791 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1792 static mapNewBlock_t mapNewBlock;
1793 static vector<CBlock*> vNewBlock;
1794 static CReserveKey reservekey(pwalletMain);
1796 if (params.size() == 0)
1799 static unsigned int nTransactionsUpdatedLast;
1800 static CBlockIndex* pindexPrev;
1801 static int64 nStart;
1802 static CBlock* pblock;
1803 if (pindexPrev != pindexBest ||
1804 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1806 if (pindexPrev != pindexBest)
1808 // Deallocate old blocks since they're obsolete now
1809 mapNewBlock.clear();
1810 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1814 nTransactionsUpdatedLast = nTransactionsUpdated;
1815 pindexPrev = pindexBest;
1819 pblock = CreateNewBlock(reservekey);
1821 throw JSONRPCError(-7, "Out of memory");
1822 vNewBlock.push_back(pblock);
1826 pblock->UpdateTime(pindexPrev);
1829 // Update nExtraNonce
1830 static unsigned int nExtraNonce = 0;
1831 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1834 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1836 // Prebuild hash buffers
1840 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1842 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1845 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1846 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1847 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1848 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1854 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1855 if (vchData.size() != 128)
1856 throw JSONRPCError(-8, "Invalid parameter");
1857 CBlock* pdata = (CBlock*)&vchData[0];
1860 for (int i = 0; i < 128/4; i++)
1861 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1864 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1866 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1868 pblock->nTime = pdata->nTime;
1869 pblock->nNonce = pdata->nNonce;
1870 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1871 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1873 return CheckWork(pblock, *pwalletMain, reservekey);
1878 Value getmemorypool(const Array& params, bool fHelp)
1880 if (fHelp || params.size() > 1)
1881 throw runtime_error(
1882 "getmemorypool [data]\n"
1883 "If [data] is not specified, returns data needed to construct a block to work on:\n"
1884 " \"version\" : block version\n"
1885 " \"previousblockhash\" : hash of current highest block\n"
1886 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1887 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1888 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1889 " \"time\" : timestamp appropriate for next block\n"
1890 " \"mintime\" : minimum timestamp appropriate for next block\n"
1891 " \"curtime\" : current timestamp\n"
1892 " \"bits\" : compressed target of next block\n"
1893 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1895 if (params.size() == 0)
1898 throw JSONRPCError(-9, "Bitcoin is not connected!");
1900 if (IsInitialBlockDownload())
1901 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1903 static CReserveKey reservekey(pwalletMain);
1906 static unsigned int nTransactionsUpdatedLast;
1907 static CBlockIndex* pindexPrev;
1908 static int64 nStart;
1909 static CBlock* pblock;
1910 if (pindexPrev != pindexBest ||
1911 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1913 nTransactionsUpdatedLast = nTransactionsUpdated;
1914 pindexPrev = pindexBest;
1920 pblock = CreateNewBlock(reservekey);
1922 throw JSONRPCError(-7, "Out of memory");
1926 pblock->UpdateTime(pindexPrev);
1930 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1934 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1937 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1941 result.push_back(Pair("version", pblock->nVersion));
1942 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1943 result.push_back(Pair("transactions", transactions));
1944 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1945 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1946 result.push_back(Pair("time", (int64_t)pblock->nTime));
1947 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1948 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1949 result.push_back(Pair("bits", HexBits(pblock->nBits)));
1956 CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
1960 return ProcessBlock(NULL, &pblock);
1964 Value getblockhash(const Array& params, bool fHelp)
1966 if (fHelp || params.size() != 1)
1967 throw runtime_error(
1968 "getblockhash <index>\n"
1969 "Returns hash of block in best-block-chain at <index>.");
1971 int nHeight = params[0].get_int();
1972 if (nHeight < 0 || nHeight > nBestHeight)
1973 throw runtime_error("Block number out of range.");
1976 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1977 while (pblockindex->nHeight > nHeight)
1978 pblockindex = pblockindex->pprev;
1979 return pblockindex->phashBlock->GetHex();
1982 Value getblock(const Array& params, bool fHelp)
1984 if (fHelp || params.size() != 1)
1985 throw runtime_error(
1987 "Returns details of a block with given block-hash.");
1989 std::string strHash = params[0].get_str();
1990 uint256 hash(strHash);
1992 if (mapBlockIndex.count(hash) == 0)
1993 throw JSONRPCError(-5, "Block not found");
1996 CBlockIndex* pblockindex = mapBlockIndex[hash];
1997 block.ReadFromDisk(pblockindex, true);
1999 return blockToJSON(block, pblockindex);
2017 static CRPCCommand vRPCCommands[] =
2018 { // name function safe mode?
2019 // ------------------------ ----------------------- ----------
2020 { "help", &help, true },
2021 { "stop", &stop, true },
2022 { "getblockcount", &getblockcount, true },
2023 { "getblocknumber", &getblocknumber, true },
2024 { "getconnectioncount", &getconnectioncount, true },
2025 { "getdifficulty", &getdifficulty, true },
2026 { "getgenerate", &getgenerate, true },
2027 { "setgenerate", &setgenerate, true },
2028 { "gethashespersec", &gethashespersec, true },
2029 { "getinfo", &getinfo, true },
2030 { "getmininginfo", &getmininginfo, true },
2031 { "getnewaddress", &getnewaddress, true },
2032 { "getaccountaddress", &getaccountaddress, true },
2033 { "setaccount", &setaccount, true },
2034 { "getaccount", &getaccount, false },
2035 { "getaddressesbyaccount", &getaddressesbyaccount, true },
2036 { "sendtoaddress", &sendtoaddress, false },
2037 { "getreceivedbyaddress", &getreceivedbyaddress, false },
2038 { "getreceivedbyaccount", &getreceivedbyaccount, false },
2039 { "listreceivedbyaddress", &listreceivedbyaddress, false },
2040 { "listreceivedbyaccount", &listreceivedbyaccount, false },
2041 { "backupwallet", &backupwallet, true },
2042 { "keypoolrefill", &keypoolrefill, true },
2043 { "walletpassphrase", &walletpassphrase, true },
2044 { "walletpassphrasechange", &walletpassphrasechange, false },
2045 { "walletlock", &walletlock, true },
2046 { "encryptwallet", &encryptwallet, false },
2047 { "validateaddress", &validateaddress, true },
2048 { "getbalance", &getbalance, false },
2049 { "move", &movecmd, false },
2050 { "sendfrom", &sendfrom, false },
2051 { "sendmany", &sendmany, false },
2052 { "addmultisigaddress", &addmultisigaddress, false },
2053 { "getblock", &getblock, false },
2054 { "getblockhash", &getblockhash, false },
2055 { "gettransaction", &gettransaction, false },
2056 { "listtransactions", &listtransactions, false },
2057 { "signmessage", &signmessage, false },
2058 { "verifymessage", &verifymessage, false },
2059 { "getwork", &getwork, true },
2060 { "listaccounts", &listaccounts, false },
2061 { "settxfee", &settxfee, false },
2062 { "getmemorypool", &getmemorypool, true },
2063 { "listsinceblock", &listsinceblock, false },
2064 { "dumpprivkey", &dumpprivkey, false },
2065 { "importprivkey", &importprivkey, false },
2068 map<string, CRPCCommand*> mapCommands;
2070 static void RegisterRPCCommands()
2072 static bool registered = false;
2078 for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
2082 pcmd = &vRPCCommands[vcidx];
2083 mapCommands[pcmd->name] = pcmd;
2091 // This ain't Apache. We're just using HTTP header for the length field
2092 // and to be compatible with other JSON-RPC implementations.
2095 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2098 s << "POST / HTTP/1.1\r\n"
2099 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2100 << "Host: 127.0.0.1\r\n"
2101 << "Content-Type: application/json\r\n"
2102 << "Content-Length: " << strMsg.size() << "\r\n"
2103 << "Connection: close\r\n"
2104 << "Accept: application/json\r\n";
2105 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2106 s << item.first << ": " << item.second << "\r\n";
2107 s << "\r\n" << strMsg;
2112 string rfc1123Time()
2117 struct tm* now_gmt = gmtime(&now);
2118 string locale(setlocale(LC_TIME, NULL));
2119 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2120 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2121 setlocale(LC_TIME, locale.c_str());
2122 return string(buffer);
2125 static string HTTPReply(int nStatus, const string& strMsg)
2128 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2130 "Server: bitcoin-json-rpc/%s\r\n"
2131 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2132 "Content-Type: text/html\r\n"
2133 "Content-Length: 296\r\n"
2135 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2136 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2139 "<TITLE>Error</TITLE>\r\n"
2140 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2142 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2143 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2144 const char *cStatus;
2145 if (nStatus == 200) cStatus = "OK";
2146 else if (nStatus == 400) cStatus = "Bad Request";
2147 else if (nStatus == 403) cStatus = "Forbidden";
2148 else if (nStatus == 404) cStatus = "Not Found";
2149 else if (nStatus == 500) cStatus = "Internal Server Error";
2152 "HTTP/1.1 %d %s\r\n"
2154 "Connection: close\r\n"
2155 "Content-Length: %d\r\n"
2156 "Content-Type: application/json\r\n"
2157 "Server: bitcoin-json-rpc/%s\r\n"
2162 rfc1123Time().c_str(),
2164 FormatFullVersion().c_str(),
2168 int ReadHTTPStatus(std::basic_istream<char>& stream)
2171 getline(stream, str);
2172 vector<string> vWords;
2173 boost::split(vWords, str, boost::is_any_of(" "));
2174 if (vWords.size() < 2)
2176 return atoi(vWords[1].c_str());
2179 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2185 std::getline(stream, str);
2186 if (str.empty() || str == "\r")
2188 string::size_type nColon = str.find(":");
2189 if (nColon != string::npos)
2191 string strHeader = str.substr(0, nColon);
2192 boost::trim(strHeader);
2193 boost::to_lower(strHeader);
2194 string strValue = str.substr(nColon+1);
2195 boost::trim(strValue);
2196 mapHeadersRet[strHeader] = strValue;
2197 if (strHeader == "content-length")
2198 nLen = atoi(strValue.c_str());
2204 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2206 mapHeadersRet.clear();
2210 int nStatus = ReadHTTPStatus(stream);
2213 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2214 if (nLen < 0 || nLen > MAX_SIZE)
2220 vector<char> vch(nLen);
2221 stream.read(&vch[0], nLen);
2222 strMessageRet = string(vch.begin(), vch.end());
2228 bool HTTPAuthorized(map<string, string>& mapHeaders)
2230 string strAuth = mapHeaders["authorization"];
2231 if (strAuth.substr(0,6) != "Basic ")
2233 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2234 string strUserPass = DecodeBase64(strUserPass64);
2235 return strUserPass == strRPCUserColonPass;
2239 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2240 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2241 // unspecified (HTTP errors and contents of 'error').
2243 // 1.0 spec: http://json-rpc.org/wiki/specification
2244 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2245 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2248 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2251 request.push_back(Pair("method", strMethod));
2252 request.push_back(Pair("params", params));
2253 request.push_back(Pair("id", id));
2254 return write_string(Value(request), false) + "\n";
2257 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2260 if (error.type() != null_type)
2261 reply.push_back(Pair("result", Value::null));
2263 reply.push_back(Pair("result", result));
2264 reply.push_back(Pair("error", error));
2265 reply.push_back(Pair("id", id));
2266 return write_string(Value(reply), false) + "\n";
2269 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2271 // Send error reply from json-rpc error object
2273 int code = find_value(objError, "code").get_int();
2274 if (code == -32600) nStatus = 400;
2275 else if (code == -32601) nStatus = 404;
2276 string strReply = JSONRPCReply(Value::null, objError, id);
2277 stream << HTTPReply(nStatus, strReply) << std::flush;
2280 bool ClientAllowed(const string& strAddress)
2282 if (strAddress == asio::ip::address_v4::loopback().to_string())
2284 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2285 BOOST_FOREACH(string strAllow, vAllow)
2286 if (WildcardMatch(strAddress, strAllow))
2292 // IOStream device that speaks SSL but can also speak non-SSL
2294 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2296 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2298 fUseSSL = fUseSSLIn;
2299 fNeedHandshake = fUseSSLIn;
2302 void handshake(ssl::stream_base::handshake_type role)
2304 if (!fNeedHandshake) return;
2305 fNeedHandshake = false;
2306 stream.handshake(role);
2308 std::streamsize read(char* s, std::streamsize n)
2310 handshake(ssl::stream_base::server); // HTTPS servers read first
2311 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2312 return stream.next_layer().read_some(asio::buffer(s, n));
2314 std::streamsize write(const char* s, std::streamsize n)
2316 handshake(ssl::stream_base::client); // HTTPS clients write first
2317 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2318 return asio::write(stream.next_layer(), asio::buffer(s, n));
2320 bool connect(const std::string& server, const std::string& port)
2322 ip::tcp::resolver resolver(stream.get_io_service());
2323 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2324 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2325 ip::tcp::resolver::iterator end;
2326 boost::system::error_code error = asio::error::host_not_found;
2327 while (error && endpoint_iterator != end)
2329 stream.lowest_layer().close();
2330 stream.lowest_layer().connect(*endpoint_iterator++, error);
2338 bool fNeedHandshake;
2343 void ThreadRPCServer(void* parg)
2345 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2348 vnThreadsRunning[THREAD_RPCSERVER]++;
2349 ThreadRPCServer2(parg);
2350 vnThreadsRunning[THREAD_RPCSERVER]--;
2352 catch (std::exception& e) {
2353 vnThreadsRunning[THREAD_RPCSERVER]--;
2354 PrintException(&e, "ThreadRPCServer()");
2356 vnThreadsRunning[THREAD_RPCSERVER]--;
2357 PrintException(NULL, "ThreadRPCServer()");
2359 printf("ThreadRPCServer exiting\n");
2362 void ThreadRPCServer2(void* parg)
2364 printf("ThreadRPCServer started\n");
2366 RegisterRPCCommands();
2368 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2369 if (mapArgs["-rpcpassword"] == "")
2371 unsigned char rand_pwd[32];
2372 RAND_bytes(rand_pwd, 32);
2373 string strWhatAmI = "To use bitcoind";
2374 if (mapArgs.count("-server"))
2375 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2376 else if (mapArgs.count("-daemon"))
2377 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2378 ThreadSafeMessageBox(strprintf(
2379 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2380 "It is recommended you use the following random password:\n"
2381 "rpcuser=bitcoinrpc\n"
2383 "(you do not need to remember this password)\n"
2384 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2386 GetConfigFile().string().c_str(),
2387 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2388 _("Error"), wxOK | wxMODAL);
2393 bool fUseSSL = GetBoolArg("-rpcssl");
2394 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2396 asio::io_service io_service;
2397 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2398 ip::tcp::acceptor acceptor(io_service);
2401 acceptor.open(endpoint.protocol());
2402 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2403 acceptor.bind(endpoint);
2404 acceptor.listen(socket_base::max_connections);
2406 catch(boost::system::system_error &e)
2408 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2409 _("Error"), wxOK | wxMODAL);
2414 ssl::context context(io_service, ssl::context::sslv23);
2417 context.set_options(ssl::context::no_sslv2);
2419 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2420 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2421 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2422 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2424 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2425 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2426 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2427 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2429 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2430 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2435 // Accept connection
2436 SSLStream sslStream(io_service, context);
2437 SSLIOStreamDevice d(sslStream, fUseSSL);
2438 iostreams::stream<SSLIOStreamDevice> stream(d);
2440 ip::tcp::endpoint peer;
2441 vnThreadsRunning[THREAD_RPCSERVER]--;
2442 acceptor.accept(sslStream.lowest_layer(), peer);
2443 vnThreadsRunning[4]++;
2447 // Restrict callers by IP
2448 if (!ClientAllowed(peer.address().to_string()))
2450 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2452 stream << HTTPReply(403, "") << std::flush;
2456 map<string, string> mapHeaders;
2459 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2460 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2463 printf("ThreadRPCServer ReadHTTP timeout\n");
2467 // Check authorization
2468 if (mapHeaders.count("authorization") == 0)
2470 stream << HTTPReply(401, "") << std::flush;
2473 if (!HTTPAuthorized(mapHeaders))
2475 printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2476 /* Deter brute-forcing short passwords.
2477 If this results in a DOS the user really
2478 shouldn't have their RPC port exposed.*/
2479 if (mapArgs["-rpcpassword"].size() < 20)
2482 stream << HTTPReply(401, "") << std::flush;
2486 Value id = Value::null;
2491 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2492 throw JSONRPCError(-32700, "Parse error");
2493 const Object& request = valRequest.get_obj();
2495 // Parse id now so errors from here on will have the id
2496 id = find_value(request, "id");
2499 Value valMethod = find_value(request, "method");
2500 if (valMethod.type() == null_type)
2501 throw JSONRPCError(-32600, "Missing method");
2502 if (valMethod.type() != str_type)
2503 throw JSONRPCError(-32600, "Method must be a string");
2504 string strMethod = valMethod.get_str();
2505 if (strMethod != "getwork" && strMethod != "getmemorypool")
2506 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2509 Value valParams = find_value(request, "params");
2511 if (valParams.type() == array_type)
2512 params = valParams.get_array();
2513 else if (valParams.type() == null_type)
2516 throw JSONRPCError(-32600, "Params must be an array");
2519 if (!mapCommands.count(strMethod))
2520 throw JSONRPCError(-32601, "Method not found");
2522 CRPCCommand *pcmd = mapCommands[strMethod];
2524 // Observe safe mode
2525 string strWarning = GetWarnings("rpc");
2526 if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
2528 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2535 LOCK2(cs_main, pwalletMain->cs_wallet);
2536 result = pcmd->actor(params, false);
2540 string strReply = JSONRPCReply(result, Value::null, id);
2541 stream << HTTPReply(200, strReply) << std::flush;
2543 catch (std::exception& e)
2545 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2548 catch (Object& objError)
2550 ErrorReply(stream, objError, id);
2552 catch (std::exception& e)
2554 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2562 Object CallRPC(const string& strMethod, const Array& params)
2564 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2565 throw runtime_error(strprintf(
2566 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2567 "If the file does not exist, create it with owner-readable-only file permissions."),
2568 GetConfigFile().string().c_str()));
2570 // Connect to localhost
2571 bool fUseSSL = GetBoolArg("-rpcssl");
2572 asio::io_service io_service;
2573 ssl::context context(io_service, ssl::context::sslv23);
2574 context.set_options(ssl::context::no_sslv2);
2575 SSLStream sslStream(io_service, context);
2576 SSLIOStreamDevice d(sslStream, fUseSSL);
2577 iostreams::stream<SSLIOStreamDevice> stream(d);
2578 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2579 throw runtime_error("couldn't connect to server");
2581 // HTTP basic authentication
2582 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2583 map<string, string> mapRequestHeaders;
2584 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2587 string strRequest = JSONRPCRequest(strMethod, params, 1);
2588 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2589 stream << strPost << std::flush;
2592 map<string, string> mapHeaders;
2594 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2596 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2597 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2598 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2599 else if (strReply.empty())
2600 throw runtime_error("no response from server");
2604 if (!read_string(strReply, valReply))
2605 throw runtime_error("couldn't parse reply from server");
2606 const Object& reply = valReply.get_obj();
2608 throw runtime_error("expected reply to have result, error and id properties");
2616 template<typename T>
2617 void ConvertTo(Value& value)
2619 if (value.type() == str_type)
2621 // reinterpret string as unquoted json value
2623 if (!read_string(value.get_str(), value2))
2624 throw runtime_error("type mismatch");
2625 value = value2.get_value<T>();
2629 value = value.get_value<T>();
2633 int CommandLineRPC(int argc, char *argv[])
2640 while (argc > 1 && IsSwitchChar(argv[1][0]))
2648 throw runtime_error("too few parameters");
2649 string strMethod = argv[1];
2651 // Parameters default to strings
2653 for (int i = 2; i < argc; i++)
2654 params.push_back(argv[i]);
2655 int n = params.size();
2658 // Special case non-string parameter types
2660 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2661 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2662 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2663 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2664 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2666 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2668 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2669 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2670 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2672 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2673 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2674 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2675 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2676 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2677 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2678 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2680 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2681 if (strMethod == "sendmany" && n > 1)
2683 string s = params[1].get_str();
2685 if (!read_string(s, v) || v.type() != obj_type)
2686 throw runtime_error("type mismatch");
2687 params[1] = v.get_obj();
2689 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2690 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2691 if (strMethod == "addmultisigaddress" && n > 1)
2693 string s = params[1].get_str();
2695 if (!read_string(s, v) || v.type() != array_type)
2696 throw runtime_error("type mismatch "+s);
2697 params[1] = v.get_array();
2701 Object reply = CallRPC(strMethod, params);
2704 const Value& result = find_value(reply, "result");
2705 const Value& error = find_value(reply, "error");
2707 if (error.type() != null_type)
2710 strPrint = "error: " + write_string(error, false);
2711 int code = find_value(error.get_obj(), "code").get_int();
2717 if (result.type() == null_type)
2719 else if (result.type() == str_type)
2720 strPrint = result.get_str();
2722 strPrint = write_string(result, true);
2725 catch (std::exception& e)
2727 strPrint = string("error: ") + e.what();
2732 PrintException(NULL, "CommandLineRPC()");
2737 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2746 int main(int argc, char *argv[])
2749 // Turn off microsoft heap dump noise
2750 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2751 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2753 setbuf(stdin, NULL);
2754 setbuf(stdout, NULL);
2755 setbuf(stderr, NULL);
2759 if (argc >= 2 && string(argv[1]) == "-server")
2761 printf("server ready\n");
2762 ThreadRPCServer(NULL);
2766 return CommandLineRPC(argc, argv);
2769 catch (std::exception& e) {
2770 PrintException(&e, "main()");
2772 PrintException(NULL, "main()");