// Copyright (c) 2010 Satoshi Nakamoto // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" #undef printf #include #include "json/json_spirit_reader_template.h" #include "json/json_spirit_writer_template.h" #include "json/json_spirit_utils.h" #define printf OutputDebugStringF // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are // precompiled in headers.h. The problem might be when the pch file goes over // a certain size around 145MB. If we need access to json_spirit outside this // file, we could use the compiled json_spirit option. using boost::asio::ip::tcp; using namespace json_spirit; void ThreadRPCServer2(void* parg); typedef Value(*rpcfn_type)(const Array& params, bool fHelp); extern map mapCallTable; void PrintConsole(const char* format, ...) { char buffer[50000]; int limit = sizeof(buffer); va_list arg_ptr; va_start(arg_ptr, format); int ret = _vsnprintf(buffer, limit, format, arg_ptr); va_end(arg_ptr); if (ret < 0 || ret >= limit) { ret = limit - 1; buffer[limit-1] = 0; } #if defined(__WXMSW__) && wxUSE_GUI MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION); #else fprintf(stdout, buffer); #endif } /// /// Note: This interface may still be subject to change. /// Value help(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "help\n" "List commands."); string strRet; set setDone; for (map::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi) { string strMethod = (*mi).first; // We already filter duplicates, but these deprecated screw up the sort order if (strMethod == "getamountreceived" || strMethod == "getallreceived") continue; try { Array params; rpcfn_type pfn = (*mi).second; if (setDone.insert(pfn).second) (*pfn)(params, true); } catch (std::exception& e) { // Help text is returned in an exception string strHelp = string(e.what()); if (strHelp.find('\n') != -1) strHelp = strHelp.substr(0, strHelp.find('\n')); strRet += strHelp + "\n"; } } strRet = strRet.substr(0,strRet.size()-1); return strRet; } Value stop(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "stop\n" "Stop bitcoin server."); // Shutdown will take long enough that the response should get back CreateThread(Shutdown, NULL); return "bitcoin server stopping"; } Value getblockcount(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getblockcount\n" "Returns the number of blocks in the longest block chain."); return nBestHeight + 1; } Value getblocknumber(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getblocknumber\n" "Returns the block number of the latest block in the longest block chain."); return nBestHeight; } Value getconnectioncount(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getconnectioncount\n" "Returns the number of connections to other nodes."); return (int)vNodes.size(); } double GetDifficulty() { // Floating point number that is a multiple of the minimum difficulty, // minimum difficulty = 1.0. if (pindexBest == NULL) return 1.0; int nShift = 256 - 32 - 31; // to fit in a uint double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint(); double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint(); return dMinimum / dCurrently; } Value getdifficulty(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getdifficulty\n" "Returns the proof-of-work difficulty as a multiple of the minimum difficulty."); return GetDifficulty(); } Value getbalance(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getbalance\n" "Returns the server's available balance."); return ((double)GetBalance() / (double)COIN); } Value getgenerate(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getgenerate\n" "Returns true or false."); return (bool)fGenerateBitcoins; } Value setgenerate(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "setgenerate [genproclimit]\n" " is true or false to turn generation on or off.\n" "Generation is limited to [genproclimit] processors, -1 is unlimited."); bool fGenerate = true; if (params.size() > 0) fGenerate = params[0].get_bool(); if (params.size() > 1) { int nGenProcLimit = params[1].get_int(); fLimitProcessors = (nGenProcLimit != -1); CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors); if (nGenProcLimit != -1) CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); } GenerateBitcoins(fGenerate); return Value::null; } Value getinfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getinfo"); Object obj; obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN)); obj.push_back(Pair("blocks", (int)nBestHeight + 1)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("generate", (bool)fGenerateBitcoins)); obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); return obj; } Value getnewaddress(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( "getnewaddress [label]\n" "Returns a new bitcoin address for receiving payments. " "If [label] is specified (recommended), it is added to the address book " "so payments received with the address will be labeled."); // Parse the label first so we don't generate a key if there's an error string strLabel; if (params.size() > 0) strLabel = params[0].get_str(); // Generate a new key that is added to wallet string strAddress = PubKeyToAddress(GenerateNewKey()); SetAddressBookName(strAddress, strLabel); return strAddress; } Value setlabel(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "setlabel