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