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