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