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