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