X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fbitcoinrpc.cpp;fp=src%2Frpc.cpp;h=92f2f9ec7c43e160d74d3809a068aefdb48b0a9a;hp=acd7a8933abfedea01644f5492fc2a2f3ef44d5b;hb=3b36da6d277c6f5ad671343e724e0336ce55c893;hpb=a2de1ea2d5776289c247bbc18c1ed13e16a4169f diff --git a/src/rpc.cpp b/src/bitcoinrpc.cpp similarity index 89% rename from src/rpc.cpp rename to src/bitcoinrpc.cpp index acd7a89..92f2f9e 100644 --- a/src/rpc.cpp +++ b/src/bitcoinrpc.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" -#include "cryptopp/sha.h" #include "db.h" #include "net.h" #include "init.h" @@ -37,6 +36,8 @@ void ThreadRPCServer2(void* parg); typedef Value(*rpcfn_type)(const Array& params, bool fHelp); extern map mapCallTable; +static std::string strRPCUserColonPass; + static int64 nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -50,13 +51,13 @@ Object JSONRPCError(int code, const string& message) } -void PrintConsole(const char* format, ...) +void PrintConsole(const std::string &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); + int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr); va_end(arg_ptr); if (ret < 0 || ret >= limit) { @@ -64,11 +65,7 @@ void PrintConsole(const char* format, ...) buffer[limit-1] = 0; } printf("%s", buffer); -#if defined(__WXMSW__) && defined(GUI) - MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION); -#else fprintf(stdout, "%s", buffer); -#endif } @@ -131,6 +128,7 @@ Value help(const Array& params, bool fHelp) // We already filter duplicates, but these deprecated screw up the sort order if (strMethod == "getamountreceived" || strMethod == "getallreceived" || + strMethod == "getblocknumber" || // deprecated (strMethod.find("label") != string::npos)) continue; if (strCommand != "" && strMethod != strCommand) @@ -165,10 +163,13 @@ Value stop(const Array& params, bool fHelp) throw runtime_error( "stop\n" "Stop bitcoin server."); - +#ifndef QT_GUI // Shutdown will take long enough that the response should get back CreateThread(Shutdown, NULL); return "bitcoin server stopping"; +#else + throw runtime_error("NYI: cannot shut down GUI with RPC command"); +#endif } @@ -183,12 +184,13 @@ Value getblockcount(const Array& params, bool fHelp) } +// deprecated 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."); + "Deprecated. Use getblockcount."); return nBestHeight; } @@ -530,6 +532,72 @@ Value sendtoaddress(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } +static const string strMessageMagic = "Bitcoin Signed Message:\n"; + +Value signmessage(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "signmessage \n" + "Sign a message with the private key of an address"); + + if (pwalletMain->IsLocked()) + throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + + string strAddress = params[0].get_str(); + string strMessage = params[1].get_str(); + + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(-3, "Invalid address"); + + CKey key; + if (!pwalletMain->GetKey(addr, key)) + throw JSONRPCError(-4, "Private key not available"); + + CDataStream ss(SER_GETHASH); + ss << strMessageMagic; + ss << strMessage; + + vector vchSig; + if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) + throw JSONRPCError(-5, "Sign failed"); + + return EncodeBase64(&vchSig[0], vchSig.size()); +} + +Value verifymessage(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "verifymessage \n" + "Verify a signed message"); + + string strAddress = params[0].get_str(); + string strSign = params[1].get_str(); + string strMessage = params[2].get_str(); + + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(-3, "Invalid address"); + + bool fInvalid = false; + vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); + + if (fInvalid) + throw JSONRPCError(-5, "Malformed base64 encoding"); + + CDataStream ss(SER_GETHASH); + ss << strMessageMagic; + ss << strMessage; + + CKey key; + if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) + return false; + + return (key.GetAddress() == addr); +} + Value getreceivedbyaddress(const Array& params, bool fHelp) { @@ -945,7 +1013,6 @@ Value ListReceived(const Array& params, bool fByAccounts) Object obj; obj.push_back(Pair("address", address.ToString())); obj.push_back(Pair("account", strAccount)); - obj.push_back(Pair("label", strAccount)); // deprecated obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); ret.push_back(obj); @@ -960,7 +1027,6 @@ Value ListReceived(const Array& params, bool fByAccounts) int nConf = (*it).second.nConf; Object obj; obj.push_back(Pair("account", (*it).first)); - obj.push_back(Pair("label", (*it).first)); // deprecated obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); ret.push_back(obj); @@ -1212,6 +1278,69 @@ Value listaccounts(const Array& params, bool fHelp) return ret; } +Value listsinceblock(const Array& params, bool fHelp) +{ + if (fHelp) + throw runtime_error( + "listsinceblock [blockhash] [target-confirmations]\n" + "Get all transactions in blocks since block [blockhash], or all transactions if omitted"); + + CBlockIndex *pindex = NULL; + int target_confirms = 1; + + if (params.size() > 0) + { + uint256 blockId = 0; + + blockId.SetHex(params[0].get_str()); + pindex = CBlockLocator(blockId).GetBlockIndex(); + } + + if (params.size() > 1) + { + target_confirms = params[1].get_int(); + + if (target_confirms < 1) + throw JSONRPCError(-8, "Invalid parameter"); + } + + int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1; + + Array transactions; + + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) + { + CWalletTx tx = (*it).second; + + if (depth == -1 || tx.GetDepthInMainChain() < depth) + ListTransactions(tx, "*", 0, true, transactions); + } + + uint256 lastblock; + + if (target_confirms == 1) + { + lastblock = hashBestChain; + } + else + { + int target_height = pindexBest->nHeight + 1 - target_confirms; + + CBlockIndex *block; + for (block = pindexBest; + block && block->nHeight > target_height; + block = block->pprev) { } + + lastblock = block ? block->GetBlockHash() : 0; + } + + Object ret; + ret.push_back(Pair("transactions", transactions)); + ret.push_back(Pair("lastblock", lastblock.GetHex())); + + return ret; +} + Value gettransaction(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1345,21 +1474,16 @@ Value walletpassphrase(const Array& params, bool fHelp) throw JSONRPCError(-17, "Error: Wallet is already unlocked."); // Note that the walletpassphrase is stored in params[0] which is not mlock()ed - string strWalletPass; + SecureString strWalletPass; strWalletPass.reserve(100); - mlock(&strWalletPass[0], strWalletPass.capacity()); - strWalletPass = params[0].get_str(); + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + strWalletPass = params[0].get_str().c_str(); if (strWalletPass.length() > 0) { if (!pwalletMain->Unlock(strWalletPass)) - { - fill(strWalletPass.begin(), strWalletPass.end(), '\0'); - munlock(&strWalletPass[0], strWalletPass.capacity()); throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect."); - } - fill(strWalletPass.begin(), strWalletPass.end(), '\0'); - munlock(&strWalletPass[0], strWalletPass.capacity()); } else throw runtime_error( @@ -1385,15 +1509,15 @@ Value walletpassphrasechange(const Array& params, bool fHelp) if (!pwalletMain->IsCrypted()) throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called."); - string strOldWalletPass; + // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + SecureString strOldWalletPass; strOldWalletPass.reserve(100); - mlock(&strOldWalletPass[0], strOldWalletPass.capacity()); - strOldWalletPass = params[0].get_str(); + strOldWalletPass = params[0].get_str().c_str(); - string strNewWalletPass; + SecureString strNewWalletPass; strNewWalletPass.reserve(100); - mlock(&strNewWalletPass[0], strNewWalletPass.capacity()); - strNewWalletPass = params[1].get_str(); + strNewWalletPass = params[1].get_str().c_str(); if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1) throw runtime_error( @@ -1401,17 +1525,7 @@ Value walletpassphrasechange(const Array& params, bool fHelp) "Changes the wallet passphrase from to ."); if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) - { - fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); - fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); - munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); - munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect."); - } - fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); - fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); - munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); - munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); return Value::null; } @@ -1451,15 +1565,16 @@ Value encryptwallet(const Array& params, bool fHelp) if (pwalletMain->IsCrypted()) throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called."); -#ifdef GUI +#ifdef QT_GUI // shutting down via RPC while the GUI is running does not work (yet): throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command"); #endif - string strWalletPass; + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + SecureString strWalletPass; strWalletPass.reserve(100); - mlock(&strWalletPass[0], strWalletPass.capacity()); - strWalletPass = params[0].get_str(); + strWalletPass = params[0].get_str().c_str(); if (strWalletPass.length() < 1) throw runtime_error( @@ -1467,13 +1582,7 @@ Value encryptwallet(const Array& params, bool fHelp) "Encrypts the wallet with ."); if (!pwalletMain->EncryptWallet(strWalletPass)) - { - fill(strWalletPass.begin(), strWalletPass.end(), '\0'); - munlock(&strWalletPass[0], strWalletPass.capacity()); throw JSONRPCError(-16, "Error: Failed to encrypt the wallet."); - } - fill(strWalletPass.begin(), strWalletPass.end(), '\0'); - munlock(&strWalletPass[0], strWalletPass.capacity()); // BDB seems to have a bad habit of writing old data into // slack space in .dat files; that is bad if the old data is @@ -1515,9 +1624,9 @@ Value getwork(const Array& params, bool fHelp) throw runtime_error( "getwork [data]\n" "If [data] is not specified, returns formatted hash data to work on:\n" - " \"midstate\" : precomputed hash state after hashing the first half of the data\n" + " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated " \"data\" : block data\n" - " \"hash1\" : formatted hash buffer for second hash\n" + " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated " \"target\" : little endian hash target\n" "If [data] is specified, tries to solve the block and returns true if it was successful."); @@ -1581,9 +1690,9 @@ Value getwork(const Array& params, bool fHelp) uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); Object result; - result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); + result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); - result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); + result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); return result; } @@ -1597,7 +1706,7 @@ Value getwork(const Array& params, bool fHelp) // Byte reverse for (int i = 0; i < 128/4; i++) - ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]); + ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); // Get saved block if (!mapNewBlock.count(pdata->hashMerkleRoot)) @@ -1614,6 +1723,93 @@ Value getwork(const Array& params, bool fHelp) } +Value getmemorypool(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getmemorypool [data]\n" + "If [data] is not specified, returns data needed to construct a block to work on:\n" + " \"version\" : block version\n" + " \"previousblockhash\" : hash of current highest block\n" + " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n" + " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n" + " \"time\" : timestamp appropriate for next block\n" + " \"bits\" : compressed target of next block\n" + "If [data] is specified, tries to solve the block and returns true if it was successful."); + + if (params.size() == 0) + { + if (vNodes.empty()) + throw JSONRPCError(-9, "Bitcoin is not connected!"); + + if (IsInitialBlockDownload()) + throw JSONRPCError(-10, "Bitcoin is downloading blocks..."); + + static CReserveKey reservekey(pwalletMain); + + // Update block + static unsigned int nTransactionsUpdatedLast; + static CBlockIndex* pindexPrev; + static int64 nStart; + static CBlock* pblock; + if (pindexPrev != pindexBest || + (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5)) + { + nTransactionsUpdatedLast = nTransactionsUpdated; + pindexPrev = pindexBest; + nStart = GetTime(); + + // Create new block + if(pblock) + delete pblock; + pblock = CreateNewBlock(reservekey); + if (!pblock) + throw JSONRPCError(-7, "Out of memory"); + } + + // Update nTime + pblock->UpdateTime(pindexPrev); + pblock->nNonce = 0; + + Array transactions; + BOOST_FOREACH(CTransaction tx, pblock->vtx) { + if(tx.IsCoinBase()) + continue; + + CDataStream ssTx; + ssTx << tx; + + transactions.push_back(HexStr(ssTx.begin(), ssTx.end())); + } + + Object result; + result.push_back(Pair("version", pblock->nVersion)); + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); + result.push_back(Pair("transactions", transactions)); + result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + result.push_back(Pair("time", (int64_t)pblock->nTime)); + + union { + int32_t nBits; + char cBits[4]; + } uBits; + uBits.nBits = htonl((int32_t)pblock->nBits); + result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits)))); + + return result; + } + else + { + // Parse parameters + CDataStream ssBlock(ParseHex(params[0].get_str())); + CBlock pblock; + ssBlock >> pblock; + + return ProcessBlock(NULL, &pblock); + } +} + + @@ -1642,20 +1838,13 @@ pair pCallTable[] = make_pair("getnewaddress", &getnewaddress), make_pair("getaccountaddress", &getaccountaddress), make_pair("setaccount", &setaccount), - make_pair("setlabel", &setaccount), // deprecated make_pair("getaccount", &getaccount), - make_pair("getlabel", &getaccount), // deprecated make_pair("getaddressesbyaccount", &getaddressesbyaccount), - make_pair("getaddressesbylabel", &getaddressesbyaccount), // deprecated make_pair("sendtoaddress", &sendtoaddress), - make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress - make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress make_pair("getreceivedbyaddress", &getreceivedbyaddress), make_pair("getreceivedbyaccount", &getreceivedbyaccount), - make_pair("getreceivedbylabel", &getreceivedbyaccount), // deprecated make_pair("listreceivedbyaddress", &listreceivedbyaddress), make_pair("listreceivedbyaccount", &listreceivedbyaccount), - make_pair("listreceivedbylabel", &listreceivedbyaccount), // deprecated make_pair("backupwallet", &backupwallet), make_pair("keypoolrefill", &keypoolrefill), make_pair("walletpassphrase", &walletpassphrase), @@ -1669,9 +1858,13 @@ pair pCallTable[] = make_pair("sendmany", &sendmany), make_pair("gettransaction", &gettransaction), make_pair("listtransactions", &listtransactions), + make_pair("signmessage", &signmessage), + make_pair("verifymessage", &verifymessage), make_pair("getwork", &getwork), make_pair("listaccounts", &listaccounts), make_pair("settxfee", &settxfee), + make_pair("getmemorypool", &getmemorypool), + make_pair("listsinceblock", &listsinceblock), }; map mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); @@ -1680,7 +1873,7 @@ string pAllowInSafeMode[] = "help", "stop", "getblockcount", - "getblocknumber", + "getblocknumber", // deprecated "getconnectioncount", "getdifficulty", "getgenerate", @@ -1689,17 +1882,15 @@ string pAllowInSafeMode[] = "getinfo", "getnewaddress", "getaccountaddress", - "setlabel", // deprecated "getaccount", - "getlabel", // deprecated "getaddressesbyaccount", - "getaddressesbylabel", // deprecated "backupwallet", "keypoolrefill", "walletpassphrase", "walletlock", "validateaddress", "getwork", + "getmemorypool", }; set setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0])); @@ -1721,6 +1912,7 @@ string HTTPPost(const string& strMsg, const map& mapRequestHeader << "Host: 127.0.0.1\r\n" << "Content-Type: application/json\r\n" << "Content-Length: " << strMsg.size() << "\r\n" + << "Connection: close\r\n" << "Accept: application/json\r\n"; BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders) s << item.first << ": " << item.second << "\r\n"; @@ -1761,12 +1953,13 @@ static string HTTPReply(int nStatus, const string& strMsg) "\r\n" "

401 Unauthorized.

\r\n" "\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str()); - string strStatus; - if (nStatus == 200) strStatus = "OK"; - else if (nStatus == 400) strStatus = "Bad Request"; - else if (nStatus == 403) strStatus = "Forbidden"; - else if (nStatus == 404) strStatus = "Not Found"; - else if (nStatus == 500) strStatus = "Internal Server Error"; + const char *cStatus; + if (nStatus == 200) cStatus = "OK"; + else if (nStatus == 400) cStatus = "Bad Request"; + else if (nStatus == 403) cStatus = "Forbidden"; + else if (nStatus == 404) cStatus = "Not Found"; + else if (nStatus == 500) cStatus = "Internal Server Error"; + else cStatus = ""; return strprintf( "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" @@ -1777,7 +1970,7 @@ static string HTTPReply(int nStatus, const string& strMsg) "\r\n" "%s", nStatus, - strStatus.c_str(), + cStatus, rfc1123Time().c_str(), strMsg.size(), FormatFullVersion().c_str(), @@ -1844,43 +2037,6 @@ int ReadHTTP(std::basic_istream& stream, map& mapHeadersRe return nStatus; } -string EncodeBase64(string s) -{ - BIO *b64, *bmem; - BUF_MEM *bptr; - - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - bmem = BIO_new(BIO_s_mem()); - b64 = BIO_push(b64, bmem); - BIO_write(b64, s.c_str(), s.size()); - BIO_flush(b64); - BIO_get_mem_ptr(b64, &bptr); - - string result(bptr->data, bptr->length); - BIO_free_all(b64); - - return result; -} - -string DecodeBase64(string s) -{ - BIO *b64, *bmem; - - char* buffer = static_cast(calloc(s.size(), sizeof(char))); - - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - bmem = BIO_new_mem_buf(const_cast(s.c_str()), s.size()); - bmem = BIO_push(b64, bmem); - BIO_read(bmem, buffer, s.size()); - BIO_free_all(bmem); - - string result(buffer); - free(buffer); - return result; -} - bool HTTPAuthorized(map& mapHeaders) { string strAuth = mapHeaders["authorization"]; @@ -1888,12 +2044,7 @@ bool HTTPAuthorized(map& mapHeaders) return false; string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); string strUserPass = DecodeBase64(strUserPass64); - string::size_type nColon = strUserPass.find(":"); - if (nColon == string::npos) - return false; - string strUser = strUserPass.substr(0, nColon); - string strPassword = strUserPass.substr(nColon+1); - return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]); + return strUserPass == strRPCUserColonPass; } // @@ -2022,11 +2173,16 @@ void ThreadRPCServer(void* parg) printf("ThreadRPCServer exiting\n"); } +#ifdef QT_GUI +extern bool HACK_SHUTDOWN; +#endif + void ThreadRPCServer2(void* parg) { printf("ThreadRPCServer started\n"); - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + if (strRPCUserColonPass == ":") { unsigned char rand_pwd[32]; RAND_bytes(rand_pwd, 32); @@ -2035,8 +2191,8 @@ void ThreadRPCServer2(void* parg) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); else if (mapArgs.count("-daemon")) strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\""); - PrintConsole( - _("Warning: %s, you must set a rpcpassword in the configuration file:\n %s\n" + ThreadSafeMessageBox(strprintf( + _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n" "It is recommended you use the following random password:\n" "rpcuser=bitcoinrpc\n" "rpcpassword=%s\n" @@ -2044,8 +2200,11 @@ void ThreadRPCServer2(void* parg) "If the file does not exist, create it with owner-readable-only file permissions.\n"), strWhatAmI.c_str(), GetConfigFile().c_str(), - EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()); + EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()), + _("Error"), wxOK | wxMODAL); +#ifndef QT_GUI CreateThread(Shutdown, NULL); +#endif return; } @@ -2054,9 +2213,27 @@ void ThreadRPCServer2(void* parg) asio::io_service io_service; ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332)); +#ifndef QT_GUI ip::tcp::acceptor acceptor(io_service, endpoint); acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); +#else + ip::tcp::acceptor acceptor(io_service); + try + { + acceptor.open(endpoint.protocol()); + acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor.bind(endpoint); + acceptor.listen(socket_base::max_connections); + } + catch(boost::system::system_error &e) + { + HACK_SHUTDOWN = true; + ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()), + _("Error"), wxOK | wxMODAL); + return; + } +#endif #ifdef USE_SSL ssl::context context(io_service, ssl::context::sslv23); @@ -2161,7 +2338,7 @@ void ThreadRPCServer2(void* parg) if (valMethod.type() != str_type) throw JSONRPCError(-32600, "Method must be a string"); string strMethod = valMethod.get_str(); - if (strMethod != "getwork") + if (strMethod != "getwork" && strMethod != "getmemorypool") printf("ThreadRPCServer method=%s\n", strMethod.c_str()); // Parse params @@ -2327,18 +2504,12 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "settxfee" && n > 0) ConvertTo(params[0]); - if (strMethod == "getamountreceived" && n > 1) ConvertTo(params[1]); // deprecated if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo(params[1]); // deprecated - if (strMethod == "getallreceived" && n > 0) ConvertTo(params[0]); // deprecated - if (strMethod == "getallreceived" && n > 1) ConvertTo(params[1]); // deprecated if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo(params[0]); if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo(params[0]); // deprecated - if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo(params[1]); // deprecated if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); if (strMethod == "move" && n > 2) ConvertTo(params[2]); if (strMethod == "move" && n > 3) ConvertTo(params[3]); @@ -2348,6 +2519,7 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); + if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); if (strMethod == "sendmany" && n > 1) { string s = params[1].get_str(); @@ -2395,13 +2567,7 @@ int CommandLineRPC(int argc, char *argv[]) if (strPrint != "") { -#if defined(__WXMSW__) && defined(GUI) - // Windows GUI apps can't print to command line, - // so settle for a message box yuck - MyMessageBox(strPrint, "Bitcoin", wxOK); -#else fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); -#endif } return nRet; }