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