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