Back to home page

Bitcoin sources

 
 

    


0001 // Copyright (c) 2010 Satoshi Nakamoto
0002 // Copyright (c) 2009-2012 The Bitcoin developers
0003 // Distributed under the MIT/X11 software license, see the accompanying
0004 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
0005 
0006 #include "headers.h"
0007 #include "db.h"
0008 #include "net.h"
0009 #include "init.h"
0010 #undef printf
0011 #include <boost/asio.hpp>
0012 #include <boost/iostreams/concepts.hpp>
0013 #include <boost/iostreams/stream.hpp>
0014 #include <boost/algorithm/string.hpp>
0015 #include "json/json_spirit_reader_template.h"
0016 #include "json/json_spirit_writer_template.h"
0017 #include "json/json_spirit_utils.h"
0018 #define printf OutputDebugStringF
0019 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
0020 // precompiled in headers.h.  The problem might be when the pch file goes over
0021 // a certain size around 145MB.  If we need access to json_spirit outside this
0022 // file, we could use the compiled json_spirit option.
0023 
0024 using namespace std;
0025 using namespace boost;
0026 using namespace boost::asio;
0027 using namespace json_spirit;
0028 
0029 void ThreadRPCServer2(void* parg);
0030 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
0031 extern map<string, rpcfn_type> mapCallTable;
0032 
0033 static std::string strRPCUserColonPass;
0034 
0035 static int64 nWalletUnlockTime;
0036 static CCriticalSection cs_nWalletUnlockTime;
0037 
0038 
0039 Object JSONRPCError(int code, const string& message)
0040 {
0041     Object error;
0042     error.push_back(Pair("code", code));
0043     error.push_back(Pair("message", message));
0044     return error;
0045 }
0046 
0047 
0048 void PrintConsole(const std::string &format, ...)
0049 {
0050     char buffer[50000];
0051     int limit = sizeof(buffer);
0052     va_list arg_ptr;
0053     va_start(arg_ptr, format);
0054     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
0055     va_end(arg_ptr);
0056     if (ret < 0 || ret >= limit)
0057     {
0058         ret = limit - 1;
0059         buffer[limit-1] = 0;
0060     }
0061     printf("%s", buffer);
0062     fprintf(stdout, "%s", buffer);
0063 }
0064 
0065 
0066 int64 AmountFromValue(const Value& value)
0067 {
0068     double dAmount = value.get_real();
0069     if (dAmount <= 0.0 || dAmount > 21000000.0)
0070         throw JSONRPCError(-3, "Invalid amount");
0071     int64 nAmount = roundint64(dAmount * COIN);
0072     if (!MoneyRange(nAmount))
0073         throw JSONRPCError(-3, "Invalid amount");
0074     return nAmount;
0075 }
0076 
0077 Value ValueFromAmount(int64 amount)
0078 {
0079     return (double)amount / (double)COIN;
0080 }
0081 
0082 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
0083 {
0084     entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
0085     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
0086     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
0087     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
0088         entry.push_back(Pair(item.first, item.second));
0089 }
0090 
0091 string AccountFromValue(const Value& value)
0092 {
0093     string strAccount = value.get_str();
0094     if (strAccount == "*")
0095         throw JSONRPCError(-11, "Invalid account name");
0096     return strAccount;
0097 }
0098 
0099 
0100 
0101 ///
0102 /// Note: This interface may still be subject to change.
0103 ///
0104 
0105 
0106 Value help(const Array& params, bool fHelp)
0107 {
0108     if (fHelp || params.size() > 1)
0109         throw runtime_error(
0110             "help [command]\n"
0111             "List commands, or get help for a command.");
0112 
0113     string strCommand;
0114     if (params.size() > 0)
0115         strCommand = params[0].get_str();
0116 
0117     string strRet;
0118     set<rpcfn_type> setDone;
0119     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
0120     {
0121         string strMethod = (*mi).first;
0122         // We already filter duplicates, but these deprecated screw up the sort order
0123         if (strMethod == "getamountreceived" ||
0124             strMethod == "getallreceived" ||
0125             strMethod == "getblocknumber" || // deprecated
0126             (strMethod.find("label") != string::npos))
0127             continue;
0128         if (strCommand != "" && strMethod != strCommand)
0129             continue;
0130         try
0131         {
0132             Array params;
0133             rpcfn_type pfn = (*mi).second;
0134             if (setDone.insert(pfn).second)
0135                 (*pfn)(params, true);
0136         }
0137         catch (std::exception& e)
0138         {
0139             // Help text is returned in an exception
0140             string strHelp = string(e.what());
0141             if (strCommand == "")
0142                 if (strHelp.find('\n') != -1)
0143                     strHelp = strHelp.substr(0, strHelp.find('\n'));
0144             strRet += strHelp + "\n";
0145         }
0146     }
0147     if (strRet == "")
0148         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
0149     strRet = strRet.substr(0,strRet.size()-1);
0150     return strRet;
0151 }
0152 
0153 
0154 Value stop(const Array& params, bool fHelp)
0155 {
0156     if (fHelp || params.size() != 0)
0157         throw runtime_error(
0158             "stop\n"
0159             "Stop bitcoin server.");
0160     // Shutdown will take long enough that the response should get back
0161     CreateThread(Shutdown, NULL);
0162     return "bitcoin server stopping";
0163 }
0164 
0165 
0166 Value getblockcount(const Array& params, bool fHelp)
0167 {
0168     if (fHelp || params.size() != 0)
0169         throw runtime_error(
0170             "getblockcount\n"
0171             "Returns the number of blocks in the longest block chain.");
0172 
0173     return nBestHeight;
0174 }
0175 
0176 
0177 // deprecated
0178 Value getblocknumber(const Array& params, bool fHelp)
0179 {
0180     if (fHelp || params.size() != 0)
0181         throw runtime_error(
0182             "getblocknumber\n"
0183             "Deprecated.  Use getblockcount.");
0184 
0185     return nBestHeight;
0186 }
0187 
0188 
0189 Value getconnectioncount(const Array& params, bool fHelp)
0190 {
0191     if (fHelp || params.size() != 0)
0192         throw runtime_error(
0193             "getconnectioncount\n"
0194             "Returns the number of connections to other nodes.");
0195 
0196     return (int)vNodes.size();
0197 }
0198 
0199 
0200 double GetDifficulty()
0201 {
0202     // Floating point number that is a multiple of the minimum difficulty,
0203     // minimum difficulty = 1.0.
0204 
0205     if (pindexBest == NULL)
0206         return 1.0;
0207     int nShift = (pindexBest->nBits >> 24) & 0xff;
0208 
0209     double dDiff =
0210         (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
0211 
0212     while (nShift < 29)
0213     {
0214         dDiff *= 256.0;
0215         nShift++;
0216     }
0217     while (nShift > 29)
0218     {
0219         dDiff /= 256.0;
0220         nShift--;
0221     }
0222 
0223     return dDiff;
0224 }
0225 
0226 Value getdifficulty(const Array& params, bool fHelp)
0227 {
0228     if (fHelp || params.size() != 0)
0229         throw runtime_error(
0230             "getdifficulty\n"
0231             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
0232 
0233     return GetDifficulty();
0234 }
0235 
0236 
0237 Value getgenerate(const Array& params, bool fHelp)
0238 {
0239     if (fHelp || params.size() != 0)
0240         throw runtime_error(
0241             "getgenerate\n"
0242             "Returns true or false.");
0243 
0244     return (bool)fGenerateBitcoins;
0245 }
0246 
0247 
0248 Value setgenerate(const Array& params, bool fHelp)
0249 {
0250     if (fHelp || params.size() < 1 || params.size() > 2)
0251         throw runtime_error(
0252             "setgenerate <generate> [genproclimit]\n"
0253             "<generate> is true or false to turn generation on or off.\n"
0254             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
0255 
0256     bool fGenerate = true;
0257     if (params.size() > 0)
0258         fGenerate = params[0].get_bool();
0259 
0260     if (params.size() > 1)
0261     {
0262         int nGenProcLimit = params[1].get_int();
0263         fLimitProcessors = (nGenProcLimit != -1);
0264         WriteSetting("fLimitProcessors", fLimitProcessors);
0265         if (nGenProcLimit != -1)
0266             WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
0267         if (nGenProcLimit == 0)
0268             fGenerate = false;
0269     }
0270 
0271     GenerateBitcoins(fGenerate, pwalletMain);
0272     return Value::null;
0273 }
0274 
0275 
0276 Value gethashespersec(const Array& params, bool fHelp)
0277 {
0278     if (fHelp || params.size() != 0)
0279         throw runtime_error(
0280             "gethashespersec\n"
0281             "Returns a recent hashes per second performance measurement while generating.");
0282 
0283     if (GetTimeMillis() - nHPSTimerStart > 8000)
0284         return (boost::int64_t)0;
0285     return (boost::int64_t)dHashesPerSec;
0286 }
0287 
0288 
0289 Value getinfo(const Array& params, bool fHelp)
0290 {
0291     if (fHelp || params.size() != 0)
0292         throw runtime_error(
0293             "getinfo\n"
0294             "Returns an object containing various state info.");
0295 
0296     Object obj;
0297     obj.push_back(Pair("version",       (int)VERSION));
0298     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
0299     obj.push_back(Pair("blocks",        (int)nBestHeight));
0300     obj.push_back(Pair("connections",   (int)vNodes.size()));
0301     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
0302     obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
0303     obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
0304     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
0305     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
0306     obj.push_back(Pair("testnet",       fTestNet));
0307     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
0308     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
0309     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
0310     if (pwalletMain->IsCrypted())
0311         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
0312     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
0313     return obj;
0314 }
0315 
0316 
0317 Value getnewaddress(const Array& params, bool fHelp)
0318 {
0319     if (fHelp || params.size() > 1)
0320         throw runtime_error(
0321             "getnewaddress [account]\n"
0322             "Returns a new bitcoin address for receiving payments.  "
0323             "If [account] is specified (recommended), it is added to the address book "
0324             "so payments received with the address will be credited to [account].");
0325 
0326     // Parse the account first so we don't generate a key if there's an error
0327     string strAccount;
0328     if (params.size() > 0)
0329         strAccount = AccountFromValue(params[0]);
0330 
0331     if (!pwalletMain->IsLocked())
0332         pwalletMain->TopUpKeyPool();
0333 
0334     // Generate a new key that is added to wallet
0335     std::vector<unsigned char> newKey;
0336     if (!pwalletMain->GetKeyFromPool(newKey, false))
0337         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
0338     CBitcoinAddress address(newKey);
0339 
0340     pwalletMain->SetAddressBookName(address, strAccount);
0341 
0342     return address.ToString();
0343 }
0344 
0345 
0346 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
0347 {
0348     CWalletDB walletdb(pwalletMain->strWalletFile);
0349 
0350     CAccount account;
0351     walletdb.ReadAccount(strAccount, account);
0352 
0353     bool bKeyUsed = false;
0354 
0355     // Check if the current key has been used
0356     if (!account.vchPubKey.empty())
0357     {
0358         CScript scriptPubKey;
0359         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
0360         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
0361              it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
0362              ++it)
0363         {
0364             const CWalletTx& wtx = (*it).second;
0365             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
0366                 if (txout.scriptPubKey == scriptPubKey)
0367                     bKeyUsed = true;
0368         }
0369     }
0370 
0371     // Generate a new key
0372     if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
0373     {
0374         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
0375             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
0376 
0377         pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
0378         walletdb.WriteAccount(strAccount, account);
0379     }
0380 
0381     return CBitcoinAddress(account.vchPubKey);
0382 }
0383 
0384 Value getaccountaddress(const Array& params, bool fHelp)
0385 {
0386     if (fHelp || params.size() != 1)
0387         throw runtime_error(
0388             "getaccountaddress <account>\n"
0389             "Returns the current bitcoin address for receiving payments to this account.");
0390 
0391     // Parse the account first so we don't generate a key if there's an error
0392     string strAccount = AccountFromValue(params[0]);
0393 
0394     Value ret;
0395 
0396     ret = GetAccountAddress(strAccount).ToString();
0397 
0398     return ret;
0399 }
0400 
0401 
0402 
0403 Value setaccount(const Array& params, bool fHelp)
0404 {
0405     if (fHelp || params.size() < 1 || params.size() > 2)
0406         throw runtime_error(
0407             "setaccount <bitcoinaddress> <account>\n"
0408             "Sets the account associated with the given address.");
0409 
0410     CBitcoinAddress address(params[0].get_str());
0411     if (!address.IsValid())
0412         throw JSONRPCError(-5, "Invalid bitcoin address");
0413 
0414 
0415     string strAccount;
0416     if (params.size() > 1)
0417         strAccount = AccountFromValue(params[1]);
0418 
0419     // Detect when changing the account of an address that is the 'unused current key' of another account:
0420     if (pwalletMain->mapAddressBook.count(address))
0421     {
0422         string strOldAccount = pwalletMain->mapAddressBook[address];
0423         if (address == GetAccountAddress(strOldAccount))
0424             GetAccountAddress(strOldAccount, true);
0425     }
0426 
0427     pwalletMain->SetAddressBookName(address, strAccount);
0428 
0429     return Value::null;
0430 }
0431 
0432 
0433 Value getaccount(const Array& params, bool fHelp)
0434 {
0435     if (fHelp || params.size() != 1)
0436         throw runtime_error(
0437             "getaccount <bitcoinaddress>\n"
0438             "Returns the account associated with the given address.");
0439 
0440     CBitcoinAddress address(params[0].get_str());
0441     if (!address.IsValid())
0442         throw JSONRPCError(-5, "Invalid bitcoin address");
0443 
0444     string strAccount;
0445     map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
0446     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
0447         strAccount = (*mi).second;
0448     return strAccount;
0449 }
0450 
0451 
0452 Value getaddressesbyaccount(const Array& params, bool fHelp)
0453 {
0454     if (fHelp || params.size() != 1)
0455         throw runtime_error(
0456             "getaddressesbyaccount <account>\n"
0457             "Returns the list of addresses for the given account.");
0458 
0459     string strAccount = AccountFromValue(params[0]);
0460 
0461     // Find all addresses that have the given account
0462     Array ret;
0463     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
0464     {
0465         const CBitcoinAddress& address = item.first;
0466         const string& strName = item.second;
0467         if (strName == strAccount)
0468             ret.push_back(address.ToString());
0469     }
0470     return ret;
0471 }
0472 
0473 Value settxfee(const Array& params, bool fHelp)
0474 {
0475     if (fHelp || params.size() < 1 || params.size() > 1)
0476         throw runtime_error(
0477             "settxfee <amount>\n"
0478             "<amount> is a real and is rounded to the nearest 0.00000001");
0479 
0480     // Amount
0481     int64 nAmount = 0;
0482     if (params[0].get_real() != 0.0)
0483         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
0484 
0485     nTransactionFee = nAmount;
0486     return true;
0487 }
0488 
0489 Value sendtoaddress(const Array& params, bool fHelp)
0490 {
0491     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
0492         throw runtime_error(
0493             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
0494             "<amount> is a real and is rounded to the nearest 0.00000001\n"
0495             "requires wallet passphrase to be set with walletpassphrase first");
0496     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
0497         throw runtime_error(
0498             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
0499             "<amount> is a real and is rounded to the nearest 0.00000001");
0500 
0501     CBitcoinAddress address(params[0].get_str());
0502     if (!address.IsValid())
0503         throw JSONRPCError(-5, "Invalid bitcoin address");
0504 
0505     // Amount
0506     int64 nAmount = AmountFromValue(params[1]);
0507 
0508     // Wallet comments
0509     CWalletTx wtx;
0510     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
0511         wtx.mapValue["comment"] = params[2].get_str();
0512     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
0513         wtx.mapValue["to"]      = params[3].get_str();
0514 
0515     if (pwalletMain->IsLocked())
0516         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
0517 
0518     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
0519     if (strError != "")
0520         throw JSONRPCError(-4, strError);
0521 
0522     return wtx.GetHash().GetHex();
0523 }
0524 
0525 static const string strMessageMagic = "Bitcoin Signed Message:\n";
0526 
0527 Value signmessage(const Array& params, bool fHelp)
0528 {
0529     if (fHelp || params.size() != 2)
0530         throw runtime_error(
0531             "signmessage <bitcoinaddress> <message>\n"
0532             "Sign a message with the private key of an address");
0533 
0534     if (pwalletMain->IsLocked())
0535         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
0536 
0537     string strAddress = params[0].get_str();
0538     string strMessage = params[1].get_str();
0539 
0540     CBitcoinAddress addr(strAddress);
0541     if (!addr.IsValid())
0542         throw JSONRPCError(-3, "Invalid address");
0543 
0544     CKey key;
0545     if (!pwalletMain->GetKey(addr, key))
0546         throw JSONRPCError(-4, "Private key not available");
0547 
0548     CDataStream ss(SER_GETHASH);
0549     ss << strMessageMagic;
0550     ss << strMessage;
0551 
0552     vector<unsigned char> vchSig;
0553     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
0554         throw JSONRPCError(-5, "Sign failed");
0555 
0556     return EncodeBase64(&vchSig[0], vchSig.size());
0557 }
0558 
0559 Value verifymessage(const Array& params, bool fHelp)
0560 {
0561     if (fHelp || params.size() != 3)
0562         throw runtime_error(
0563             "verifymessage <bitcoinaddress> <signature> <message>\n"
0564             "Verify a signed message");
0565 
0566     string strAddress  = params[0].get_str();
0567     string strSign     = params[1].get_str();
0568     string strMessage  = params[2].get_str();
0569 
0570     CBitcoinAddress addr(strAddress);
0571     if (!addr.IsValid())
0572         throw JSONRPCError(-3, "Invalid address");
0573 
0574     bool fInvalid = false;
0575     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
0576 
0577     if (fInvalid)
0578         throw JSONRPCError(-5, "Malformed base64 encoding");
0579 
0580     CDataStream ss(SER_GETHASH);
0581     ss << strMessageMagic;
0582     ss << strMessage;
0583 
0584     CKey key;
0585     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
0586         return false;
0587 
0588     return (key.GetAddress() == addr);
0589 }
0590 
0591 
0592 Value getreceivedbyaddress(const Array& params, bool fHelp)
0593 {
0594     if (fHelp || params.size() < 1 || params.size() > 2)
0595         throw runtime_error(
0596             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
0597             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
0598 
0599     // Bitcoin address
0600     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
0601     CScript scriptPubKey;
0602     if (!address.IsValid())
0603         throw JSONRPCError(-5, "Invalid bitcoin address");
0604     scriptPubKey.SetBitcoinAddress(address);
0605     if (!IsMine(*pwalletMain,scriptPubKey))
0606         return (double)0.0;
0607 
0608     // Minimum confirmations
0609     int nMinDepth = 1;
0610     if (params.size() > 1)
0611         nMinDepth = params[1].get_int();
0612 
0613     // Tally
0614     int64 nAmount = 0;
0615     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
0616     {
0617         const CWalletTx& wtx = (*it).second;
0618         if (wtx.IsCoinBase() || !wtx.IsFinal())
0619             continue;
0620 
0621         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
0622             if (txout.scriptPubKey == scriptPubKey)
0623                 if (wtx.GetDepthInMainChain() >= nMinDepth)
0624                     nAmount += txout.nValue;
0625     }
0626 
0627     return  ValueFromAmount(nAmount);
0628 }
0629 
0630 
0631 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
0632 {
0633     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
0634     {
0635         const CBitcoinAddress& address = item.first;
0636         const string& strName = item.second;
0637         if (strName == strAccount)
0638             setAddress.insert(address);
0639     }
0640 }
0641 
0642 
0643 Value getreceivedbyaccount(const Array& params, bool fHelp)
0644 {
0645     if (fHelp || params.size() < 1 || params.size() > 2)
0646         throw runtime_error(
0647             "getreceivedbyaccount <account> [minconf=1]\n"
0648             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
0649 
0650     // Minimum confirmations
0651     int nMinDepth = 1;
0652     if (params.size() > 1)
0653         nMinDepth = params[1].get_int();
0654 
0655     // Get the set of pub keys that have the label
0656     string strAccount = AccountFromValue(params[0]);
0657     set<CBitcoinAddress> setAddress;
0658     GetAccountAddresses(strAccount, setAddress);
0659 
0660     // Tally
0661     int64 nAmount = 0;
0662     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
0663     {
0664         const CWalletTx& wtx = (*it).second;
0665         if (wtx.IsCoinBase() || !wtx.IsFinal())
0666             continue;
0667 
0668         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
0669         {
0670             CBitcoinAddress address;
0671             if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
0672                 if (wtx.GetDepthInMainChain() >= nMinDepth)
0673                     nAmount += txout.nValue;
0674         }
0675     }
0676 
0677     return (double)nAmount / (double)COIN;
0678 }
0679 
0680 
0681 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
0682 {
0683     int64 nBalance = 0;
0684 
0685     // Tally wallet transactions
0686     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
0687     {
0688         const CWalletTx& wtx = (*it).second;
0689         if (!wtx.IsFinal())
0690             continue;
0691 
0692         int64 nGenerated, nReceived, nSent, nFee;
0693         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
0694 
0695         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
0696             nBalance += nReceived;
0697         nBalance += nGenerated - nSent - nFee;
0698     }
0699 
0700     // Tally internal accounting entries
0701     nBalance += walletdb.GetAccountCreditDebit(strAccount);
0702 
0703     return nBalance;
0704 }
0705 
0706 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
0707 {
0708     CWalletDB walletdb(pwalletMain->strWalletFile);
0709     return GetAccountBalance(walletdb, strAccount, nMinDepth);
0710 }
0711 
0712 
0713 Value getbalance(const Array& params, bool fHelp)
0714 {
0715     if (fHelp || params.size() > 2)
0716         throw runtime_error(
0717             "getbalance [account] [minconf=1]\n"
0718             "If [account] is not specified, returns the server's total available balance.\n"
0719             "If [account] is specified, returns the balance in the account.");
0720 
0721     if (params.size() == 0)
0722         return  ValueFromAmount(pwalletMain->GetBalance());
0723 
0724     int nMinDepth = 1;
0725     if (params.size() > 1)
0726         nMinDepth = params[1].get_int();
0727 
0728     if (params[0].get_str() == "*") {
0729         // Calculate total balance a different way from GetBalance()
0730         // (GetBalance() sums up all unspent TxOuts)
0731         // getbalance and getbalance '*' should always return the same number.
0732         int64 nBalance = 0;
0733         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
0734         {
0735             const CWalletTx& wtx = (*it).second;
0736             if (!wtx.IsFinal())
0737                 continue;
0738 
0739             int64 allGeneratedImmature, allGeneratedMature, allFee;
0740             allGeneratedImmature = allGeneratedMature = allFee = 0;
0741             string strSentAccount;
0742             list<pair<CBitcoinAddress, int64> > listReceived;
0743             list<pair<CBitcoinAddress, int64> > listSent;
0744             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
0745             if (wtx.GetDepthInMainChain() >= nMinDepth)
0746                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
0747                     nBalance += r.second;
0748             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
0749                 nBalance -= r.second;
0750             nBalance -= allFee;
0751             nBalance += allGeneratedMature;
0752         }
0753         return  ValueFromAmount(nBalance);
0754     }
0755 
0756     string strAccount = AccountFromValue(params[0]);
0757 
0758     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
0759 
0760     return ValueFromAmount(nBalance);
0761 }
0762 
0763 
0764 Value movecmd(const Array& params, bool fHelp)
0765 {
0766     if (fHelp || params.size() < 3 || params.size() > 5)
0767         throw runtime_error(
0768             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
0769             "Move from one account in your wallet to another.");
0770 
0771     string strFrom = AccountFromValue(params[0]);
0772     string strTo = AccountFromValue(params[1]);
0773     int64 nAmount = AmountFromValue(params[2]);
0774     if (params.size() > 3)
0775         // unused parameter, used to be nMinDepth, keep type-checking it though
0776         (void)params[3].get_int();
0777     string strComment;
0778     if (params.size() > 4)
0779         strComment = params[4].get_str();
0780 
0781     CWalletDB walletdb(pwalletMain->strWalletFile);
0782     walletdb.TxnBegin();
0783 
0784     int64 nNow = GetAdjustedTime();
0785 
0786     // Debit
0787     CAccountingEntry debit;
0788     debit.strAccount = strFrom;
0789     debit.nCreditDebit = -nAmount;
0790     debit.nTime = nNow;
0791     debit.strOtherAccount = strTo;
0792     debit.strComment = strComment;
0793     walletdb.WriteAccountingEntry(debit);
0794 
0795     // Credit
0796     CAccountingEntry credit;
0797     credit.strAccount = strTo;
0798     credit.nCreditDebit = nAmount;
0799     credit.nTime = nNow;
0800     credit.strOtherAccount = strFrom;
0801     credit.strComment = strComment;
0802     walletdb.WriteAccountingEntry(credit);
0803 
0804     walletdb.TxnCommit();
0805 
0806     return true;
0807 }
0808 
0809 
0810 Value sendfrom(const Array& params, bool fHelp)
0811 {
0812     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
0813         throw runtime_error(
0814             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
0815             "<amount> is a real and is rounded to the nearest 0.00000001\n"
0816             "requires wallet passphrase to be set with walletpassphrase first");
0817     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
0818         throw runtime_error(
0819             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
0820             "<amount> is a real and is rounded to the nearest 0.00000001");
0821 
0822     string strAccount = AccountFromValue(params[0]);
0823     CBitcoinAddress address(params[1].get_str());
0824     if (!address.IsValid())
0825         throw JSONRPCError(-5, "Invalid bitcoin address");
0826     int64 nAmount = AmountFromValue(params[2]);
0827     int nMinDepth = 1;
0828     if (params.size() > 3)
0829         nMinDepth = params[3].get_int();
0830 
0831     CWalletTx wtx;
0832     wtx.strFromAccount = strAccount;
0833     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
0834         wtx.mapValue["comment"] = params[4].get_str();
0835     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
0836         wtx.mapValue["to"]      = params[5].get_str();
0837 
0838     if (pwalletMain->IsLocked())
0839         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
0840 
0841     // Check funds
0842     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
0843     if (nAmount > nBalance)
0844         throw JSONRPCError(-6, "Account has insufficient funds");
0845 
0846     // Send
0847     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
0848     if (strError != "")
0849         throw JSONRPCError(-4, strError);
0850 
0851     return wtx.GetHash().GetHex();
0852 }
0853 
0854 
0855 Value sendmany(const Array& params, bool fHelp)
0856 {
0857     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
0858         throw runtime_error(
0859             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
0860             "amounts are double-precision floating point numbers\n"
0861             "requires wallet passphrase to be set with walletpassphrase first");
0862     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
0863         throw runtime_error(
0864             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
0865             "amounts are double-precision floating point numbers");
0866 
0867     string strAccount = AccountFromValue(params[0]);
0868     Object sendTo = params[1].get_obj();
0869     int nMinDepth = 1;
0870     if (params.size() > 2)
0871         nMinDepth = params[2].get_int();
0872 
0873     CWalletTx wtx;
0874     wtx.strFromAccount = strAccount;
0875     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
0876         wtx.mapValue["comment"] = params[3].get_str();
0877 
0878     set<CBitcoinAddress> setAddress;
0879     vector<pair<CScript, int64> > vecSend;
0880 
0881     int64 totalAmount = 0;
0882     BOOST_FOREACH(const Pair& s, sendTo)
0883     {
0884         CBitcoinAddress address(s.name_);
0885         if (!address.IsValid())
0886             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
0887 
0888         if (setAddress.count(address))
0889             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
0890         setAddress.insert(address);
0891 
0892         CScript scriptPubKey;
0893         scriptPubKey.SetBitcoinAddress(address);
0894         int64 nAmount = AmountFromValue(s.value_); 
0895         totalAmount += nAmount;
0896 
0897         vecSend.push_back(make_pair(scriptPubKey, nAmount));
0898     }
0899 
0900     if (pwalletMain->IsLocked())
0901         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
0902 
0903     // Check funds
0904     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
0905     if (totalAmount > nBalance)
0906         throw JSONRPCError(-6, "Account has insufficient funds");
0907 
0908     // Send
0909     CReserveKey keyChange(pwalletMain);
0910     int64 nFeeRequired = 0;
0911     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
0912     if (!fCreated)
0913     {
0914         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
0915             throw JSONRPCError(-6, "Insufficient funds");
0916         throw JSONRPCError(-4, "Transaction creation failed");
0917     }
0918     if (!pwalletMain->CommitTransaction(wtx, keyChange))
0919         throw JSONRPCError(-4, "Transaction commit failed");
0920 
0921     return wtx.GetHash().GetHex();
0922 }
0923 
0924 
0925 struct tallyitem
0926 {
0927     int64 nAmount;
0928     int nConf;
0929     tallyitem()
0930     {
0931         nAmount = 0;
0932         nConf = INT_MAX;
0933     }
0934 };
0935 
0936 Value ListReceived(const Array& params, bool fByAccounts)
0937 {
0938     // Minimum confirmations
0939     int nMinDepth = 1;
0940     if (params.size() > 0)
0941         nMinDepth = params[0].get_int();
0942 
0943     // Whether to include empty accounts
0944     bool fIncludeEmpty = false;
0945     if (params.size() > 1)
0946         fIncludeEmpty = params[1].get_bool();
0947 
0948     // Tally
0949     map<CBitcoinAddress, tallyitem> mapTally;
0950     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
0951     {
0952         const CWalletTx& wtx = (*it).second;
0953         if (wtx.IsCoinBase() || !wtx.IsFinal())
0954             continue;
0955 
0956         int nDepth = wtx.GetDepthInMainChain();
0957         if (nDepth < nMinDepth)
0958             continue;
0959 
0960         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
0961         {
0962             CBitcoinAddress address;
0963             if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
0964                 continue;
0965 
0966             tallyitem& item = mapTally[address];
0967             item.nAmount += txout.nValue;
0968             item.nConf = min(item.nConf, nDepth);
0969         }
0970     }
0971 
0972     // Reply
0973     Array ret;
0974     map<string, tallyitem> mapAccountTally;
0975     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
0976     {
0977         const CBitcoinAddress& address = item.first;
0978         const string& strAccount = item.second;
0979         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
0980         if (it == mapTally.end() && !fIncludeEmpty)
0981             continue;
0982 
0983         int64 nAmount = 0;
0984         int nConf = INT_MAX;
0985         if (it != mapTally.end())
0986         {
0987             nAmount = (*it).second.nAmount;
0988             nConf = (*it).second.nConf;
0989         }
0990 
0991         if (fByAccounts)
0992         {
0993             tallyitem& item = mapAccountTally[strAccount];
0994             item.nAmount += nAmount;
0995             item.nConf = min(item.nConf, nConf);
0996         }
0997         else
0998         {
0999             Object obj;
1000             obj.push_back(Pair("address",       address.ToString()));
1001             obj.push_back(Pair("account",       strAccount));
1002             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1003             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1004             ret.push_back(obj);
1005         }
1006     }
1007 
1008     if (fByAccounts)
1009     {
1010         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1011         {
1012             int64 nAmount = (*it).second.nAmount;
1013             int nConf = (*it).second.nConf;
1014             Object obj;
1015             obj.push_back(Pair("account",       (*it).first));
1016             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1017             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1018             ret.push_back(obj);
1019         }
1020     }
1021 
1022     return ret;
1023 }
1024 
1025 Value listreceivedbyaddress(const Array& params, bool fHelp)
1026 {
1027     if (fHelp || params.size() > 2)
1028         throw runtime_error(
1029             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1030             "[minconf] is the minimum number of confirmations before payments are included.\n"
1031             "[includeempty] whether to include addresses that haven't received any payments.\n"
1032             "Returns an array of objects containing:\n"
1033             "  \"address\" : receiving address\n"
1034             "  \"account\" : the account of the receiving address\n"
1035             "  \"amount\" : total amount received by the address\n"
1036             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1037 
1038     return ListReceived(params, false);
1039 }
1040 
1041 Value listreceivedbyaccount(const Array& params, bool fHelp)
1042 {
1043     if (fHelp || params.size() > 2)
1044         throw runtime_error(
1045             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1046             "[minconf] is the minimum number of confirmations before payments are included.\n"
1047             "[includeempty] whether to include accounts that haven't received any payments.\n"
1048             "Returns an array of objects containing:\n"
1049             "  \"account\" : the account of the receiving addresses\n"
1050             "  \"amount\" : total amount received by addresses with this account\n"
1051             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1052 
1053     return ListReceived(params, true);
1054 }
1055 
1056 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1057 {
1058     int64 nGeneratedImmature, nGeneratedMature, nFee;
1059     string strSentAccount;
1060     list<pair<CBitcoinAddress, int64> > listReceived;
1061     list<pair<CBitcoinAddress, int64> > listSent;
1062     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1063 
1064     bool fAllAccounts = (strAccount == string("*"));
1065 
1066     // Generated blocks assigned to account ""
1067     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1068     {
1069         Object entry;
1070         entry.push_back(Pair("account", string("")));
1071         if (nGeneratedImmature)
1072         {
1073             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1074             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1075         }
1076         else
1077         {
1078             entry.push_back(Pair("category", "generate"));
1079             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1080         }
1081         if (fLong)
1082             WalletTxToJSON(wtx, entry);
1083         ret.push_back(entry);
1084     }
1085 
1086     // Sent
1087     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1088     {
1089         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1090         {
1091             Object entry;
1092             entry.push_back(Pair("account", strSentAccount));
1093             entry.push_back(Pair("address", s.first.ToString()));
1094             entry.push_back(Pair("category", "send"));
1095             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1096             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1097             if (fLong)
1098                 WalletTxToJSON(wtx, entry);
1099             ret.push_back(entry);
1100         }
1101     }
1102 
1103     // Received
1104     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1105         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1106         {
1107             string account;
1108             if (pwalletMain->mapAddressBook.count(r.first))
1109                 account = pwalletMain->mapAddressBook[r.first];
1110             if (fAllAccounts || (account == strAccount))
1111             {
1112                 Object entry;
1113                 entry.push_back(Pair("account", account));
1114                 entry.push_back(Pair("address", r.first.ToString()));
1115                 entry.push_back(Pair("category", "receive"));
1116                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1117                 if (fLong)
1118                     WalletTxToJSON(wtx, entry);
1119                 ret.push_back(entry);
1120             }
1121         }
1122 }
1123 
1124 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1125 {
1126     bool fAllAccounts = (strAccount == string("*"));
1127 
1128     if (fAllAccounts || acentry.strAccount == strAccount)
1129     {
1130         Object entry;
1131         entry.push_back(Pair("account", acentry.strAccount));
1132         entry.push_back(Pair("category", "move"));
1133         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1134         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1135         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1136         entry.push_back(Pair("comment", acentry.strComment));
1137         ret.push_back(entry);
1138     }
1139 }
1140 
1141 Value listtransactions(const Array& params, bool fHelp)
1142 {
1143     if (fHelp || params.size() > 3)
1144         throw runtime_error(
1145             "listtransactions [account] [count=10] [from=0]\n"
1146             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1147 
1148     string strAccount = "*";
1149     if (params.size() > 0)
1150         strAccount = params[0].get_str();
1151     int nCount = 10;
1152     if (params.size() > 1)
1153         nCount = params[1].get_int();
1154     int nFrom = 0;
1155     if (params.size() > 2)
1156         nFrom = params[2].get_int();
1157 
1158     Array ret;
1159     CWalletDB walletdb(pwalletMain->strWalletFile);
1160 
1161     // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1162     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1163     typedef multimap<int64, TxPair > TxItems;
1164     TxItems txByTime;
1165 
1166     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1167     {
1168         CWalletTx* wtx = &((*it).second);
1169         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1170     }
1171     list<CAccountingEntry> acentries;
1172     walletdb.ListAccountCreditDebit(strAccount, acentries);
1173     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1174     {
1175         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1176     }
1177 
1178     // Now: iterate backwards until we have nCount items to return:
1179     TxItems::reverse_iterator it = txByTime.rbegin();
1180     if (txByTime.size() > nFrom) std::advance(it, nFrom);
1181     for (; it != txByTime.rend(); ++it)
1182     {
1183         CWalletTx *const pwtx = (*it).second.first;
1184         if (pwtx != 0)
1185             ListTransactions(*pwtx, strAccount, 0, true, ret);
1186         CAccountingEntry *const pacentry = (*it).second.second;
1187         if (pacentry != 0)
1188             AcentryToJSON(*pacentry, strAccount, ret);
1189 
1190         if (ret.size() >= nCount) break;
1191     }
1192     // ret is now newest to oldest
1193     
1194     // Make sure we return only last nCount items (sends-to-self might give us an extra):
1195     if (ret.size() > nCount)
1196     {
1197         Array::iterator last = ret.begin();
1198         std::advance(last, nCount);
1199         ret.erase(last, ret.end());
1200     }
1201     std::reverse(ret.begin(), ret.end()); // oldest to newest
1202 
1203     return ret;
1204 }
1205 
1206 Value listaccounts(const Array& params, bool fHelp)
1207 {
1208     if (fHelp || params.size() > 1)
1209         throw runtime_error(
1210             "listaccounts [minconf=1]\n"
1211             "Returns Object that has account names as keys, account balances as values.");
1212 
1213     int nMinDepth = 1;
1214     if (params.size() > 0)
1215         nMinDepth = params[0].get_int();
1216 
1217     map<string, int64> mapAccountBalances;
1218     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1219         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1220             mapAccountBalances[entry.second] = 0;
1221     }
1222 
1223     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1224     {
1225         const CWalletTx& wtx = (*it).second;
1226         int64 nGeneratedImmature, nGeneratedMature, nFee;
1227         string strSentAccount;
1228         list<pair<CBitcoinAddress, int64> > listReceived;
1229         list<pair<CBitcoinAddress, int64> > listSent;
1230         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1231         mapAccountBalances[strSentAccount] -= nFee;
1232         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1233             mapAccountBalances[strSentAccount] -= s.second;
1234         if (wtx.GetDepthInMainChain() >= nMinDepth)
1235         {
1236             mapAccountBalances[""] += nGeneratedMature;
1237             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1238                 if (pwalletMain->mapAddressBook.count(r.first))
1239                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1240                 else
1241                     mapAccountBalances[""] += r.second;
1242         }
1243     }
1244 
1245     list<CAccountingEntry> acentries;
1246     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1247     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1248         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1249 
1250     Object ret;
1251     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1252         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1253     }
1254     return ret;
1255 }
1256 
1257 Value listsinceblock(const Array& params, bool fHelp)
1258 {
1259     if (fHelp)
1260         throw runtime_error(
1261             "listsinceblock [blockid] [target-confirmations]\n"
1262             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1263 
1264     CBlockIndex *pindex = NULL;
1265     int target_confirms = 1;
1266 
1267     if (params.size() > 0)
1268     {
1269         uint256 blockId = 0;
1270 
1271         blockId.SetHex(params[0].get_str());
1272         pindex = CBlockLocator(blockId).GetBlockIndex();
1273     }
1274 
1275     if (params.size() > 1)
1276     {
1277         target_confirms = params[1].get_int();
1278 
1279         if (target_confirms < 1)
1280             throw JSONRPCError(-8, "Invalid parameter");
1281     }
1282 
1283     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1284 
1285     Array transactions;
1286 
1287     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1288     {
1289         CWalletTx tx = (*it).second;
1290 
1291         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1292             ListTransactions(tx, "*", 0, true, transactions);
1293     }
1294 
1295     uint256 lastblock;
1296 
1297     if (target_confirms == 1)
1298     {
1299         printf("oops!\n");
1300         lastblock = hashBestChain;
1301     }
1302     else
1303     {
1304         int target_height = pindexBest->nHeight + 1 - target_confirms;
1305 
1306         CBlockIndex *block;
1307         for (block = pindexBest;
1308              block && block->nHeight > target_height;
1309              block = block->pprev)  { }
1310 
1311         lastblock = block ? block->GetBlockHash() : 0;
1312     }
1313 
1314     Object ret;
1315     ret.push_back(Pair("transactions", transactions));
1316     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1317 
1318     return ret;
1319 }
1320 
1321 Value gettransaction(const Array& params, bool fHelp)
1322 {
1323     if (fHelp || params.size() != 1)
1324         throw runtime_error(
1325             "gettransaction <txid>\n"
1326             "Get detailed information about <txid>");
1327 
1328     uint256 hash;
1329     hash.SetHex(params[0].get_str());
1330 
1331     Object entry;
1332 
1333     if (!pwalletMain->mapWallet.count(hash))
1334         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1335     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1336 
1337     int64 nCredit = wtx.GetCredit();
1338     int64 nDebit = wtx.GetDebit();
1339     int64 nNet = nCredit - nDebit;
1340     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1341 
1342     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1343     if (wtx.IsFromMe())
1344         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1345 
1346     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1347 
1348     Array details;
1349     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1350     entry.push_back(Pair("details", details));
1351 
1352     return entry;
1353 }
1354 
1355 
1356 Value backupwallet(const Array& params, bool fHelp)
1357 {
1358     if (fHelp || params.size() != 1)
1359         throw runtime_error(
1360             "backupwallet <destination>\n"
1361             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1362 
1363     string strDest = params[0].get_str();
1364     BackupWallet(*pwalletMain, strDest);
1365 
1366     return Value::null;
1367 }
1368 
1369 
1370 Value keypoolrefill(const Array& params, bool fHelp)
1371 {
1372     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1373         throw runtime_error(
1374             "keypoolrefill\n"
1375             "Fills the keypool, requires wallet passphrase to be set.");
1376     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1377         throw runtime_error(
1378             "keypoolrefill\n"
1379             "Fills the keypool.");
1380 
1381     if (pwalletMain->IsLocked())
1382         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1383 
1384     pwalletMain->TopUpKeyPool();
1385 
1386     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1387         throw JSONRPCError(-4, "Error refreshing keypool.");
1388 
1389     return Value::null;
1390 }
1391 
1392 
1393 void ThreadTopUpKeyPool(void* parg)
1394 {
1395     pwalletMain->TopUpKeyPool();
1396 }
1397 
1398 void ThreadCleanWalletPassphrase(void* parg)
1399 {
1400     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1401 
1402     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1403 
1404     if (nWalletUnlockTime == 0)
1405     {
1406         nWalletUnlockTime = nMyWakeTime;
1407 
1408         do
1409         {
1410             if (nWalletUnlockTime==0)
1411                 break;
1412             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1413             if (nToSleep <= 0)
1414                 break;
1415 
1416             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1417             Sleep(nToSleep);
1418             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1419 
1420         } while(1);
1421 
1422         if (nWalletUnlockTime)
1423         {
1424             nWalletUnlockTime = 0;
1425             pwalletMain->Lock();
1426         }
1427     }
1428     else
1429     {
1430         if (nWalletUnlockTime < nMyWakeTime)
1431             nWalletUnlockTime = nMyWakeTime;
1432     }
1433 
1434     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1435 
1436     delete (int64*)parg;
1437 }
1438 
1439 Value walletpassphrase(const Array& params, bool fHelp)
1440 {
1441     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1442         throw runtime_error(
1443             "walletpassphrase <passphrase> <timeout>\n"
1444             "Stores the wallet decryption key in memory for <timeout> seconds.");
1445     if (fHelp)
1446         return true;
1447     if (!pwalletMain->IsCrypted())
1448         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1449 
1450     if (!pwalletMain->IsLocked())
1451         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1452 
1453     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1454     SecureString strWalletPass;
1455     strWalletPass.reserve(100);
1456     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1457     // Alternately, find a way to make params[0] mlock()'d to begin with.
1458     strWalletPass = params[0].get_str().c_str();
1459 
1460     if (strWalletPass.length() > 0)
1461     {
1462         if (!pwalletMain->Unlock(strWalletPass))
1463             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1464     }
1465     else
1466         throw runtime_error(
1467             "walletpassphrase <passphrase> <timeout>\n"
1468             "Stores the wallet decryption key in memory for <timeout> seconds.");
1469 
1470     CreateThread(ThreadTopUpKeyPool, NULL);
1471     int64* pnSleepTime = new int64(params[1].get_int64());
1472     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1473 
1474     return Value::null;
1475 }
1476 
1477 
1478 Value walletpassphrasechange(const Array& params, bool fHelp)
1479 {
1480     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1481         throw runtime_error(
1482             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1483             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1484     if (fHelp)
1485         return true;
1486     if (!pwalletMain->IsCrypted())
1487         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1488 
1489     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1490     // Alternately, find a way to make params[0] mlock()'d to begin with.
1491     SecureString strOldWalletPass;
1492     strOldWalletPass.reserve(100);
1493     strOldWalletPass = params[0].get_str().c_str();
1494 
1495     SecureString strNewWalletPass;
1496     strNewWalletPass.reserve(100);
1497     strNewWalletPass = params[1].get_str().c_str();
1498 
1499     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1500         throw runtime_error(
1501             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1502             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1503 
1504     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1505         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1506 
1507     return Value::null;
1508 }
1509 
1510 
1511 Value walletlock(const Array& params, bool fHelp)
1512 {
1513     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1514         throw runtime_error(
1515             "walletlock\n"
1516             "Removes the wallet encryption key from memory, locking the wallet.\n"
1517             "After calling this method, you will need to call walletpassphrase again\n"
1518             "before being able to call any methods which require the wallet to be unlocked.");
1519     if (fHelp)
1520         return true;
1521     if (!pwalletMain->IsCrypted())
1522         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1523 
1524     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1525     {
1526         pwalletMain->Lock();
1527         nWalletUnlockTime = 0;
1528     }
1529 
1530     return Value::null;
1531 }
1532 
1533 
1534 Value encryptwallet(const Array& params, bool fHelp)
1535 {
1536     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1537         throw runtime_error(
1538             "encryptwallet <passphrase>\n"
1539             "Encrypts the wallet with <passphrase>.");
1540     if (fHelp)
1541         return true;
1542     if (pwalletMain->IsCrypted())
1543         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1544 
1545     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1546     // Alternately, find a way to make params[0] mlock()'d to begin with.
1547     SecureString strWalletPass;
1548     strWalletPass.reserve(100);
1549     strWalletPass = params[0].get_str().c_str();
1550 
1551     if (strWalletPass.length() < 1)
1552         throw runtime_error(
1553             "encryptwallet <passphrase>\n"
1554             "Encrypts the wallet with <passphrase>.");
1555 
1556     if (!pwalletMain->EncryptWallet(strWalletPass))
1557         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1558 
1559     // BDB seems to have a bad habit of writing old data into
1560     // slack space in .dat files; that is bad if the old data is
1561     // unencrypted private keys.  So:
1562     CreateThread(Shutdown, NULL);
1563     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1564 }
1565 
1566 
1567 Value validateaddress(const Array& params, bool fHelp)
1568 {
1569     if (fHelp || params.size() != 1)
1570         throw runtime_error(
1571             "validateaddress <bitcoinaddress>\n"
1572             "Return information about <bitcoinaddress>.");
1573 
1574     CBitcoinAddress address(params[0].get_str());
1575     bool isValid = address.IsValid();
1576 
1577     Object ret;
1578     ret.push_back(Pair("isvalid", isValid));
1579     if (isValid)
1580     {
1581         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1582         // version of the address:
1583         string currentAddress = address.ToString();
1584         ret.push_back(Pair("address", currentAddress));
1585         ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1586         if (pwalletMain->mapAddressBook.count(address))
1587             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1588     }
1589     return ret;
1590 }
1591 
1592 
1593 Value getwork(const Array& params, bool fHelp)
1594 {
1595     if (fHelp || params.size() > 1)
1596         throw runtime_error(
1597             "getwork [data]\n"
1598             "If [data] is not specified, returns formatted hash data to work on:\n"
1599             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1600             "  \"data\" : block data\n"
1601             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1602             "  \"target\" : little endian hash target\n"
1603             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1604 
1605     if (vNodes.empty())
1606         throw JSONRPCError(-9, "Bitcoin is not connected!");
1607 
1608     if (IsInitialBlockDownload())
1609         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1610 
1611     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1612     static mapNewBlock_t mapNewBlock;
1613     static vector<CBlock*> vNewBlock;
1614     static CReserveKey reservekey(pwalletMain);
1615 
1616     if (params.size() == 0)
1617     {
1618         // Update block
1619         static unsigned int nTransactionsUpdatedLast;
1620         static CBlockIndex* pindexPrev;
1621         static int64 nStart;
1622         static CBlock* pblock;
1623         if (pindexPrev != pindexBest ||
1624             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1625         {
1626             if (pindexPrev != pindexBest)
1627             {
1628                 // Deallocate old blocks since they're obsolete now
1629                 mapNewBlock.clear();
1630                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1631                     delete pblock;
1632                 vNewBlock.clear();
1633             }
1634             nTransactionsUpdatedLast = nTransactionsUpdated;
1635             pindexPrev = pindexBest;
1636             nStart = GetTime();
1637 
1638             // Create new block
1639             pblock = CreateNewBlock(reservekey);
1640             if (!pblock)
1641                 throw JSONRPCError(-7, "Out of memory");
1642             vNewBlock.push_back(pblock);
1643         }
1644 
1645         // Update nTime
1646         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1647         pblock->nNonce = 0;
1648 
1649         // Update nExtraNonce
1650         static unsigned int nExtraNonce = 0;
1651         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1652 
1653         // Save
1654         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1655 
1656         // Prebuild hash buffers
1657         char pmidstate[32];
1658         char pdata[128];
1659         char phash1[64];
1660         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1661 
1662         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1663 
1664         Object result;
1665         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1666         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1667         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1668         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1669         return result;
1670     }
1671     else
1672     {
1673         // Parse parameters
1674         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1675         if (vchData.size() != 128)
1676             throw JSONRPCError(-8, "Invalid parameter");
1677         CBlock* pdata = (CBlock*)&vchData[0];
1678 
1679         // Byte reverse
1680         for (int i = 0; i < 128/4; i++)
1681             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1682 
1683         // Get saved block
1684         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1685             return false;
1686         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1687 
1688         pblock->nTime = pdata->nTime;
1689         pblock->nNonce = pdata->nNonce;
1690         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1691         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1692 
1693         return CheckWork(pblock, *pwalletMain, reservekey);
1694     }
1695 }
1696 
1697 
1698 Value getmemorypool(const Array& params, bool fHelp)
1699 {
1700     if (fHelp || params.size() > 1)
1701         throw runtime_error(
1702             "getmemorypool [data]\n"
1703             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1704             "  \"version\" : block version\n"
1705             "  \"previousblockhash\" : hash of current highest block\n"
1706             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1707             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1708             "  \"time\" : timestamp appropriate for next block\n"
1709             "  \"bits\" : compressed target of next block\n"
1710             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1711 
1712     if (params.size() == 0)
1713     {
1714         if (vNodes.empty())
1715             throw JSONRPCError(-9, "Bitcoin is not connected!");
1716 
1717         if (IsInitialBlockDownload())
1718             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1719 
1720         static CReserveKey reservekey(pwalletMain);
1721 
1722         // Update block
1723         static unsigned int nTransactionsUpdatedLast;
1724         static CBlockIndex* pindexPrev;
1725         static int64 nStart;
1726         static CBlock* pblock;
1727         if (pindexPrev != pindexBest ||
1728             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1729         {
1730             nTransactionsUpdatedLast = nTransactionsUpdated;
1731             pindexPrev = pindexBest;
1732             nStart = GetTime();
1733 
1734             // Create new block
1735             if(pblock)
1736                 delete pblock;
1737             pblock = CreateNewBlock(reservekey);
1738             if (!pblock)
1739                 throw JSONRPCError(-7, "Out of memory");
1740         }
1741 
1742         // Update nTime
1743         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1744         pblock->nNonce = 0;
1745 
1746         Array transactions;
1747         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1748             if(tx.IsCoinBase())
1749                 continue;
1750 
1751             CDataStream ssTx;
1752             ssTx << tx;
1753 
1754             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1755         }
1756 
1757         Object result;
1758         result.push_back(Pair("version", pblock->nVersion));
1759         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1760         result.push_back(Pair("transactions", transactions));
1761         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1762         result.push_back(Pair("time", (int64_t)pblock->nTime));
1763 
1764         union {
1765             int32_t nBits;
1766             char cBits[4];
1767         } uBits;
1768         uBits.nBits = htonl((int32_t)pblock->nBits);
1769         result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
1770 
1771         return result;
1772     }
1773     else
1774     {
1775         // Parse parameters
1776         CDataStream ssBlock(ParseHex(params[0].get_str()));
1777         CBlock pblock;
1778         ssBlock >> pblock;
1779 
1780         return ProcessBlock(NULL, &pblock);
1781     }
1782 }
1783 
1784 
1785 
1786 
1787 
1788 
1789 
1790 
1791 
1792 
1793 
1794 //
1795 // Call Table
1796 //
1797 
1798 pair<string, rpcfn_type> pCallTable[] =
1799 {
1800     make_pair("help",                   &help),
1801     make_pair("stop",                   &stop),
1802     make_pair("getblockcount",          &getblockcount),
1803     make_pair("getblocknumber",         &getblocknumber),
1804     make_pair("getconnectioncount",     &getconnectioncount),
1805     make_pair("getdifficulty",          &getdifficulty),
1806     make_pair("getgenerate",            &getgenerate),
1807     make_pair("setgenerate",            &setgenerate),
1808     make_pair("gethashespersec",        &gethashespersec),
1809     make_pair("getinfo",                &getinfo),
1810     make_pair("getnewaddress",          &getnewaddress),
1811     make_pair("getaccountaddress",      &getaccountaddress),
1812     make_pair("setaccount",             &setaccount),
1813     make_pair("getaccount",             &getaccount),
1814     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
1815     make_pair("sendtoaddress",          &sendtoaddress),
1816     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
1817     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
1818     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
1819     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
1820     make_pair("backupwallet",           &backupwallet),
1821     make_pair("keypoolrefill",          &keypoolrefill),
1822     make_pair("walletpassphrase",       &walletpassphrase),
1823     make_pair("walletpassphrasechange", &walletpassphrasechange),
1824     make_pair("walletlock",             &walletlock),
1825     make_pair("encryptwallet",          &encryptwallet),
1826     make_pair("validateaddress",        &validateaddress),
1827     make_pair("getbalance",             &getbalance),
1828     make_pair("move",                   &movecmd),
1829     make_pair("sendfrom",               &sendfrom),
1830     make_pair("sendmany",               &sendmany),
1831     make_pair("gettransaction",         &gettransaction),
1832     make_pair("listtransactions",       &listtransactions),
1833     make_pair("signmessage",           &signmessage),
1834     make_pair("verifymessage",         &verifymessage),
1835     make_pair("getwork",                &getwork),
1836     make_pair("listaccounts",           &listaccounts),
1837     make_pair("settxfee",               &settxfee),
1838     make_pair("getmemorypool",          &getmemorypool),
1839     make_pair("listsinceblock",        &listsinceblock),
1840 };
1841 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1842 
1843 string pAllowInSafeMode[] =
1844 {
1845     "help",
1846     "stop",
1847     "getblockcount",
1848     "getblocknumber",  // deprecated
1849     "getconnectioncount",
1850     "getdifficulty",
1851     "getgenerate",
1852     "setgenerate",
1853     "gethashespersec",
1854     "getinfo",
1855     "getnewaddress",
1856     "getaccountaddress",
1857     "getaccount",
1858     "getaddressesbyaccount",
1859     "backupwallet",
1860     "keypoolrefill",
1861     "walletpassphrase",
1862     "walletlock",
1863     "validateaddress",
1864     "getwork",
1865     "getmemorypool",
1866 };
1867 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1868 
1869 
1870 
1871 
1872 //
1873 // HTTP protocol
1874 //
1875 // This ain't Apache.  We're just using HTTP header for the length field
1876 // and to be compatible with other JSON-RPC implementations.
1877 //
1878 
1879 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1880 {
1881     ostringstream s;
1882     s << "POST / HTTP/1.1\r\n"
1883       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1884       << "Host: 127.0.0.1\r\n"
1885       << "Content-Type: application/json\r\n"
1886       << "Content-Length: " << strMsg.size() << "\r\n"
1887       << "Connection: close\r\n"
1888       << "Accept: application/json\r\n";
1889     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1890         s << item.first << ": " << item.second << "\r\n";
1891     s << "\r\n" << strMsg;
1892 
1893     return s.str();
1894 }
1895 
1896 string rfc1123Time()
1897 {
1898     char buffer[64];
1899     time_t now;
1900     time(&now);
1901     struct tm* now_gmt = gmtime(&now);
1902     string locale(setlocale(LC_TIME, NULL));
1903     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1904     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1905     setlocale(LC_TIME, locale.c_str());
1906     return string(buffer);
1907 }
1908 
1909 static string HTTPReply(int nStatus, const string& strMsg)
1910 {
1911     if (nStatus == 401)
1912         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1913             "Date: %s\r\n"
1914             "Server: bitcoin-json-rpc/%s\r\n"
1915             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1916             "Content-Type: text/html\r\n"
1917             "Content-Length: 296\r\n"
1918             "\r\n"
1919             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1920             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1921             "<HTML>\r\n"
1922             "<HEAD>\r\n"
1923             "<TITLE>Error</TITLE>\r\n"
1924             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1925             "</HEAD>\r\n"
1926             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1927             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1928     const char *cStatus;
1929          if (nStatus == 200) cStatus = "OK";
1930     else if (nStatus == 400) cStatus = "Bad Request";
1931     else if (nStatus == 403) cStatus = "Forbidden";
1932     else if (nStatus == 404) cStatus = "Not Found";
1933     else if (nStatus == 500) cStatus = "Internal Server Error";
1934     else cStatus = "";
1935     return strprintf(
1936             "HTTP/1.1 %d %s\r\n"
1937             "Date: %s\r\n"
1938             "Connection: close\r\n"
1939             "Content-Length: %d\r\n"
1940             "Content-Type: application/json\r\n"
1941             "Server: bitcoin-json-rpc/%s\r\n"
1942             "\r\n"
1943             "%s",
1944         nStatus,
1945         cStatus,
1946         rfc1123Time().c_str(),
1947         strMsg.size(),
1948         FormatFullVersion().c_str(),
1949         strMsg.c_str());
1950 }
1951 
1952 int ReadHTTPStatus(std::basic_istream<char>& stream)
1953 {
1954     string str;
1955     getline(stream, str);
1956     vector<string> vWords;
1957     boost::split(vWords, str, boost::is_any_of(" "));
1958     if (vWords.size() < 2)
1959         return 500;
1960     return atoi(vWords[1].c_str());
1961 }
1962 
1963 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1964 {
1965     int nLen = 0;
1966     loop
1967     {
1968         string str;
1969         std::getline(stream, str);
1970         if (str.empty() || str == "\r")
1971             break;
1972         string::size_type nColon = str.find(":");
1973         if (nColon != string::npos)
1974         {
1975             string strHeader = str.substr(0, nColon);
1976             boost::trim(strHeader);
1977             boost::to_lower(strHeader);
1978             string strValue = str.substr(nColon+1);
1979             boost::trim(strValue);
1980             mapHeadersRet[strHeader] = strValue;
1981             if (strHeader == "content-length")
1982                 nLen = atoi(strValue.c_str());
1983         }
1984     }
1985     return nLen;
1986 }
1987 
1988 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1989 {
1990     mapHeadersRet.clear();
1991     strMessageRet = "";
1992 
1993     // Read status
1994     int nStatus = ReadHTTPStatus(stream);
1995 
1996     // Read header
1997     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1998     if (nLen < 0 || nLen > MAX_SIZE)
1999         return 500;
2000 
2001     // Read message
2002     if (nLen > 0)
2003     {
2004         vector<char> vch(nLen);
2005         stream.read(&vch[0], nLen);
2006         strMessageRet = string(vch.begin(), vch.end());
2007     }
2008 
2009     return nStatus;
2010 }
2011 
2012 bool HTTPAuthorized(map<string, string>& mapHeaders)
2013 {
2014     string strAuth = mapHeaders["authorization"];
2015     if (strAuth.substr(0,6) != "Basic ")
2016         return false;
2017     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2018     string strUserPass = DecodeBase64(strUserPass64);
2019     return strUserPass == strRPCUserColonPass;
2020 }
2021 
2022 //
2023 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2024 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2025 // unspecified (HTTP errors and contents of 'error').
2026 //
2027 // 1.0 spec: http://json-rpc.org/wiki/specification
2028 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2029 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2030 //
2031 
2032 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2033 {
2034     Object request;
2035     request.push_back(Pair("method", strMethod));
2036     request.push_back(Pair("params", params));
2037     request.push_back(Pair("id", id));
2038     return write_string(Value(request), false) + "\n";
2039 }
2040 
2041 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2042 {
2043     Object reply;
2044     if (error.type() != null_type)
2045         reply.push_back(Pair("result", Value::null));
2046     else
2047         reply.push_back(Pair("result", result));
2048     reply.push_back(Pair("error", error));
2049     reply.push_back(Pair("id", id));
2050     return write_string(Value(reply), false) + "\n";
2051 }
2052 
2053 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2054 {
2055     // Send error reply from json-rpc error object
2056     int nStatus = 500;
2057     int code = find_value(objError, "code").get_int();
2058     if (code == -32600) nStatus = 400;
2059     else if (code == -32601) nStatus = 404;
2060     string strReply = JSONRPCReply(Value::null, objError, id);
2061     stream << HTTPReply(nStatus, strReply) << std::flush;
2062 }
2063 
2064 bool ClientAllowed(const string& strAddress)
2065 {
2066     if (strAddress == asio::ip::address_v4::loopback().to_string())
2067         return true;
2068     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2069     BOOST_FOREACH(string strAllow, vAllow)
2070         if (WildcardMatch(strAddress, strAllow))
2071             return true;
2072     return false;
2073 }
2074 
2075 void ThreadRPCServer(void* parg)
2076 {
2077     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2078     try
2079     {
2080         vnThreadsRunning[4]++;
2081         ThreadRPCServer2(parg);
2082         vnThreadsRunning[4]--;
2083     }
2084     catch (std::exception& e) {
2085         vnThreadsRunning[4]--;
2086         PrintException(&e, "ThreadRPCServer()");
2087     } catch (...) {
2088         vnThreadsRunning[4]--;
2089         PrintException(NULL, "ThreadRPCServer()");
2090     }
2091     printf("ThreadRPCServer exiting\n");
2092 }
2093 
2094 void ThreadRPCServer2(void* parg)
2095 {
2096     printf("ThreadRPCServer started\n");
2097 
2098     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2099     if (strRPCUserColonPass == ":")
2100     {
2101         unsigned char rand_pwd[32];
2102         RAND_bytes(rand_pwd, 32);
2103         string strWhatAmI = "To use bitcoind";
2104         if (mapArgs.count("-server"))
2105             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2106         else if (mapArgs.count("-daemon"))
2107             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2108         PrintConsole(
2109             _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2110               "It is recommended you use the following random password:\n"
2111               "rpcuser=bitcoinrpc\n"
2112               "rpcpassword=%s\n"
2113               "(you do not need to remember this password)\n"
2114               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2115                 strWhatAmI.c_str(),
2116                 GetConfigFile().c_str(),
2117                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2118         CreateThread(Shutdown, NULL);
2119         return;
2120     }
2121 
2122     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2123 
2124     asio::io_service io_service;
2125     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2126     ip::tcp::acceptor acceptor(io_service, endpoint);
2127 
2128     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2129 
2130     loop
2131     {
2132         // Accept connection
2133         ip::tcp::iostream stream;
2134 
2135         ip::tcp::endpoint peer;
2136         vnThreadsRunning[4]--;
2137         acceptor.accept(*stream.rdbuf(), peer);
2138         vnThreadsRunning[4]++;
2139         if (fShutdown)
2140             return;
2141 
2142         // Restrict callers by IP
2143         if (!ClientAllowed(peer.address().to_string()))
2144         {
2145         // snipsnipsnip
2146             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2147             //if (!fUseSSL)
2148             stream << HTTPReply(403, "") << std::flush;
2149             continue;
2150         }
2151 
2152         map<string, string> mapHeaders;
2153         string strRequest;
2154 
2155         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2156         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2157         {   // Timed out:
2158             acceptor.cancel();
2159             printf("ThreadRPCServer ReadHTTP timeout\n");
2160             continue;
2161         }
2162 
2163         // Check authorization
2164         if (mapHeaders.count("authorization") == 0)
2165         {
2166             stream << HTTPReply(401, "") << std::flush;
2167             continue;
2168         }
2169         if (!HTTPAuthorized(mapHeaders))
2170         {
2171             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2172             /* Deter brute-forcing short passwords.
2173                If this results in a DOS the user really
2174                shouldn't have their RPC port exposed.*/
2175             if (mapArgs["-rpcpassword"].size() < 20)
2176                 Sleep(250);
2177 
2178             stream << HTTPReply(401, "") << std::flush;
2179             continue;
2180         }
2181 
2182         Value id = Value::null;
2183         try
2184         {
2185             // Parse request
2186             Value valRequest;
2187             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2188                 throw JSONRPCError(-32700, "Parse error");
2189             const Object& request = valRequest.get_obj();
2190 
2191             // Parse id now so errors from here on will have the id
2192             id = find_value(request, "id");
2193 
2194             // Parse method
2195             Value valMethod = find_value(request, "method");
2196             if (valMethod.type() == null_type)
2197                 throw JSONRPCError(-32600, "Missing method");
2198             if (valMethod.type() != str_type)
2199                 throw JSONRPCError(-32600, "Method must be a string");
2200             string strMethod = valMethod.get_str();
2201             if (strMethod != "getwork" && strMethod != "getmemorypool")
2202                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2203 
2204             // Parse params
2205             Value valParams = find_value(request, "params");
2206             Array params;
2207             if (valParams.type() == array_type)
2208                 params = valParams.get_array();
2209             else if (valParams.type() == null_type)
2210                 params = Array();
2211             else
2212                 throw JSONRPCError(-32600, "Params must be an array");
2213 
2214             // Find method
2215             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2216             if (mi == mapCallTable.end())
2217                 throw JSONRPCError(-32601, "Method not found");
2218 
2219             // Observe safe mode
2220             string strWarning = GetWarnings("rpc");
2221             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2222                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2223 
2224             try
2225             {
2226                 // Execute
2227                 Value result;
2228                 CRITICAL_BLOCK(cs_main)
2229                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2230                     result = (*(*mi).second)(params, false);
2231 
2232                 // Send reply
2233                 string strReply = JSONRPCReply(result, Value::null, id);
2234                 stream << HTTPReply(200, strReply) << std::flush;
2235             }
2236             catch (std::exception& e)
2237             {
2238                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2239             }
2240         }
2241         catch (Object& objError)
2242         {
2243             ErrorReply(stream, objError, id);
2244         }
2245         catch (std::exception& e)
2246         {
2247             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2248         }
2249     }
2250 }
2251 
2252 
2253 
2254 
2255 Object CallRPC(const string& strMethod, const Array& params)
2256 {
2257     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2258         throw runtime_error(strprintf(
2259             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2260               "If the file does not exist, create it with owner-readable-only file permissions."),
2261                 GetConfigFile().c_str()));
2262 
2263     // Connect to localhost
2264     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2265     if (stream.fail())
2266         throw runtime_error("couldn't connect to server");
2267 
2268     // HTTP basic authentication
2269     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2270     map<string, string> mapRequestHeaders;
2271     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2272 
2273     // Send request
2274     string strRequest = JSONRPCRequest(strMethod, params, 1);
2275     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2276     stream << strPost << std::flush;
2277 
2278     // Receive reply
2279     map<string, string> mapHeaders;
2280     string strReply;
2281     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2282     if (nStatus == 401)
2283         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2284     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2285         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2286     else if (strReply.empty())
2287         throw runtime_error("no response from server");
2288 
2289     // Parse reply
2290     Value valReply;
2291     if (!read_string(strReply, valReply))
2292         throw runtime_error("couldn't parse reply from server");
2293     const Object& reply = valReply.get_obj();
2294     if (reply.empty())
2295         throw runtime_error("expected reply to have result, error and id properties");
2296 
2297     return reply;
2298 }
2299 
2300 
2301 
2302 
2303 template<typename T>
2304 void ConvertTo(Value& value)
2305 {
2306     if (value.type() == str_type)
2307     {
2308         // reinterpret string as unquoted json value
2309         Value value2;
2310         if (!read_string(value.get_str(), value2))
2311             throw runtime_error("type mismatch");
2312         value = value2.get_value<T>();
2313     }
2314     else
2315     {
2316         value = value.get_value<T>();
2317     }
2318 }
2319 
2320 int CommandLineRPC(int argc, char *argv[])
2321 {
2322     string strPrint;
2323     int nRet = 0;
2324     try
2325     {
2326         // Skip switches
2327         while (argc > 1 && IsSwitchChar(argv[1][0]))
2328         {
2329             argc--;
2330             argv++;
2331         }
2332 
2333         // Method
2334         if (argc < 2)
2335             throw runtime_error("too few parameters");
2336         string strMethod = argv[1];
2337 
2338         // Parameters default to strings
2339         Array params;
2340         for (int i = 2; i < argc; i++)
2341             params.push_back(argv[i]);
2342         int n = params.size();
2343 
2344         //
2345         // Special case non-string parameter types
2346         //
2347         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2348         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2349         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2350         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2351         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2352         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2353         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2354         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2355         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2356         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2357         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2358         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2359         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2360         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2361         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2362         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2363         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2364         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2365         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2366         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2367         if (strMethod == "sendmany"               && n > 1)
2368         {
2369             string s = params[1].get_str();
2370             Value v;
2371             if (!read_string(s, v) || v.type() != obj_type)
2372                 throw runtime_error("type mismatch");
2373             params[1] = v.get_obj();
2374         }
2375         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2376 
2377         // Execute
2378         Object reply = CallRPC(strMethod, params);
2379 
2380         // Parse reply
2381         const Value& result = find_value(reply, "result");
2382         const Value& error  = find_value(reply, "error");
2383 
2384         if (error.type() != null_type)
2385         {
2386             // Error
2387             strPrint = "error: " + write_string(error, false);
2388             int code = find_value(error.get_obj(), "code").get_int();
2389             nRet = abs(code);
2390         }
2391         else
2392         {
2393             // Result
2394             if (result.type() == null_type)
2395                 strPrint = "";
2396             else if (result.type() == str_type)
2397                 strPrint = result.get_str();
2398             else
2399                 strPrint = write_string(result, true);
2400         }
2401     }
2402     catch (std::exception& e)
2403     {
2404         strPrint = string("error: ") + e.what();
2405         nRet = 87;
2406     }
2407     catch (...)
2408     {
2409         PrintException(NULL, "CommandLineRPC()");
2410     }
2411 
2412     if (strPrint != "")
2413     {
2414         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2415     }
2416     return nRet;
2417 }
2418 
2419 
2420 
2421 
2422 #ifdef TEST
2423 int main(int argc, char *argv[])
2424 {
2425     setbuf(stdin, NULL);
2426     setbuf(stdout, NULL);
2427     setbuf(stderr, NULL);
2428 
2429     try
2430     {
2431         if (argc >= 2 && string(argv[1]) == "-server")
2432         {
2433             printf("server ready\n");
2434             ThreadRPCServer(NULL);
2435         }
2436         else
2437         {
2438             return CommandLineRPC(argc, argv);
2439         }
2440     }
2441     catch (std::exception& e) {
2442         PrintException(&e, "main()");
2443     } catch (...) {
2444         PrintException(NULL, "main()");
2445     }
2446     return 0;
2447 }
2448 #endif