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