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