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