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