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