Merge pull request #524 from sipa/signandverif
[novacoin.git] / src / bitcoinrpc.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "cryptopp/sha.h"
8 #include "db.h"
9 #include "net.h"
10 #include "init.h"
11 #undef printf
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #ifdef USE_SSL
17 #include <boost/asio/ssl.hpp> 
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #endif
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h.  The problem might be when the pch file goes over
28 // a certain size around 145MB.  If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
30
31 using namespace std;
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
35
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
39
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
42
43
44 Object JSONRPCError(int code, const string& message)
45 {
46     Object error;
47     error.push_back(Pair("code", code));
48     error.push_back(Pair("message", message));
49     return error;
50 }
51
52
53 void PrintConsole(const std::string &format, ...)
54 {
55     char buffer[50000];
56     int limit = sizeof(buffer);
57     va_list arg_ptr;
58     va_start(arg_ptr, format);
59     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
60     va_end(arg_ptr);
61     if (ret < 0 || ret >= limit)
62     {
63         ret = limit - 1;
64         buffer[limit-1] = 0;
65     }
66     printf("%s", buffer);
67     fprintf(stdout, "%s", buffer);
68 }
69
70
71 int64 AmountFromValue(const Value& value)
72 {
73     double dAmount = value.get_real();
74     if (dAmount <= 0.0 || dAmount > 21000000.0)
75         throw JSONRPCError(-3, "Invalid amount");
76     int64 nAmount = roundint64(dAmount * COIN);
77     if (!MoneyRange(nAmount))
78         throw JSONRPCError(-3, "Invalid amount");
79     return nAmount;
80 }
81
82 Value ValueFromAmount(int64 amount)
83 {
84     return (double)amount / (double)COIN;
85 }
86
87 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
88 {
89     entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
90     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
91     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
92     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
93         entry.push_back(Pair(item.first, item.second));
94 }
95
96 string AccountFromValue(const Value& value)
97 {
98     string strAccount = value.get_str();
99     if (strAccount == "*")
100         throw JSONRPCError(-11, "Invalid account name");
101     return strAccount;
102 }
103
104
105
106 ///
107 /// Note: This interface may still be subject to change.
108 ///
109
110
111 Value help(const Array& params, bool fHelp)
112 {
113     if (fHelp || params.size() > 1)
114         throw runtime_error(
115             "help [command]\n"
116             "List commands, or get help for a command.");
117
118     string strCommand;
119     if (params.size() > 0)
120         strCommand = params[0].get_str();
121
122     string strRet;
123     set<rpcfn_type> setDone;
124     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
125     {
126         string strMethod = (*mi).first;
127         // We already filter duplicates, but these deprecated screw up the sort order
128         if (strMethod == "getamountreceived" ||
129             strMethod == "getallreceived" ||
130             (strMethod.find("label") != string::npos))
131             continue;
132         if (strCommand != "" && strMethod != strCommand)
133             continue;
134         try
135         {
136             Array params;
137             rpcfn_type pfn = (*mi).second;
138             if (setDone.insert(pfn).second)
139                 (*pfn)(params, true);
140         }
141         catch (std::exception& e)
142         {
143             // Help text is returned in an exception
144             string strHelp = string(e.what());
145             if (strCommand == "")
146                 if (strHelp.find('\n') != -1)
147                     strHelp = strHelp.substr(0, strHelp.find('\n'));
148             strRet += strHelp + "\n";
149         }
150     }
151     if (strRet == "")
152         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
153     strRet = strRet.substr(0,strRet.size()-1);
154     return strRet;
155 }
156
157
158 Value stop(const Array& params, bool fHelp)
159 {
160     if (fHelp || params.size() != 0)
161         throw runtime_error(
162             "stop\n"
163             "Stop bitcoin server.");
164
165     // Shutdown will take long enough that the response should get back
166     CreateThread(Shutdown, NULL);
167     return "bitcoin server stopping";
168 }
169
170
171 Value getblockcount(const Array& params, bool fHelp)
172 {
173     if (fHelp || params.size() != 0)
174         throw runtime_error(
175             "getblockcount\n"
176             "Returns the number of blocks in the longest block chain.");
177
178     return nBestHeight;
179 }
180
181
182 Value getblocknumber(const Array& params, bool fHelp)
183 {
184     if (fHelp || params.size() != 0)
185         throw runtime_error(
186             "getblocknumber\n"
187             "Returns the block number of the latest block in the longest block chain.");
188
189     return nBestHeight;
190 }
191
192
193 Value getconnectioncount(const Array& params, bool fHelp)
194 {
195     if (fHelp || params.size() != 0)
196         throw runtime_error(
197             "getconnectioncount\n"
198             "Returns the number of connections to other nodes.");
199
200     return (int)vNodes.size();
201 }
202
203
204 double GetDifficulty()
205 {
206     // Floating point number that is a multiple of the minimum difficulty,
207     // minimum difficulty = 1.0.
208
209     if (pindexBest == NULL)
210         return 1.0;
211     int nShift = (pindexBest->nBits >> 24) & 0xff;
212
213     double dDiff =
214         (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
215
216     while (nShift < 29)
217     {
218         dDiff *= 256.0;
219         nShift++;
220     }
221     while (nShift > 29)
222     {
223         dDiff /= 256.0;
224         nShift--;
225     }
226
227     return dDiff;
228 }
229
230 Value getdifficulty(const Array& params, bool fHelp)
231 {
232     if (fHelp || params.size() != 0)
233         throw runtime_error(
234             "getdifficulty\n"
235             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
236
237     return GetDifficulty();
238 }
239
240
241 Value getgenerate(const Array& params, bool fHelp)
242 {
243     if (fHelp || params.size() != 0)
244         throw runtime_error(
245             "getgenerate\n"
246             "Returns true or false.");
247
248     return (bool)fGenerateBitcoins;
249 }
250
251
252 Value setgenerate(const Array& params, bool fHelp)
253 {
254     if (fHelp || params.size() < 1 || params.size() > 2)
255         throw runtime_error(
256             "setgenerate <generate> [genproclimit]\n"
257             "<generate> is true or false to turn generation on or off.\n"
258             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
259
260     bool fGenerate = true;
261     if (params.size() > 0)
262         fGenerate = params[0].get_bool();
263
264     if (params.size() > 1)
265     {
266         int nGenProcLimit = params[1].get_int();
267         fLimitProcessors = (nGenProcLimit != -1);
268         WriteSetting("fLimitProcessors", fLimitProcessors);
269         if (nGenProcLimit != -1)
270             WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
271         if (nGenProcLimit == 0)
272             fGenerate = false;
273     }
274
275     GenerateBitcoins(fGenerate, pwalletMain);
276     return Value::null;
277 }
278
279
280 Value gethashespersec(const Array& params, bool fHelp)
281 {
282     if (fHelp || params.size() != 0)
283         throw runtime_error(
284             "gethashespersec\n"
285             "Returns a recent hashes per second performance measurement while generating.");
286
287     if (GetTimeMillis() - nHPSTimerStart > 8000)
288         return (boost::int64_t)0;
289     return (boost::int64_t)dHashesPerSec;
290 }
291
292
293 Value getinfo(const Array& params, bool fHelp)
294 {
295     if (fHelp || params.size() != 0)
296         throw runtime_error(
297             "getinfo\n"
298             "Returns an object containing various state info.");
299
300     Object obj;
301     obj.push_back(Pair("version",       (int)VERSION));
302     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
303     obj.push_back(Pair("blocks",        (int)nBestHeight));
304     obj.push_back(Pair("connections",   (int)vNodes.size()));
305     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
306     obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
307     obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
308     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
309     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
310     obj.push_back(Pair("testnet",       fTestNet));
311     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
312     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
313     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
314     if (pwalletMain->IsCrypted())
315         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
316     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
317     return obj;
318 }
319
320
321 Value getnewaddress(const Array& params, bool fHelp)
322 {
323     if (fHelp || params.size() > 1)
324         throw runtime_error(
325             "getnewaddress [account]\n"
326             "Returns a new bitcoin address for receiving payments.  "
327             "If [account] is specified (recommended), it is added to the address book "
328             "so payments received with the address will be credited to [account].");
329
330     // Parse the account first so we don't generate a key if there's an error
331     string strAccount;
332     if (params.size() > 0)
333         strAccount = AccountFromValue(params[0]);
334
335     if (!pwalletMain->IsLocked())
336         pwalletMain->TopUpKeyPool();
337
338     // Generate a new key that is added to wallet
339     std::vector<unsigned char> newKey;
340     if (!pwalletMain->GetKeyFromPool(newKey, false))
341         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
342     CBitcoinAddress address(newKey);
343
344     pwalletMain->SetAddressBookName(address, strAccount);
345
346     return address.ToString();
347 }
348
349
350 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
351 {
352     CWalletDB walletdb(pwalletMain->strWalletFile);
353
354     CAccount account;
355     walletdb.ReadAccount(strAccount, account);
356
357     bool bKeyUsed = false;
358
359     // Check if the current key has been used
360     if (!account.vchPubKey.empty())
361     {
362         CScript scriptPubKey;
363         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
364         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
365              it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
366              ++it)
367         {
368             const CWalletTx& wtx = (*it).second;
369             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
370                 if (txout.scriptPubKey == scriptPubKey)
371                     bKeyUsed = true;
372         }
373     }
374
375     // Generate a new key
376     if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
377     {
378         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
379             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
380
381         pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
382         walletdb.WriteAccount(strAccount, account);
383     }
384
385     return CBitcoinAddress(account.vchPubKey);
386 }
387
388 Value getaccountaddress(const Array& params, bool fHelp)
389 {
390     if (fHelp || params.size() != 1)
391         throw runtime_error(
392             "getaccountaddress <account>\n"
393             "Returns the current bitcoin address for receiving payments to this account.");
394
395     // Parse the account first so we don't generate a key if there's an error
396     string strAccount = AccountFromValue(params[0]);
397
398     Value ret;
399
400     ret = GetAccountAddress(strAccount).ToString();
401
402     return ret;
403 }
404
405
406
407 Value setaccount(const Array& params, bool fHelp)
408 {
409     if (fHelp || params.size() < 1 || params.size() > 2)
410         throw runtime_error(
411             "setaccount <bitcoinaddress> <account>\n"
412             "Sets the account associated with the given address.");
413
414     CBitcoinAddress address(params[0].get_str());
415     if (!address.IsValid())
416         throw JSONRPCError(-5, "Invalid bitcoin address");
417
418
419     string strAccount;
420     if (params.size() > 1)
421         strAccount = AccountFromValue(params[1]);
422
423     // Detect when changing the account of an address that is the 'unused current key' of another account:
424     if (pwalletMain->mapAddressBook.count(address))
425     {
426         string strOldAccount = pwalletMain->mapAddressBook[address];
427         if (address == GetAccountAddress(strOldAccount))
428             GetAccountAddress(strOldAccount, true);
429     }
430
431     pwalletMain->SetAddressBookName(address, strAccount);
432
433     return Value::null;
434 }
435
436
437 Value getaccount(const Array& params, bool fHelp)
438 {
439     if (fHelp || params.size() != 1)
440         throw runtime_error(
441             "getaccount <bitcoinaddress>\n"
442             "Returns the account associated with the given address.");
443
444     CBitcoinAddress address(params[0].get_str());
445     if (!address.IsValid())
446         throw JSONRPCError(-5, "Invalid bitcoin address");
447
448     string strAccount;
449     map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
450     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
451         strAccount = (*mi).second;
452     return strAccount;
453 }
454
455
456 Value getaddressesbyaccount(const Array& params, bool fHelp)
457 {
458     if (fHelp || params.size() != 1)
459         throw runtime_error(
460             "getaddressesbyaccount <account>\n"
461             "Returns the list of addresses for the given account.");
462
463     string strAccount = AccountFromValue(params[0]);
464
465     // Find all addresses that have the given account
466     Array ret;
467     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
468     {
469         const CBitcoinAddress& address = item.first;
470         const string& strName = item.second;
471         if (strName == strAccount)
472             ret.push_back(address.ToString());
473     }
474     return ret;
475 }
476
477 Value settxfee(const Array& params, bool fHelp)
478 {
479     if (fHelp || params.size() < 1 || params.size() > 1)
480         throw runtime_error(
481             "settxfee <amount>\n"
482             "<amount> is a real and is rounded to the nearest 0.00000001");
483
484     // Amount
485     int64 nAmount = 0;
486     if (params[0].get_real() != 0.0)
487         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
488
489     nTransactionFee = nAmount;
490     return true;
491 }
492
493 Value sendtoaddress(const Array& params, bool fHelp)
494 {
495     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
496         throw runtime_error(
497             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
498             "<amount> is a real and is rounded to the nearest 0.00000001\n"
499             "requires wallet passphrase to be set with walletpassphrase first");
500     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
501         throw runtime_error(
502             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503             "<amount> is a real and is rounded to the nearest 0.00000001");
504
505     CBitcoinAddress address(params[0].get_str());
506     if (!address.IsValid())
507         throw JSONRPCError(-5, "Invalid bitcoin address");
508
509     // Amount
510     int64 nAmount = AmountFromValue(params[1]);
511
512     // Wallet comments
513     CWalletTx wtx;
514     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
515         wtx.mapValue["comment"] = params[2].get_str();
516     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
517         wtx.mapValue["to"]      = params[3].get_str();
518
519     if (pwalletMain->IsLocked())
520         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
521
522     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
523     if (strError != "")
524         throw JSONRPCError(-4, strError);
525
526     return wtx.GetHash().GetHex();
527 }
528
529 static const string strMessageMagic = "Bitcoin Signed Message:\n";
530
531 Value signmessage(const Array& params, bool fHelp)
532 {
533     if (fHelp || params.size() != 2)
534         throw runtime_error(
535             "signmessage <bitcoinaddress> <message>\n"
536             "Sign a message with the private key of an address");
537
538     if (pwalletMain->IsLocked())
539         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
540
541     string strAddress = params[0].get_str();
542     string strMessage = params[1].get_str();
543
544     CBitcoinAddress addr(strAddress);
545     if (!addr.IsValid())
546         throw JSONRPCError(-3, "Invalid address");
547
548     CKey key;
549     if (!pwalletMain->GetKey(addr, key))
550         throw JSONRPCError(-4, "Private key not available");
551
552     CDataStream ss(SER_GETHASH);
553     ss << strMessageMagic;
554     ss << strMessage;
555
556     vector<unsigned char> vchSig;
557     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
558         throw JSONRPCError(-5, "Sign failed");
559
560     return EncodeBase64(&vchSig[0], vchSig.size());
561 }
562
563 Value verifymessage(const Array& params, bool fHelp)
564 {
565     if (fHelp || params.size() != 3)
566         throw runtime_error(
567             "verifymessage <bitcoinaddress> <signature> <message>\n"
568             "Verify a signed message");
569
570     string strAddress  = params[0].get_str();
571     string strSign     = params[1].get_str();
572     string strMessage  = params[2].get_str();
573
574     CBitcoinAddress addr(strAddress);
575     if (!addr.IsValid())
576         throw JSONRPCError(-3, "Invalid address");
577
578     bool fInvalid = false;
579     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
580
581     if (fInvalid)
582         throw JSONRPCError(-5, "Malformed base64 encoding");
583
584     CDataStream ss(SER_GETHASH);
585     ss << strMessageMagic;
586     ss << strMessage;
587
588     CKey key;
589     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
590         return false;
591
592     return (key.GetAddress() == addr);
593 }
594
595
596 Value getreceivedbyaddress(const Array& params, bool fHelp)
597 {
598     if (fHelp || params.size() < 1 || params.size() > 2)
599         throw runtime_error(
600             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
601             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
602
603     // Bitcoin address
604     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
605     CScript scriptPubKey;
606     if (!address.IsValid())
607         throw JSONRPCError(-5, "Invalid bitcoin address");
608     scriptPubKey.SetBitcoinAddress(address);
609     if (!IsMine(*pwalletMain,scriptPubKey))
610         return (double)0.0;
611
612     // Minimum confirmations
613     int nMinDepth = 1;
614     if (params.size() > 1)
615         nMinDepth = params[1].get_int();
616
617     // Tally
618     int64 nAmount = 0;
619     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
620     {
621         const CWalletTx& wtx = (*it).second;
622         if (wtx.IsCoinBase() || !wtx.IsFinal())
623             continue;
624
625         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
626             if (txout.scriptPubKey == scriptPubKey)
627                 if (wtx.GetDepthInMainChain() >= nMinDepth)
628                     nAmount += txout.nValue;
629     }
630
631     return  ValueFromAmount(nAmount);
632 }
633
634
635 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
636 {
637     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
638     {
639         const CBitcoinAddress& address = item.first;
640         const string& strName = item.second;
641         if (strName == strAccount)
642             setAddress.insert(address);
643     }
644 }
645
646
647 Value getreceivedbyaccount(const Array& params, bool fHelp)
648 {
649     if (fHelp || params.size() < 1 || params.size() > 2)
650         throw runtime_error(
651             "getreceivedbyaccount <account> [minconf=1]\n"
652             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
653
654     // Minimum confirmations
655     int nMinDepth = 1;
656     if (params.size() > 1)
657         nMinDepth = params[1].get_int();
658
659     // Get the set of pub keys that have the label
660     string strAccount = AccountFromValue(params[0]);
661     set<CBitcoinAddress> setAddress;
662     GetAccountAddresses(strAccount, setAddress);
663
664     // Tally
665     int64 nAmount = 0;
666     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
667     {
668         const CWalletTx& wtx = (*it).second;
669         if (wtx.IsCoinBase() || !wtx.IsFinal())
670             continue;
671
672         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
673         {
674             CBitcoinAddress address;
675             if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
676                 if (wtx.GetDepthInMainChain() >= nMinDepth)
677                     nAmount += txout.nValue;
678         }
679     }
680
681     return (double)nAmount / (double)COIN;
682 }
683
684
685 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
686 {
687     int64 nBalance = 0;
688
689     // Tally wallet transactions
690     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
691     {
692         const CWalletTx& wtx = (*it).second;
693         if (!wtx.IsFinal())
694             continue;
695
696         int64 nGenerated, nReceived, nSent, nFee;
697         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
698
699         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
700             nBalance += nReceived;
701         nBalance += nGenerated - nSent - nFee;
702     }
703
704     // Tally internal accounting entries
705     nBalance += walletdb.GetAccountCreditDebit(strAccount);
706
707     return nBalance;
708 }
709
710 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
711 {
712     CWalletDB walletdb(pwalletMain->strWalletFile);
713     return GetAccountBalance(walletdb, strAccount, nMinDepth);
714 }
715
716
717 Value getbalance(const Array& params, bool fHelp)
718 {
719     if (fHelp || params.size() > 2)
720         throw runtime_error(
721             "getbalance [account] [minconf=1]\n"
722             "If [account] is not specified, returns the server's total available balance.\n"
723             "If [account] is specified, returns the balance in the account.");
724
725     if (params.size() == 0)
726         return  ValueFromAmount(pwalletMain->GetBalance());
727
728     int nMinDepth = 1;
729     if (params.size() > 1)
730         nMinDepth = params[1].get_int();
731
732     if (params[0].get_str() == "*") {
733         // Calculate total balance a different way from GetBalance()
734         // (GetBalance() sums up all unspent TxOuts)
735         // getbalance and getbalance '*' should always return the same number.
736         int64 nBalance = 0;
737         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
738         {
739             const CWalletTx& wtx = (*it).second;
740             if (!wtx.IsFinal())
741                 continue;
742
743             int64 allGeneratedImmature, allGeneratedMature, allFee;
744             allGeneratedImmature = allGeneratedMature = allFee = 0;
745             string strSentAccount;
746             list<pair<CBitcoinAddress, int64> > listReceived;
747             list<pair<CBitcoinAddress, int64> > listSent;
748             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
749             if (wtx.GetDepthInMainChain() >= nMinDepth)
750                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
751                     nBalance += r.second;
752             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
753                 nBalance -= r.second;
754             nBalance -= allFee;
755             nBalance += allGeneratedMature;
756         }
757         return  ValueFromAmount(nBalance);
758     }
759
760     string strAccount = AccountFromValue(params[0]);
761
762     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
763
764     return ValueFromAmount(nBalance);
765 }
766
767
768 Value movecmd(const Array& params, bool fHelp)
769 {
770     if (fHelp || params.size() < 3 || params.size() > 5)
771         throw runtime_error(
772             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
773             "Move from one account in your wallet to another.");
774
775     string strFrom = AccountFromValue(params[0]);
776     string strTo = AccountFromValue(params[1]);
777     int64 nAmount = AmountFromValue(params[2]);
778     if (params.size() > 3)
779         // unused parameter, used to be nMinDepth, keep type-checking it though
780         (void)params[3].get_int();
781     string strComment;
782     if (params.size() > 4)
783         strComment = params[4].get_str();
784
785     CWalletDB walletdb(pwalletMain->strWalletFile);
786     walletdb.TxnBegin();
787
788     int64 nNow = GetAdjustedTime();
789
790     // Debit
791     CAccountingEntry debit;
792     debit.strAccount = strFrom;
793     debit.nCreditDebit = -nAmount;
794     debit.nTime = nNow;
795     debit.strOtherAccount = strTo;
796     debit.strComment = strComment;
797     walletdb.WriteAccountingEntry(debit);
798
799     // Credit
800     CAccountingEntry credit;
801     credit.strAccount = strTo;
802     credit.nCreditDebit = nAmount;
803     credit.nTime = nNow;
804     credit.strOtherAccount = strFrom;
805     credit.strComment = strComment;
806     walletdb.WriteAccountingEntry(credit);
807
808     walletdb.TxnCommit();
809
810     return true;
811 }
812
813
814 Value sendfrom(const Array& params, bool fHelp)
815 {
816     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
817         throw runtime_error(
818             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
819             "<amount> is a real and is rounded to the nearest 0.00000001\n"
820             "requires wallet passphrase to be set with walletpassphrase first");
821     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
822         throw runtime_error(
823             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
824             "<amount> is a real and is rounded to the nearest 0.00000001");
825
826     string strAccount = AccountFromValue(params[0]);
827     CBitcoinAddress address(params[1].get_str());
828     if (!address.IsValid())
829         throw JSONRPCError(-5, "Invalid bitcoin address");
830     int64 nAmount = AmountFromValue(params[2]);
831     int nMinDepth = 1;
832     if (params.size() > 3)
833         nMinDepth = params[3].get_int();
834
835     CWalletTx wtx;
836     wtx.strFromAccount = strAccount;
837     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
838         wtx.mapValue["comment"] = params[4].get_str();
839     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
840         wtx.mapValue["to"]      = params[5].get_str();
841
842     if (pwalletMain->IsLocked())
843         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
844
845     // Check funds
846     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
847     if (nAmount > nBalance)
848         throw JSONRPCError(-6, "Account has insufficient funds");
849
850     // Send
851     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
852     if (strError != "")
853         throw JSONRPCError(-4, strError);
854
855     return wtx.GetHash().GetHex();
856 }
857
858
859 Value sendmany(const Array& params, bool fHelp)
860 {
861     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
862         throw runtime_error(
863             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
864             "amounts are double-precision floating point numbers\n"
865             "requires wallet passphrase to be set with walletpassphrase first");
866     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
867         throw runtime_error(
868             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
869             "amounts are double-precision floating point numbers");
870
871     string strAccount = AccountFromValue(params[0]);
872     Object sendTo = params[1].get_obj();
873     int nMinDepth = 1;
874     if (params.size() > 2)
875         nMinDepth = params[2].get_int();
876
877     CWalletTx wtx;
878     wtx.strFromAccount = strAccount;
879     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
880         wtx.mapValue["comment"] = params[3].get_str();
881
882     set<CBitcoinAddress> setAddress;
883     vector<pair<CScript, int64> > vecSend;
884
885     int64 totalAmount = 0;
886     BOOST_FOREACH(const Pair& s, sendTo)
887     {
888         CBitcoinAddress address(s.name_);
889         if (!address.IsValid())
890             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
891
892         if (setAddress.count(address))
893             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
894         setAddress.insert(address);
895
896         CScript scriptPubKey;
897         scriptPubKey.SetBitcoinAddress(address);
898         int64 nAmount = AmountFromValue(s.value_); 
899         totalAmount += nAmount;
900
901         vecSend.push_back(make_pair(scriptPubKey, nAmount));
902     }
903
904     if (pwalletMain->IsLocked())
905         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
906
907     // Check funds
908     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
909     if (totalAmount > nBalance)
910         throw JSONRPCError(-6, "Account has insufficient funds");
911
912     // Send
913     CReserveKey keyChange(pwalletMain);
914     int64 nFeeRequired = 0;
915     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
916     if (!fCreated)
917     {
918         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
919             throw JSONRPCError(-6, "Insufficient funds");
920         throw JSONRPCError(-4, "Transaction creation failed");
921     }
922     if (!pwalletMain->CommitTransaction(wtx, keyChange))
923         throw JSONRPCError(-4, "Transaction commit failed");
924
925     return wtx.GetHash().GetHex();
926 }
927
928
929 struct tallyitem
930 {
931     int64 nAmount;
932     int nConf;
933     tallyitem()
934     {
935         nAmount = 0;
936         nConf = INT_MAX;
937     }
938 };
939
940 Value ListReceived(const Array& params, bool fByAccounts)
941 {
942     // Minimum confirmations
943     int nMinDepth = 1;
944     if (params.size() > 0)
945         nMinDepth = params[0].get_int();
946
947     // Whether to include empty accounts
948     bool fIncludeEmpty = false;
949     if (params.size() > 1)
950         fIncludeEmpty = params[1].get_bool();
951
952     // Tally
953     map<CBitcoinAddress, tallyitem> mapTally;
954     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
955     {
956         const CWalletTx& wtx = (*it).second;
957         if (wtx.IsCoinBase() || !wtx.IsFinal())
958             continue;
959
960         int nDepth = wtx.GetDepthInMainChain();
961         if (nDepth < nMinDepth)
962             continue;
963
964         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
965         {
966             CBitcoinAddress address;
967             if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
968                 continue;
969
970             tallyitem& item = mapTally[address];
971             item.nAmount += txout.nValue;
972             item.nConf = min(item.nConf, nDepth);
973         }
974     }
975
976     // Reply
977     Array ret;
978     map<string, tallyitem> mapAccountTally;
979     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
980     {
981         const CBitcoinAddress& address = item.first;
982         const string& strAccount = item.second;
983         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
984         if (it == mapTally.end() && !fIncludeEmpty)
985             continue;
986
987         int64 nAmount = 0;
988         int nConf = INT_MAX;
989         if (it != mapTally.end())
990         {
991             nAmount = (*it).second.nAmount;
992             nConf = (*it).second.nConf;
993         }
994
995         if (fByAccounts)
996         {
997             tallyitem& item = mapAccountTally[strAccount];
998             item.nAmount += nAmount;
999             item.nConf = min(item.nConf, nConf);
1000         }
1001         else
1002         {
1003             Object obj;
1004             obj.push_back(Pair("address",       address.ToString()));
1005             obj.push_back(Pair("account",       strAccount));
1006             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1007             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
1008             ret.push_back(obj);
1009         }
1010     }
1011
1012     if (fByAccounts)
1013     {
1014         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1015         {
1016             int64 nAmount = (*it).second.nAmount;
1017             int nConf = (*it).second.nConf;
1018             Object obj;
1019             obj.push_back(Pair("account",       (*it).first));
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 (DEPRECATED)\n" // deprecated
1550             "  \"data\" : block data\n"
1551             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
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)))); // deprecated
1616         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1617         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
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("getaccount",             &getaccount),
1677     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
1678     make_pair("sendtoaddress",          &sendtoaddress),
1679     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
1680     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
1681     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
1682     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
1683     make_pair("backupwallet",           &backupwallet),
1684     make_pair("keypoolrefill",          &keypoolrefill),
1685     make_pair("walletpassphrase",       &walletpassphrase),
1686     make_pair("walletpassphrasechange", &walletpassphrasechange),
1687     make_pair("walletlock",             &walletlock),
1688     make_pair("encryptwallet",          &encryptwallet),
1689     make_pair("validateaddress",        &validateaddress),
1690     make_pair("getbalance",             &getbalance),
1691     make_pair("move",                   &movecmd),
1692     make_pair("sendfrom",               &sendfrom),
1693     make_pair("sendmany",               &sendmany),
1694     make_pair("gettransaction",         &gettransaction),
1695     make_pair("listtransactions",       &listtransactions),
1696     make_pair("signmessage",           &signmessage),
1697     make_pair("verifymessage",         &verifymessage),
1698     make_pair("getwork",                &getwork),
1699     make_pair("listaccounts",           &listaccounts),
1700     make_pair("settxfee",               &settxfee),
1701 };
1702 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1703
1704 string pAllowInSafeMode[] =
1705 {
1706     "help",
1707     "stop",
1708     "getblockcount",
1709     "getblocknumber",
1710     "getconnectioncount",
1711     "getdifficulty",
1712     "getgenerate",
1713     "setgenerate",
1714     "gethashespersec",
1715     "getinfo",
1716     "getnewaddress",
1717     "getaccountaddress",
1718     "getaccount",
1719     "getaddressesbyaccount",
1720     "backupwallet",
1721     "keypoolrefill",
1722     "walletpassphrase",
1723     "walletlock",
1724     "validateaddress",
1725     "getwork",
1726 };
1727 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1728
1729
1730
1731
1732 //
1733 // HTTP protocol
1734 //
1735 // This ain't Apache.  We're just using HTTP header for the length field
1736 // and to be compatible with other JSON-RPC implementations.
1737 //
1738
1739 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1740 {
1741     ostringstream s;
1742     s << "POST / HTTP/1.1\r\n"
1743       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1744       << "Host: 127.0.0.1\r\n"
1745       << "Content-Type: application/json\r\n"
1746       << "Content-Length: " << strMsg.size() << "\r\n"
1747       << "Accept: application/json\r\n";
1748     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1749         s << item.first << ": " << item.second << "\r\n";
1750     s << "\r\n" << strMsg;
1751
1752     return s.str();
1753 }
1754
1755 string rfc1123Time()
1756 {
1757     char buffer[64];
1758     time_t now;
1759     time(&now);
1760     struct tm* now_gmt = gmtime(&now);
1761     string locale(setlocale(LC_TIME, NULL));
1762     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1763     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1764     setlocale(LC_TIME, locale.c_str());
1765     return string(buffer);
1766 }
1767
1768 static string HTTPReply(int nStatus, const string& strMsg)
1769 {
1770     if (nStatus == 401)
1771         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1772             "Date: %s\r\n"
1773             "Server: bitcoin-json-rpc/%s\r\n"
1774             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1775             "Content-Type: text/html\r\n"
1776             "Content-Length: 296\r\n"
1777             "\r\n"
1778             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1779             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1780             "<HTML>\r\n"
1781             "<HEAD>\r\n"
1782             "<TITLE>Error</TITLE>\r\n"
1783             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1784             "</HEAD>\r\n"
1785             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1786             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1787     string strStatus;
1788          if (nStatus == 200) strStatus = "OK";
1789     else if (nStatus == 400) strStatus = "Bad Request";
1790     else if (nStatus == 403) strStatus = "Forbidden";
1791     else if (nStatus == 404) strStatus = "Not Found";
1792     else if (nStatus == 500) strStatus = "Internal Server Error";
1793     return strprintf(
1794             "HTTP/1.1 %d %s\r\n"
1795             "Date: %s\r\n"
1796             "Connection: close\r\n"
1797             "Content-Length: %d\r\n"
1798             "Content-Type: application/json\r\n"
1799             "Server: bitcoin-json-rpc/%s\r\n"
1800             "\r\n"
1801             "%s",
1802         nStatus,
1803         strStatus.c_str(),
1804         rfc1123Time().c_str(),
1805         strMsg.size(),
1806         FormatFullVersion().c_str(),
1807         strMsg.c_str());
1808 }
1809
1810 int ReadHTTPStatus(std::basic_istream<char>& stream)
1811 {
1812     string str;
1813     getline(stream, str);
1814     vector<string> vWords;
1815     boost::split(vWords, str, boost::is_any_of(" "));
1816     if (vWords.size() < 2)
1817         return 500;
1818     return atoi(vWords[1].c_str());
1819 }
1820
1821 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1822 {
1823     int nLen = 0;
1824     loop
1825     {
1826         string str;
1827         std::getline(stream, str);
1828         if (str.empty() || str == "\r")
1829             break;
1830         string::size_type nColon = str.find(":");
1831         if (nColon != string::npos)
1832         {
1833             string strHeader = str.substr(0, nColon);
1834             boost::trim(strHeader);
1835             boost::to_lower(strHeader);
1836             string strValue = str.substr(nColon+1);
1837             boost::trim(strValue);
1838             mapHeadersRet[strHeader] = strValue;
1839             if (strHeader == "content-length")
1840                 nLen = atoi(strValue.c_str());
1841         }
1842     }
1843     return nLen;
1844 }
1845
1846 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1847 {
1848     mapHeadersRet.clear();
1849     strMessageRet = "";
1850
1851     // Read status
1852     int nStatus = ReadHTTPStatus(stream);
1853
1854     // Read header
1855     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1856     if (nLen < 0 || nLen > MAX_SIZE)
1857         return 500;
1858
1859     // Read message
1860     if (nLen > 0)
1861     {
1862         vector<char> vch(nLen);
1863         stream.read(&vch[0], nLen);
1864         strMessageRet = string(vch.begin(), vch.end());
1865     }
1866
1867     return nStatus;
1868 }
1869
1870 bool HTTPAuthorized(map<string, string>& mapHeaders)
1871 {
1872     string strAuth = mapHeaders["authorization"];
1873     if (strAuth.substr(0,6) != "Basic ")
1874         return false;
1875     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1876     string strUserPass = DecodeBase64(strUserPass64);
1877     string::size_type nColon = strUserPass.find(":");
1878     if (nColon == string::npos)
1879         return false;
1880     string strUser = strUserPass.substr(0, nColon);
1881     string strPassword = strUserPass.substr(nColon+1);
1882     return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1883 }
1884
1885 //
1886 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
1887 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1888 // unspecified (HTTP errors and contents of 'error').
1889 //
1890 // 1.0 spec: http://json-rpc.org/wiki/specification
1891 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1892 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1893 //
1894
1895 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1896 {
1897     Object request;
1898     request.push_back(Pair("method", strMethod));
1899     request.push_back(Pair("params", params));
1900     request.push_back(Pair("id", id));
1901     return write_string(Value(request), false) + "\n";
1902 }
1903
1904 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1905 {
1906     Object reply;
1907     if (error.type() != null_type)
1908         reply.push_back(Pair("result", Value::null));
1909     else
1910         reply.push_back(Pair("result", result));
1911     reply.push_back(Pair("error", error));
1912     reply.push_back(Pair("id", id));
1913     return write_string(Value(reply), false) + "\n";
1914 }
1915
1916 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1917 {
1918     // Send error reply from json-rpc error object
1919     int nStatus = 500;
1920     int code = find_value(objError, "code").get_int();
1921     if (code == -32600) nStatus = 400;
1922     else if (code == -32601) nStatus = 404;
1923     string strReply = JSONRPCReply(Value::null, objError, id);
1924     stream << HTTPReply(nStatus, strReply) << std::flush;
1925 }
1926
1927 bool ClientAllowed(const string& strAddress)
1928 {
1929     if (strAddress == asio::ip::address_v4::loopback().to_string())
1930         return true;
1931     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
1932     BOOST_FOREACH(string strAllow, vAllow)
1933         if (WildcardMatch(strAddress, strAllow))
1934             return true;
1935     return false;
1936 }
1937
1938 #ifdef USE_SSL
1939 //
1940 // IOStream device that speaks SSL but can also speak non-SSL
1941 //
1942 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
1943 public:
1944     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
1945     {
1946         fUseSSL = fUseSSLIn;
1947         fNeedHandshake = fUseSSLIn;
1948     }
1949
1950     void handshake(ssl::stream_base::handshake_type role)
1951     {
1952         if (!fNeedHandshake) return;
1953         fNeedHandshake = false;
1954         stream.handshake(role);
1955     }
1956     std::streamsize read(char* s, std::streamsize n)
1957     {
1958         handshake(ssl::stream_base::server); // HTTPS servers read first
1959         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
1960         return stream.next_layer().read_some(asio::buffer(s, n));
1961     }
1962     std::streamsize write(const char* s, std::streamsize n)
1963     {
1964         handshake(ssl::stream_base::client); // HTTPS clients write first
1965         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
1966         return asio::write(stream.next_layer(), asio::buffer(s, n));
1967     }
1968     bool connect(const std::string& server, const std::string& port)
1969     {
1970         ip::tcp::resolver resolver(stream.get_io_service());
1971         ip::tcp::resolver::query query(server.c_str(), port.c_str());
1972         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
1973         ip::tcp::resolver::iterator end;
1974         boost::system::error_code error = asio::error::host_not_found;
1975         while (error && endpoint_iterator != end)
1976         {
1977             stream.lowest_layer().close();
1978             stream.lowest_layer().connect(*endpoint_iterator++, error);
1979         }
1980         if (error)
1981             return false;
1982         return true;
1983     }
1984
1985 private:
1986     bool fNeedHandshake;
1987     bool fUseSSL;
1988     SSLStream& stream;
1989 };
1990 #endif
1991
1992 void ThreadRPCServer(void* parg)
1993 {
1994     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
1995     try
1996     {
1997         vnThreadsRunning[4]++;
1998         ThreadRPCServer2(parg);
1999         vnThreadsRunning[4]--;
2000     }
2001     catch (std::exception& e) {
2002         vnThreadsRunning[4]--;
2003         PrintException(&e, "ThreadRPCServer()");
2004     } catch (...) {
2005         vnThreadsRunning[4]--;
2006         PrintException(NULL, "ThreadRPCServer()");
2007     }
2008     printf("ThreadRPCServer exiting\n");
2009 }
2010
2011 void ThreadRPCServer2(void* parg)
2012 {
2013     printf("ThreadRPCServer started\n");
2014
2015     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2016     {
2017         string strWhatAmI = "To use bitcoind";
2018         if (mapArgs.count("-server"))
2019             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2020         else if (mapArgs.count("-daemon"))
2021             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2022         PrintConsole(
2023             _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2024               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2025                 strWhatAmI.c_str(),
2026                 GetConfigFile().c_str());
2027         CreateThread(Shutdown, NULL);
2028         return;
2029     }
2030
2031     bool fUseSSL = GetBoolArg("-rpcssl");
2032     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2033
2034     asio::io_service io_service;
2035     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2036     ip::tcp::acceptor acceptor(io_service, endpoint);
2037
2038     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2039
2040 #ifdef USE_SSL
2041     ssl::context context(io_service, ssl::context::sslv23);
2042     if (fUseSSL)
2043     {
2044         context.set_options(ssl::context::no_sslv2);
2045         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2046         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2047         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2048         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2049         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2050         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2051         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2052         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2053
2054         string ciphers = GetArg("-rpcsslciphers",
2055                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2056         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2057     }
2058 #else
2059     if (fUseSSL)
2060         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2061 #endif
2062
2063     loop
2064     {
2065         // Accept connection
2066 #ifdef USE_SSL
2067         SSLStream sslStream(io_service, context);
2068         SSLIOStreamDevice d(sslStream, fUseSSL);
2069         iostreams::stream<SSLIOStreamDevice> stream(d);
2070 #else
2071         ip::tcp::iostream stream;
2072 #endif
2073
2074         ip::tcp::endpoint peer;
2075         vnThreadsRunning[4]--;
2076 #ifdef USE_SSL
2077         acceptor.accept(sslStream.lowest_layer(), peer);
2078 #else
2079         acceptor.accept(*stream.rdbuf(), peer);
2080 #endif
2081         vnThreadsRunning[4]++;
2082         if (fShutdown)
2083             return;
2084
2085         // Restrict callers by IP
2086         if (!ClientAllowed(peer.address().to_string()))
2087         {
2088             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2089             if (!fUseSSL)
2090                 stream << HTTPReply(403, "") << std::flush;
2091             continue;
2092         }
2093
2094         map<string, string> mapHeaders;
2095         string strRequest;
2096
2097         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2098         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2099         {   // Timed out:
2100             acceptor.cancel();
2101             printf("ThreadRPCServer ReadHTTP timeout\n");
2102             continue;
2103         }
2104
2105         // Check authorization
2106         if (mapHeaders.count("authorization") == 0)
2107         {
2108             stream << HTTPReply(401, "") << std::flush;
2109             continue;
2110         }
2111         if (!HTTPAuthorized(mapHeaders))
2112         {
2113             // Deter brute-forcing short passwords
2114             if (mapArgs["-rpcpassword"].size() < 15)
2115                 Sleep(50);
2116
2117             stream << HTTPReply(401, "") << std::flush;
2118             printf("ThreadRPCServer incorrect password attempt\n");
2119             continue;
2120         }
2121
2122         Value id = Value::null;
2123         try
2124         {
2125             // Parse request
2126             Value valRequest;
2127             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2128                 throw JSONRPCError(-32700, "Parse error");
2129             const Object& request = valRequest.get_obj();
2130
2131             // Parse id now so errors from here on will have the id
2132             id = find_value(request, "id");
2133
2134             // Parse method
2135             Value valMethod = find_value(request, "method");
2136             if (valMethod.type() == null_type)
2137                 throw JSONRPCError(-32600, "Missing method");
2138             if (valMethod.type() != str_type)
2139                 throw JSONRPCError(-32600, "Method must be a string");
2140             string strMethod = valMethod.get_str();
2141             if (strMethod != "getwork")
2142                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2143
2144             // Parse params
2145             Value valParams = find_value(request, "params");
2146             Array params;
2147             if (valParams.type() == array_type)
2148                 params = valParams.get_array();
2149             else if (valParams.type() == null_type)
2150                 params = Array();
2151             else
2152                 throw JSONRPCError(-32600, "Params must be an array");
2153
2154             // Find method
2155             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2156             if (mi == mapCallTable.end())
2157                 throw JSONRPCError(-32601, "Method not found");
2158
2159             // Observe safe mode
2160             string strWarning = GetWarnings("rpc");
2161             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2162                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2163
2164             try
2165             {
2166                 // Execute
2167                 Value result;
2168                 CRITICAL_BLOCK(cs_main)
2169                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2170                     result = (*(*mi).second)(params, false);
2171
2172                 // Send reply
2173                 string strReply = JSONRPCReply(result, Value::null, id);
2174                 stream << HTTPReply(200, strReply) << std::flush;
2175             }
2176             catch (std::exception& e)
2177             {
2178                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2179             }
2180         }
2181         catch (Object& objError)
2182         {
2183             ErrorReply(stream, objError, id);
2184         }
2185         catch (std::exception& e)
2186         {
2187             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2188         }
2189     }
2190 }
2191
2192
2193
2194
2195 Object CallRPC(const string& strMethod, const Array& params)
2196 {
2197     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2198         throw runtime_error(strprintf(
2199             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2200               "If the file does not exist, create it with owner-readable-only file permissions."),
2201                 GetConfigFile().c_str()));
2202
2203     // Connect to localhost
2204     bool fUseSSL = GetBoolArg("-rpcssl");
2205 #ifdef USE_SSL
2206     asio::io_service io_service;
2207     ssl::context context(io_service, ssl::context::sslv23);
2208     context.set_options(ssl::context::no_sslv2);
2209     SSLStream sslStream(io_service, context);
2210     SSLIOStreamDevice d(sslStream, fUseSSL);
2211     iostreams::stream<SSLIOStreamDevice> stream(d);
2212     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2213         throw runtime_error("couldn't connect to server");
2214 #else
2215     if (fUseSSL)
2216         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2217
2218     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2219     if (stream.fail())
2220         throw runtime_error("couldn't connect to server");
2221 #endif
2222
2223
2224     // HTTP basic authentication
2225     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2226     map<string, string> mapRequestHeaders;
2227     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2228
2229     // Send request
2230     string strRequest = JSONRPCRequest(strMethod, params, 1);
2231     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2232     stream << strPost << std::flush;
2233
2234     // Receive reply
2235     map<string, string> mapHeaders;
2236     string strReply;
2237     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2238     if (nStatus == 401)
2239         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2240     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2241         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2242     else if (strReply.empty())
2243         throw runtime_error("no response from server");
2244
2245     // Parse reply
2246     Value valReply;
2247     if (!read_string(strReply, valReply))
2248         throw runtime_error("couldn't parse reply from server");
2249     const Object& reply = valReply.get_obj();
2250     if (reply.empty())
2251         throw runtime_error("expected reply to have result, error and id properties");
2252
2253     return reply;
2254 }
2255
2256
2257
2258
2259 template<typename T>
2260 void ConvertTo(Value& value)
2261 {
2262     if (value.type() == str_type)
2263     {
2264         // reinterpret string as unquoted json value
2265         Value value2;
2266         if (!read_string(value.get_str(), value2))
2267             throw runtime_error("type mismatch");
2268         value = value2.get_value<T>();
2269     }
2270     else
2271     {
2272         value = value.get_value<T>();
2273     }
2274 }
2275
2276 int CommandLineRPC(int argc, char *argv[])
2277 {
2278     string strPrint;
2279     int nRet = 0;
2280     try
2281     {
2282         // Skip switches
2283         while (argc > 1 && IsSwitchChar(argv[1][0]))
2284         {
2285             argc--;
2286             argv++;
2287         }
2288
2289         // Method
2290         if (argc < 2)
2291             throw runtime_error("too few parameters");
2292         string strMethod = argv[1];
2293
2294         // Parameters default to strings
2295         Array params;
2296         for (int i = 2; i < argc; i++)
2297             params.push_back(argv[i]);
2298         int n = params.size();
2299
2300         //
2301         // Special case non-string parameter types
2302         //
2303         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2304         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2305         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2306         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2307         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2308         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2309         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2310         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2311         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2312         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2313         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2314         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2315         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2316         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2317         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2318         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2319         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2320         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2321         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2322         if (strMethod == "sendmany"               && n > 1)
2323         {
2324             string s = params[1].get_str();
2325             Value v;
2326             if (!read_string(s, v) || v.type() != obj_type)
2327                 throw runtime_error("type mismatch");
2328             params[1] = v.get_obj();
2329         }
2330         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2331
2332         // Execute
2333         Object reply = CallRPC(strMethod, params);
2334
2335         // Parse reply
2336         const Value& result = find_value(reply, "result");
2337         const Value& error  = find_value(reply, "error");
2338
2339         if (error.type() != null_type)
2340         {
2341             // Error
2342             strPrint = "error: " + write_string(error, false);
2343             int code = find_value(error.get_obj(), "code").get_int();
2344             nRet = abs(code);
2345         }
2346         else
2347         {
2348             // Result
2349             if (result.type() == null_type)
2350                 strPrint = "";
2351             else if (result.type() == str_type)
2352                 strPrint = result.get_str();
2353             else
2354                 strPrint = write_string(result, true);
2355         }
2356     }
2357     catch (std::exception& e)
2358     {
2359         strPrint = string("error: ") + e.what();
2360         nRet = 87;
2361     }
2362     catch (...)
2363     {
2364         PrintException(NULL, "CommandLineRPC()");
2365     }
2366
2367     if (strPrint != "")
2368     {
2369         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2370     }
2371     return nRet;
2372 }
2373
2374
2375
2376
2377 #ifdef TEST
2378 int main(int argc, char *argv[])
2379 {
2380 #ifdef _MSC_VER
2381     // Turn off microsoft heap dump noise
2382     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2383     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2384 #endif
2385     setbuf(stdin, NULL);
2386     setbuf(stdout, NULL);
2387     setbuf(stderr, NULL);
2388
2389     try
2390     {
2391         if (argc >= 2 && string(argv[1]) == "-server")
2392         {
2393             printf("server ready\n");
2394             ThreadRPCServer(NULL);
2395         }
2396         else
2397         {
2398             return CommandLineRPC(argc, argv);
2399         }
2400     }
2401     catch (std::exception& e) {
2402         PrintException(&e, "main()");
2403     } catch (...) {
2404         PrintException(NULL, "main()");
2405     }
2406     return 0;
2407 }
2408 #endif