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