Fix loop index var types, fixing many minor sign comparison warnings
[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') != string::npos)
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             {
800                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
801                     nBalance += r.second;
802             }
803             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
804                 nBalance -= r.second;
805             nBalance -= allFee;
806             nBalance += allGeneratedMature;
807         }
808         return  ValueFromAmount(nBalance);
809     }
810
811     string strAccount = AccountFromValue(params[0]);
812
813     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
814
815     return ValueFromAmount(nBalance);
816 }
817
818
819 Value movecmd(const Array& params, bool fHelp)
820 {
821     if (fHelp || params.size() < 3 || params.size() > 5)
822         throw runtime_error(
823             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
824             "Move from one account in your wallet to another.");
825
826     string strFrom = AccountFromValue(params[0]);
827     string strTo = AccountFromValue(params[1]);
828     int64 nAmount = AmountFromValue(params[2]);
829     if (params.size() > 3)
830         // unused parameter, used to be nMinDepth, keep type-checking it though
831         (void)params[3].get_int();
832     string strComment;
833     if (params.size() > 4)
834         strComment = params[4].get_str();
835
836     CWalletDB walletdb(pwalletMain->strWalletFile);
837     walletdb.TxnBegin();
838
839     int64 nNow = GetAdjustedTime();
840
841     // Debit
842     CAccountingEntry debit;
843     debit.strAccount = strFrom;
844     debit.nCreditDebit = -nAmount;
845     debit.nTime = nNow;
846     debit.strOtherAccount = strTo;
847     debit.strComment = strComment;
848     walletdb.WriteAccountingEntry(debit);
849
850     // Credit
851     CAccountingEntry credit;
852     credit.strAccount = strTo;
853     credit.nCreditDebit = nAmount;
854     credit.nTime = nNow;
855     credit.strOtherAccount = strFrom;
856     credit.strComment = strComment;
857     walletdb.WriteAccountingEntry(credit);
858
859     walletdb.TxnCommit();
860
861     return true;
862 }
863
864
865 Value sendfrom(const Array& params, bool fHelp)
866 {
867     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
868         throw runtime_error(
869             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
870             "<amount> is a real and is rounded to the nearest 0.00000001\n"
871             "requires wallet passphrase to be set with walletpassphrase first");
872     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
873         throw runtime_error(
874             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
875             "<amount> is a real and is rounded to the nearest 0.00000001");
876
877     string strAccount = AccountFromValue(params[0]);
878     CBitcoinAddress address(params[1].get_str());
879     if (!address.IsValid())
880         throw JSONRPCError(-5, "Invalid bitcoin address");
881     int64 nAmount = AmountFromValue(params[2]);
882     int nMinDepth = 1;
883     if (params.size() > 3)
884         nMinDepth = params[3].get_int();
885
886     CWalletTx wtx;
887     wtx.strFromAccount = strAccount;
888     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
889         wtx.mapValue["comment"] = params[4].get_str();
890     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
891         wtx.mapValue["to"]      = params[5].get_str();
892
893     if (pwalletMain->IsLocked())
894         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
895
896     // Check funds
897     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
898     if (nAmount > nBalance)
899         throw JSONRPCError(-6, "Account has insufficient funds");
900
901     // Send
902     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
903     if (strError != "")
904         throw JSONRPCError(-4, strError);
905
906     return wtx.GetHash().GetHex();
907 }
908
909
910 Value sendmany(const Array& params, bool fHelp)
911 {
912     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
913         throw runtime_error(
914             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
915             "amounts are double-precision floating point numbers\n"
916             "requires wallet passphrase to be set with walletpassphrase first");
917     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
918         throw runtime_error(
919             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
920             "amounts are double-precision floating point numbers");
921
922     string strAccount = AccountFromValue(params[0]);
923     Object sendTo = params[1].get_obj();
924     int nMinDepth = 1;
925     if (params.size() > 2)
926         nMinDepth = params[2].get_int();
927
928     CWalletTx wtx;
929     wtx.strFromAccount = strAccount;
930     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
931         wtx.mapValue["comment"] = params[3].get_str();
932
933     set<CBitcoinAddress> setAddress;
934     vector<pair<CScript, int64> > vecSend;
935
936     int64 totalAmount = 0;
937     BOOST_FOREACH(const Pair& s, sendTo)
938     {
939         CBitcoinAddress address(s.name_);
940         if (!address.IsValid())
941             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
942
943         if (setAddress.count(address))
944             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
945         setAddress.insert(address);
946
947         CScript scriptPubKey;
948         scriptPubKey.SetBitcoinAddress(address);
949         int64 nAmount = AmountFromValue(s.value_); 
950         totalAmount += nAmount;
951
952         vecSend.push_back(make_pair(scriptPubKey, nAmount));
953     }
954
955     if (pwalletMain->IsLocked())
956         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
957
958     // Check funds
959     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
960     if (totalAmount > nBalance)
961         throw JSONRPCError(-6, "Account has insufficient funds");
962
963     // Send
964     CReserveKey keyChange(pwalletMain);
965     int64 nFeeRequired = 0;
966     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
967     if (!fCreated)
968     {
969         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
970             throw JSONRPCError(-6, "Insufficient funds");
971         throw JSONRPCError(-4, "Transaction creation failed");
972     }
973     if (!pwalletMain->CommitTransaction(wtx, keyChange))
974         throw JSONRPCError(-4, "Transaction commit failed");
975
976     return wtx.GetHash().GetHex();
977 }
978
979 Value addmultisigaddress(const Array& params, bool fHelp)
980 {
981     if (fHelp || params.size() < 2 || params.size() > 3)
982     {
983         string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
984             "Add a nrequired-to-sign multisignature address to the wallet\"\n"
985             "each key is a bitcoin address or hex-encoded public key\n"
986             "If [account] is specified, assign address to [account].";
987         throw runtime_error(msg);
988     }
989
990     int nRequired = params[0].get_int();
991     const Array& keys = params[1].get_array();
992     string strAccount;
993     if (params.size() > 2)
994         strAccount = AccountFromValue(params[2]);
995
996     // Gather public keys
997     if (nRequired < 1 || keys.size() < nRequired)
998         throw runtime_error(
999             strprintf("wrong number of keys"
1000                       "(got %d, need at least %d)", keys.size(), nRequired));
1001     std::vector<CKey> pubkeys;
1002     pubkeys.resize(keys.size());
1003     for (unsigned int i = 0; i < keys.size(); i++)
1004     {
1005         const std::string& ks = keys[i].get_str();
1006
1007         // Case 1: bitcoin address and we have full public key:
1008         CBitcoinAddress address(ks);
1009         if (address.IsValid())
1010         {
1011             if (address.IsScript())
1012                 throw runtime_error(
1013                     strprintf("%s is a pay-to-script address",ks.c_str()));
1014             std::vector<unsigned char> vchPubKey;
1015             if (!pwalletMain->GetPubKey(address, vchPubKey))
1016                 throw runtime_error(
1017                     strprintf("no full public key for address %s",ks.c_str()));
1018             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1019                 throw runtime_error(" Invalid public key: "+ks);
1020         }
1021
1022         // Case 2: hex public key
1023         else if (IsHex(ks))
1024         {
1025             vector<unsigned char> vchPubKey = ParseHex(ks);
1026             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1027                 throw runtime_error(" Invalid public key: "+ks);
1028         }
1029         else
1030         {
1031             throw runtime_error(" Invalid public key: "+ks);
1032         }
1033     }
1034
1035     // Construct using pay-to-script-hash:
1036     CScript inner;
1037     inner.SetMultisig(nRequired, pubkeys);
1038
1039     uint160 scriptHash = Hash160(inner);
1040     CScript scriptPubKey;
1041     scriptPubKey.SetPayToScriptHash(inner);
1042     pwalletMain->AddCScript(inner);
1043     CBitcoinAddress address;
1044     address.SetScriptHash160(scriptHash);
1045
1046     pwalletMain->SetAddressBookName(address, strAccount);
1047     return address.ToString();
1048 }
1049
1050
1051 struct tallyitem
1052 {
1053     int64 nAmount;
1054     int nConf;
1055     tallyitem()
1056     {
1057         nAmount = 0;
1058         nConf = std::numeric_limits<int>::max();
1059     }
1060 };
1061
1062 Value ListReceived(const Array& params, bool fByAccounts)
1063 {
1064     // Minimum confirmations
1065     int nMinDepth = 1;
1066     if (params.size() > 0)
1067         nMinDepth = params[0].get_int();
1068
1069     // Whether to include empty accounts
1070     bool fIncludeEmpty = false;
1071     if (params.size() > 1)
1072         fIncludeEmpty = params[1].get_bool();
1073
1074     // Tally
1075     map<CBitcoinAddress, tallyitem> mapTally;
1076     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1077     {
1078         const CWalletTx& wtx = (*it).second;
1079
1080         if (wtx.IsCoinBase() || !wtx.IsFinal())
1081             continue;
1082
1083         int nDepth = wtx.GetDepthInMainChain();
1084         if (nDepth < nMinDepth)
1085             continue;
1086
1087         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1088         {
1089             CBitcoinAddress address;
1090             if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1091                 continue;
1092
1093             tallyitem& item = mapTally[address];
1094             item.nAmount += txout.nValue;
1095             item.nConf = min(item.nConf, nDepth);
1096         }
1097     }
1098
1099     // Reply
1100     Array ret;
1101     map<string, tallyitem> mapAccountTally;
1102     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1103     {
1104         const CBitcoinAddress& address = item.first;
1105         const string& strAccount = item.second;
1106         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1107         if (it == mapTally.end() && !fIncludeEmpty)
1108             continue;
1109
1110         int64 nAmount = 0;
1111         int nConf = std::numeric_limits<int>::max();
1112         if (it != mapTally.end())
1113         {
1114             nAmount = (*it).second.nAmount;
1115             nConf = (*it).second.nConf;
1116         }
1117
1118         if (fByAccounts)
1119         {
1120             tallyitem& item = mapAccountTally[strAccount];
1121             item.nAmount += nAmount;
1122             item.nConf = min(item.nConf, nConf);
1123         }
1124         else
1125         {
1126             Object obj;
1127             obj.push_back(Pair("address",       address.ToString()));
1128             obj.push_back(Pair("account",       strAccount));
1129             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1130             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1131             ret.push_back(obj);
1132         }
1133     }
1134
1135     if (fByAccounts)
1136     {
1137         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1138         {
1139             int64 nAmount = (*it).second.nAmount;
1140             int nConf = (*it).second.nConf;
1141             Object obj;
1142             obj.push_back(Pair("account",       (*it).first));
1143             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1144             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1145             ret.push_back(obj);
1146         }
1147     }
1148
1149     return ret;
1150 }
1151
1152 Value listreceivedbyaddress(const Array& params, bool fHelp)
1153 {
1154     if (fHelp || params.size() > 2)
1155         throw runtime_error(
1156             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1157             "[minconf] is the minimum number of confirmations before payments are included.\n"
1158             "[includeempty] whether to include addresses that haven't received any payments.\n"
1159             "Returns an array of objects containing:\n"
1160             "  \"address\" : receiving address\n"
1161             "  \"account\" : the account of the receiving address\n"
1162             "  \"amount\" : total amount received by the address\n"
1163             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1164
1165     return ListReceived(params, false);
1166 }
1167
1168 Value listreceivedbyaccount(const Array& params, bool fHelp)
1169 {
1170     if (fHelp || params.size() > 2)
1171         throw runtime_error(
1172             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1173             "[minconf] is the minimum number of confirmations before payments are included.\n"
1174             "[includeempty] whether to include accounts that haven't received any payments.\n"
1175             "Returns an array of objects containing:\n"
1176             "  \"account\" : the account of the receiving addresses\n"
1177             "  \"amount\" : total amount received by addresses with this account\n"
1178             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1179
1180     return ListReceived(params, true);
1181 }
1182
1183 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1184 {
1185     int64 nGeneratedImmature, nGeneratedMature, nFee;
1186     string strSentAccount;
1187     list<pair<CBitcoinAddress, int64> > listReceived;
1188     list<pair<CBitcoinAddress, int64> > listSent;
1189
1190     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1191
1192     bool fAllAccounts = (strAccount == string("*"));
1193
1194     // Generated blocks assigned to account ""
1195     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1196     {
1197         Object entry;
1198         entry.push_back(Pair("account", string("")));
1199         if (nGeneratedImmature)
1200         {
1201             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1202             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1203         }
1204         else
1205         {
1206             entry.push_back(Pair("category", "generate"));
1207             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1208         }
1209         if (fLong)
1210             WalletTxToJSON(wtx, entry);
1211         ret.push_back(entry);
1212     }
1213
1214     // Sent
1215     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1216     {
1217         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1218         {
1219             Object entry;
1220             entry.push_back(Pair("account", strSentAccount));
1221             entry.push_back(Pair("address", s.first.ToString()));
1222             entry.push_back(Pair("category", "send"));
1223             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1224             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1225             if (fLong)
1226                 WalletTxToJSON(wtx, entry);
1227             ret.push_back(entry);
1228         }
1229     }
1230
1231     // Received
1232     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1233     {
1234         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1235         {
1236             string account;
1237             if (pwalletMain->mapAddressBook.count(r.first))
1238                 account = pwalletMain->mapAddressBook[r.first];
1239             if (fAllAccounts || (account == strAccount))
1240             {
1241                 Object entry;
1242                 entry.push_back(Pair("account", account));
1243                 entry.push_back(Pair("address", r.first.ToString()));
1244                 entry.push_back(Pair("category", "receive"));
1245                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1246                 if (fLong)
1247                     WalletTxToJSON(wtx, entry);
1248                 ret.push_back(entry);
1249             }
1250         }
1251     }
1252 }
1253
1254 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1255 {
1256     bool fAllAccounts = (strAccount == string("*"));
1257
1258     if (fAllAccounts || acentry.strAccount == strAccount)
1259     {
1260         Object entry;
1261         entry.push_back(Pair("account", acentry.strAccount));
1262         entry.push_back(Pair("category", "move"));
1263         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1264         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1265         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1266         entry.push_back(Pair("comment", acentry.strComment));
1267         ret.push_back(entry);
1268     }
1269 }
1270
1271 Value listtransactions(const Array& params, bool fHelp)
1272 {
1273     if (fHelp || params.size() > 3)
1274         throw runtime_error(
1275             "listtransactions [account] [count=10] [from=0]\n"
1276             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1277
1278     string strAccount = "*";
1279     if (params.size() > 0)
1280         strAccount = params[0].get_str();
1281     int nCount = 10;
1282     if (params.size() > 1)
1283         nCount = params[1].get_int();
1284     int nFrom = 0;
1285     if (params.size() > 2)
1286         nFrom = params[2].get_int();
1287
1288     if (nCount < 0)
1289         throw JSONRPCError(-8, "Negative count");
1290     if (nFrom < 0)
1291         throw JSONRPCError(-8, "Negative from");
1292
1293     Array ret;
1294     CWalletDB walletdb(pwalletMain->strWalletFile);
1295
1296     // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1297     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1298     typedef multimap<int64, TxPair > TxItems;
1299     TxItems txByTime;
1300
1301     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1302     // would make this much faster for applications that do this a lot.
1303     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1304     {
1305         CWalletTx* wtx = &((*it).second);
1306         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1307     }
1308     list<CAccountingEntry> acentries;
1309     walletdb.ListAccountCreditDebit(strAccount, acentries);
1310     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1311     {
1312         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1313     }
1314
1315     // iterate backwards until we have nCount items to return:
1316     for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1317     {
1318         CWalletTx *const pwtx = (*it).second.first;
1319         if (pwtx != 0)
1320             ListTransactions(*pwtx, strAccount, 0, true, ret);
1321         CAccountingEntry *const pacentry = (*it).second.second;
1322         if (pacentry != 0)
1323             AcentryToJSON(*pacentry, strAccount, ret);
1324
1325         if (ret.size() >= (nCount+nFrom)) break;
1326     }
1327     // ret is newest to oldest
1328     
1329     if (nFrom > ret.size()) nFrom = ret.size();
1330     if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1331     Array::iterator first = ret.begin();
1332     std::advance(first, nFrom);
1333     Array::iterator last = ret.begin();
1334     std::advance(last, nFrom+nCount);
1335
1336     if (last != ret.end()) ret.erase(last, ret.end());
1337     if (first != ret.begin()) ret.erase(ret.begin(), first);
1338
1339     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1340
1341     return ret;
1342 }
1343
1344 Value listaccounts(const Array& params, bool fHelp)
1345 {
1346     if (fHelp || params.size() > 1)
1347         throw runtime_error(
1348             "listaccounts [minconf=1]\n"
1349             "Returns Object that has account names as keys, account balances as values.");
1350
1351     int nMinDepth = 1;
1352     if (params.size() > 0)
1353         nMinDepth = params[0].get_int();
1354
1355     map<string, int64> mapAccountBalances;
1356     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1357         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1358             mapAccountBalances[entry.second] = 0;
1359     }
1360
1361     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1362     {
1363         const CWalletTx& wtx = (*it).second;
1364         int64 nGeneratedImmature, nGeneratedMature, nFee;
1365         string strSentAccount;
1366         list<pair<CBitcoinAddress, int64> > listReceived;
1367         list<pair<CBitcoinAddress, int64> > listSent;
1368         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1369         mapAccountBalances[strSentAccount] -= nFee;
1370         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1371             mapAccountBalances[strSentAccount] -= s.second;
1372         if (wtx.GetDepthInMainChain() >= nMinDepth)
1373         {
1374             mapAccountBalances[""] += nGeneratedMature;
1375             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1376                 if (pwalletMain->mapAddressBook.count(r.first))
1377                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1378                 else
1379                     mapAccountBalances[""] += r.second;
1380         }
1381     }
1382
1383     list<CAccountingEntry> acentries;
1384     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1385     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1386         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1387
1388     Object ret;
1389     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1390         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1391     }
1392     return ret;
1393 }
1394
1395 Value listsinceblock(const Array& params, bool fHelp)
1396 {
1397     if (fHelp)
1398         throw runtime_error(
1399             "listsinceblock [blockid] [target-confirmations]\n"
1400             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1401
1402     CBlockIndex *pindex = NULL;
1403     int target_confirms = 1;
1404
1405     if (params.size() > 0)
1406     {
1407         uint256 blockId = 0;
1408
1409         blockId.SetHex(params[0].get_str());
1410         pindex = CBlockLocator(blockId).GetBlockIndex();
1411     }
1412
1413     if (params.size() > 1)
1414     {
1415         target_confirms = params[1].get_int();
1416
1417         if (target_confirms < 1)
1418             throw JSONRPCError(-8, "Invalid parameter");
1419     }
1420
1421     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1422
1423     Array transactions;
1424
1425     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1426     {
1427         CWalletTx tx = (*it).second;
1428
1429         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1430             ListTransactions(tx, "*", 0, true, transactions);
1431     }
1432
1433     uint256 lastblock;
1434
1435     if (target_confirms == 1)
1436     {
1437         printf("oops!\n");
1438         lastblock = hashBestChain;
1439     }
1440     else
1441     {
1442         int target_height = pindexBest->nHeight + 1 - target_confirms;
1443
1444         CBlockIndex *block;
1445         for (block = pindexBest;
1446              block && block->nHeight > target_height;
1447              block = block->pprev)  { }
1448
1449         lastblock = block ? block->GetBlockHash() : 0;
1450     }
1451
1452     Object ret;
1453     ret.push_back(Pair("transactions", transactions));
1454     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1455
1456     return ret;
1457 }
1458
1459 Value gettransaction(const Array& params, bool fHelp)
1460 {
1461     if (fHelp || params.size() != 1)
1462         throw runtime_error(
1463             "gettransaction <txid>\n"
1464             "Get detailed information about <txid>");
1465
1466     uint256 hash;
1467     hash.SetHex(params[0].get_str());
1468
1469     Object entry;
1470
1471     if (!pwalletMain->mapWallet.count(hash))
1472         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1473     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1474
1475     int64 nCredit = wtx.GetCredit();
1476     int64 nDebit = wtx.GetDebit();
1477     int64 nNet = nCredit - nDebit;
1478     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1479
1480     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1481     if (wtx.IsFromMe())
1482         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1483
1484     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1485
1486     Array details;
1487     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1488     entry.push_back(Pair("details", details));
1489
1490     return entry;
1491 }
1492
1493
1494 Value backupwallet(const Array& params, bool fHelp)
1495 {
1496     if (fHelp || params.size() != 1)
1497         throw runtime_error(
1498             "backupwallet <destination>\n"
1499             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1500
1501     string strDest = params[0].get_str();
1502     BackupWallet(*pwalletMain, strDest);
1503
1504     return Value::null;
1505 }
1506
1507
1508 Value keypoolrefill(const Array& params, bool fHelp)
1509 {
1510     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1511         throw runtime_error(
1512             "keypoolrefill\n"
1513             "Fills the keypool, requires wallet passphrase to be set.");
1514     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1515         throw runtime_error(
1516             "keypoolrefill\n"
1517             "Fills the keypool.");
1518
1519     if (pwalletMain->IsLocked())
1520         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1521
1522     pwalletMain->TopUpKeyPool();
1523
1524     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1525         throw JSONRPCError(-4, "Error refreshing keypool.");
1526
1527     return Value::null;
1528 }
1529
1530
1531 void ThreadTopUpKeyPool(void* parg)
1532 {
1533     pwalletMain->TopUpKeyPool();
1534 }
1535
1536 void ThreadCleanWalletPassphrase(void* parg)
1537 {
1538     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1539
1540     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1541
1542     if (nWalletUnlockTime == 0)
1543     {
1544         nWalletUnlockTime = nMyWakeTime;
1545
1546         do
1547         {
1548             if (nWalletUnlockTime==0)
1549                 break;
1550             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1551             if (nToSleep <= 0)
1552                 break;
1553
1554             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1555             Sleep(nToSleep);
1556             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1557
1558         } while(1);
1559
1560         if (nWalletUnlockTime)
1561         {
1562             nWalletUnlockTime = 0;
1563             pwalletMain->Lock();
1564         }
1565     }
1566     else
1567     {
1568         if (nWalletUnlockTime < nMyWakeTime)
1569             nWalletUnlockTime = nMyWakeTime;
1570     }
1571
1572     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1573
1574     delete (int64*)parg;
1575 }
1576
1577 Value walletpassphrase(const Array& params, bool fHelp)
1578 {
1579     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1580         throw runtime_error(
1581             "walletpassphrase <passphrase> <timeout>\n"
1582             "Stores the wallet decryption key in memory for <timeout> seconds.");
1583     if (fHelp)
1584         return true;
1585     if (!pwalletMain->IsCrypted())
1586         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1587
1588     if (!pwalletMain->IsLocked())
1589         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1590
1591     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1592     SecureString strWalletPass;
1593     strWalletPass.reserve(100);
1594     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1595     // Alternately, find a way to make params[0] mlock()'d to begin with.
1596     strWalletPass = params[0].get_str().c_str();
1597
1598     if (strWalletPass.length() > 0)
1599     {
1600         if (!pwalletMain->Unlock(strWalletPass))
1601             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1602     }
1603     else
1604         throw runtime_error(
1605             "walletpassphrase <passphrase> <timeout>\n"
1606             "Stores the wallet decryption key in memory for <timeout> seconds.");
1607
1608     CreateThread(ThreadTopUpKeyPool, NULL);
1609     int64* pnSleepTime = new int64(params[1].get_int64());
1610     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1611
1612     return Value::null;
1613 }
1614
1615
1616 Value walletpassphrasechange(const Array& params, bool fHelp)
1617 {
1618     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1619         throw runtime_error(
1620             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1621             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1622     if (fHelp)
1623         return true;
1624     if (!pwalletMain->IsCrypted())
1625         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1626
1627     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1628     // Alternately, find a way to make params[0] mlock()'d to begin with.
1629     SecureString strOldWalletPass;
1630     strOldWalletPass.reserve(100);
1631     strOldWalletPass = params[0].get_str().c_str();
1632
1633     SecureString strNewWalletPass;
1634     strNewWalletPass.reserve(100);
1635     strNewWalletPass = params[1].get_str().c_str();
1636
1637     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1638         throw runtime_error(
1639             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1640             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1641
1642     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1643         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1644
1645     return Value::null;
1646 }
1647
1648
1649 Value walletlock(const Array& params, bool fHelp)
1650 {
1651     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1652         throw runtime_error(
1653             "walletlock\n"
1654             "Removes the wallet encryption key from memory, locking the wallet.\n"
1655             "After calling this method, you will need to call walletpassphrase again\n"
1656             "before being able to call any methods which require the wallet to be unlocked.");
1657     if (fHelp)
1658         return true;
1659     if (!pwalletMain->IsCrypted())
1660         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1661
1662     {
1663         LOCK(cs_nWalletUnlockTime);
1664         pwalletMain->Lock();
1665         nWalletUnlockTime = 0;
1666     }
1667
1668     return Value::null;
1669 }
1670
1671
1672 Value encryptwallet(const Array& params, bool fHelp)
1673 {
1674     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1675         throw runtime_error(
1676             "encryptwallet <passphrase>\n"
1677             "Encrypts the wallet with <passphrase>.");
1678     if (fHelp)
1679         return true;
1680     if (pwalletMain->IsCrypted())
1681         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1682
1683     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1684     // Alternately, find a way to make params[0] mlock()'d to begin with.
1685     SecureString strWalletPass;
1686     strWalletPass.reserve(100);
1687     strWalletPass = params[0].get_str().c_str();
1688
1689     if (strWalletPass.length() < 1)
1690         throw runtime_error(
1691             "encryptwallet <passphrase>\n"
1692             "Encrypts the wallet with <passphrase>.");
1693
1694     if (!pwalletMain->EncryptWallet(strWalletPass))
1695         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1696
1697     // BDB seems to have a bad habit of writing old data into
1698     // slack space in .dat files; that is bad if the old data is
1699     // unencrypted private keys.  So:
1700     QueueShutdown();
1701     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1702 }
1703
1704
1705 Value validateaddress(const Array& params, bool fHelp)
1706 {
1707     if (fHelp || params.size() != 1)
1708         throw runtime_error(
1709             "validateaddress <bitcoinaddress>\n"
1710             "Return information about <bitcoinaddress>.");
1711
1712     CBitcoinAddress address(params[0].get_str());
1713     bool isValid = address.IsValid();
1714
1715     Object ret;
1716     ret.push_back(Pair("isvalid", isValid));
1717     if (isValid)
1718     {
1719         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1720         // version of the address:
1721         string currentAddress = address.ToString();
1722         ret.push_back(Pair("address", currentAddress));
1723         if (pwalletMain->HaveKey(address))
1724         {
1725             ret.push_back(Pair("ismine", true));
1726             std::vector<unsigned char> vchPubKey;
1727             pwalletMain->GetPubKey(address, vchPubKey);
1728             ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1729             CKey key;
1730             key.SetPubKey(vchPubKey);
1731             ret.push_back(Pair("iscompressed", key.IsCompressed()));
1732         }
1733         else if (pwalletMain->HaveCScript(address.GetHash160()))
1734         {
1735             ret.push_back(Pair("isscript", true));
1736             CScript subscript;
1737             pwalletMain->GetCScript(address.GetHash160(), subscript);
1738             ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1739             std::vector<CBitcoinAddress> addresses;
1740             txnouttype whichType;
1741             int nRequired;
1742             ExtractAddresses(subscript, whichType, addresses, nRequired);
1743             ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1744             Array a;
1745             BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1746                 a.push_back(addr.ToString());
1747             ret.push_back(Pair("addresses", a));
1748             if (whichType == TX_MULTISIG)
1749                 ret.push_back(Pair("sigsrequired", nRequired));
1750         }
1751         else
1752             ret.push_back(Pair("ismine", false));
1753         if (pwalletMain->mapAddressBook.count(address))
1754             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1755     }
1756     return ret;
1757 }
1758
1759 Value getwork(const Array& params, bool fHelp)
1760 {
1761     if (fHelp || params.size() > 1)
1762         throw runtime_error(
1763             "getwork [data]\n"
1764             "If [data] is not specified, returns formatted hash data to work on:\n"
1765             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1766             "  \"data\" : block data\n"
1767             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1768             "  \"target\" : little endian hash target\n"
1769             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1770
1771     if (vNodes.empty())
1772         throw JSONRPCError(-9, "Bitcoin is not connected!");
1773
1774     if (IsInitialBlockDownload())
1775         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1776
1777     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1778     static mapNewBlock_t mapNewBlock;
1779     static vector<CBlock*> vNewBlock;
1780     static CReserveKey reservekey(pwalletMain);
1781
1782     if (params.size() == 0)
1783     {
1784         // Update block
1785         static unsigned int nTransactionsUpdatedLast;
1786         static CBlockIndex* pindexPrev;
1787         static int64 nStart;
1788         static CBlock* pblock;
1789         if (pindexPrev != pindexBest ||
1790             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1791         {
1792             if (pindexPrev != pindexBest)
1793             {
1794                 // Deallocate old blocks since they're obsolete now
1795                 mapNewBlock.clear();
1796                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1797                     delete pblock;
1798                 vNewBlock.clear();
1799             }
1800             nTransactionsUpdatedLast = nTransactionsUpdated;
1801             pindexPrev = pindexBest;
1802             nStart = GetTime();
1803
1804             // Create new block
1805             pblock = CreateNewBlock(reservekey);
1806             if (!pblock)
1807                 throw JSONRPCError(-7, "Out of memory");
1808             vNewBlock.push_back(pblock);
1809         }
1810
1811         // Update nTime
1812         pblock->UpdateTime(pindexPrev);
1813         pblock->nNonce = 0;
1814
1815         // Update nExtraNonce
1816         static unsigned int nExtraNonce = 0;
1817         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1818
1819         // Save
1820         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1821
1822         // Prebuild hash buffers
1823         char pmidstate[32];
1824         char pdata[128];
1825         char phash1[64];
1826         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1827
1828         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1829
1830         Object result;
1831         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1832         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1833         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1834         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1835         return result;
1836     }
1837     else
1838     {
1839         // Parse parameters
1840         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1841         if (vchData.size() != 128)
1842             throw JSONRPCError(-8, "Invalid parameter");
1843         CBlock* pdata = (CBlock*)&vchData[0];
1844
1845         // Byte reverse
1846         for (int i = 0; i < 128/4; i++)
1847             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1848
1849         // Get saved block
1850         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1851             return false;
1852         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1853
1854         pblock->nTime = pdata->nTime;
1855         pblock->nNonce = pdata->nNonce;
1856         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1857         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1858
1859         return CheckWork(pblock, *pwalletMain, reservekey);
1860     }
1861 }
1862
1863
1864 Value getmemorypool(const Array& params, bool fHelp)
1865 {
1866     if (fHelp || params.size() > 1)
1867         throw runtime_error(
1868             "getmemorypool [data]\n"
1869             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1870             "  \"version\" : block version\n"
1871             "  \"previousblockhash\" : hash of current highest block\n"
1872             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1873             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1874             "  \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1875             "  \"time\" : timestamp appropriate for next block\n"
1876             "  \"mintime\" : minimum timestamp appropriate for next block\n"
1877             "  \"curtime\" : current timestamp\n"
1878             "  \"bits\" : compressed target of next block\n"
1879             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1880
1881     if (params.size() == 0)
1882     {
1883         if (vNodes.empty())
1884             throw JSONRPCError(-9, "Bitcoin is not connected!");
1885
1886         if (IsInitialBlockDownload())
1887             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1888
1889         static CReserveKey reservekey(pwalletMain);
1890
1891         // Update block
1892         static unsigned int nTransactionsUpdatedLast;
1893         static CBlockIndex* pindexPrev;
1894         static int64 nStart;
1895         static CBlock* pblock;
1896         if (pindexPrev != pindexBest ||
1897             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1898         {
1899             nTransactionsUpdatedLast = nTransactionsUpdated;
1900             pindexPrev = pindexBest;
1901             nStart = GetTime();
1902
1903             // Create new block
1904             if(pblock)
1905                 delete pblock;
1906             pblock = CreateNewBlock(reservekey);
1907             if (!pblock)
1908                 throw JSONRPCError(-7, "Out of memory");
1909         }
1910
1911         // Update nTime
1912         pblock->UpdateTime(pindexPrev);
1913         pblock->nNonce = 0;
1914
1915         Array transactions;
1916         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1917             if(tx.IsCoinBase())
1918                 continue;
1919
1920             CDataStream ssTx;
1921             ssTx << tx;
1922
1923             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1924         }
1925
1926         Object result;
1927         result.push_back(Pair("version", pblock->nVersion));
1928         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1929         result.push_back(Pair("transactions", transactions));
1930         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1931         result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1932         result.push_back(Pair("time", (int64_t)pblock->nTime));
1933         result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1934         result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1935         result.push_back(Pair("bits", HexBits(pblock->nBits)));
1936
1937         return result;
1938     }
1939     else
1940     {
1941         // Parse parameters
1942         CDataStream ssBlock(ParseHex(params[0].get_str()));
1943         CBlock pblock;
1944         ssBlock >> pblock;
1945
1946         return ProcessBlock(NULL, &pblock);
1947     }
1948 }
1949
1950 Value getblockhash(const Array& params, bool fHelp)
1951 {
1952     if (fHelp || params.size() != 1)
1953         throw runtime_error(
1954             "getblockhash <index>\n"
1955             "Returns hash of block in best-block-chain at <index>.");
1956
1957     int nHeight = params[0].get_int();
1958     if (nHeight < 0 || nHeight > nBestHeight)
1959         throw runtime_error("Block number out of range.");
1960
1961     CBlock block;
1962     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1963     while (pblockindex->nHeight > nHeight)
1964         pblockindex = pblockindex->pprev;
1965     return pblockindex->phashBlock->GetHex();
1966 }
1967
1968 Value getblock(const Array& params, bool fHelp)
1969 {
1970     if (fHelp || params.size() != 1)
1971         throw runtime_error(
1972             "getblock <hash>\n"
1973             "Returns details of a block with given block-hash.");
1974
1975     std::string strHash = params[0].get_str();
1976     uint256 hash(strHash);
1977
1978     if (mapBlockIndex.count(hash) == 0)
1979         throw JSONRPCError(-5, "Block not found");
1980
1981     CBlock block;
1982     CBlockIndex* pblockindex = mapBlockIndex[hash];
1983     block.ReadFromDisk(pblockindex, true);
1984
1985     return blockToJSON(block, pblockindex);
1986 }
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998 //
1999 // Call Table
2000 //
2001
2002 pair<string, rpcfn_type> pCallTable[] =
2003 {
2004     make_pair("help",                   &help),
2005     make_pair("stop",                   &stop),
2006     make_pair("getblockcount",          &getblockcount),
2007     make_pair("getblocknumber",         &getblocknumber),
2008     make_pair("getconnectioncount",     &getconnectioncount),
2009     make_pair("getdifficulty",          &getdifficulty),
2010     make_pair("getgenerate",            &getgenerate),
2011     make_pair("setgenerate",            &setgenerate),
2012     make_pair("gethashespersec",        &gethashespersec),
2013     make_pair("getinfo",                &getinfo),
2014     make_pair("getmininginfo",          &getmininginfo),
2015     make_pair("getnewaddress",          &getnewaddress),
2016     make_pair("getaccountaddress",      &getaccountaddress),
2017     make_pair("setaccount",             &setaccount),
2018     make_pair("getaccount",             &getaccount),
2019     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
2020     make_pair("sendtoaddress",          &sendtoaddress),
2021     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
2022     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
2023     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
2024     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
2025     make_pair("backupwallet",           &backupwallet),
2026     make_pair("keypoolrefill",          &keypoolrefill),
2027     make_pair("walletpassphrase",       &walletpassphrase),
2028     make_pair("walletpassphrasechange", &walletpassphrasechange),
2029     make_pair("walletlock",             &walletlock),
2030     make_pair("encryptwallet",          &encryptwallet),
2031     make_pair("validateaddress",        &validateaddress),
2032     make_pair("getbalance",             &getbalance),
2033     make_pair("move",                   &movecmd),
2034     make_pair("sendfrom",               &sendfrom),
2035     make_pair("sendmany",               &sendmany),
2036     make_pair("addmultisigaddress",     &addmultisigaddress),
2037     make_pair("getblock",               &getblock),
2038     make_pair("getblockhash",           &getblockhash),
2039     make_pair("gettransaction",         &gettransaction),
2040     make_pair("listtransactions",       &listtransactions),
2041     make_pair("signmessage",            &signmessage),
2042     make_pair("verifymessage",          &verifymessage),
2043     make_pair("getwork",                &getwork),
2044     make_pair("listaccounts",           &listaccounts),
2045     make_pair("settxfee",               &settxfee),
2046     make_pair("getmemorypool",          &getmemorypool),
2047     make_pair("listsinceblock",         &listsinceblock),
2048     make_pair("dumpprivkey",            &dumpprivkey),
2049     make_pair("importprivkey",          &importprivkey)
2050 };
2051 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2052
2053 string pAllowInSafeMode[] =
2054 {
2055     "help",
2056     "stop",
2057     "getblockcount",
2058     "getblocknumber",  // deprecated
2059     "getconnectioncount",
2060     "getdifficulty",
2061     "getgenerate",
2062     "setgenerate",
2063     "gethashespersec",
2064     "getinfo",
2065     "getmininginfo",
2066     "getnewaddress",
2067     "getaccountaddress",
2068     "getaccount",
2069     "getaddressesbyaccount",
2070     "backupwallet",
2071     "keypoolrefill",
2072     "walletpassphrase",
2073     "walletlock",
2074     "validateaddress",
2075     "getwork",
2076     "getmemorypool",
2077 };
2078 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2079
2080
2081
2082
2083 //
2084 // HTTP protocol
2085 //
2086 // This ain't Apache.  We're just using HTTP header for the length field
2087 // and to be compatible with other JSON-RPC implementations.
2088 //
2089
2090 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2091 {
2092     ostringstream s;
2093     s << "POST / HTTP/1.1\r\n"
2094       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2095       << "Host: 127.0.0.1\r\n"
2096       << "Content-Type: application/json\r\n"
2097       << "Content-Length: " << strMsg.size() << "\r\n"
2098       << "Connection: close\r\n"
2099       << "Accept: application/json\r\n";
2100     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2101         s << item.first << ": " << item.second << "\r\n";
2102     s << "\r\n" << strMsg;
2103
2104     return s.str();
2105 }
2106
2107 string rfc1123Time()
2108 {
2109     char buffer[64];
2110     time_t now;
2111     time(&now);
2112     struct tm* now_gmt = gmtime(&now);
2113     string locale(setlocale(LC_TIME, NULL));
2114     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2115     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2116     setlocale(LC_TIME, locale.c_str());
2117     return string(buffer);
2118 }
2119
2120 static string HTTPReply(int nStatus, const string& strMsg)
2121 {
2122     if (nStatus == 401)
2123         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2124             "Date: %s\r\n"
2125             "Server: bitcoin-json-rpc/%s\r\n"
2126             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2127             "Content-Type: text/html\r\n"
2128             "Content-Length: 296\r\n"
2129             "\r\n"
2130             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2131             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2132             "<HTML>\r\n"
2133             "<HEAD>\r\n"
2134             "<TITLE>Error</TITLE>\r\n"
2135             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2136             "</HEAD>\r\n"
2137             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2138             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2139     const char *cStatus;
2140          if (nStatus == 200) cStatus = "OK";
2141     else if (nStatus == 400) cStatus = "Bad Request";
2142     else if (nStatus == 403) cStatus = "Forbidden";
2143     else if (nStatus == 404) cStatus = "Not Found";
2144     else if (nStatus == 500) cStatus = "Internal Server Error";
2145     else cStatus = "";
2146     return strprintf(
2147             "HTTP/1.1 %d %s\r\n"
2148             "Date: %s\r\n"
2149             "Connection: close\r\n"
2150             "Content-Length: %d\r\n"
2151             "Content-Type: application/json\r\n"
2152             "Server: bitcoin-json-rpc/%s\r\n"
2153             "\r\n"
2154             "%s",
2155         nStatus,
2156         cStatus,
2157         rfc1123Time().c_str(),
2158         strMsg.size(),
2159         FormatFullVersion().c_str(),
2160         strMsg.c_str());
2161 }
2162
2163 int ReadHTTPStatus(std::basic_istream<char>& stream)
2164 {
2165     string str;
2166     getline(stream, str);
2167     vector<string> vWords;
2168     boost::split(vWords, str, boost::is_any_of(" "));
2169     if (vWords.size() < 2)
2170         return 500;
2171     return atoi(vWords[1].c_str());
2172 }
2173
2174 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2175 {
2176     int nLen = 0;
2177     loop
2178     {
2179         string str;
2180         std::getline(stream, str);
2181         if (str.empty() || str == "\r")
2182             break;
2183         string::size_type nColon = str.find(":");
2184         if (nColon != string::npos)
2185         {
2186             string strHeader = str.substr(0, nColon);
2187             boost::trim(strHeader);
2188             boost::to_lower(strHeader);
2189             string strValue = str.substr(nColon+1);
2190             boost::trim(strValue);
2191             mapHeadersRet[strHeader] = strValue;
2192             if (strHeader == "content-length")
2193                 nLen = atoi(strValue.c_str());
2194         }
2195     }
2196     return nLen;
2197 }
2198
2199 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2200 {
2201     mapHeadersRet.clear();
2202     strMessageRet = "";
2203
2204     // Read status
2205     int nStatus = ReadHTTPStatus(stream);
2206
2207     // Read header
2208     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2209     if (nLen < 0 || nLen > MAX_SIZE)
2210         return 500;
2211
2212     // Read message
2213     if (nLen > 0)
2214     {
2215         vector<char> vch(nLen);
2216         stream.read(&vch[0], nLen);
2217         strMessageRet = string(vch.begin(), vch.end());
2218     }
2219
2220     return nStatus;
2221 }
2222
2223 bool HTTPAuthorized(map<string, string>& mapHeaders)
2224 {
2225     string strAuth = mapHeaders["authorization"];
2226     if (strAuth.substr(0,6) != "Basic ")
2227         return false;
2228     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2229     string strUserPass = DecodeBase64(strUserPass64);
2230     return strUserPass == strRPCUserColonPass;
2231 }
2232
2233 //
2234 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2235 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2236 // unspecified (HTTP errors and contents of 'error').
2237 //
2238 // 1.0 spec: http://json-rpc.org/wiki/specification
2239 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2240 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2241 //
2242
2243 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2244 {
2245     Object request;
2246     request.push_back(Pair("method", strMethod));
2247     request.push_back(Pair("params", params));
2248     request.push_back(Pair("id", id));
2249     return write_string(Value(request), false) + "\n";
2250 }
2251
2252 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2253 {
2254     Object reply;
2255     if (error.type() != null_type)
2256         reply.push_back(Pair("result", Value::null));
2257     else
2258         reply.push_back(Pair("result", result));
2259     reply.push_back(Pair("error", error));
2260     reply.push_back(Pair("id", id));
2261     return write_string(Value(reply), false) + "\n";
2262 }
2263
2264 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2265 {
2266     // Send error reply from json-rpc error object
2267     int nStatus = 500;
2268     int code = find_value(objError, "code").get_int();
2269     if (code == -32600) nStatus = 400;
2270     else if (code == -32601) nStatus = 404;
2271     string strReply = JSONRPCReply(Value::null, objError, id);
2272     stream << HTTPReply(nStatus, strReply) << std::flush;
2273 }
2274
2275 bool ClientAllowed(const string& strAddress)
2276 {
2277     if (strAddress == asio::ip::address_v4::loopback().to_string())
2278         return true;
2279     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2280     BOOST_FOREACH(string strAllow, vAllow)
2281         if (WildcardMatch(strAddress, strAllow))
2282             return true;
2283     return false;
2284 }
2285
2286 //
2287 // IOStream device that speaks SSL but can also speak non-SSL
2288 //
2289 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2290 public:
2291     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2292     {
2293         fUseSSL = fUseSSLIn;
2294         fNeedHandshake = fUseSSLIn;
2295     }
2296
2297     void handshake(ssl::stream_base::handshake_type role)
2298     {
2299         if (!fNeedHandshake) return;
2300         fNeedHandshake = false;
2301         stream.handshake(role);
2302     }
2303     std::streamsize read(char* s, std::streamsize n)
2304     {
2305         handshake(ssl::stream_base::server); // HTTPS servers read first
2306         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2307         return stream.next_layer().read_some(asio::buffer(s, n));
2308     }
2309     std::streamsize write(const char* s, std::streamsize n)
2310     {
2311         handshake(ssl::stream_base::client); // HTTPS clients write first
2312         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2313         return asio::write(stream.next_layer(), asio::buffer(s, n));
2314     }
2315     bool connect(const std::string& server, const std::string& port)
2316     {
2317         ip::tcp::resolver resolver(stream.get_io_service());
2318         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2319         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2320         ip::tcp::resolver::iterator end;
2321         boost::system::error_code error = asio::error::host_not_found;
2322         while (error && endpoint_iterator != end)
2323         {
2324             stream.lowest_layer().close();
2325             stream.lowest_layer().connect(*endpoint_iterator++, error);
2326         }
2327         if (error)
2328             return false;
2329         return true;
2330     }
2331
2332 private:
2333     bool fNeedHandshake;
2334     bool fUseSSL;
2335     SSLStream& stream;
2336 };
2337
2338 void ThreadRPCServer(void* parg)
2339 {
2340     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2341     try
2342     {
2343         vnThreadsRunning[THREAD_RPCSERVER]++;
2344         ThreadRPCServer2(parg);
2345         vnThreadsRunning[THREAD_RPCSERVER]--;
2346     }
2347     catch (std::exception& e) {
2348         vnThreadsRunning[THREAD_RPCSERVER]--;
2349         PrintException(&e, "ThreadRPCServer()");
2350     } catch (...) {
2351         vnThreadsRunning[THREAD_RPCSERVER]--;
2352         PrintException(NULL, "ThreadRPCServer()");
2353     }
2354     printf("ThreadRPCServer exiting\n");
2355 }
2356
2357 void ThreadRPCServer2(void* parg)
2358 {
2359     printf("ThreadRPCServer started\n");
2360
2361     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2362     if (mapArgs["-rpcpassword"] == "")
2363     {
2364         unsigned char rand_pwd[32];
2365         RAND_bytes(rand_pwd, 32);
2366         string strWhatAmI = "To use bitcoind";
2367         if (mapArgs.count("-server"))
2368             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2369         else if (mapArgs.count("-daemon"))
2370             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2371         ThreadSafeMessageBox(strprintf(
2372             _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2373               "It is recommended you use the following random password:\n"
2374               "rpcuser=bitcoinrpc\n"
2375               "rpcpassword=%s\n"
2376               "(you do not need to remember this password)\n"
2377               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2378                 strWhatAmI.c_str(),
2379                 GetConfigFile().string().c_str(),
2380                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2381             _("Error"), wxOK | wxMODAL);
2382         QueueShutdown();
2383         return;
2384     }
2385
2386     bool fUseSSL = GetBoolArg("-rpcssl");
2387     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2388
2389     asio::io_service io_service;
2390     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2391     ip::tcp::acceptor acceptor(io_service);
2392     try
2393     {
2394         acceptor.open(endpoint.protocol());
2395         acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2396         acceptor.bind(endpoint);
2397         acceptor.listen(socket_base::max_connections);
2398     }
2399     catch(boost::system::system_error &e)
2400     {
2401         ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2402                              _("Error"), wxOK | wxMODAL);
2403         QueueShutdown();
2404         return;
2405     }
2406
2407     ssl::context context(io_service, ssl::context::sslv23);
2408     if (fUseSSL)
2409     {
2410         context.set_options(ssl::context::no_sslv2);
2411
2412         filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2413         if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2414         if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2415         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2416
2417         filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2418         if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2419         if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2420         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2421
2422         string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2423         SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2424     }
2425
2426     loop
2427     {
2428         // Accept connection
2429         SSLStream sslStream(io_service, context);
2430         SSLIOStreamDevice d(sslStream, fUseSSL);
2431         iostreams::stream<SSLIOStreamDevice> stream(d);
2432
2433         ip::tcp::endpoint peer;
2434         vnThreadsRunning[THREAD_RPCSERVER]--;
2435         acceptor.accept(sslStream.lowest_layer(), peer);
2436         vnThreadsRunning[4]++;
2437         if (fShutdown)
2438             return;
2439
2440         // Restrict callers by IP
2441         if (!ClientAllowed(peer.address().to_string()))
2442         {
2443             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2444             if (!fUseSSL)
2445                 stream << HTTPReply(403, "") << std::flush;
2446             continue;
2447         }
2448
2449         map<string, string> mapHeaders;
2450         string strRequest;
2451
2452         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2453         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2454         {   // Timed out:
2455             acceptor.cancel();
2456             printf("ThreadRPCServer ReadHTTP timeout\n");
2457             continue;
2458         }
2459
2460         // Check authorization
2461         if (mapHeaders.count("authorization") == 0)
2462         {
2463             stream << HTTPReply(401, "") << std::flush;
2464             continue;
2465         }
2466         if (!HTTPAuthorized(mapHeaders))
2467         {
2468             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2469             /* Deter brute-forcing short passwords.
2470                If this results in a DOS the user really
2471                shouldn't have their RPC port exposed.*/
2472             if (mapArgs["-rpcpassword"].size() < 20)
2473                 Sleep(250);
2474
2475             stream << HTTPReply(401, "") << std::flush;
2476             continue;
2477         }
2478
2479         Value id = Value::null;
2480         try
2481         {
2482             // Parse request
2483             Value valRequest;
2484             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2485                 throw JSONRPCError(-32700, "Parse error");
2486             const Object& request = valRequest.get_obj();
2487
2488             // Parse id now so errors from here on will have the id
2489             id = find_value(request, "id");
2490
2491             // Parse method
2492             Value valMethod = find_value(request, "method");
2493             if (valMethod.type() == null_type)
2494                 throw JSONRPCError(-32600, "Missing method");
2495             if (valMethod.type() != str_type)
2496                 throw JSONRPCError(-32600, "Method must be a string");
2497             string strMethod = valMethod.get_str();
2498             if (strMethod != "getwork" && strMethod != "getmemorypool")
2499                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2500
2501             // Parse params
2502             Value valParams = find_value(request, "params");
2503             Array params;
2504             if (valParams.type() == array_type)
2505                 params = valParams.get_array();
2506             else if (valParams.type() == null_type)
2507                 params = Array();
2508             else
2509                 throw JSONRPCError(-32600, "Params must be an array");
2510
2511             // Find method
2512             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2513             if (mi == mapCallTable.end())
2514                 throw JSONRPCError(-32601, "Method not found");
2515
2516             // Observe safe mode
2517             string strWarning = GetWarnings("rpc");
2518             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2519                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2520
2521             try
2522             {
2523                 // Execute
2524                 Value result;
2525                 {
2526                     LOCK2(cs_main, pwalletMain->cs_wallet);
2527                     result = (*(*mi).second)(params, false);
2528                 }
2529
2530                 // Send reply
2531                 string strReply = JSONRPCReply(result, Value::null, id);
2532                 stream << HTTPReply(200, strReply) << std::flush;
2533             }
2534             catch (std::exception& e)
2535             {
2536                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2537             }
2538         }
2539         catch (Object& objError)
2540         {
2541             ErrorReply(stream, objError, id);
2542         }
2543         catch (std::exception& e)
2544         {
2545             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2546         }
2547     }
2548 }
2549
2550
2551
2552
2553 Object CallRPC(const string& strMethod, const Array& params)
2554 {
2555     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2556         throw runtime_error(strprintf(
2557             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2558               "If the file does not exist, create it with owner-readable-only file permissions."),
2559                 GetConfigFile().string().c_str()));
2560
2561     // Connect to localhost
2562     bool fUseSSL = GetBoolArg("-rpcssl");
2563     asio::io_service io_service;
2564     ssl::context context(io_service, ssl::context::sslv23);
2565     context.set_options(ssl::context::no_sslv2);
2566     SSLStream sslStream(io_service, context);
2567     SSLIOStreamDevice d(sslStream, fUseSSL);
2568     iostreams::stream<SSLIOStreamDevice> stream(d);
2569     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2570         throw runtime_error("couldn't connect to server");
2571
2572     // HTTP basic authentication
2573     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2574     map<string, string> mapRequestHeaders;
2575     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2576
2577     // Send request
2578     string strRequest = JSONRPCRequest(strMethod, params, 1);
2579     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2580     stream << strPost << std::flush;
2581
2582     // Receive reply
2583     map<string, string> mapHeaders;
2584     string strReply;
2585     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2586     if (nStatus == 401)
2587         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2588     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2589         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2590     else if (strReply.empty())
2591         throw runtime_error("no response from server");
2592
2593     // Parse reply
2594     Value valReply;
2595     if (!read_string(strReply, valReply))
2596         throw runtime_error("couldn't parse reply from server");
2597     const Object& reply = valReply.get_obj();
2598     if (reply.empty())
2599         throw runtime_error("expected reply to have result, error and id properties");
2600
2601     return reply;
2602 }
2603
2604
2605
2606
2607 template<typename T>
2608 void ConvertTo(Value& value)
2609 {
2610     if (value.type() == str_type)
2611     {
2612         // reinterpret string as unquoted json value
2613         Value value2;
2614         if (!read_string(value.get_str(), value2))
2615             throw runtime_error("type mismatch");
2616         value = value2.get_value<T>();
2617     }
2618     else
2619     {
2620         value = value.get_value<T>();
2621     }
2622 }
2623
2624 int CommandLineRPC(int argc, char *argv[])
2625 {
2626     string strPrint;
2627     int nRet = 0;
2628     try
2629     {
2630         // Skip switches
2631         while (argc > 1 && IsSwitchChar(argv[1][0]))
2632         {
2633             argc--;
2634             argv++;
2635         }
2636
2637         // Method
2638         if (argc < 2)
2639             throw runtime_error("too few parameters");
2640         string strMethod = argv[1];
2641
2642         // Parameters default to strings
2643         Array params;
2644         for (int i = 2; i < argc; i++)
2645             params.push_back(argv[i]);
2646         int n = params.size();
2647
2648         //
2649         // Special case non-string parameter types
2650         //
2651         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2652         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2654         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2655         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2657         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2658         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2659         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2661         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2662         if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2663         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2664         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2665         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2666         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2667         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2669         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2670         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2672         if (strMethod == "sendmany"               && n > 1)
2673         {
2674             string s = params[1].get_str();
2675             Value v;
2676             if (!read_string(s, v) || v.type() != obj_type)
2677                 throw runtime_error("type mismatch");
2678             params[1] = v.get_obj();
2679         }
2680         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2681         if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
2682         if (strMethod == "addmultisigaddress"      && n > 1)
2683         {
2684             string s = params[1].get_str();
2685             Value v;
2686             if (!read_string(s, v) || v.type() != array_type)
2687                 throw runtime_error("type mismatch "+s);
2688             params[1] = v.get_array();
2689         }
2690
2691         // Execute
2692         Object reply = CallRPC(strMethod, params);
2693
2694         // Parse reply
2695         const Value& result = find_value(reply, "result");
2696         const Value& error  = find_value(reply, "error");
2697
2698         if (error.type() != null_type)
2699         {
2700             // Error
2701             strPrint = "error: " + write_string(error, false);
2702             int code = find_value(error.get_obj(), "code").get_int();
2703             nRet = abs(code);
2704         }
2705         else
2706         {
2707             // Result
2708             if (result.type() == null_type)
2709                 strPrint = "";
2710             else if (result.type() == str_type)
2711                 strPrint = result.get_str();
2712             else
2713                 strPrint = write_string(result, true);
2714         }
2715     }
2716     catch (std::exception& e)
2717     {
2718         strPrint = string("error: ") + e.what();
2719         nRet = 87;
2720     }
2721     catch (...)
2722     {
2723         PrintException(NULL, "CommandLineRPC()");
2724     }
2725
2726     if (strPrint != "")
2727     {
2728         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2729     }
2730     return nRet;
2731 }
2732
2733
2734
2735
2736 #ifdef TEST
2737 int main(int argc, char *argv[])
2738 {
2739 #ifdef _MSC_VER
2740     // Turn off microsoft heap dump noise
2741     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2742     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2743 #endif
2744     setbuf(stdin, NULL);
2745     setbuf(stdout, NULL);
2746     setbuf(stderr, NULL);
2747
2748     try
2749     {
2750         if (argc >= 2 && string(argv[1]) == "-server")
2751         {
2752             printf("server ready\n");
2753             ThreadRPCServer(NULL);
2754         }
2755         else
2756         {
2757             return CommandLineRPC(argc, argv);
2758         }
2759     }
2760     catch (std::exception& e) {
2761         PrintException(&e, "main()");
2762     } catch (...) {
2763         PrintException(NULL, "main()");
2764     }
2765     return 0;
2766 }
2767 #endif