Fixed non-sensical error message
[novacoin.git] / src / bitcoinrpc.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "db.h"
8 #include "net.h"
9 #include "init.h"
10 #undef printf
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
17 #ifdef USE_SSL
18 #include <boost/asio/ssl.hpp> 
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #endif
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h.  The problem might be when the pch file goes over
29 // a certain size around 145MB.  If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
31
32 using namespace std;
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
36
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
40
41 static std::string strRPCUserColonPass;
42
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
45
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
48
49 Object JSONRPCError(int code, const string& message)
50 {
51     Object error;
52     error.push_back(Pair("code", code));
53     error.push_back(Pair("message", message));
54     return error;
55 }
56
57 double GetDifficulty(const CBlockIndex* blockindex = NULL)
58 {
59     // Floating point number that is a multiple of the minimum difficulty,
60     // minimum difficulty = 1.0.
61     if (blockindex == NULL)
62     {
63         if (pindexBest == NULL)
64             return 1.0;
65         else
66             blockindex = pindexBest;
67     }
68
69     int nShift = (blockindex->nBits >> 24) & 0xff;
70
71     double dDiff =
72         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
73
74     while (nShift < 29)
75     {
76         dDiff *= 256.0;
77         nShift++;
78     }
79     while (nShift > 29)
80     {
81         dDiff /= 256.0;
82         nShift--;
83     }
84
85     return dDiff;
86 }
87
88
89 int64 AmountFromValue(const Value& value)
90 {
91     double dAmount = value.get_real();
92     if (dAmount <= 0.0 || dAmount > 21000000.0)
93         throw JSONRPCError(-3, "Invalid amount");
94     int64 nAmount = roundint64(dAmount * COIN);
95     if (!MoneyRange(nAmount))
96         throw JSONRPCError(-3, "Invalid amount");
97     return nAmount;
98 }
99
100 Value ValueFromAmount(int64 amount)
101 {
102     return (double)amount / (double)COIN;
103 }
104
105 std::string
106 HexBits(unsigned int nBits)
107 {
108     union {
109         int32_t nBits;
110         char cBits[4];
111     } uBits;
112     uBits.nBits = htonl((int32_t)nBits);
113     return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
114 }
115
116 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
117 {
118     int confirms = wtx.GetDepthInMainChain();
119     entry.push_back(Pair("confirmations", confirms));
120     if (confirms)
121     {
122         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
123         entry.push_back(Pair("blockindex", wtx.nIndex));
124     }
125     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
126     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
127     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
128         entry.push_back(Pair(item.first, item.second));
129 }
130
131 string AccountFromValue(const Value& value)
132 {
133     string strAccount = value.get_str();
134     if (strAccount == "*")
135         throw JSONRPCError(-11, "Invalid account name");
136     return strAccount;
137 }
138
139 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
140 {
141     Object result;
142     result.push_back(Pair("hash", block.GetHash().GetHex()));
143     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
144     result.push_back(Pair("height", blockindex->nHeight));
145     result.push_back(Pair("version", block.nVersion));
146     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
147     result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
148     result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
149     result.push_back(Pair("bits", HexBits(block.nBits)));
150     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
151     Array txhashes;
152     BOOST_FOREACH (const CTransaction&tx, block.vtx)
153         txhashes.push_back(tx.GetHash().GetHex());
154     result.push_back(Pair("tx", txhashes));
155
156     if (blockindex->pprev)
157         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
158     if (blockindex->pnext)
159         result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
160     return result;
161 }
162
163
164
165 ///
166 /// Note: This interface may still be subject to change.
167 ///
168
169
170 Value help(const Array& params, bool fHelp)
171 {
172     if (fHelp || params.size() > 1)
173         throw runtime_error(
174             "help [command]\n"
175             "List commands, or get help for a command.");
176
177     string strCommand;
178     if (params.size() > 0)
179         strCommand = params[0].get_str();
180
181     string strRet;
182     set<rpcfn_type> setDone;
183     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
184     {
185         string strMethod = (*mi).first;
186         // We already filter duplicates, but these deprecated screw up the sort order
187         if (strMethod == "getamountreceived" ||
188             strMethod == "getallreceived" ||
189             strMethod == "getblocknumber" || // deprecated
190             (strMethod.find("label") != string::npos))
191             continue;
192         if (strCommand != "" && strMethod != strCommand)
193             continue;
194         try
195         {
196             Array params;
197             rpcfn_type pfn = (*mi).second;
198             if (setDone.insert(pfn).second)
199                 (*pfn)(params, true);
200         }
201         catch (std::exception& e)
202         {
203             // Help text is returned in an exception
204             string strHelp = string(e.what());
205             if (strCommand == "")
206                 if (strHelp.find('\n') != string::npos)
207                     strHelp = strHelp.substr(0, strHelp.find('\n'));
208             strRet += strHelp + "\n";
209         }
210     }
211     if (strRet == "")
212         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
213     strRet = strRet.substr(0,strRet.size()-1);
214     return strRet;
215 }
216
217
218 Value stop(const Array& params, bool fHelp)
219 {
220     if (fHelp || params.size() != 0)
221         throw runtime_error(
222             "stop\n"
223             "Stop bitcoin server.");
224 #ifndef QT_GUI
225     // Shutdown will take long enough that the response should get back
226     CreateThread(Shutdown, NULL);
227     return "bitcoin server stopping";
228 #else
229     throw runtime_error("NYI: cannot shut down GUI with RPC command");
230 #endif
231 }
232
233
234 Value getblockcount(const Array& params, bool fHelp)
235 {
236     if (fHelp || params.size() != 0)
237         throw runtime_error(
238             "getblockcount\n"
239             "Returns the number of blocks in the longest block chain.");
240
241     return nBestHeight;
242 }
243
244
245 // deprecated
246 Value getblocknumber(const Array& params, bool fHelp)
247 {
248     if (fHelp || params.size() != 0)
249         throw runtime_error(
250             "getblocknumber\n"
251             "Deprecated.  Use getblockcount.");
252
253     return nBestHeight;
254 }
255
256
257 Value getconnectioncount(const Array& params, bool fHelp)
258 {
259     if (fHelp || params.size() != 0)
260         throw runtime_error(
261             "getconnectioncount\n"
262             "Returns the number of connections to other nodes.");
263
264     return (int)vNodes.size();
265 }
266
267
268 Value getdifficulty(const Array& params, bool fHelp)
269 {
270     if (fHelp || params.size() != 0)
271         throw runtime_error(
272             "getdifficulty\n"
273             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
274
275     return GetDifficulty();
276 }
277
278
279 Value getgenerate(const Array& params, bool fHelp)
280 {
281     if (fHelp || params.size() != 0)
282         throw runtime_error(
283             "getgenerate\n"
284             "Returns true or false.");
285
286     return GetBoolArg("-gen");
287 }
288
289
290 Value setgenerate(const Array& params, bool fHelp)
291 {
292     if (fHelp || params.size() < 1 || params.size() > 2)
293         throw runtime_error(
294             "setgenerate <generate> [genproclimit]\n"
295             "<generate> is true or false to turn generation on or off.\n"
296             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
297
298     bool fGenerate = true;
299     if (params.size() > 0)
300         fGenerate = params[0].get_bool();
301
302     if (params.size() > 1)
303     {
304         int nGenProcLimit = params[1].get_int();
305         mapArgs["-genproclimit"] = itostr(nGenProcLimit);
306         if (nGenProcLimit == 0)
307             fGenerate = false;
308     }
309     mapArgs["-gen"] = (fGenerate ? "1" : "0");
310
311     GenerateBitcoins(fGenerate, pwalletMain);
312     return Value::null;
313 }
314
315
316 Value gethashespersec(const Array& params, bool fHelp)
317 {
318     if (fHelp || params.size() != 0)
319         throw runtime_error(
320             "gethashespersec\n"
321             "Returns a recent hashes per second performance measurement while generating.");
322
323     if (GetTimeMillis() - nHPSTimerStart > 8000)
324         return (boost::int64_t)0;
325     return (boost::int64_t)dHashesPerSec;
326 }
327
328
329 Value getinfo(const Array& params, bool fHelp)
330 {
331     if (fHelp || params.size() != 0)
332         throw runtime_error(
333             "getinfo\n"
334             "Returns an object containing various state info.");
335
336     Object obj;
337     obj.push_back(Pair("version",       (int)CLIENT_VERSION));
338     obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
339     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
340     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
341     obj.push_back(Pair("blocks",        (int)nBestHeight));
342     obj.push_back(Pair("connections",   (int)vNodes.size()));
343     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
344     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
345     obj.push_back(Pair("testnet",       fTestNet));
346     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
347     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
348     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
349     if (pwalletMain->IsCrypted())
350         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
351     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
352     return obj;
353 }
354
355
356 Value getmininginfo(const Array& params, bool fHelp)
357 {
358     if (fHelp || params.size() != 0)
359         throw runtime_error(
360             "getmininginfo\n"
361             "Returns an object containing mining-related information.");
362
363     Object obj;
364     obj.push_back(Pair("blocks",        (int)nBestHeight));
365     obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
366     obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
367     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
368     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
369     obj.push_back(Pair("generate",      GetBoolArg("-gen")));
370     obj.push_back(Pair("genproclimit",  (int)GetArg("-genproclimit", -1)));
371     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
372     obj.push_back(Pair("pooledtx",      (uint64_t)nPooledTx));
373     obj.push_back(Pair("testnet",       fTestNet));
374     return obj;
375 }
376
377
378 Value getnewaddress(const Array& params, bool fHelp)
379 {
380     if (fHelp || params.size() > 1)
381         throw runtime_error(
382             "getnewaddress [account]\n"
383             "Returns a new bitcoin address for receiving payments.  "
384             "If [account] is specified (recommended), it is added to the address book "
385             "so payments received with the address will be credited to [account].");
386
387     // Parse the account first so we don't generate a key if there's an error
388     string strAccount;
389     if (params.size() > 0)
390         strAccount = AccountFromValue(params[0]);
391
392     if (!pwalletMain->IsLocked())
393         pwalletMain->TopUpKeyPool();
394
395     // Generate a new key that is added to wallet
396     std::vector<unsigned char> newKey;
397     if (!pwalletMain->GetKeyFromPool(newKey, false))
398         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
399     CBitcoinAddress address(newKey);
400
401     pwalletMain->SetAddressBookName(address, strAccount);
402
403     return address.ToString();
404 }
405
406
407 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
408 {
409     CWalletDB walletdb(pwalletMain->strWalletFile);
410
411     CAccount account;
412     walletdb.ReadAccount(strAccount, account);
413
414     bool bKeyUsed = false;
415
416     // Check if the current key has been used
417     if (!account.vchPubKey.empty())
418     {
419         CScript scriptPubKey;
420         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
421         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
422              it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
423              ++it)
424         {
425             const CWalletTx& wtx = (*it).second;
426             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
427                 if (txout.scriptPubKey == scriptPubKey)
428                     bKeyUsed = true;
429         }
430     }
431
432     // Generate a new key
433     if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
434     {
435         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
436             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
437
438         pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
439         walletdb.WriteAccount(strAccount, account);
440     }
441
442     return CBitcoinAddress(account.vchPubKey);
443 }
444
445 Value getaccountaddress(const Array& params, bool fHelp)
446 {
447     if (fHelp || params.size() != 1)
448         throw runtime_error(
449             "getaccountaddress <account>\n"
450             "Returns the current bitcoin address for receiving payments to this account.");
451
452     // Parse the account first so we don't generate a key if there's an error
453     string strAccount = AccountFromValue(params[0]);
454
455     Value ret;
456
457     ret = GetAccountAddress(strAccount).ToString();
458
459     return ret;
460 }
461
462
463
464 Value setaccount(const Array& params, bool fHelp)
465 {
466     if (fHelp || params.size() < 1 || params.size() > 2)
467         throw runtime_error(
468             "setaccount <bitcoinaddress> <account>\n"
469             "Sets the account associated with the given address.");
470
471     CBitcoinAddress address(params[0].get_str());
472     if (!address.IsValid())
473         throw JSONRPCError(-5, "Invalid bitcoin address");
474
475
476     string strAccount;
477     if (params.size() > 1)
478         strAccount = AccountFromValue(params[1]);
479
480     // Detect when changing the account of an address that is the 'unused current key' of another account:
481     if (pwalletMain->mapAddressBook.count(address))
482     {
483         string strOldAccount = pwalletMain->mapAddressBook[address];
484         if (address == GetAccountAddress(strOldAccount))
485             GetAccountAddress(strOldAccount, true);
486     }
487
488     pwalletMain->SetAddressBookName(address, strAccount);
489
490     return Value::null;
491 }
492
493
494 Value getaccount(const Array& params, bool fHelp)
495 {
496     if (fHelp || params.size() != 1)
497         throw runtime_error(
498             "getaccount <bitcoinaddress>\n"
499             "Returns the account associated with the given address.");
500
501     CBitcoinAddress address(params[0].get_str());
502     if (!address.IsValid())
503         throw JSONRPCError(-5, "Invalid bitcoin address");
504
505     string strAccount;
506     map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
507     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
508         strAccount = (*mi).second;
509     return strAccount;
510 }
511
512
513 Value getaddressesbyaccount(const Array& params, bool fHelp)
514 {
515     if (fHelp || params.size() != 1)
516         throw runtime_error(
517             "getaddressesbyaccount <account>\n"
518             "Returns the list of addresses for the given account.");
519
520     string strAccount = AccountFromValue(params[0]);
521
522     // Find all addresses that have the given account
523     Array ret;
524     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
525     {
526         const CBitcoinAddress& address = item.first;
527         const string& strName = item.second;
528         if (strName == strAccount)
529             ret.push_back(address.ToString());
530     }
531     return ret;
532 }
533
534 Value settxfee(const Array& params, bool fHelp)
535 {
536     if (fHelp || params.size() < 1 || params.size() > 1)
537         throw runtime_error(
538             "settxfee <amount>\n"
539             "<amount> is a real and is rounded to the nearest 0.00000001");
540
541     // Amount
542     int64 nAmount = 0;
543     if (params[0].get_real() != 0.0)
544         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
545
546     nTransactionFee = nAmount;
547     return true;
548 }
549
550 Value sendtoaddress(const Array& params, bool fHelp)
551 {
552     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
553         throw runtime_error(
554             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
555             "<amount> is a real and is rounded to the nearest 0.00000001\n"
556             "requires wallet passphrase to be set with walletpassphrase first");
557     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
558         throw runtime_error(
559             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
560             "<amount> is a real and is rounded to the nearest 0.00000001");
561
562     CBitcoinAddress address(params[0].get_str());
563     if (!address.IsValid())
564         throw JSONRPCError(-5, "Invalid bitcoin address");
565
566     // Amount
567     int64 nAmount = AmountFromValue(params[1]);
568
569     // Wallet comments
570     CWalletTx wtx;
571     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
572         wtx.mapValue["comment"] = params[2].get_str();
573     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
574         wtx.mapValue["to"]      = params[3].get_str();
575
576     if (pwalletMain->IsLocked())
577         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
578
579     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
580     if (strError != "")
581         throw JSONRPCError(-4, strError);
582
583     return wtx.GetHash().GetHex();
584 }
585
586 Value signmessage(const Array& params, bool fHelp)
587 {
588     if (fHelp || params.size() != 2)
589         throw runtime_error(
590             "signmessage <bitcoinaddress> <message>\n"
591             "Sign a message with the private key of an address");
592
593     if (pwalletMain->IsLocked())
594         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
595
596     string strAddress = params[0].get_str();
597     string strMessage = params[1].get_str();
598
599     CBitcoinAddress addr(strAddress);
600     if (!addr.IsValid())
601         throw JSONRPCError(-3, "Invalid address");
602
603     CKey key;
604     if (!pwalletMain->GetKey(addr, key))
605         throw JSONRPCError(-4, "Private key not available");
606
607     CDataStream ss(SER_GETHASH);
608     ss << strMessageMagic;
609     ss << strMessage;
610
611     vector<unsigned char> vchSig;
612     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
613         throw JSONRPCError(-5, "Sign failed");
614
615     return EncodeBase64(&vchSig[0], vchSig.size());
616 }
617
618 Value verifymessage(const Array& params, bool fHelp)
619 {
620     if (fHelp || params.size() != 3)
621         throw runtime_error(
622             "verifymessage <bitcoinaddress> <signature> <message>\n"
623             "Verify a signed message");
624
625     string strAddress  = params[0].get_str();
626     string strSign     = params[1].get_str();
627     string strMessage  = params[2].get_str();
628
629     CBitcoinAddress addr(strAddress);
630     if (!addr.IsValid())
631         throw JSONRPCError(-3, "Invalid address");
632
633     bool fInvalid = false;
634     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
635
636     if (fInvalid)
637         throw JSONRPCError(-5, "Malformed base64 encoding");
638
639     CDataStream ss(SER_GETHASH);
640     ss << strMessageMagic;
641     ss << strMessage;
642
643     CKey key;
644     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
645         return false;
646
647     return (CBitcoinAddress(key.GetPubKey()) == addr);
648 }
649
650
651 Value getreceivedbyaddress(const Array& params, bool fHelp)
652 {
653     if (fHelp || params.size() < 1 || params.size() > 2)
654         throw runtime_error(
655             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
656             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
657
658     // Bitcoin address
659     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
660     CScript scriptPubKey;
661     if (!address.IsValid())
662         throw JSONRPCError(-5, "Invalid bitcoin address");
663     scriptPubKey.SetBitcoinAddress(address);
664     if (!IsMine(*pwalletMain,scriptPubKey))
665         return (double)0.0;
666
667     // Minimum confirmations
668     int nMinDepth = 1;
669     if (params.size() > 1)
670         nMinDepth = params[1].get_int();
671
672     // Tally
673     int64 nAmount = 0;
674     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
675     {
676         const CWalletTx& wtx = (*it).second;
677         if (wtx.IsCoinBase() || !wtx.IsFinal())
678             continue;
679
680         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
681             if (txout.scriptPubKey == scriptPubKey)
682                 if (wtx.GetDepthInMainChain() >= nMinDepth)
683                     nAmount += txout.nValue;
684     }
685
686     return  ValueFromAmount(nAmount);
687 }
688
689
690 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
691 {
692     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
693     {
694         const CBitcoinAddress& address = item.first;
695         const string& strName = item.second;
696         if (strName == strAccount)
697             setAddress.insert(address);
698     }
699 }
700
701
702 Value getreceivedbyaccount(const Array& params, bool fHelp)
703 {
704     if (fHelp || params.size() < 1 || params.size() > 2)
705         throw runtime_error(
706             "getreceivedbyaccount <account> [minconf=1]\n"
707             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
708
709     // Minimum confirmations
710     int nMinDepth = 1;
711     if (params.size() > 1)
712         nMinDepth = params[1].get_int();
713
714     // Get the set of pub keys assigned to account
715     string strAccount = AccountFromValue(params[0]);
716     set<CBitcoinAddress> setAddress;
717     GetAccountAddresses(strAccount, setAddress);
718
719     // Tally
720     int64 nAmount = 0;
721     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
722     {
723         const CWalletTx& wtx = (*it).second;
724         if (wtx.IsCoinBase() || !wtx.IsFinal())
725             continue;
726
727         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
728         {
729             CBitcoinAddress address;
730             if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
731                 if (wtx.GetDepthInMainChain() >= nMinDepth)
732                     nAmount += txout.nValue;
733         }
734     }
735
736     return (double)nAmount / (double)COIN;
737 }
738
739
740 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
741 {
742     int64 nBalance = 0;
743
744     // Tally wallet transactions
745     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
746     {
747         const CWalletTx& wtx = (*it).second;
748         if (!wtx.IsFinal())
749             continue;
750
751         int64 nGenerated, nReceived, nSent, nFee;
752         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
753
754         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
755             nBalance += nReceived;
756         nBalance += nGenerated - nSent - nFee;
757     }
758
759     // Tally internal accounting entries
760     nBalance += walletdb.GetAccountCreditDebit(strAccount);
761
762     return nBalance;
763 }
764
765 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
766 {
767     CWalletDB walletdb(pwalletMain->strWalletFile);
768     return GetAccountBalance(walletdb, strAccount, nMinDepth);
769 }
770
771
772 Value getbalance(const Array& params, bool fHelp)
773 {
774     if (fHelp || params.size() > 2)
775         throw runtime_error(
776             "getbalance [account] [minconf=1]\n"
777             "If [account] is not specified, returns the server's total available balance.\n"
778             "If [account] is specified, returns the balance in the account.");
779
780     if (params.size() == 0)
781         return  ValueFromAmount(pwalletMain->GetBalance());
782
783     int nMinDepth = 1;
784     if (params.size() > 1)
785         nMinDepth = params[1].get_int();
786
787     if (params[0].get_str() == "*") {
788         // Calculate total balance a different way from GetBalance()
789         // (GetBalance() sums up all unspent TxOuts)
790         // getbalance and getbalance '*' should always return the same number.
791         int64 nBalance = 0;
792         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
793         {
794             const CWalletTx& wtx = (*it).second;
795             if (!wtx.IsFinal())
796                 continue;
797
798             int64 allGeneratedImmature, allGeneratedMature, allFee;
799             allGeneratedImmature = allGeneratedMature = allFee = 0;
800             string strSentAccount;
801             list<pair<CBitcoinAddress, int64> > listReceived;
802             list<pair<CBitcoinAddress, int64> > listSent;
803             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
804             if (wtx.GetDepthInMainChain() >= nMinDepth)
805             {
806                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
807                     nBalance += r.second;
808             }
809             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
810                 nBalance -= r.second;
811             nBalance -= allFee;
812             nBalance += allGeneratedMature;
813         }
814         return  ValueFromAmount(nBalance);
815     }
816
817     string strAccount = AccountFromValue(params[0]);
818
819     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
820
821     return ValueFromAmount(nBalance);
822 }
823
824
825 Value movecmd(const Array& params, bool fHelp)
826 {
827     if (fHelp || params.size() < 3 || params.size() > 5)
828         throw runtime_error(
829             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
830             "Move from one account in your wallet to another.");
831
832     string strFrom = AccountFromValue(params[0]);
833     string strTo = AccountFromValue(params[1]);
834     int64 nAmount = AmountFromValue(params[2]);
835     if (params.size() > 3)
836         // unused parameter, used to be nMinDepth, keep type-checking it though
837         (void)params[3].get_int();
838     string strComment;
839     if (params.size() > 4)
840         strComment = params[4].get_str();
841
842     CWalletDB walletdb(pwalletMain->strWalletFile);
843     walletdb.TxnBegin();
844
845     int64 nNow = GetAdjustedTime();
846
847     // Debit
848     CAccountingEntry debit;
849     debit.strAccount = strFrom;
850     debit.nCreditDebit = -nAmount;
851     debit.nTime = nNow;
852     debit.strOtherAccount = strTo;
853     debit.strComment = strComment;
854     walletdb.WriteAccountingEntry(debit);
855
856     // Credit
857     CAccountingEntry credit;
858     credit.strAccount = strTo;
859     credit.nCreditDebit = nAmount;
860     credit.nTime = nNow;
861     credit.strOtherAccount = strFrom;
862     credit.strComment = strComment;
863     walletdb.WriteAccountingEntry(credit);
864
865     walletdb.TxnCommit();
866
867     return true;
868 }
869
870
871 Value sendfrom(const Array& params, bool fHelp)
872 {
873     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
874         throw runtime_error(
875             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
876             "<amount> is a real and is rounded to the nearest 0.00000001\n"
877             "requires wallet passphrase to be set with walletpassphrase first");
878     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
879         throw runtime_error(
880             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
881             "<amount> is a real and is rounded to the nearest 0.00000001");
882
883     string strAccount = AccountFromValue(params[0]);
884     CBitcoinAddress address(params[1].get_str());
885     if (!address.IsValid())
886         throw JSONRPCError(-5, "Invalid bitcoin address");
887     int64 nAmount = AmountFromValue(params[2]);
888     int nMinDepth = 1;
889     if (params.size() > 3)
890         nMinDepth = params[3].get_int();
891
892     CWalletTx wtx;
893     wtx.strFromAccount = strAccount;
894     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
895         wtx.mapValue["comment"] = params[4].get_str();
896     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
897         wtx.mapValue["to"]      = params[5].get_str();
898
899     if (pwalletMain->IsLocked())
900         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
901
902     // Check funds
903     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
904     if (nAmount > nBalance)
905         throw JSONRPCError(-6, "Account has insufficient funds");
906
907     // Send
908     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
909     if (strError != "")
910         throw JSONRPCError(-4, strError);
911
912     return wtx.GetHash().GetHex();
913 }
914
915
916 Value sendmany(const Array& params, bool fHelp)
917 {
918     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
919         throw runtime_error(
920             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
921             "amounts are double-precision floating point numbers\n"
922             "requires wallet passphrase to be set with walletpassphrase first");
923     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
924         throw runtime_error(
925             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
926             "amounts are double-precision floating point numbers");
927
928     string strAccount = AccountFromValue(params[0]);
929     Object sendTo = params[1].get_obj();
930     int nMinDepth = 1;
931     if (params.size() > 2)
932         nMinDepth = params[2].get_int();
933
934     CWalletTx wtx;
935     wtx.strFromAccount = strAccount;
936     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
937         wtx.mapValue["comment"] = params[3].get_str();
938
939     set<CBitcoinAddress> setAddress;
940     vector<pair<CScript, int64> > vecSend;
941
942     int64 totalAmount = 0;
943     BOOST_FOREACH(const Pair& s, sendTo)
944     {
945         CBitcoinAddress address(s.name_);
946         if (!address.IsValid())
947             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
948
949         if (setAddress.count(address))
950             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
951         setAddress.insert(address);
952
953         CScript scriptPubKey;
954         scriptPubKey.SetBitcoinAddress(address);
955         int64 nAmount = AmountFromValue(s.value_); 
956         totalAmount += nAmount;
957
958         vecSend.push_back(make_pair(scriptPubKey, nAmount));
959     }
960
961     if (pwalletMain->IsLocked())
962         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
963
964     // Check funds
965     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
966     if (totalAmount > nBalance)
967         throw JSONRPCError(-6, "Account has insufficient funds");
968
969     // Send
970     CReserveKey keyChange(pwalletMain);
971     int64 nFeeRequired = 0;
972     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
973     if (!fCreated)
974     {
975         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
976             throw JSONRPCError(-6, "Insufficient funds");
977         throw JSONRPCError(-4, "Transaction creation failed");
978     }
979     if (!pwalletMain->CommitTransaction(wtx, keyChange))
980         throw JSONRPCError(-4, "Transaction commit failed");
981
982     return wtx.GetHash().GetHex();
983 }
984
985 Value addmultisigaddress(const Array& params, bool fHelp)
986 {
987     if (fHelp || params.size() < 2 || params.size() > 3)
988     {
989         string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
990             "Add a nrequired-to-sign multisignature address to the wallet\"\n"
991             "each key is a bitcoin address or hex-encoded public key\n"
992             "If [account] is specified, assign address to [account].";
993         throw runtime_error(msg);
994     }
995     if (!fTestNet)
996         throw runtime_error("addmultisigaddress available only when running -testnet\n");
997
998     int nRequired = params[0].get_int();
999     const Array& keys = params[1].get_array();
1000     string strAccount;
1001     if (params.size() > 2)
1002         strAccount = AccountFromValue(params[2]);
1003
1004     // Gather public keys
1005     if (nRequired < 1)
1006         throw runtime_error("a multisignature address must require at least one key to redeem");
1007     if (keys.size() < nRequired)
1008         throw runtime_error(
1009             strprintf("not enough keys supplied "
1010                       "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1011     std::vector<CKey> pubkeys;
1012     pubkeys.resize(keys.size());
1013     for (unsigned int i = 0; i < keys.size(); i++)
1014     {
1015         const std::string& ks = keys[i].get_str();
1016
1017         // Case 1: bitcoin address and we have full public key:
1018         CBitcoinAddress address(ks);
1019         if (address.IsValid())
1020         {
1021             if (address.IsScript())
1022                 throw runtime_error(
1023                     strprintf("%s is a pay-to-script address",ks.c_str()));
1024             std::vector<unsigned char> vchPubKey;
1025             if (!pwalletMain->GetPubKey(address, vchPubKey))
1026                 throw runtime_error(
1027                     strprintf("no full public key for address %s",ks.c_str()));
1028             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1029                 throw runtime_error(" Invalid public key: "+ks);
1030         }
1031
1032         // Case 2: hex public key
1033         else if (IsHex(ks))
1034         {
1035             vector<unsigned char> vchPubKey = ParseHex(ks);
1036             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1037                 throw runtime_error(" Invalid public key: "+ks);
1038         }
1039         else
1040         {
1041             throw runtime_error(" Invalid public key: "+ks);
1042         }
1043     }
1044
1045     // Construct using pay-to-script-hash:
1046     CScript inner;
1047     inner.SetMultisig(nRequired, pubkeys);
1048
1049     uint160 scriptHash = Hash160(inner);
1050     CScript scriptPubKey;
1051     scriptPubKey.SetPayToScriptHash(inner);
1052     pwalletMain->AddCScript(inner);
1053     CBitcoinAddress address;
1054     address.SetScriptHash160(scriptHash);
1055
1056     pwalletMain->SetAddressBookName(address, strAccount);
1057     return address.ToString();
1058 }
1059
1060
1061 struct tallyitem
1062 {
1063     int64 nAmount;
1064     int nConf;
1065     tallyitem()
1066     {
1067         nAmount = 0;
1068         nConf = std::numeric_limits<int>::max();
1069     }
1070 };
1071
1072 Value ListReceived(const Array& params, bool fByAccounts)
1073 {
1074     // Minimum confirmations
1075     int nMinDepth = 1;
1076     if (params.size() > 0)
1077         nMinDepth = params[0].get_int();
1078
1079     // Whether to include empty accounts
1080     bool fIncludeEmpty = false;
1081     if (params.size() > 1)
1082         fIncludeEmpty = params[1].get_bool();
1083
1084     // Tally
1085     map<CBitcoinAddress, tallyitem> mapTally;
1086     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1087     {
1088         const CWalletTx& wtx = (*it).second;
1089
1090         if (wtx.IsCoinBase() || !wtx.IsFinal())
1091             continue;
1092
1093         int nDepth = wtx.GetDepthInMainChain();
1094         if (nDepth < nMinDepth)
1095             continue;
1096
1097         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1098         {
1099             CBitcoinAddress address;
1100             if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1101                 continue;
1102
1103             tallyitem& item = mapTally[address];
1104             item.nAmount += txout.nValue;
1105             item.nConf = min(item.nConf, nDepth);
1106         }
1107     }
1108
1109     // Reply
1110     Array ret;
1111     map<string, tallyitem> mapAccountTally;
1112     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1113     {
1114         const CBitcoinAddress& address = item.first;
1115         const string& strAccount = item.second;
1116         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1117         if (it == mapTally.end() && !fIncludeEmpty)
1118             continue;
1119
1120         int64 nAmount = 0;
1121         int nConf = std::numeric_limits<int>::max();
1122         if (it != mapTally.end())
1123         {
1124             nAmount = (*it).second.nAmount;
1125             nConf = (*it).second.nConf;
1126         }
1127
1128         if (fByAccounts)
1129         {
1130             tallyitem& item = mapAccountTally[strAccount];
1131             item.nAmount += nAmount;
1132             item.nConf = min(item.nConf, nConf);
1133         }
1134         else
1135         {
1136             Object obj;
1137             obj.push_back(Pair("address",       address.ToString()));
1138             obj.push_back(Pair("account",       strAccount));
1139             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1140             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1141             ret.push_back(obj);
1142         }
1143     }
1144
1145     if (fByAccounts)
1146     {
1147         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1148         {
1149             int64 nAmount = (*it).second.nAmount;
1150             int nConf = (*it).second.nConf;
1151             Object obj;
1152             obj.push_back(Pair("account",       (*it).first));
1153             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1154             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1155             ret.push_back(obj);
1156         }
1157     }
1158
1159     return ret;
1160 }
1161
1162 Value listreceivedbyaddress(const Array& params, bool fHelp)
1163 {
1164     if (fHelp || params.size() > 2)
1165         throw runtime_error(
1166             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1167             "[minconf] is the minimum number of confirmations before payments are included.\n"
1168             "[includeempty] whether to include addresses that haven't received any payments.\n"
1169             "Returns an array of objects containing:\n"
1170             "  \"address\" : receiving address\n"
1171             "  \"account\" : the account of the receiving address\n"
1172             "  \"amount\" : total amount received by the address\n"
1173             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1174
1175     return ListReceived(params, false);
1176 }
1177
1178 Value listreceivedbyaccount(const Array& params, bool fHelp)
1179 {
1180     if (fHelp || params.size() > 2)
1181         throw runtime_error(
1182             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1183             "[minconf] is the minimum number of confirmations before payments are included.\n"
1184             "[includeempty] whether to include accounts that haven't received any payments.\n"
1185             "Returns an array of objects containing:\n"
1186             "  \"account\" : the account of the receiving addresses\n"
1187             "  \"amount\" : total amount received by addresses with this account\n"
1188             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1189
1190     return ListReceived(params, true);
1191 }
1192
1193 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1194 {
1195     int64 nGeneratedImmature, nGeneratedMature, nFee;
1196     string strSentAccount;
1197     list<pair<CBitcoinAddress, int64> > listReceived;
1198     list<pair<CBitcoinAddress, int64> > listSent;
1199
1200     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1201
1202     bool fAllAccounts = (strAccount == string("*"));
1203
1204     // Generated blocks assigned to account ""
1205     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1206     {
1207         Object entry;
1208         entry.push_back(Pair("account", string("")));
1209         if (nGeneratedImmature)
1210         {
1211             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1212             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1213         }
1214         else
1215         {
1216             entry.push_back(Pair("category", "generate"));
1217             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1218         }
1219         if (fLong)
1220             WalletTxToJSON(wtx, entry);
1221         ret.push_back(entry);
1222     }
1223
1224     // Sent
1225     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1226     {
1227         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1228         {
1229             Object entry;
1230             entry.push_back(Pair("account", strSentAccount));
1231             entry.push_back(Pair("address", s.first.ToString()));
1232             entry.push_back(Pair("category", "send"));
1233             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1234             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1235             if (fLong)
1236                 WalletTxToJSON(wtx, entry);
1237             ret.push_back(entry);
1238         }
1239     }
1240
1241     // Received
1242     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1243     {
1244         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1245         {
1246             string account;
1247             if (pwalletMain->mapAddressBook.count(r.first))
1248                 account = pwalletMain->mapAddressBook[r.first];
1249             if (fAllAccounts || (account == strAccount))
1250             {
1251                 Object entry;
1252                 entry.push_back(Pair("account", account));
1253                 entry.push_back(Pair("address", r.first.ToString()));
1254                 entry.push_back(Pair("category", "receive"));
1255                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1256                 if (fLong)
1257                     WalletTxToJSON(wtx, entry);
1258                 ret.push_back(entry);
1259             }
1260         }
1261     }
1262 }
1263
1264 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1265 {
1266     bool fAllAccounts = (strAccount == string("*"));
1267
1268     if (fAllAccounts || acentry.strAccount == strAccount)
1269     {
1270         Object entry;
1271         entry.push_back(Pair("account", acentry.strAccount));
1272         entry.push_back(Pair("category", "move"));
1273         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1274         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1275         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1276         entry.push_back(Pair("comment", acentry.strComment));
1277         ret.push_back(entry);
1278     }
1279 }
1280
1281 Value listtransactions(const Array& params, bool fHelp)
1282 {
1283     if (fHelp || params.size() > 3)
1284         throw runtime_error(
1285             "listtransactions [account] [count=10] [from=0]\n"
1286             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1287
1288     string strAccount = "*";
1289     if (params.size() > 0)
1290         strAccount = params[0].get_str();
1291     int nCount = 10;
1292     if (params.size() > 1)
1293         nCount = params[1].get_int();
1294     int nFrom = 0;
1295     if (params.size() > 2)
1296         nFrom = params[2].get_int();
1297
1298     if (nCount < 0)
1299         throw JSONRPCError(-8, "Negative count");
1300     if (nFrom < 0)
1301         throw JSONRPCError(-8, "Negative from");
1302
1303     Array ret;
1304     CWalletDB walletdb(pwalletMain->strWalletFile);
1305
1306     // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1307     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1308     typedef multimap<int64, TxPair > TxItems;
1309     TxItems txByTime;
1310
1311     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1312     // would make this much faster for applications that do this a lot.
1313     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1314     {
1315         CWalletTx* wtx = &((*it).second);
1316         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1317     }
1318     list<CAccountingEntry> acentries;
1319     walletdb.ListAccountCreditDebit(strAccount, acentries);
1320     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1321     {
1322         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1323     }
1324
1325     // iterate backwards until we have nCount items to return:
1326     for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1327     {
1328         CWalletTx *const pwtx = (*it).second.first;
1329         if (pwtx != 0)
1330             ListTransactions(*pwtx, strAccount, 0, true, ret);
1331         CAccountingEntry *const pacentry = (*it).second.second;
1332         if (pacentry != 0)
1333             AcentryToJSON(*pacentry, strAccount, ret);
1334
1335         if (ret.size() >= (nCount+nFrom)) break;
1336     }
1337     // ret is newest to oldest
1338     
1339     if (nFrom > ret.size()) nFrom = ret.size();
1340     if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1341     Array::iterator first = ret.begin();
1342     std::advance(first, nFrom);
1343     Array::iterator last = ret.begin();
1344     std::advance(last, nFrom+nCount);
1345
1346     if (last != ret.end()) ret.erase(last, ret.end());
1347     if (first != ret.begin()) ret.erase(ret.begin(), first);
1348
1349     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1350
1351     return ret;
1352 }
1353
1354 Value listaccounts(const Array& params, bool fHelp)
1355 {
1356     if (fHelp || params.size() > 1)
1357         throw runtime_error(
1358             "listaccounts [minconf=1]\n"
1359             "Returns Object that has account names as keys, account balances as values.");
1360
1361     int nMinDepth = 1;
1362     if (params.size() > 0)
1363         nMinDepth = params[0].get_int();
1364
1365     map<string, int64> mapAccountBalances;
1366     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1367         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1368             mapAccountBalances[entry.second] = 0;
1369     }
1370
1371     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1372     {
1373         const CWalletTx& wtx = (*it).second;
1374         int64 nGeneratedImmature, nGeneratedMature, nFee;
1375         string strSentAccount;
1376         list<pair<CBitcoinAddress, int64> > listReceived;
1377         list<pair<CBitcoinAddress, int64> > listSent;
1378         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1379         mapAccountBalances[strSentAccount] -= nFee;
1380         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1381             mapAccountBalances[strSentAccount] -= s.second;
1382         if (wtx.GetDepthInMainChain() >= nMinDepth)
1383         {
1384             mapAccountBalances[""] += nGeneratedMature;
1385             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1386                 if (pwalletMain->mapAddressBook.count(r.first))
1387                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1388                 else
1389                     mapAccountBalances[""] += r.second;
1390         }
1391     }
1392
1393     list<CAccountingEntry> acentries;
1394     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1395     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1396         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1397
1398     Object ret;
1399     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1400         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1401     }
1402     return ret;
1403 }
1404
1405 Value listsinceblock(const Array& params, bool fHelp)
1406 {
1407     if (fHelp)
1408         throw runtime_error(
1409             "listsinceblock [blockhash] [target-confirmations]\n"
1410             "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1411
1412     CBlockIndex *pindex = NULL;
1413     int target_confirms = 1;
1414
1415     if (params.size() > 0)
1416     {
1417         uint256 blockId = 0;
1418
1419         blockId.SetHex(params[0].get_str());
1420         pindex = CBlockLocator(blockId).GetBlockIndex();
1421     }
1422
1423     if (params.size() > 1)
1424     {
1425         target_confirms = params[1].get_int();
1426
1427         if (target_confirms < 1)
1428             throw JSONRPCError(-8, "Invalid parameter");
1429     }
1430
1431     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1432
1433     Array transactions;
1434
1435     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1436     {
1437         CWalletTx tx = (*it).second;
1438
1439         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1440             ListTransactions(tx, "*", 0, true, transactions);
1441     }
1442
1443     uint256 lastblock;
1444
1445     if (target_confirms == 1)
1446     {
1447         lastblock = hashBestChain;
1448     }
1449     else
1450     {
1451         int target_height = pindexBest->nHeight + 1 - target_confirms;
1452
1453         CBlockIndex *block;
1454         for (block = pindexBest;
1455              block && block->nHeight > target_height;
1456              block = block->pprev)  { }
1457
1458         lastblock = block ? block->GetBlockHash() : 0;
1459     }
1460
1461     Object ret;
1462     ret.push_back(Pair("transactions", transactions));
1463     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1464
1465     return ret;
1466 }
1467
1468 Value gettransaction(const Array& params, bool fHelp)
1469 {
1470     if (fHelp || params.size() != 1)
1471         throw runtime_error(
1472             "gettransaction <txid>\n"
1473             "Get detailed information about <txid>");
1474
1475     uint256 hash;
1476     hash.SetHex(params[0].get_str());
1477
1478     Object entry;
1479
1480     if (!pwalletMain->mapWallet.count(hash))
1481         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1482     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1483
1484     int64 nCredit = wtx.GetCredit();
1485     int64 nDebit = wtx.GetDebit();
1486     int64 nNet = nCredit - nDebit;
1487     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1488
1489     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1490     if (wtx.IsFromMe())
1491         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1492
1493     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1494
1495     Array details;
1496     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1497     entry.push_back(Pair("details", details));
1498
1499     return entry;
1500 }
1501
1502
1503 Value backupwallet(const Array& params, bool fHelp)
1504 {
1505     if (fHelp || params.size() != 1)
1506         throw runtime_error(
1507             "backupwallet <destination>\n"
1508             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1509
1510     string strDest = params[0].get_str();
1511     BackupWallet(*pwalletMain, strDest);
1512
1513     return Value::null;
1514 }
1515
1516
1517 Value keypoolrefill(const Array& params, bool fHelp)
1518 {
1519     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1520         throw runtime_error(
1521             "keypoolrefill\n"
1522             "Fills the keypool, requires wallet passphrase to be set.");
1523     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1524         throw runtime_error(
1525             "keypoolrefill\n"
1526             "Fills the keypool.");
1527
1528     if (pwalletMain->IsLocked())
1529         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1530
1531     pwalletMain->TopUpKeyPool();
1532
1533     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1534         throw JSONRPCError(-4, "Error refreshing keypool.");
1535
1536     return Value::null;
1537 }
1538
1539
1540 void ThreadTopUpKeyPool(void* parg)
1541 {
1542     pwalletMain->TopUpKeyPool();
1543 }
1544
1545 void ThreadCleanWalletPassphrase(void* parg)
1546 {
1547     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1548
1549     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1550
1551     if (nWalletUnlockTime == 0)
1552     {
1553         nWalletUnlockTime = nMyWakeTime;
1554
1555         do
1556         {
1557             if (nWalletUnlockTime==0)
1558                 break;
1559             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1560             if (nToSleep <= 0)
1561                 break;
1562
1563             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1564             Sleep(nToSleep);
1565             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1566
1567         } while(1);
1568
1569         if (nWalletUnlockTime)
1570         {
1571             nWalletUnlockTime = 0;
1572             pwalletMain->Lock();
1573         }
1574     }
1575     else
1576     {
1577         if (nWalletUnlockTime < nMyWakeTime)
1578             nWalletUnlockTime = nMyWakeTime;
1579     }
1580
1581     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1582
1583     delete (int64*)parg;
1584 }
1585
1586 Value walletpassphrase(const Array& params, bool fHelp)
1587 {
1588     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1589         throw runtime_error(
1590             "walletpassphrase <passphrase> <timeout>\n"
1591             "Stores the wallet decryption key in memory for <timeout> seconds.");
1592     if (fHelp)
1593         return true;
1594     if (!pwalletMain->IsCrypted())
1595         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1596
1597     if (!pwalletMain->IsLocked())
1598         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1599
1600     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1601     SecureString strWalletPass;
1602     strWalletPass.reserve(100);
1603     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1604     // Alternately, find a way to make params[0] mlock()'d to begin with.
1605     strWalletPass = params[0].get_str().c_str();
1606
1607     if (strWalletPass.length() > 0)
1608     {
1609         if (!pwalletMain->Unlock(strWalletPass))
1610             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1611     }
1612     else
1613         throw runtime_error(
1614             "walletpassphrase <passphrase> <timeout>\n"
1615             "Stores the wallet decryption key in memory for <timeout> seconds.");
1616
1617     CreateThread(ThreadTopUpKeyPool, NULL);
1618     int64* pnSleepTime = new int64(params[1].get_int64());
1619     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1620
1621     return Value::null;
1622 }
1623
1624
1625 Value walletpassphrasechange(const Array& params, bool fHelp)
1626 {
1627     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1628         throw runtime_error(
1629             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1630             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1631     if (fHelp)
1632         return true;
1633     if (!pwalletMain->IsCrypted())
1634         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1635
1636     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1637     // Alternately, find a way to make params[0] mlock()'d to begin with.
1638     SecureString strOldWalletPass;
1639     strOldWalletPass.reserve(100);
1640     strOldWalletPass = params[0].get_str().c_str();
1641
1642     SecureString strNewWalletPass;
1643     strNewWalletPass.reserve(100);
1644     strNewWalletPass = params[1].get_str().c_str();
1645
1646     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1647         throw runtime_error(
1648             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1649             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1650
1651     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1652         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1653
1654     return Value::null;
1655 }
1656
1657
1658 Value walletlock(const Array& params, bool fHelp)
1659 {
1660     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1661         throw runtime_error(
1662             "walletlock\n"
1663             "Removes the wallet encryption key from memory, locking the wallet.\n"
1664             "After calling this method, you will need to call walletpassphrase again\n"
1665             "before being able to call any methods which require the wallet to be unlocked.");
1666     if (fHelp)
1667         return true;
1668     if (!pwalletMain->IsCrypted())
1669         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1670
1671     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1672     {
1673         pwalletMain->Lock();
1674         nWalletUnlockTime = 0;
1675     }
1676
1677     return Value::null;
1678 }
1679
1680
1681 Value encryptwallet(const Array& params, bool fHelp)
1682 {
1683     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1684         throw runtime_error(
1685             "encryptwallet <passphrase>\n"
1686             "Encrypts the wallet with <passphrase>.");
1687     if (fHelp)
1688         return true;
1689     if (pwalletMain->IsCrypted())
1690         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1691
1692 #ifdef QT_GUI
1693     // shutting down via RPC while the GUI is running does not work (yet):
1694     throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1695 #endif
1696
1697     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1698     // Alternately, find a way to make params[0] mlock()'d to begin with.
1699     SecureString strWalletPass;
1700     strWalletPass.reserve(100);
1701     strWalletPass = params[0].get_str().c_str();
1702
1703     if (strWalletPass.length() < 1)
1704         throw runtime_error(
1705             "encryptwallet <passphrase>\n"
1706             "Encrypts the wallet with <passphrase>.");
1707
1708     if (!pwalletMain->EncryptWallet(strWalletPass))
1709         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1710
1711     // BDB seems to have a bad habit of writing old data into
1712     // slack space in .dat files; that is bad if the old data is
1713     // unencrypted private keys.  So:
1714     CreateThread(Shutdown, NULL);
1715     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1716 }
1717
1718
1719 Value validateaddress(const Array& params, bool fHelp)
1720 {
1721     if (fHelp || params.size() != 1)
1722         throw runtime_error(
1723             "validateaddress <bitcoinaddress>\n"
1724             "Return information about <bitcoinaddress>.");
1725
1726     CBitcoinAddress address(params[0].get_str());
1727     bool isValid = address.IsValid();
1728
1729     Object ret;
1730     ret.push_back(Pair("isvalid", isValid));
1731     if (isValid)
1732     {
1733         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1734         // version of the address:
1735         string currentAddress = address.ToString();
1736         ret.push_back(Pair("address", currentAddress));
1737         if (pwalletMain->HaveKey(address))
1738         {
1739             ret.push_back(Pair("ismine", true));
1740             std::vector<unsigned char> vchPubKey;
1741             pwalletMain->GetPubKey(address, vchPubKey);
1742             ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1743             CKey key;
1744             key.SetPubKey(vchPubKey);
1745             ret.push_back(Pair("iscompressed", key.IsCompressed()));
1746         }
1747         else if (pwalletMain->HaveCScript(address.GetHash160()))
1748         {
1749             ret.push_back(Pair("isscript", true));
1750             CScript subscript;
1751             pwalletMain->GetCScript(address.GetHash160(), subscript);
1752             ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1753             std::vector<CBitcoinAddress> addresses;
1754             txnouttype whichType;
1755             int nRequired;
1756             ExtractAddresses(subscript, whichType, addresses, nRequired);
1757             ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1758             Array a;
1759             BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1760                 a.push_back(addr.ToString());
1761             ret.push_back(Pair("addresses", a));
1762             if (whichType == TX_MULTISIG)
1763                 ret.push_back(Pair("sigsrequired", nRequired));
1764         }
1765         else
1766             ret.push_back(Pair("ismine", false));
1767         if (pwalletMain->mapAddressBook.count(address))
1768             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1769     }
1770     return ret;
1771 }
1772
1773 Value getwork(const Array& params, bool fHelp)
1774 {
1775     if (fHelp || params.size() > 1)
1776         throw runtime_error(
1777             "getwork [data]\n"
1778             "If [data] is not specified, returns formatted hash data to work on:\n"
1779             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1780             "  \"data\" : block data\n"
1781             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1782             "  \"target\" : little endian hash target\n"
1783             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1784
1785     if (vNodes.empty())
1786         throw JSONRPCError(-9, "Bitcoin is not connected!");
1787
1788     if (IsInitialBlockDownload())
1789         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1790
1791     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1792     static mapNewBlock_t mapNewBlock;
1793     static vector<CBlock*> vNewBlock;
1794     static CReserveKey reservekey(pwalletMain);
1795
1796     if (params.size() == 0)
1797     {
1798         // Update block
1799         static unsigned int nTransactionsUpdatedLast;
1800         static CBlockIndex* pindexPrev;
1801         static int64 nStart;
1802         static CBlock* pblock;
1803         if (pindexPrev != pindexBest ||
1804             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1805         {
1806             if (pindexPrev != pindexBest)
1807             {
1808                 // Deallocate old blocks since they're obsolete now
1809                 mapNewBlock.clear();
1810                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1811                     delete pblock;
1812                 vNewBlock.clear();
1813             }
1814             nTransactionsUpdatedLast = nTransactionsUpdated;
1815             pindexPrev = pindexBest;
1816             nStart = GetTime();
1817
1818             // Create new block
1819             pblock = CreateNewBlock(reservekey);
1820             if (!pblock)
1821                 throw JSONRPCError(-7, "Out of memory");
1822             vNewBlock.push_back(pblock);
1823         }
1824
1825         // Update nTime
1826         pblock->UpdateTime(pindexPrev);
1827         pblock->nNonce = 0;
1828
1829         // Update nExtraNonce
1830         static unsigned int nExtraNonce = 0;
1831         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1832
1833         // Save
1834         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1835
1836         // Prebuild hash buffers
1837         char pmidstate[32];
1838         char pdata[128];
1839         char phash1[64];
1840         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1841
1842         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1843
1844         Object result;
1845         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1846         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1847         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1848         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1849         return result;
1850     }
1851     else
1852     {
1853         // Parse parameters
1854         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1855         if (vchData.size() != 128)
1856             throw JSONRPCError(-8, "Invalid parameter");
1857         CBlock* pdata = (CBlock*)&vchData[0];
1858
1859         // Byte reverse
1860         for (int i = 0; i < 128/4; i++)
1861             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1862
1863         // Get saved block
1864         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1865             return false;
1866         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1867
1868         pblock->nTime = pdata->nTime;
1869         pblock->nNonce = pdata->nNonce;
1870         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1871         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1872
1873         return CheckWork(pblock, *pwalletMain, reservekey);
1874     }
1875 }
1876
1877
1878 Value getmemorypool(const Array& params, bool fHelp)
1879 {
1880     if (fHelp || params.size() > 1)
1881         throw runtime_error(
1882             "getmemorypool [data]\n"
1883             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1884             "  \"version\" : block version\n"
1885             "  \"previousblockhash\" : hash of current highest block\n"
1886             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1887             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1888             "  \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1889             "  \"time\" : timestamp appropriate for next block\n"
1890             "  \"mintime\" : minimum timestamp appropriate for next block\n"
1891             "  \"curtime\" : current timestamp\n"
1892             "  \"bits\" : compressed target of next block\n"
1893             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1894
1895     if (params.size() == 0)
1896     {
1897         if (vNodes.empty())
1898             throw JSONRPCError(-9, "Bitcoin is not connected!");
1899
1900         if (IsInitialBlockDownload())
1901             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1902
1903         static CReserveKey reservekey(pwalletMain);
1904
1905         // Update block
1906         static unsigned int nTransactionsUpdatedLast;
1907         static CBlockIndex* pindexPrev;
1908         static int64 nStart;
1909         static CBlock* pblock;
1910         if (pindexPrev != pindexBest ||
1911             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1912         {
1913             nTransactionsUpdatedLast = nTransactionsUpdated;
1914             pindexPrev = pindexBest;
1915             nStart = GetTime();
1916
1917             // Create new block
1918             if(pblock)
1919                 delete pblock;
1920             pblock = CreateNewBlock(reservekey);
1921             if (!pblock)
1922                 throw JSONRPCError(-7, "Out of memory");
1923         }
1924
1925         // Update nTime
1926         pblock->UpdateTime(pindexPrev);
1927         pblock->nNonce = 0;
1928
1929         Array transactions;
1930         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1931             if(tx.IsCoinBase())
1932                 continue;
1933
1934             CDataStream ssTx;
1935             ssTx << tx;
1936
1937             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1938         }
1939
1940         Object result;
1941         result.push_back(Pair("version", pblock->nVersion));
1942         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1943         result.push_back(Pair("transactions", transactions));
1944         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1945         result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1946         result.push_back(Pair("time", (int64_t)pblock->nTime));
1947         result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1948         result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1949         result.push_back(Pair("bits", HexBits(pblock->nBits)));
1950
1951         return result;
1952     }
1953     else
1954     {
1955         // Parse parameters
1956         CDataStream ssBlock(ParseHex(params[0].get_str()));
1957         CBlock pblock;
1958         ssBlock >> pblock;
1959
1960         return ProcessBlock(NULL, &pblock);
1961     }
1962 }
1963
1964 Value getblockhash(const Array& params, bool fHelp)
1965 {
1966     if (fHelp || params.size() != 1)
1967         throw runtime_error(
1968             "getblockhash <index>\n"
1969             "Returns hash of block in best-block-chain at <index>.");
1970
1971     int nHeight = params[0].get_int();
1972     if (nHeight < 0 || nHeight > nBestHeight)
1973         throw runtime_error("Block number out of range.");
1974
1975     CBlock block;
1976     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1977     while (pblockindex->nHeight > nHeight)
1978         pblockindex = pblockindex->pprev;
1979     return pblockindex->phashBlock->GetHex();
1980 }
1981
1982 Value getblock(const Array& params, bool fHelp)
1983 {
1984     if (fHelp || params.size() != 1)
1985         throw runtime_error(
1986             "getblock <hash>\n"
1987             "Returns details of a block with given block-hash.");
1988
1989     std::string strHash = params[0].get_str();
1990     uint256 hash(strHash);
1991
1992     if (mapBlockIndex.count(hash) == 0)
1993         throw JSONRPCError(-5, "Block not found");
1994
1995     CBlock block;
1996     CBlockIndex* pblockindex = mapBlockIndex[hash];
1997     block.ReadFromDisk(pblockindex, true);
1998
1999     return blockToJSON(block, pblockindex);
2000 }
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012 //
2013 // Call Table
2014 //
2015
2016 pair<string, rpcfn_type> pCallTable[] =
2017 {
2018     make_pair("help",                   &help),
2019     make_pair("stop",                   &stop),
2020     make_pair("getblockcount",          &getblockcount),
2021     make_pair("getblocknumber",         &getblocknumber),
2022     make_pair("getconnectioncount",     &getconnectioncount),
2023     make_pair("getdifficulty",          &getdifficulty),
2024     make_pair("getgenerate",            &getgenerate),
2025     make_pair("setgenerate",            &setgenerate),
2026     make_pair("gethashespersec",        &gethashespersec),
2027     make_pair("getinfo",                &getinfo),
2028     make_pair("getmininginfo",          &getmininginfo),
2029     make_pair("getnewaddress",          &getnewaddress),
2030     make_pair("getaccountaddress",      &getaccountaddress),
2031     make_pair("setaccount",             &setaccount),
2032     make_pair("getaccount",             &getaccount),
2033     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
2034     make_pair("sendtoaddress",          &sendtoaddress),
2035     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
2036     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
2037     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
2038     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
2039     make_pair("backupwallet",           &backupwallet),
2040     make_pair("keypoolrefill",          &keypoolrefill),
2041     make_pair("walletpassphrase",       &walletpassphrase),
2042     make_pair("walletpassphrasechange", &walletpassphrasechange),
2043     make_pair("walletlock",             &walletlock),
2044     make_pair("encryptwallet",          &encryptwallet),
2045     make_pair("validateaddress",        &validateaddress),
2046     make_pair("getbalance",             &getbalance),
2047     make_pair("move",                   &movecmd),
2048     make_pair("sendfrom",               &sendfrom),
2049     make_pair("sendmany",               &sendmany),
2050     make_pair("addmultisigaddress",     &addmultisigaddress),
2051     make_pair("getblock",               &getblock),
2052     make_pair("getblockhash",           &getblockhash),
2053     make_pair("gettransaction",         &gettransaction),
2054     make_pair("listtransactions",       &listtransactions),
2055     make_pair("signmessage",            &signmessage),
2056     make_pair("verifymessage",          &verifymessage),
2057     make_pair("getwork",                &getwork),
2058     make_pair("listaccounts",           &listaccounts),
2059     make_pair("settxfee",               &settxfee),
2060     make_pair("getmemorypool",          &getmemorypool),
2061     make_pair("listsinceblock",         &listsinceblock),
2062     make_pair("dumpprivkey",            &dumpprivkey),
2063     make_pair("importprivkey",          &importprivkey)
2064 };
2065 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2066
2067 string pAllowInSafeMode[] =
2068 {
2069     "help",
2070     "stop",
2071     "getblockcount",
2072     "getblocknumber",  // deprecated
2073     "getconnectioncount",
2074     "getdifficulty",
2075     "getgenerate",
2076     "setgenerate",
2077     "gethashespersec",
2078     "getinfo",
2079     "getmininginfo",
2080     "getnewaddress",
2081     "getaccountaddress",
2082     "getaccount",
2083     "getaddressesbyaccount",
2084     "backupwallet",
2085     "keypoolrefill",
2086     "walletpassphrase",
2087     "walletlock",
2088     "validateaddress",
2089     "getwork",
2090     "getmemorypool",
2091 };
2092 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2093
2094
2095
2096
2097 //
2098 // HTTP protocol
2099 //
2100 // This ain't Apache.  We're just using HTTP header for the length field
2101 // and to be compatible with other JSON-RPC implementations.
2102 //
2103
2104 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2105 {
2106     ostringstream s;
2107     s << "POST / HTTP/1.1\r\n"
2108       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2109       << "Host: 127.0.0.1\r\n"
2110       << "Content-Type: application/json\r\n"
2111       << "Content-Length: " << strMsg.size() << "\r\n"
2112       << "Connection: close\r\n"
2113       << "Accept: application/json\r\n";
2114     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2115         s << item.first << ": " << item.second << "\r\n";
2116     s << "\r\n" << strMsg;
2117
2118     return s.str();
2119 }
2120
2121 string rfc1123Time()
2122 {
2123     char buffer[64];
2124     time_t now;
2125     time(&now);
2126     struct tm* now_gmt = gmtime(&now);
2127     string locale(setlocale(LC_TIME, NULL));
2128     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2129     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2130     setlocale(LC_TIME, locale.c_str());
2131     return string(buffer);
2132 }
2133
2134 static string HTTPReply(int nStatus, const string& strMsg)
2135 {
2136     if (nStatus == 401)
2137         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2138             "Date: %s\r\n"
2139             "Server: bitcoin-json-rpc/%s\r\n"
2140             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2141             "Content-Type: text/html\r\n"
2142             "Content-Length: 296\r\n"
2143             "\r\n"
2144             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2145             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2146             "<HTML>\r\n"
2147             "<HEAD>\r\n"
2148             "<TITLE>Error</TITLE>\r\n"
2149             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2150             "</HEAD>\r\n"
2151             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2152             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2153     const char *cStatus;
2154          if (nStatus == 200) cStatus = "OK";
2155     else if (nStatus == 400) cStatus = "Bad Request";
2156     else if (nStatus == 403) cStatus = "Forbidden";
2157     else if (nStatus == 404) cStatus = "Not Found";
2158     else if (nStatus == 500) cStatus = "Internal Server Error";
2159     else cStatus = "";
2160     return strprintf(
2161             "HTTP/1.1 %d %s\r\n"
2162             "Date: %s\r\n"
2163             "Connection: close\r\n"
2164             "Content-Length: %d\r\n"
2165             "Content-Type: application/json\r\n"
2166             "Server: bitcoin-json-rpc/%s\r\n"
2167             "\r\n"
2168             "%s",
2169         nStatus,
2170         cStatus,
2171         rfc1123Time().c_str(),
2172         strMsg.size(),
2173         FormatFullVersion().c_str(),
2174         strMsg.c_str());
2175 }
2176
2177 int ReadHTTPStatus(std::basic_istream<char>& stream)
2178 {
2179     string str;
2180     getline(stream, str);
2181     vector<string> vWords;
2182     boost::split(vWords, str, boost::is_any_of(" "));
2183     if (vWords.size() < 2)
2184         return 500;
2185     return atoi(vWords[1].c_str());
2186 }
2187
2188 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2189 {
2190     int nLen = 0;
2191     loop
2192     {
2193         string str;
2194         std::getline(stream, str);
2195         if (str.empty() || str == "\r")
2196             break;
2197         string::size_type nColon = str.find(":");
2198         if (nColon != string::npos)
2199         {
2200             string strHeader = str.substr(0, nColon);
2201             boost::trim(strHeader);
2202             boost::to_lower(strHeader);
2203             string strValue = str.substr(nColon+1);
2204             boost::trim(strValue);
2205             mapHeadersRet[strHeader] = strValue;
2206             if (strHeader == "content-length")
2207                 nLen = atoi(strValue.c_str());
2208         }
2209     }
2210     return nLen;
2211 }
2212
2213 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2214 {
2215     mapHeadersRet.clear();
2216     strMessageRet = "";
2217
2218     // Read status
2219     int nStatus = ReadHTTPStatus(stream);
2220
2221     // Read header
2222     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2223     if (nLen < 0 || nLen > MAX_SIZE)
2224         return 500;
2225
2226     // Read message
2227     if (nLen > 0)
2228     {
2229         vector<char> vch(nLen);
2230         stream.read(&vch[0], nLen);
2231         strMessageRet = string(vch.begin(), vch.end());
2232     }
2233
2234     return nStatus;
2235 }
2236
2237 bool HTTPAuthorized(map<string, string>& mapHeaders)
2238 {
2239     string strAuth = mapHeaders["authorization"];
2240     if (strAuth.substr(0,6) != "Basic ")
2241         return false;
2242     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2243     string strUserPass = DecodeBase64(strUserPass64);
2244     return strUserPass == strRPCUserColonPass;
2245 }
2246
2247 //
2248 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2249 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2250 // unspecified (HTTP errors and contents of 'error').
2251 //
2252 // 1.0 spec: http://json-rpc.org/wiki/specification
2253 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2254 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2255 //
2256
2257 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2258 {
2259     Object request;
2260     request.push_back(Pair("method", strMethod));
2261     request.push_back(Pair("params", params));
2262     request.push_back(Pair("id", id));
2263     return write_string(Value(request), false) + "\n";
2264 }
2265
2266 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2267 {
2268     Object reply;
2269     if (error.type() != null_type)
2270         reply.push_back(Pair("result", Value::null));
2271     else
2272         reply.push_back(Pair("result", result));
2273     reply.push_back(Pair("error", error));
2274     reply.push_back(Pair("id", id));
2275     return write_string(Value(reply), false) + "\n";
2276 }
2277
2278 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2279 {
2280     // Send error reply from json-rpc error object
2281     int nStatus = 500;
2282     int code = find_value(objError, "code").get_int();
2283     if (code == -32600) nStatus = 400;
2284     else if (code == -32601) nStatus = 404;
2285     string strReply = JSONRPCReply(Value::null, objError, id);
2286     stream << HTTPReply(nStatus, strReply) << std::flush;
2287 }
2288
2289 bool ClientAllowed(const string& strAddress)
2290 {
2291     if (strAddress == asio::ip::address_v4::loopback().to_string())
2292         return true;
2293     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2294     BOOST_FOREACH(string strAllow, vAllow)
2295         if (WildcardMatch(strAddress, strAllow))
2296             return true;
2297     return false;
2298 }
2299
2300 #ifdef USE_SSL
2301 //
2302 // IOStream device that speaks SSL but can also speak non-SSL
2303 //
2304 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2305 public:
2306     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2307     {
2308         fUseSSL = fUseSSLIn;
2309         fNeedHandshake = fUseSSLIn;
2310     }
2311
2312     void handshake(ssl::stream_base::handshake_type role)
2313     {
2314         if (!fNeedHandshake) return;
2315         fNeedHandshake = false;
2316         stream.handshake(role);
2317     }
2318     std::streamsize read(char* s, std::streamsize n)
2319     {
2320         handshake(ssl::stream_base::server); // HTTPS servers read first
2321         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2322         return stream.next_layer().read_some(asio::buffer(s, n));
2323     }
2324     std::streamsize write(const char* s, std::streamsize n)
2325     {
2326         handshake(ssl::stream_base::client); // HTTPS clients write first
2327         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2328         return asio::write(stream.next_layer(), asio::buffer(s, n));
2329     }
2330     bool connect(const std::string& server, const std::string& port)
2331     {
2332         ip::tcp::resolver resolver(stream.get_io_service());
2333         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2334         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2335         ip::tcp::resolver::iterator end;
2336         boost::system::error_code error = asio::error::host_not_found;
2337         while (error && endpoint_iterator != end)
2338         {
2339             stream.lowest_layer().close();
2340             stream.lowest_layer().connect(*endpoint_iterator++, error);
2341         }
2342         if (error)
2343             return false;
2344         return true;
2345     }
2346
2347 private:
2348     bool fNeedHandshake;
2349     bool fUseSSL;
2350     SSLStream& stream;
2351 };
2352 #endif
2353
2354 void ThreadRPCServer(void* parg)
2355 {
2356     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2357     try
2358     {
2359         vnThreadsRunning[THREAD_RPCSERVER]++;
2360         ThreadRPCServer2(parg);
2361         vnThreadsRunning[THREAD_RPCSERVER]--;
2362     }
2363     catch (std::exception& e) {
2364         vnThreadsRunning[THREAD_RPCSERVER]--;
2365         PrintException(&e, "ThreadRPCServer()");
2366     } catch (...) {
2367         vnThreadsRunning[THREAD_RPCSERVER]--;
2368         PrintException(NULL, "ThreadRPCServer()");
2369     }
2370     printf("ThreadRPCServer exiting\n");
2371 }
2372
2373 #ifdef QT_GUI
2374 extern bool HACK_SHUTDOWN;
2375 #endif
2376
2377 void ThreadRPCServer2(void* parg)
2378 {
2379     printf("ThreadRPCServer started\n");
2380
2381     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2382     if (mapArgs["-rpcpassword"] == "")
2383     {
2384         unsigned char rand_pwd[32];
2385         RAND_bytes(rand_pwd, 32);
2386         string strWhatAmI = "To use bitcoind";
2387         if (mapArgs.count("-server"))
2388             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2389         else if (mapArgs.count("-daemon"))
2390             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2391         ThreadSafeMessageBox(strprintf(
2392             _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2393               "It is recommended you use the following random password:\n"
2394               "rpcuser=bitcoinrpc\n"
2395               "rpcpassword=%s\n"
2396               "(you do not need to remember this password)\n"
2397               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2398                 strWhatAmI.c_str(),
2399                 GetConfigFile().c_str(),
2400                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2401             _("Error"), wxOK | wxMODAL);
2402 #ifndef QT_GUI
2403         CreateThread(Shutdown, NULL);
2404 #endif
2405         return;
2406     }
2407
2408     bool fUseSSL = GetBoolArg("-rpcssl");
2409     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2410
2411     asio::io_service io_service;
2412     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2413 #ifndef QT_GUI
2414     ip::tcp::acceptor acceptor(io_service, endpoint);
2415
2416     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2417 #else
2418     ip::tcp::acceptor acceptor(io_service);
2419     try
2420     {
2421         acceptor.open(endpoint.protocol());
2422         acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2423         acceptor.bind(endpoint);
2424         acceptor.listen(socket_base::max_connections);
2425     }
2426     catch(boost::system::system_error &e)
2427     {
2428         HACK_SHUTDOWN = true;
2429         ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2430                              _("Error"), wxOK | wxMODAL);
2431         return;
2432     }
2433 #endif
2434
2435 #ifdef USE_SSL
2436     ssl::context context(io_service, ssl::context::sslv23);
2437     if (fUseSSL)
2438     {
2439         context.set_options(ssl::context::no_sslv2);
2440         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2441         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2442         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2443         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2444         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2445         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2446         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2447         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2448
2449         string ciphers = GetArg("-rpcsslciphers",
2450                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2451         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2452     }
2453 #else
2454     if (fUseSSL)
2455         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2456 #endif
2457
2458     loop
2459     {
2460         // Accept connection
2461 #ifdef USE_SSL
2462         SSLStream sslStream(io_service, context);
2463         SSLIOStreamDevice d(sslStream, fUseSSL);
2464         iostreams::stream<SSLIOStreamDevice> stream(d);
2465 #else
2466         ip::tcp::iostream stream;
2467 #endif
2468
2469         ip::tcp::endpoint peer;
2470         vnThreadsRunning[THREAD_RPCSERVER]--;
2471 #ifdef USE_SSL
2472         acceptor.accept(sslStream.lowest_layer(), peer);
2473 #else
2474         acceptor.accept(*stream.rdbuf(), peer);
2475 #endif
2476         vnThreadsRunning[4]++;
2477         if (fShutdown)
2478             return;
2479
2480         // Restrict callers by IP
2481         if (!ClientAllowed(peer.address().to_string()))
2482         {
2483             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2484             if (!fUseSSL)
2485                 stream << HTTPReply(403, "") << std::flush;
2486             continue;
2487         }
2488
2489         map<string, string> mapHeaders;
2490         string strRequest;
2491
2492         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2493         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2494         {   // Timed out:
2495             acceptor.cancel();
2496             printf("ThreadRPCServer ReadHTTP timeout\n");
2497             continue;
2498         }
2499
2500         // Check authorization
2501         if (mapHeaders.count("authorization") == 0)
2502         {
2503             stream << HTTPReply(401, "") << std::flush;
2504             continue;
2505         }
2506         if (!HTTPAuthorized(mapHeaders))
2507         {
2508             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2509             /* Deter brute-forcing short passwords.
2510                If this results in a DOS the user really
2511                shouldn't have their RPC port exposed.*/
2512             if (mapArgs["-rpcpassword"].size() < 20)
2513                 Sleep(250);
2514
2515             stream << HTTPReply(401, "") << std::flush;
2516             continue;
2517         }
2518
2519         Value id = Value::null;
2520         try
2521         {
2522             // Parse request
2523             Value valRequest;
2524             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2525                 throw JSONRPCError(-32700, "Parse error");
2526             const Object& request = valRequest.get_obj();
2527
2528             // Parse id now so errors from here on will have the id
2529             id = find_value(request, "id");
2530
2531             // Parse method
2532             Value valMethod = find_value(request, "method");
2533             if (valMethod.type() == null_type)
2534                 throw JSONRPCError(-32600, "Missing method");
2535             if (valMethod.type() != str_type)
2536                 throw JSONRPCError(-32600, "Method must be a string");
2537             string strMethod = valMethod.get_str();
2538             if (strMethod != "getwork" && strMethod != "getmemorypool")
2539                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2540
2541             // Parse params
2542             Value valParams = find_value(request, "params");
2543             Array params;
2544             if (valParams.type() == array_type)
2545                 params = valParams.get_array();
2546             else if (valParams.type() == null_type)
2547                 params = Array();
2548             else
2549                 throw JSONRPCError(-32600, "Params must be an array");
2550
2551             // Find method
2552             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2553             if (mi == mapCallTable.end())
2554                 throw JSONRPCError(-32601, "Method not found");
2555
2556             // Observe safe mode
2557             string strWarning = GetWarnings("rpc");
2558             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2559                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2560
2561             try
2562             {
2563                 // Execute
2564                 Value result;
2565                 CRITICAL_BLOCK(cs_main)
2566                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2567                     result = (*(*mi).second)(params, false);
2568
2569                 // Send reply
2570                 string strReply = JSONRPCReply(result, Value::null, id);
2571                 stream << HTTPReply(200, strReply) << std::flush;
2572             }
2573             catch (std::exception& e)
2574             {
2575                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2576             }
2577         }
2578         catch (Object& objError)
2579         {
2580             ErrorReply(stream, objError, id);
2581         }
2582         catch (std::exception& e)
2583         {
2584             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2585         }
2586     }
2587 }
2588
2589
2590
2591
2592 Object CallRPC(const string& strMethod, const Array& params)
2593 {
2594     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2595         throw runtime_error(strprintf(
2596             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2597               "If the file does not exist, create it with owner-readable-only file permissions."),
2598                 GetConfigFile().c_str()));
2599
2600     // Connect to localhost
2601     bool fUseSSL = GetBoolArg("-rpcssl");
2602 #ifdef USE_SSL
2603     asio::io_service io_service;
2604     ssl::context context(io_service, ssl::context::sslv23);
2605     context.set_options(ssl::context::no_sslv2);
2606     SSLStream sslStream(io_service, context);
2607     SSLIOStreamDevice d(sslStream, fUseSSL);
2608     iostreams::stream<SSLIOStreamDevice> stream(d);
2609     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2610         throw runtime_error("couldn't connect to server");
2611 #else
2612     if (fUseSSL)
2613         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2614
2615     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2616     if (stream.fail())
2617         throw runtime_error("couldn't connect to server");
2618 #endif
2619
2620
2621     // HTTP basic authentication
2622     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2623     map<string, string> mapRequestHeaders;
2624     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2625
2626     // Send request
2627     string strRequest = JSONRPCRequest(strMethod, params, 1);
2628     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2629     stream << strPost << std::flush;
2630
2631     // Receive reply
2632     map<string, string> mapHeaders;
2633     string strReply;
2634     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2635     if (nStatus == 401)
2636         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2637     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2638         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2639     else if (strReply.empty())
2640         throw runtime_error("no response from server");
2641
2642     // Parse reply
2643     Value valReply;
2644     if (!read_string(strReply, valReply))
2645         throw runtime_error("couldn't parse reply from server");
2646     const Object& reply = valReply.get_obj();
2647     if (reply.empty())
2648         throw runtime_error("expected reply to have result, error and id properties");
2649
2650     return reply;
2651 }
2652
2653
2654
2655
2656 template<typename T>
2657 void ConvertTo(Value& value)
2658 {
2659     if (value.type() == str_type)
2660     {
2661         // reinterpret string as unquoted json value
2662         Value value2;
2663         if (!read_string(value.get_str(), value2))
2664             throw runtime_error("type mismatch");
2665         value = value2.get_value<T>();
2666     }
2667     else
2668     {
2669         value = value.get_value<T>();
2670     }
2671 }
2672
2673 int CommandLineRPC(int argc, char *argv[])
2674 {
2675     string strPrint;
2676     int nRet = 0;
2677     try
2678     {
2679         // Skip switches
2680         while (argc > 1 && IsSwitchChar(argv[1][0]))
2681         {
2682             argc--;
2683             argv++;
2684         }
2685
2686         // Method
2687         if (argc < 2)
2688             throw runtime_error("too few parameters");
2689         string strMethod = argv[1];
2690
2691         // Parameters default to strings
2692         Array params;
2693         for (int i = 2; i < argc; i++)
2694             params.push_back(argv[i]);
2695         int n = params.size();
2696
2697         //
2698         // Special case non-string parameter types
2699         //
2700         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2701         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2702         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2703         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2704         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2705         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2706         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2707         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2708         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2709         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2710         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2711         if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2712         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2713         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2714         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2715         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2716         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2717         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2718         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2719         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2720         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2721         if (strMethod == "sendmany"               && n > 1)
2722         {
2723             string s = params[1].get_str();
2724             Value v;
2725             if (!read_string(s, v) || v.type() != obj_type)
2726                 throw runtime_error("type mismatch");
2727             params[1] = v.get_obj();
2728         }
2729         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2730         if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
2731         if (strMethod == "addmultisigaddress"      && n > 1)
2732         {
2733             string s = params[1].get_str();
2734             Value v;
2735             if (!read_string(s, v) || v.type() != array_type)
2736                 throw runtime_error("type mismatch "+s);
2737             params[1] = v.get_array();
2738         }
2739
2740         // Execute
2741         Object reply = CallRPC(strMethod, params);
2742
2743         // Parse reply
2744         const Value& result = find_value(reply, "result");
2745         const Value& error  = find_value(reply, "error");
2746
2747         if (error.type() != null_type)
2748         {
2749             // Error
2750             strPrint = "error: " + write_string(error, false);
2751             int code = find_value(error.get_obj(), "code").get_int();
2752             nRet = abs(code);
2753         }
2754         else
2755         {
2756             // Result
2757             if (result.type() == null_type)
2758                 strPrint = "";
2759             else if (result.type() == str_type)
2760                 strPrint = result.get_str();
2761             else
2762                 strPrint = write_string(result, true);
2763         }
2764     }
2765     catch (std::exception& e)
2766     {
2767         strPrint = string("error: ") + e.what();
2768         nRet = 87;
2769     }
2770     catch (...)
2771     {
2772         PrintException(NULL, "CommandLineRPC()");
2773     }
2774
2775     if (strPrint != "")
2776     {
2777         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2778     }
2779     return nRet;
2780 }
2781
2782
2783
2784
2785 #ifdef TEST
2786 int main(int argc, char *argv[])
2787 {
2788 #ifdef _MSC_VER
2789     // Turn off microsoft heap dump noise
2790     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2791     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2792 #endif
2793     setbuf(stdin, NULL);
2794     setbuf(stdout, NULL);
2795     setbuf(stderr, NULL);
2796
2797     try
2798     {
2799         if (argc >= 2 && string(argv[1]) == "-server")
2800         {
2801             printf("server ready\n");
2802             ThreadRPCServer(NULL);
2803         }
2804         else
2805         {
2806             return CommandLineRPC(argc, argv);
2807         }
2808     }
2809     catch (std::exception& e) {
2810         PrintException(&e, "main()");
2811     } catch (...) {
2812         PrintException(NULL, "main()");
2813     }
2814     return 0;
2815 }
2816 #endif