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