1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 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.
7 #include "cryptopp/sha.h"
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h. The problem might be when the pch file goes over
28 // a certain size around 145MB. If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
44 Object JSONRPCError(int code, const string& message)
47 error.push_back(Pair("code", code));
48 error.push_back(Pair("message", message));
53 void PrintConsole(const std::string &format, ...)
56 int limit = sizeof(buffer);
58 va_start(arg_ptr, format);
59 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
61 if (ret < 0 || ret >= limit)
67 fprintf(stdout, "%s", buffer);
71 int64 AmountFromValue(const Value& value)
73 double dAmount = value.get_real();
74 if (dAmount <= 0.0 || dAmount > 21000000.0)
75 throw JSONRPCError(-3, "Invalid amount");
76 int64 nAmount = roundint64(dAmount * COIN);
77 if (!MoneyRange(nAmount))
78 throw JSONRPCError(-3, "Invalid amount");
82 Value ValueFromAmount(int64 amount)
84 return (double)amount / (double)COIN;
87 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
89 entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
90 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
91 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
92 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
93 entry.push_back(Pair(item.first, item.second));
96 string AccountFromValue(const Value& value)
98 string strAccount = value.get_str();
99 if (strAccount == "*")
100 throw JSONRPCError(-11, "Invalid account name");
107 /// Note: This interface may still be subject to change.
111 Value help(const Array& params, bool fHelp)
113 if (fHelp || params.size() > 1)
116 "List commands, or get help for a command.");
119 if (params.size() > 0)
120 strCommand = params[0].get_str();
123 set<rpcfn_type> setDone;
124 for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
126 string strMethod = (*mi).first;
127 // We already filter duplicates, but these deprecated screw up the sort order
128 if (strMethod == "getamountreceived" ||
129 strMethod == "getallreceived" ||
130 (strMethod.find("label") != string::npos))
132 if (strCommand != "" && strMethod != strCommand)
137 rpcfn_type pfn = (*mi).second;
138 if (setDone.insert(pfn).second)
139 (*pfn)(params, true);
141 catch (std::exception& e)
143 // Help text is returned in an exception
144 string strHelp = string(e.what());
145 if (strCommand == "")
146 if (strHelp.find('\n') != -1)
147 strHelp = strHelp.substr(0, strHelp.find('\n'));
148 strRet += strHelp + "\n";
152 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
153 strRet = strRet.substr(0,strRet.size()-1);
158 Value stop(const Array& params, bool fHelp)
160 if (fHelp || params.size() != 0)
163 "Stop bitcoin server.");
165 // Shutdown will take long enough that the response should get back
166 CreateThread(Shutdown, NULL);
167 return "bitcoin server stopping";
171 Value getblockcount(const Array& params, bool fHelp)
173 if (fHelp || params.size() != 0)
176 "Returns the number of blocks in the longest block chain.");
182 Value getblocknumber(const Array& params, bool fHelp)
184 if (fHelp || params.size() != 0)
187 "Returns the block number of the latest block in the longest block chain.");
193 Value getconnectioncount(const Array& params, bool fHelp)
195 if (fHelp || params.size() != 0)
197 "getconnectioncount\n"
198 "Returns the number of connections to other nodes.");
200 return (int)vNodes.size();
204 double GetDifficulty()
206 // Floating point number that is a multiple of the minimum difficulty,
207 // minimum difficulty = 1.0.
209 if (pindexBest == NULL)
211 int nShift = (pindexBest->nBits >> 24) & 0xff;
214 (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
230 Value getdifficulty(const Array& params, bool fHelp)
232 if (fHelp || params.size() != 0)
235 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
237 return GetDifficulty();
241 Value getgenerate(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 0)
246 "Returns true or false.");
248 return (bool)fGenerateBitcoins;
252 Value setgenerate(const Array& params, bool fHelp)
254 if (fHelp || params.size() < 1 || params.size() > 2)
256 "setgenerate <generate> [genproclimit]\n"
257 "<generate> is true or false to turn generation on or off.\n"
258 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
260 bool fGenerate = true;
261 if (params.size() > 0)
262 fGenerate = params[0].get_bool();
264 if (params.size() > 1)
266 int nGenProcLimit = params[1].get_int();
267 fLimitProcessors = (nGenProcLimit != -1);
268 WriteSetting("fLimitProcessors", fLimitProcessors);
269 if (nGenProcLimit != -1)
270 WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
271 if (nGenProcLimit == 0)
275 GenerateBitcoins(fGenerate, pwalletMain);
280 Value gethashespersec(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 0)
285 "Returns a recent hashes per second performance measurement while generating.");
287 if (GetTimeMillis() - nHPSTimerStart > 8000)
288 return (boost::int64_t)0;
289 return (boost::int64_t)dHashesPerSec;
293 Value getinfo(const Array& params, bool fHelp)
295 if (fHelp || params.size() != 0)
298 "Returns an object containing various state info.");
301 obj.push_back(Pair("version", (int)VERSION));
302 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
303 obj.push_back(Pair("blocks", (int)nBestHeight));
304 obj.push_back(Pair("connections", (int)vNodes.size()));
305 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
306 obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
307 obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
308 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
309 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
310 obj.push_back(Pair("testnet", fTestNet));
311 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
312 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
313 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
314 if (pwalletMain->IsCrypted())
315 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
316 obj.push_back(Pair("errors", GetWarnings("statusbar")));
321 Value getnewaddress(const Array& params, bool fHelp)
323 if (fHelp || params.size() > 1)
325 "getnewaddress [account]\n"
326 "Returns a new bitcoin address for receiving payments. "
327 "If [account] is specified (recommended), it is added to the address book "
328 "so payments received with the address will be credited to [account].");
330 // Parse the account first so we don't generate a key if there's an error
332 if (params.size() > 0)
333 strAccount = AccountFromValue(params[0]);
335 if (!pwalletMain->IsLocked())
336 pwalletMain->TopUpKeyPool();
338 // Generate a new key that is added to wallet
339 std::vector<unsigned char> newKey;
340 if (!pwalletMain->GetKeyFromPool(newKey, false))
341 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
342 CBitcoinAddress address(newKey);
344 pwalletMain->SetAddressBookName(address, strAccount);
346 return address.ToString();
350 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
352 CWalletDB walletdb(pwalletMain->strWalletFile);
355 walletdb.ReadAccount(strAccount, account);
357 bool bKeyUsed = false;
359 // Check if the current key has been used
360 if (!account.vchPubKey.empty())
362 CScript scriptPubKey;
363 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
364 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
365 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
368 const CWalletTx& wtx = (*it).second;
369 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
370 if (txout.scriptPubKey == scriptPubKey)
375 // Generate a new key
376 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
378 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
379 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
381 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
382 walletdb.WriteAccount(strAccount, account);
385 return CBitcoinAddress(account.vchPubKey);
388 Value getaccountaddress(const Array& params, bool fHelp)
390 if (fHelp || params.size() != 1)
392 "getaccountaddress <account>\n"
393 "Returns the current bitcoin address for receiving payments to this account.");
395 // Parse the account first so we don't generate a key if there's an error
396 string strAccount = AccountFromValue(params[0]);
400 ret = GetAccountAddress(strAccount).ToString();
407 Value setaccount(const Array& params, bool fHelp)
409 if (fHelp || params.size() < 1 || params.size() > 2)
411 "setaccount <bitcoinaddress> <account>\n"
412 "Sets the account associated with the given address.");
414 CBitcoinAddress address(params[0].get_str());
415 if (!address.IsValid())
416 throw JSONRPCError(-5, "Invalid bitcoin address");
420 if (params.size() > 1)
421 strAccount = AccountFromValue(params[1]);
423 // Detect when changing the account of an address that is the 'unused current key' of another account:
424 if (pwalletMain->mapAddressBook.count(address))
426 string strOldAccount = pwalletMain->mapAddressBook[address];
427 if (address == GetAccountAddress(strOldAccount))
428 GetAccountAddress(strOldAccount, true);
431 pwalletMain->SetAddressBookName(address, strAccount);
437 Value getaccount(const Array& params, bool fHelp)
439 if (fHelp || params.size() != 1)
441 "getaccount <bitcoinaddress>\n"
442 "Returns the account associated with the given address.");
444 CBitcoinAddress address(params[0].get_str());
445 if (!address.IsValid())
446 throw JSONRPCError(-5, "Invalid bitcoin address");
449 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
450 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
451 strAccount = (*mi).second;
456 Value getaddressesbyaccount(const Array& params, bool fHelp)
458 if (fHelp || params.size() != 1)
460 "getaddressesbyaccount <account>\n"
461 "Returns the list of addresses for the given account.");
463 string strAccount = AccountFromValue(params[0]);
465 // Find all addresses that have the given account
467 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
469 const CBitcoinAddress& address = item.first;
470 const string& strName = item.second;
471 if (strName == strAccount)
472 ret.push_back(address.ToString());
477 Value settxfee(const Array& params, bool fHelp)
479 if (fHelp || params.size() < 1 || params.size() > 1)
481 "settxfee <amount>\n"
482 "<amount> is a real and is rounded to the nearest 0.00000001");
486 if (params[0].get_real() != 0.0)
487 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
489 nTransactionFee = nAmount;
493 Value sendtoaddress(const Array& params, bool fHelp)
495 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
497 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
498 "<amount> is a real and is rounded to the nearest 0.00000001\n"
499 "requires wallet passphrase to be set with walletpassphrase first");
500 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
502 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503 "<amount> is a real and is rounded to the nearest 0.00000001");
505 CBitcoinAddress address(params[0].get_str());
506 if (!address.IsValid())
507 throw JSONRPCError(-5, "Invalid bitcoin address");
510 int64 nAmount = AmountFromValue(params[1]);
514 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
515 wtx.mapValue["comment"] = params[2].get_str();
516 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
517 wtx.mapValue["to"] = params[3].get_str();
519 if (pwalletMain->IsLocked())
520 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
522 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
524 throw JSONRPCError(-4, strError);
526 return wtx.GetHash().GetHex();
529 static const string strMessageMagic = "Bitcoin Signed Message:\n";
531 Value signmessage(const Array& params, bool fHelp)
533 if (fHelp || params.size() != 2)
535 "signmessage <bitcoinaddress> <message>\n"
536 "Sign a message with the private key of an address");
538 if (pwalletMain->IsLocked())
539 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
541 string strAddress = params[0].get_str();
542 string strMessage = params[1].get_str();
544 CBitcoinAddress addr(strAddress);
546 throw JSONRPCError(-3, "Invalid address");
549 if (!pwalletMain->GetKey(addr, key))
550 throw JSONRPCError(-4, "Private key not available");
552 CDataStream ss(SER_GETHASH);
553 ss << strMessageMagic;
556 vector<unsigned char> vchSig;
557 if (!key.Sign(Hash(ss.begin(), ss.end()), vchSig))
558 throw JSONRPCError(-5, "Sign failed");
560 CDataStream sres(SER_NETWORK);
561 sres << key.GetPubKey(); // public key
562 sres << vchSig; // signature;
564 vector<unsigned char> vchRet(sres.begin(), sres.end());
565 return EncodeBase64(&vchRet[0], vchRet.size());
568 Value verifymessage(const Array& params, bool fHelp)
570 if (fHelp || params.size() != 3)
572 "verifymessage <bitcoinaddress> <signature> <message>\n"
573 "Verify a signed message");
575 string strAddress = params[0].get_str();
576 string strSign = params[1].get_str();
577 string strMessage = params[2].get_str();
579 CBitcoinAddress addr(strAddress);
581 throw JSONRPCError(-3, "Invalid address");
583 bool fInvalid = false;
584 vector<unsigned char> vchResult = DecodeBase64(strSign.c_str(), &fInvalid);
587 throw JSONRPCError(-5, "Malformed base64 encoding");
589 CDataStream sres(vchResult);
591 std::vector<unsigned char> vchPubKey;
593 std::vector<unsigned char> vchSig;
597 if (!key.SetPubKey(vchPubKey))
598 throw JSONRPCError(-5, "Invalid public key in signature");
600 if (key.GetAddress() == addr)
602 CDataStream ss(SER_GETHASH);
603 ss << strMessageMagic;
605 return key.Verify(Hash(ss.begin(), ss.end()), vchSig);
612 Value getreceivedbyaddress(const Array& params, bool fHelp)
614 if (fHelp || params.size() < 1 || params.size() > 2)
616 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
617 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
620 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
621 CScript scriptPubKey;
622 if (!address.IsValid())
623 throw JSONRPCError(-5, "Invalid bitcoin address");
624 scriptPubKey.SetBitcoinAddress(address);
625 if (!IsMine(*pwalletMain,scriptPubKey))
628 // Minimum confirmations
630 if (params.size() > 1)
631 nMinDepth = params[1].get_int();
635 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
637 const CWalletTx& wtx = (*it).second;
638 if (wtx.IsCoinBase() || !wtx.IsFinal())
641 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
642 if (txout.scriptPubKey == scriptPubKey)
643 if (wtx.GetDepthInMainChain() >= nMinDepth)
644 nAmount += txout.nValue;
647 return ValueFromAmount(nAmount);
651 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
653 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
655 const CBitcoinAddress& address = item.first;
656 const string& strName = item.second;
657 if (strName == strAccount)
658 setAddress.insert(address);
663 Value getreceivedbyaccount(const Array& params, bool fHelp)
665 if (fHelp || params.size() < 1 || params.size() > 2)
667 "getreceivedbyaccount <account> [minconf=1]\n"
668 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
670 // Minimum confirmations
672 if (params.size() > 1)
673 nMinDepth = params[1].get_int();
675 // Get the set of pub keys that have the label
676 string strAccount = AccountFromValue(params[0]);
677 set<CBitcoinAddress> setAddress;
678 GetAccountAddresses(strAccount, setAddress);
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)
690 CBitcoinAddress address;
691 if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
692 if (wtx.GetDepthInMainChain() >= nMinDepth)
693 nAmount += txout.nValue;
697 return (double)nAmount / (double)COIN;
701 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
705 // Tally wallet transactions
706 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
708 const CWalletTx& wtx = (*it).second;
712 int64 nGenerated, nReceived, nSent, nFee;
713 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
715 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
716 nBalance += nReceived;
717 nBalance += nGenerated - nSent - nFee;
720 // Tally internal accounting entries
721 nBalance += walletdb.GetAccountCreditDebit(strAccount);
726 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
728 CWalletDB walletdb(pwalletMain->strWalletFile);
729 return GetAccountBalance(walletdb, strAccount, nMinDepth);
733 Value getbalance(const Array& params, bool fHelp)
735 if (fHelp || params.size() > 2)
737 "getbalance [account] [minconf=1]\n"
738 "If [account] is not specified, returns the server's total available balance.\n"
739 "If [account] is specified, returns the balance in the account.");
741 if (params.size() == 0)
742 return ValueFromAmount(pwalletMain->GetBalance());
745 if (params.size() > 1)
746 nMinDepth = params[1].get_int();
748 if (params[0].get_str() == "*") {
749 // Calculate total balance a different way from GetBalance()
750 // (GetBalance() sums up all unspent TxOuts)
751 // getbalance and getbalance '*' should always return the same number.
753 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
755 const CWalletTx& wtx = (*it).second;
759 int64 allGeneratedImmature, allGeneratedMature, allFee;
760 allGeneratedImmature = allGeneratedMature = allFee = 0;
761 string strSentAccount;
762 list<pair<CBitcoinAddress, int64> > listReceived;
763 list<pair<CBitcoinAddress, int64> > listSent;
764 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
765 if (wtx.GetDepthInMainChain() >= nMinDepth)
766 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
767 nBalance += r.second;
768 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
769 nBalance -= r.second;
771 nBalance += allGeneratedMature;
773 return ValueFromAmount(nBalance);
776 string strAccount = AccountFromValue(params[0]);
778 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
780 return ValueFromAmount(nBalance);
784 Value movecmd(const Array& params, bool fHelp)
786 if (fHelp || params.size() < 3 || params.size() > 5)
788 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
789 "Move from one account in your wallet to another.");
791 string strFrom = AccountFromValue(params[0]);
792 string strTo = AccountFromValue(params[1]);
793 int64 nAmount = AmountFromValue(params[2]);
794 if (params.size() > 3)
795 // unused parameter, used to be nMinDepth, keep type-checking it though
796 (void)params[3].get_int();
798 if (params.size() > 4)
799 strComment = params[4].get_str();
801 CWalletDB walletdb(pwalletMain->strWalletFile);
804 int64 nNow = GetAdjustedTime();
807 CAccountingEntry debit;
808 debit.strAccount = strFrom;
809 debit.nCreditDebit = -nAmount;
811 debit.strOtherAccount = strTo;
812 debit.strComment = strComment;
813 walletdb.WriteAccountingEntry(debit);
816 CAccountingEntry credit;
817 credit.strAccount = strTo;
818 credit.nCreditDebit = nAmount;
820 credit.strOtherAccount = strFrom;
821 credit.strComment = strComment;
822 walletdb.WriteAccountingEntry(credit);
824 walletdb.TxnCommit();
830 Value sendfrom(const Array& params, bool fHelp)
832 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
834 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
835 "<amount> is a real and is rounded to the nearest 0.00000001\n"
836 "requires wallet passphrase to be set with walletpassphrase first");
837 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
839 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
840 "<amount> is a real and is rounded to the nearest 0.00000001");
842 string strAccount = AccountFromValue(params[0]);
843 CBitcoinAddress address(params[1].get_str());
844 if (!address.IsValid())
845 throw JSONRPCError(-5, "Invalid bitcoin address");
846 int64 nAmount = AmountFromValue(params[2]);
848 if (params.size() > 3)
849 nMinDepth = params[3].get_int();
852 wtx.strFromAccount = strAccount;
853 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
854 wtx.mapValue["comment"] = params[4].get_str();
855 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
856 wtx.mapValue["to"] = params[5].get_str();
858 if (pwalletMain->IsLocked())
859 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
862 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
863 if (nAmount > nBalance)
864 throw JSONRPCError(-6, "Account has insufficient funds");
867 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
869 throw JSONRPCError(-4, strError);
871 return wtx.GetHash().GetHex();
875 Value sendmany(const Array& params, bool fHelp)
877 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
879 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
880 "amounts are double-precision floating point numbers\n"
881 "requires wallet passphrase to be set with walletpassphrase first");
882 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
884 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
885 "amounts are double-precision floating point numbers");
887 string strAccount = AccountFromValue(params[0]);
888 Object sendTo = params[1].get_obj();
890 if (params.size() > 2)
891 nMinDepth = params[2].get_int();
894 wtx.strFromAccount = strAccount;
895 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
896 wtx.mapValue["comment"] = params[3].get_str();
898 set<CBitcoinAddress> setAddress;
899 vector<pair<CScript, int64> > vecSend;
901 int64 totalAmount = 0;
902 BOOST_FOREACH(const Pair& s, sendTo)
904 CBitcoinAddress address(s.name_);
905 if (!address.IsValid())
906 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
908 if (setAddress.count(address))
909 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
910 setAddress.insert(address);
912 CScript scriptPubKey;
913 scriptPubKey.SetBitcoinAddress(address);
914 int64 nAmount = AmountFromValue(s.value_);
915 totalAmount += nAmount;
917 vecSend.push_back(make_pair(scriptPubKey, nAmount));
920 if (pwalletMain->IsLocked())
921 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
924 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
925 if (totalAmount > nBalance)
926 throw JSONRPCError(-6, "Account has insufficient funds");
929 CReserveKey keyChange(pwalletMain);
930 int64 nFeeRequired = 0;
931 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
934 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
935 throw JSONRPCError(-6, "Insufficient funds");
936 throw JSONRPCError(-4, "Transaction creation failed");
938 if (!pwalletMain->CommitTransaction(wtx, keyChange))
939 throw JSONRPCError(-4, "Transaction commit failed");
941 return wtx.GetHash().GetHex();
956 Value ListReceived(const Array& params, bool fByAccounts)
958 // Minimum confirmations
960 if (params.size() > 0)
961 nMinDepth = params[0].get_int();
963 // Whether to include empty accounts
964 bool fIncludeEmpty = false;
965 if (params.size() > 1)
966 fIncludeEmpty = params[1].get_bool();
969 map<CBitcoinAddress, tallyitem> mapTally;
970 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
972 const CWalletTx& wtx = (*it).second;
973 if (wtx.IsCoinBase() || !wtx.IsFinal())
976 int nDepth = wtx.GetDepthInMainChain();
977 if (nDepth < nMinDepth)
980 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
982 CBitcoinAddress address;
983 if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
986 tallyitem& item = mapTally[address];
987 item.nAmount += txout.nValue;
988 item.nConf = min(item.nConf, nDepth);
994 map<string, tallyitem> mapAccountTally;
995 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
997 const CBitcoinAddress& address = item.first;
998 const string& strAccount = item.second;
999 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1000 if (it == mapTally.end() && !fIncludeEmpty)
1004 int nConf = INT_MAX;
1005 if (it != mapTally.end())
1007 nAmount = (*it).second.nAmount;
1008 nConf = (*it).second.nConf;
1013 tallyitem& item = mapAccountTally[strAccount];
1014 item.nAmount += nAmount;
1015 item.nConf = min(item.nConf, nConf);
1020 obj.push_back(Pair("address", address.ToString()));
1021 obj.push_back(Pair("account", strAccount));
1022 obj.push_back(Pair("label", strAccount)); // deprecated
1023 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1024 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1031 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1033 int64 nAmount = (*it).second.nAmount;
1034 int nConf = (*it).second.nConf;
1036 obj.push_back(Pair("account", (*it).first));
1037 obj.push_back(Pair("label", (*it).first)); // deprecated
1038 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1039 obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1047 Value listreceivedbyaddress(const Array& params, bool fHelp)
1049 if (fHelp || params.size() > 2)
1050 throw runtime_error(
1051 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1052 "[minconf] is the minimum number of confirmations before payments are included.\n"
1053 "[includeempty] whether to include addresses that haven't received any payments.\n"
1054 "Returns an array of objects containing:\n"
1055 " \"address\" : receiving address\n"
1056 " \"account\" : the account of the receiving address\n"
1057 " \"amount\" : total amount received by the address\n"
1058 " \"confirmations\" : number of confirmations of the most recent transaction included");
1060 return ListReceived(params, false);
1063 Value listreceivedbyaccount(const Array& params, bool fHelp)
1065 if (fHelp || params.size() > 2)
1066 throw runtime_error(
1067 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1068 "[minconf] is the minimum number of confirmations before payments are included.\n"
1069 "[includeempty] whether to include accounts that haven't received any payments.\n"
1070 "Returns an array of objects containing:\n"
1071 " \"account\" : the account of the receiving addresses\n"
1072 " \"amount\" : total amount received by addresses with this account\n"
1073 " \"confirmations\" : number of confirmations of the most recent transaction included");
1075 return ListReceived(params, true);
1078 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1080 int64 nGeneratedImmature, nGeneratedMature, nFee;
1081 string strSentAccount;
1082 list<pair<CBitcoinAddress, int64> > listReceived;
1083 list<pair<CBitcoinAddress, int64> > listSent;
1084 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1086 bool fAllAccounts = (strAccount == string("*"));
1088 // Generated blocks assigned to account ""
1089 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1092 entry.push_back(Pair("account", string("")));
1093 if (nGeneratedImmature)
1095 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1096 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1100 entry.push_back(Pair("category", "generate"));
1101 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1104 WalletTxToJSON(wtx, entry);
1105 ret.push_back(entry);
1109 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1111 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1114 entry.push_back(Pair("account", strSentAccount));
1115 entry.push_back(Pair("address", s.first.ToString()));
1116 entry.push_back(Pair("category", "send"));
1117 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1118 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1120 WalletTxToJSON(wtx, entry);
1121 ret.push_back(entry);
1126 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1127 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1130 if (pwalletMain->mapAddressBook.count(r.first))
1131 account = pwalletMain->mapAddressBook[r.first];
1132 if (fAllAccounts || (account == strAccount))
1135 entry.push_back(Pair("account", account));
1136 entry.push_back(Pair("address", r.first.ToString()));
1137 entry.push_back(Pair("category", "receive"));
1138 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1140 WalletTxToJSON(wtx, entry);
1141 ret.push_back(entry);
1146 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1148 bool fAllAccounts = (strAccount == string("*"));
1150 if (fAllAccounts || acentry.strAccount == strAccount)
1153 entry.push_back(Pair("account", acentry.strAccount));
1154 entry.push_back(Pair("category", "move"));
1155 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1156 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1157 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1158 entry.push_back(Pair("comment", acentry.strComment));
1159 ret.push_back(entry);
1163 Value listtransactions(const Array& params, bool fHelp)
1165 if (fHelp || params.size() > 3)
1166 throw runtime_error(
1167 "listtransactions [account] [count=10] [from=0]\n"
1168 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1170 string strAccount = "*";
1171 if (params.size() > 0)
1172 strAccount = params[0].get_str();
1174 if (params.size() > 1)
1175 nCount = params[1].get_int();
1177 if (params.size() > 2)
1178 nFrom = params[2].get_int();
1181 CWalletDB walletdb(pwalletMain->strWalletFile);
1183 // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1184 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1185 typedef multimap<int64, TxPair > TxItems;
1188 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1190 CWalletTx* wtx = &((*it).second);
1191 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1193 list<CAccountingEntry> acentries;
1194 walletdb.ListAccountCreditDebit(strAccount, acentries);
1195 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1197 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1200 // Now: iterate backwards until we have nCount items to return:
1201 TxItems::reverse_iterator it = txByTime.rbegin();
1202 if (txByTime.size() > nFrom) std::advance(it, nFrom);
1203 for (; it != txByTime.rend(); ++it)
1205 CWalletTx *const pwtx = (*it).second.first;
1207 ListTransactions(*pwtx, strAccount, 0, true, ret);
1208 CAccountingEntry *const pacentry = (*it).second.second;
1210 AcentryToJSON(*pacentry, strAccount, ret);
1212 if (ret.size() >= nCount) break;
1214 // ret is now newest to oldest
1216 // Make sure we return only last nCount items (sends-to-self might give us an extra):
1217 if (ret.size() > nCount)
1219 Array::iterator last = ret.begin();
1220 std::advance(last, nCount);
1221 ret.erase(last, ret.end());
1223 std::reverse(ret.begin(), ret.end()); // oldest to newest
1228 Value listaccounts(const Array& params, bool fHelp)
1230 if (fHelp || params.size() > 1)
1231 throw runtime_error(
1232 "listaccounts [minconf=1]\n"
1233 "Returns Object that has account names as keys, account balances as values.");
1236 if (params.size() > 0)
1237 nMinDepth = params[0].get_int();
1239 map<string, int64> mapAccountBalances;
1240 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1241 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1242 mapAccountBalances[entry.second] = 0;
1245 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1247 const CWalletTx& wtx = (*it).second;
1248 int64 nGeneratedImmature, nGeneratedMature, nFee;
1249 string strSentAccount;
1250 list<pair<CBitcoinAddress, int64> > listReceived;
1251 list<pair<CBitcoinAddress, int64> > listSent;
1252 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1253 mapAccountBalances[strSentAccount] -= nFee;
1254 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1255 mapAccountBalances[strSentAccount] -= s.second;
1256 if (wtx.GetDepthInMainChain() >= nMinDepth)
1258 mapAccountBalances[""] += nGeneratedMature;
1259 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1260 if (pwalletMain->mapAddressBook.count(r.first))
1261 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1263 mapAccountBalances[""] += r.second;
1267 list<CAccountingEntry> acentries;
1268 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1269 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1270 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1273 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1274 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1279 Value gettransaction(const Array& params, bool fHelp)
1281 if (fHelp || params.size() != 1)
1282 throw runtime_error(
1283 "gettransaction <txid>\n"
1284 "Get detailed information about <txid>");
1287 hash.SetHex(params[0].get_str());
1291 if (!pwalletMain->mapWallet.count(hash))
1292 throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1293 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1295 int64 nCredit = wtx.GetCredit();
1296 int64 nDebit = wtx.GetDebit();
1297 int64 nNet = nCredit - nDebit;
1298 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1300 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1302 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1304 WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1307 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1308 entry.push_back(Pair("details", details));
1314 Value backupwallet(const Array& params, bool fHelp)
1316 if (fHelp || params.size() != 1)
1317 throw runtime_error(
1318 "backupwallet <destination>\n"
1319 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1321 string strDest = params[0].get_str();
1322 BackupWallet(*pwalletMain, strDest);
1328 Value keypoolrefill(const Array& params, bool fHelp)
1330 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1331 throw runtime_error(
1333 "Fills the keypool, requires wallet passphrase to be set.");
1334 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1335 throw runtime_error(
1337 "Fills the keypool.");
1339 if (pwalletMain->IsLocked())
1340 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1342 pwalletMain->TopUpKeyPool();
1344 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1345 throw JSONRPCError(-4, "Error refreshing keypool.");
1351 void ThreadTopUpKeyPool(void* parg)
1353 pwalletMain->TopUpKeyPool();
1356 void ThreadCleanWalletPassphrase(void* parg)
1358 int64 nMyWakeTime = GetTime() + *((int*)parg);
1360 if (nWalletUnlockTime == 0)
1362 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1364 nWalletUnlockTime = nMyWakeTime;
1367 while (GetTime() < nWalletUnlockTime)
1368 Sleep(GetTime() - nWalletUnlockTime);
1370 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1372 nWalletUnlockTime = 0;
1377 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1379 if (nWalletUnlockTime < nMyWakeTime)
1380 nWalletUnlockTime = nMyWakeTime;
1386 pwalletMain->Lock();
1391 Value walletpassphrase(const Array& params, bool fHelp)
1393 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1394 throw runtime_error(
1395 "walletpassphrase <passphrase> <timeout>\n"
1396 "Stores the wallet decryption key in memory for <timeout> seconds.");
1399 if (!pwalletMain->IsCrypted())
1400 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1402 if (!pwalletMain->IsLocked())
1403 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1405 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1406 string strWalletPass;
1407 strWalletPass.reserve(100);
1408 mlock(&strWalletPass[0], strWalletPass.capacity());
1409 strWalletPass = params[0].get_str();
1411 if (strWalletPass.length() > 0)
1413 if (!pwalletMain->Unlock(strWalletPass))
1415 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1416 munlock(&strWalletPass[0], strWalletPass.capacity());
1417 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1419 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1420 munlock(&strWalletPass[0], strWalletPass.capacity());
1423 throw runtime_error(
1424 "walletpassphrase <passphrase> <timeout>\n"
1425 "Stores the wallet decryption key in memory for <timeout> seconds.");
1427 CreateThread(ThreadTopUpKeyPool, NULL);
1428 int* pnSleepTime = new int(params[1].get_int());
1429 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1435 Value walletpassphrasechange(const Array& params, bool fHelp)
1437 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1438 throw runtime_error(
1439 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1440 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1443 if (!pwalletMain->IsCrypted())
1444 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1446 string strOldWalletPass;
1447 strOldWalletPass.reserve(100);
1448 mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1449 strOldWalletPass = params[0].get_str();
1451 string strNewWalletPass;
1452 strNewWalletPass.reserve(100);
1453 mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1454 strNewWalletPass = params[1].get_str();
1456 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1457 throw runtime_error(
1458 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1459 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1461 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1463 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1464 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1465 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1466 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1467 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1469 fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1470 fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1471 munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1472 munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1478 Value walletlock(const Array& params, bool fHelp)
1480 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1481 throw runtime_error(
1483 "Removes the wallet encryption key from memory, locking the wallet.\n"
1484 "After calling this method, you will need to call walletpassphrase again\n"
1485 "before being able to call any methods which require the wallet to be unlocked.");
1488 if (!pwalletMain->IsCrypted())
1489 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1491 pwalletMain->Lock();
1492 CRITICAL_BLOCK(cs_nWalletUnlockTime)
1494 nWalletUnlockTime = 0;
1501 Value encryptwallet(const Array& params, bool fHelp)
1503 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1504 throw runtime_error(
1505 "encryptwallet <passphrase>\n"
1506 "Encrypts the wallet with <passphrase>.");
1509 if (pwalletMain->IsCrypted())
1510 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1512 string strWalletPass;
1513 strWalletPass.reserve(100);
1514 mlock(&strWalletPass[0], strWalletPass.capacity());
1515 strWalletPass = params[0].get_str();
1517 if (strWalletPass.length() < 1)
1518 throw runtime_error(
1519 "encryptwallet <passphrase>\n"
1520 "Encrypts the wallet with <passphrase>.");
1522 if (!pwalletMain->EncryptWallet(strWalletPass))
1524 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1525 munlock(&strWalletPass[0], strWalletPass.capacity());
1526 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1528 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1529 munlock(&strWalletPass[0], strWalletPass.capacity());
1535 Value validateaddress(const Array& params, bool fHelp)
1537 if (fHelp || params.size() != 1)
1538 throw runtime_error(
1539 "validateaddress <bitcoinaddress>\n"
1540 "Return information about <bitcoinaddress>.");
1542 CBitcoinAddress address(params[0].get_str());
1543 bool isValid = address.IsValid();
1546 ret.push_back(Pair("isvalid", isValid));
1549 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1550 // version of the address:
1551 string currentAddress = address.ToString();
1552 ret.push_back(Pair("address", currentAddress));
1553 ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1554 if (pwalletMain->mapAddressBook.count(address))
1555 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1561 Value getwork(const Array& params, bool fHelp)
1563 if (fHelp || params.size() > 1)
1564 throw runtime_error(
1566 "If [data] is not specified, returns formatted hash data to work on:\n"
1567 " \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1568 " \"data\" : block data\n"
1569 " \"hash1\" : formatted hash buffer for second hash\n"
1570 " \"target\" : little endian hash target\n"
1571 "If [data] is specified, tries to solve the block and returns true if it was successful.");
1574 throw JSONRPCError(-9, "Bitcoin is not connected!");
1576 if (IsInitialBlockDownload())
1577 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1579 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1580 static mapNewBlock_t mapNewBlock;
1581 static vector<CBlock*> vNewBlock;
1582 static CReserveKey reservekey(pwalletMain);
1584 if (params.size() == 0)
1587 static unsigned int nTransactionsUpdatedLast;
1588 static CBlockIndex* pindexPrev;
1589 static int64 nStart;
1590 static CBlock* pblock;
1591 if (pindexPrev != pindexBest ||
1592 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1594 if (pindexPrev != pindexBest)
1596 // Deallocate old blocks since they're obsolete now
1597 mapNewBlock.clear();
1598 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1602 nTransactionsUpdatedLast = nTransactionsUpdated;
1603 pindexPrev = pindexBest;
1607 pblock = CreateNewBlock(reservekey);
1609 throw JSONRPCError(-7, "Out of memory");
1610 vNewBlock.push_back(pblock);
1614 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1617 // Update nExtraNonce
1618 static unsigned int nExtraNonce = 0;
1619 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1622 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1624 // Prebuild hash buffers
1628 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1630 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1633 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1634 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
1635 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
1636 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
1642 vector<unsigned char> vchData = ParseHex(params[0].get_str());
1643 if (vchData.size() != 128)
1644 throw JSONRPCError(-8, "Invalid parameter");
1645 CBlock* pdata = (CBlock*)&vchData[0];
1648 for (int i = 0; i < 128/4; i++)
1649 ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1652 if (!mapNewBlock.count(pdata->hashMerkleRoot))
1654 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1656 pblock->nTime = pdata->nTime;
1657 pblock->nNonce = pdata->nNonce;
1658 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1659 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1661 return CheckWork(pblock, *pwalletMain, reservekey);
1679 pair<string, rpcfn_type> pCallTable[] =
1681 make_pair("help", &help),
1682 make_pair("stop", &stop),
1683 make_pair("getblockcount", &getblockcount),
1684 make_pair("getblocknumber", &getblocknumber),
1685 make_pair("getconnectioncount", &getconnectioncount),
1686 make_pair("getdifficulty", &getdifficulty),
1687 make_pair("getgenerate", &getgenerate),
1688 make_pair("setgenerate", &setgenerate),
1689 make_pair("gethashespersec", &gethashespersec),
1690 make_pair("getinfo", &getinfo),
1691 make_pair("getnewaddress", &getnewaddress),
1692 make_pair("getaccountaddress", &getaccountaddress),
1693 make_pair("setaccount", &setaccount),
1694 make_pair("setlabel", &setaccount), // deprecated
1695 make_pair("getaccount", &getaccount),
1696 make_pair("getlabel", &getaccount), // deprecated
1697 make_pair("getaddressesbyaccount", &getaddressesbyaccount),
1698 make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated
1699 make_pair("sendtoaddress", &sendtoaddress),
1700 make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1701 make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1702 make_pair("getreceivedbyaddress", &getreceivedbyaddress),
1703 make_pair("getreceivedbyaccount", &getreceivedbyaccount),
1704 make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated
1705 make_pair("listreceivedbyaddress", &listreceivedbyaddress),
1706 make_pair("listreceivedbyaccount", &listreceivedbyaccount),
1707 make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated
1708 make_pair("backupwallet", &backupwallet),
1709 make_pair("keypoolrefill", &keypoolrefill),
1710 make_pair("walletpassphrase", &walletpassphrase),
1711 make_pair("walletpassphrasechange", &walletpassphrasechange),
1712 make_pair("walletlock", &walletlock),
1713 make_pair("encryptwallet", &encryptwallet),
1714 make_pair("validateaddress", &validateaddress),
1715 make_pair("getbalance", &getbalance),
1716 make_pair("move", &movecmd),
1717 make_pair("sendfrom", &sendfrom),
1718 make_pair("sendmany", &sendmany),
1719 make_pair("gettransaction", &gettransaction),
1720 make_pair("listtransactions", &listtransactions),
1721 make_pair("signmessage", &signmessage),
1722 make_pair("verifymessage", &verifymessage),
1723 make_pair("getwork", &getwork),
1724 make_pair("listaccounts", &listaccounts),
1725 make_pair("settxfee", &settxfee),
1727 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1729 string pAllowInSafeMode[] =
1735 "getconnectioncount",
1742 "getaccountaddress",
1743 "setlabel", // deprecated
1745 "getlabel", // deprecated
1746 "getaddressesbyaccount",
1747 "getaddressesbylabel", // deprecated
1755 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1763 // This ain't Apache. We're just using HTTP header for the length field
1764 // and to be compatible with other JSON-RPC implementations.
1767 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1770 s << "POST / HTTP/1.1\r\n"
1771 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1772 << "Host: 127.0.0.1\r\n"
1773 << "Content-Type: application/json\r\n"
1774 << "Content-Length: " << strMsg.size() << "\r\n"
1775 << "Accept: application/json\r\n";
1776 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1777 s << item.first << ": " << item.second << "\r\n";
1778 s << "\r\n" << strMsg;
1783 string rfc1123Time()
1788 struct tm* now_gmt = gmtime(&now);
1789 string locale(setlocale(LC_TIME, NULL));
1790 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1791 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1792 setlocale(LC_TIME, locale.c_str());
1793 return string(buffer);
1796 static string HTTPReply(int nStatus, const string& strMsg)
1799 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1801 "Server: bitcoin-json-rpc/%s\r\n"
1802 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1803 "Content-Type: text/html\r\n"
1804 "Content-Length: 296\r\n"
1806 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1807 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1810 "<TITLE>Error</TITLE>\r\n"
1811 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1813 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1814 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1816 if (nStatus == 200) strStatus = "OK";
1817 else if (nStatus == 400) strStatus = "Bad Request";
1818 else if (nStatus == 403) strStatus = "Forbidden";
1819 else if (nStatus == 404) strStatus = "Not Found";
1820 else if (nStatus == 500) strStatus = "Internal Server Error";
1822 "HTTP/1.1 %d %s\r\n"
1824 "Connection: close\r\n"
1825 "Content-Length: %d\r\n"
1826 "Content-Type: application/json\r\n"
1827 "Server: bitcoin-json-rpc/%s\r\n"
1832 rfc1123Time().c_str(),
1834 FormatFullVersion().c_str(),
1838 int ReadHTTPStatus(std::basic_istream<char>& stream)
1841 getline(stream, str);
1842 vector<string> vWords;
1843 boost::split(vWords, str, boost::is_any_of(" "));
1844 if (vWords.size() < 2)
1846 return atoi(vWords[1].c_str());
1849 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1855 std::getline(stream, str);
1856 if (str.empty() || str == "\r")
1858 string::size_type nColon = str.find(":");
1859 if (nColon != string::npos)
1861 string strHeader = str.substr(0, nColon);
1862 boost::trim(strHeader);
1863 boost::to_lower(strHeader);
1864 string strValue = str.substr(nColon+1);
1865 boost::trim(strValue);
1866 mapHeadersRet[strHeader] = strValue;
1867 if (strHeader == "content-length")
1868 nLen = atoi(strValue.c_str());
1874 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1876 mapHeadersRet.clear();
1880 int nStatus = ReadHTTPStatus(stream);
1883 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1884 if (nLen < 0 || nLen > MAX_SIZE)
1890 vector<char> vch(nLen);
1891 stream.read(&vch[0], nLen);
1892 strMessageRet = string(vch.begin(), vch.end());
1898 bool HTTPAuthorized(map<string, string>& mapHeaders)
1900 string strAuth = mapHeaders["authorization"];
1901 if (strAuth.substr(0,6) != "Basic ")
1903 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1904 string strUserPass = DecodeBase64(strUserPass64);
1905 string::size_type nColon = strUserPass.find(":");
1906 if (nColon == string::npos)
1908 string strUser = strUserPass.substr(0, nColon);
1909 string strPassword = strUserPass.substr(nColon+1);
1910 return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1914 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
1915 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1916 // unspecified (HTTP errors and contents of 'error').
1918 // 1.0 spec: http://json-rpc.org/wiki/specification
1919 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1920 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1923 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1926 request.push_back(Pair("method", strMethod));
1927 request.push_back(Pair("params", params));
1928 request.push_back(Pair("id", id));
1929 return write_string(Value(request), false) + "\n";
1932 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1935 if (error.type() != null_type)
1936 reply.push_back(Pair("result", Value::null));
1938 reply.push_back(Pair("result", result));
1939 reply.push_back(Pair("error", error));
1940 reply.push_back(Pair("id", id));
1941 return write_string(Value(reply), false) + "\n";
1944 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1946 // Send error reply from json-rpc error object
1948 int code = find_value(objError, "code").get_int();
1949 if (code == -32600) nStatus = 400;
1950 else if (code == -32601) nStatus = 404;
1951 string strReply = JSONRPCReply(Value::null, objError, id);
1952 stream << HTTPReply(nStatus, strReply) << std::flush;
1955 bool ClientAllowed(const string& strAddress)
1957 if (strAddress == asio::ip::address_v4::loopback().to_string())
1959 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1960 BOOST_FOREACH(string strAllow, vAllow)
1961 if (WildcardMatch(strAddress, strAllow))
1968 // IOStream device that speaks SSL but can also speak non-SSL
1970 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1972 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1974 fUseSSL = fUseSSLIn;
1975 fNeedHandshake = fUseSSLIn;
1978 void handshake(ssl::stream_base::handshake_type role)
1980 if (!fNeedHandshake) return;
1981 fNeedHandshake = false;
1982 stream.handshake(role);
1984 std::streamsize read(char* s, std::streamsize n)
1986 handshake(ssl::stream_base::server); // HTTPS servers read first
1987 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1988 return stream.next_layer().read_some(asio::buffer(s, n));
1990 std::streamsize write(const char* s, std::streamsize n)
1992 handshake(ssl::stream_base::client); // HTTPS clients write first
1993 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1994 return asio::write(stream.next_layer(), asio::buffer(s, n));
1996 bool connect(const std::string& server, const std::string& port)
1998 ip::tcp::resolver resolver(stream.get_io_service());
1999 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2000 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2001 ip::tcp::resolver::iterator end;
2002 boost::system::error_code error = asio::error::host_not_found;
2003 while (error && endpoint_iterator != end)
2005 stream.lowest_layer().close();
2006 stream.lowest_layer().connect(*endpoint_iterator++, error);
2014 bool fNeedHandshake;
2020 void ThreadRPCServer(void* parg)
2022 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2025 vnThreadsRunning[4]++;
2026 ThreadRPCServer2(parg);
2027 vnThreadsRunning[4]--;
2029 catch (std::exception& e) {
2030 vnThreadsRunning[4]--;
2031 PrintException(&e, "ThreadRPCServer()");
2033 vnThreadsRunning[4]--;
2034 PrintException(NULL, "ThreadRPCServer()");
2036 printf("ThreadRPCServer exiting\n");
2039 void ThreadRPCServer2(void* parg)
2041 printf("ThreadRPCServer started\n");
2043 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2045 string strWhatAmI = "To use bitcoind";
2046 if (mapArgs.count("-server"))
2047 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2048 else if (mapArgs.count("-daemon"))
2049 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2051 _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2052 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2054 GetConfigFile().c_str());
2055 CreateThread(Shutdown, NULL);
2059 bool fUseSSL = GetBoolArg("-rpcssl");
2060 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2062 asio::io_service io_service;
2063 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2064 ip::tcp::acceptor acceptor(io_service, endpoint);
2066 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2069 ssl::context context(io_service, ssl::context::sslv23);
2072 context.set_options(ssl::context::no_sslv2);
2073 filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2074 if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2075 if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2076 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2077 filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2078 if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2079 if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2080 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2082 string ciphers = GetArg("-rpcsslciphers",
2083 "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2084 SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2088 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2093 // Accept connection
2095 SSLStream sslStream(io_service, context);
2096 SSLIOStreamDevice d(sslStream, fUseSSL);
2097 iostreams::stream<SSLIOStreamDevice> stream(d);
2099 ip::tcp::iostream stream;
2102 ip::tcp::endpoint peer;
2103 vnThreadsRunning[4]--;
2105 acceptor.accept(sslStream.lowest_layer(), peer);
2107 acceptor.accept(*stream.rdbuf(), peer);
2109 vnThreadsRunning[4]++;
2113 // Restrict callers by IP
2114 if (!ClientAllowed(peer.address().to_string()))
2116 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2118 stream << HTTPReply(403, "") << std::flush;
2122 map<string, string> mapHeaders;
2125 boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2126 if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2129 printf("ThreadRPCServer ReadHTTP timeout\n");
2133 // Check authorization
2134 if (mapHeaders.count("authorization") == 0)
2136 stream << HTTPReply(401, "") << std::flush;
2139 if (!HTTPAuthorized(mapHeaders))
2141 // Deter brute-forcing short passwords
2142 if (mapArgs["-rpcpassword"].size() < 15)
2145 stream << HTTPReply(401, "") << std::flush;
2146 printf("ThreadRPCServer incorrect password attempt\n");
2150 Value id = Value::null;
2155 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2156 throw JSONRPCError(-32700, "Parse error");
2157 const Object& request = valRequest.get_obj();
2159 // Parse id now so errors from here on will have the id
2160 id = find_value(request, "id");
2163 Value valMethod = find_value(request, "method");
2164 if (valMethod.type() == null_type)
2165 throw JSONRPCError(-32600, "Missing method");
2166 if (valMethod.type() != str_type)
2167 throw JSONRPCError(-32600, "Method must be a string");
2168 string strMethod = valMethod.get_str();
2169 if (strMethod != "getwork")
2170 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2173 Value valParams = find_value(request, "params");
2175 if (valParams.type() == array_type)
2176 params = valParams.get_array();
2177 else if (valParams.type() == null_type)
2180 throw JSONRPCError(-32600, "Params must be an array");
2183 map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2184 if (mi == mapCallTable.end())
2185 throw JSONRPCError(-32601, "Method not found");
2187 // Observe safe mode
2188 string strWarning = GetWarnings("rpc");
2189 if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2190 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2196 CRITICAL_BLOCK(cs_main)
2197 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2198 result = (*(*mi).second)(params, false);
2201 string strReply = JSONRPCReply(result, Value::null, id);
2202 stream << HTTPReply(200, strReply) << std::flush;
2204 catch (std::exception& e)
2206 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2209 catch (Object& objError)
2211 ErrorReply(stream, objError, id);
2213 catch (std::exception& e)
2215 ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2223 Object CallRPC(const string& strMethod, const Array& params)
2225 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2226 throw runtime_error(strprintf(
2227 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2228 "If the file does not exist, create it with owner-readable-only file permissions."),
2229 GetConfigFile().c_str()));
2231 // Connect to localhost
2232 bool fUseSSL = GetBoolArg("-rpcssl");
2234 asio::io_service io_service;
2235 ssl::context context(io_service, ssl::context::sslv23);
2236 context.set_options(ssl::context::no_sslv2);
2237 SSLStream sslStream(io_service, context);
2238 SSLIOStreamDevice d(sslStream, fUseSSL);
2239 iostreams::stream<SSLIOStreamDevice> stream(d);
2240 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2241 throw runtime_error("couldn't connect to server");
2244 throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2246 ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2248 throw runtime_error("couldn't connect to server");
2252 // HTTP basic authentication
2253 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2254 map<string, string> mapRequestHeaders;
2255 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2258 string strRequest = JSONRPCRequest(strMethod, params, 1);
2259 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2260 stream << strPost << std::flush;
2263 map<string, string> mapHeaders;
2265 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2267 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2268 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2269 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2270 else if (strReply.empty())
2271 throw runtime_error("no response from server");
2275 if (!read_string(strReply, valReply))
2276 throw runtime_error("couldn't parse reply from server");
2277 const Object& reply = valReply.get_obj();
2279 throw runtime_error("expected reply to have result, error and id properties");
2287 template<typename T>
2288 void ConvertTo(Value& value)
2290 if (value.type() == str_type)
2292 // reinterpret string as unquoted json value
2294 if (!read_string(value.get_str(), value2))
2295 throw runtime_error("type mismatch");
2296 value = value2.get_value<T>();
2300 value = value.get_value<T>();
2304 int CommandLineRPC(int argc, char *argv[])
2311 while (argc > 1 && IsSwitchChar(argv[1][0]))
2319 throw runtime_error("too few parameters");
2320 string strMethod = argv[1];
2322 // Parameters default to strings
2324 for (int i = 2; i < argc; i++)
2325 params.push_back(argv[i]);
2326 int n = params.size();
2329 // Special case non-string parameter types
2331 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2332 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2333 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2334 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2335 if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2336 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2337 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2338 if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2339 if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2340 if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2341 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2342 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2343 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2344 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2345 if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2346 if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // deprecated
2347 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2348 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2349 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2350 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2351 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2352 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2353 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2354 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2355 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2356 if (strMethod == "sendmany" && n > 1)
2358 string s = params[1].get_str();
2360 if (!read_string(s, v) || v.type() != obj_type)
2361 throw runtime_error("type mismatch");
2362 params[1] = v.get_obj();
2364 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2367 Object reply = CallRPC(strMethod, params);
2370 const Value& result = find_value(reply, "result");
2371 const Value& error = find_value(reply, "error");
2373 if (error.type() != null_type)
2376 strPrint = "error: " + write_string(error, false);
2377 int code = find_value(error.get_obj(), "code").get_int();
2383 if (result.type() == null_type)
2385 else if (result.type() == str_type)
2386 strPrint = result.get_str();
2388 strPrint = write_string(result, true);
2391 catch (std::exception& e)
2393 strPrint = string("error: ") + e.what();
2398 PrintException(NULL, "CommandLineRPC()");
2403 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2412 int main(int argc, char *argv[])
2415 // Turn off microsoft heap dump noise
2416 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2417 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2419 setbuf(stdin, NULL);
2420 setbuf(stdout, NULL);
2421 setbuf(stderr, NULL);
2425 if (argc >= 2 && string(argv[1]) == "-server")
2427 printf("server ready\n");
2428 ThreadRPCServer(NULL);
2432 return CommandLineRPC(argc, argv);
2435 catch (std::exception& e) {
2436 PrintException(&e, "main()");
2438 PrintException(NULL, "main()");