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