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