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