X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbitcoinrpc.cpp;h=5571c344a322cc9e0ea5d8c91560591c81ac5622;hb=82a10c81707dcff5ee24dec7ef7ebf8eccfded03;hp=09be73af3de838894aa64d757c9f86e6bfaf0449;hpb=8a53cb0b9d6a6c780c3458a2c3801409c2e3b0ca;p=novacoin.git diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 09be73a..5571c34 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. @@ -120,6 +120,17 @@ Value ValueFromAmount(int64 amount) return (double)amount / (double)COIN; } +std::string +HexBits(unsigned int nBits) +{ + union { + int32_t nBits; + char cBits[4]; + } uBits; + uBits.nBits = htonl((int32_t)nBits); + return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -147,11 +158,13 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) { Object result; result.push_back(Pair("hash", block.GetHash().GetHex())); - result.push_back(Pair("blockcount", blockindex->nHeight)); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK))); + result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime())); result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce)); + result.push_back(Pair("bits", HexBits(block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); Array txhashes; BOOST_FOREACH (const CTransaction&tx, block.vtx) @@ -159,9 +172,9 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) result.push_back(Pair("tx", txhashes)); if (blockindex->pprev) - result.push_back(Pair("hashprevious", blockindex->pprev->GetBlockHash().GetHex())); + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); if (blockindex->pnext) - result.push_back(Pair("hashnext", blockindex->pnext->GetBlockHash().GetHex())); + result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); return result; } @@ -288,7 +301,7 @@ Value getgenerate(const Array& params, bool fHelp) "getgenerate\n" "Returns true or false."); - return (bool)fGenerateBitcoins; + return GetBoolArg("-gen"); } @@ -307,13 +320,11 @@ Value setgenerate(const Array& params, bool fHelp) if (params.size() > 1) { int nGenProcLimit = params[1].get_int(); - fLimitProcessors = (nGenProcLimit != -1); - WriteSetting("fLimitProcessors", fLimitProcessors); - if (nGenProcLimit != -1) - WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); + mapArgs["-genproclimit"] = itostr(nGenProcLimit); if (nGenProcLimit == 0) fGenerate = false; } + mapArgs["-gen"] = (fGenerate ? "1" : "0"); GenerateBitcoins(fGenerate, pwalletMain); return Value::null; @@ -347,17 +358,36 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("blocks", (int)nBestHeight)); 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())); - obj.push_back(Pair("hashespersec", gethashespersec(params, false))); obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); if (pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000)); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + return obj; +} + + +Value getmininginfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getmininginfo\n" + "Returns an object containing mining-related information."); + + Object obj; + obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize)); + obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx)); + obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("errors", GetWarnings("statusbar"))); + obj.push_back(Pair("generate", GetBoolArg("-gen"))); + obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); + obj.push_back(Pair("hashespersec", gethashespersec(params, false))); + obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx)); + obj.push_back(Pair("testnet", fTestNet)); return obj; } @@ -570,8 +600,6 @@ 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) @@ -975,7 +1003,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) { string msg = "addmultisigaddress <'[\"key\",\"key\"]'> [account]\n" "Add a nrequired-to-sign multisignature address to the wallet\"\n" - "each key is a bitcoin address, hex or base58 public key\n" + "each key is a bitcoin address or hex-encoded public key\n" "If [account] is specified, assign address to [account]."; throw runtime_error(msg); } @@ -989,41 +1017,52 @@ Value addmultisigaddress(const Array& params, bool fHelp) strAccount = AccountFromValue(params[2]); // Gather public keys - if (keys.size() < nRequired) + if (nRequired < 1 || keys.size() < nRequired) throw runtime_error( - strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired)); + strprintf("wrong number of keys" + "(got %d, need at least %d)", keys.size(), nRequired)); std::vector pubkeys; pubkeys.resize(keys.size()); for (int i = 0; i < keys.size(); i++) { const std::string& ks = keys[i].get_str(); - if (ks.size() == 130) // hex public key - pubkeys[i].SetPubKey(ParseHex(ks)); - else if (ks.size() > 34) // base58-encoded + + // Case 1: bitcoin address and we have full public key: + CBitcoinAddress address(ks); + if (address.IsValid()) { + if (address.IsScript()) + throw runtime_error( + strprintf("%s is a pay-to-script address",ks.c_str())); std::vector vchPubKey; - if (DecodeBase58(ks, vchPubKey)) - pubkeys[i].SetPubKey(vchPubKey); - else - throw runtime_error("Error base58 decoding key: "+ks); + if (!pwalletMain->GetPubKey(address, vchPubKey)) + throw runtime_error( + strprintf("no full public key for address %s",ks.c_str())); + if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); } - else // bitcoin address for key in this wallet + + // Case 2: hex public key + else if (IsHex(ks)) { - CBitcoinAddress address(ks); - if (!pwalletMain->GetKey(address, pubkeys[i])) - throw runtime_error( - strprintf("addmultisigaddress: unknown address: %s",ks.c_str())); + vector vchPubKey = ParseHex(ks); + if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); + } + else + { + throw runtime_error(" Invalid public key: "+ks); } } - // Construct using OP_EVAL + // Construct using pay-to-script-hash: CScript inner; inner.SetMultisig(nRequired, pubkeys); uint160 scriptHash = Hash160(inner); CScript scriptPubKey; - scriptPubKey.SetEval(inner); - pwalletMain->AddCScript(scriptHash, inner); + scriptPubKey.SetPayToScriptHash(inner); + pwalletMain->AddCScript(inner); CBitcoinAddress address; address.SetScriptHash160(scriptHash); @@ -1418,7 +1457,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *block; for (block = pindexBest; block && block->nHeight > target_height; - block = block->pprev); + block = block->pprev) { } lastblock = block ? block->GetBlockHash() : 0; } @@ -1509,37 +1548,43 @@ void ThreadTopUpKeyPool(void* parg) void ThreadCleanWalletPassphrase(void* parg) { - int64 nMyWakeTime = GetTime() + *((int*)parg); + int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000; + + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); if (nWalletUnlockTime == 0) { - CRITICAL_BLOCK(cs_nWalletUnlockTime) + nWalletUnlockTime = nMyWakeTime; + + do { - nWalletUnlockTime = nMyWakeTime; - } + if (nWalletUnlockTime==0) + break; + int64 nToSleep = nWalletUnlockTime - GetTimeMillis(); + if (nToSleep <= 0) + break; + + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); + Sleep(nToSleep); + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); - while (GetTime() < nWalletUnlockTime) - Sleep(GetTime() - nWalletUnlockTime); + } while(1); - CRITICAL_BLOCK(cs_nWalletUnlockTime) + if (nWalletUnlockTime) { nWalletUnlockTime = 0; + pwalletMain->Lock(); } } else { - CRITICAL_BLOCK(cs_nWalletUnlockTime) - { - if (nWalletUnlockTime < nMyWakeTime) - nWalletUnlockTime = nMyWakeTime; - } - free(parg); - return; + if (nWalletUnlockTime < nMyWakeTime) + nWalletUnlockTime = nMyWakeTime; } - pwalletMain->Lock(); + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); - delete (int*)parg; + delete (int64*)parg; } Value walletpassphrase(const Array& params, bool fHelp) @@ -1574,7 +1619,7 @@ Value walletpassphrase(const Array& params, bool fHelp) "Stores the wallet decryption key in memory for seconds."); CreateThread(ThreadTopUpKeyPool, NULL); - int* pnSleepTime = new int(params[1].get_int()); + int64* pnSleepTime = new int64(params[1].get_int64()); CreateThread(ThreadCleanWalletPassphrase, pnSleepTime); return Value::null; @@ -1627,9 +1672,9 @@ Value walletlock(const Array& params, bool fHelp) if (!pwalletMain->IsCrypted()) throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called."); - pwalletMain->Lock(); CRITICAL_BLOCK(cs_nWalletUnlockTime) { + pwalletMain->Lock(); nWalletUnlockTime = 0; } @@ -1699,8 +1744,9 @@ Value validateaddress(const Array& params, bool fHelp) std::vector vchPubKey; pwalletMain->GetPubKey(address, vchPubKey); ret.push_back(Pair("pubkey", HexStr(vchPubKey))); - std::string strPubKey(vchPubKey.begin(), vchPubKey.end()); - ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey))); + CKey key; + key.SetPubKey(vchPubKey); + ret.push_back(Pair("iscompressed", key.IsCompressed())); } else if (pwalletMain->HaveCScript(address.GetHash160())) { @@ -1781,7 +1827,7 @@ Value getwork(const Array& params, bool fHelp) } // Update nTime - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; // Update nExtraNonce @@ -1843,7 +1889,10 @@ Value getmemorypool(const Array& params, bool fHelp) " \"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" + " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n" " \"time\" : timestamp appropriate for next block\n" + " \"mintime\" : minimum timestamp appropriate for next block\n" + " \"curtime\" : current timestamp\n" " \"bits\" : compressed target of next block\n" "If [data] is specified, tries to solve the block and returns true if it was successful."); @@ -1878,7 +1927,7 @@ Value getmemorypool(const Array& params, bool fHelp) } // Update nTime - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; Array transactions; @@ -1897,14 +1946,11 @@ Value getmemorypool(const Array& params, bool fHelp) 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("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); 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)))); + result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); + result.push_back(Pair("curtime", (int64_t)GetAdjustedTime())); + result.push_back(Pair("bits", HexBits(pblock->nBits))); return result; } @@ -1983,6 +2029,7 @@ pair pCallTable[] = make_pair("setgenerate", &setgenerate), make_pair("gethashespersec", &gethashespersec), make_pair("getinfo", &getinfo), + make_pair("getmininginfo", &getmininginfo), make_pair("getnewaddress", &getnewaddress), make_pair("getaccountaddress", &getaccountaddress), make_pair("setaccount", &setaccount), @@ -2033,6 +2080,7 @@ string pAllowInSafeMode[] = "setgenerate", "gethashespersec", "getinfo", + "getmininginfo", "getnewaddress", "getaccountaddress", "getaccount", @@ -2312,15 +2360,15 @@ void ThreadRPCServer(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg)); try { - vnThreadsRunning[4]++; + vnThreadsRunning[THREAD_RPCSERVER]++; ThreadRPCServer2(parg); - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; } catch (std::exception& e) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(&e, "ThreadRPCServer()"); } catch (...) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(NULL, "ThreadRPCServer()"); } printf("ThreadRPCServer exiting\n"); @@ -2331,18 +2379,25 @@ void ThreadRPCServer2(void* parg) printf("ThreadRPCServer started\n"); strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; - if (strRPCUserColonPass == ":") + if (mapArgs["-rpcpassword"] == "") { + unsigned char rand_pwd[32]; + RAND_bytes(rand_pwd, 32); string strWhatAmI = "To use bitcoind"; if (mapArgs.count("-server")) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); else if (mapArgs.count("-daemon")) strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\""); PrintConsole( - _("Error: %s, you must set rpcpassword=\nin the configuration file: %s\n" + _("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" + "(you do not need to remember this password)\n" "If the file does not exist, create it with owner-readable-only file permissions.\n"), strWhatAmI.c_str(), - GetConfigFile().c_str()); + GetConfigFile().c_str(), + EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()); #ifndef QT_GUI CreateThread(Shutdown, NULL); #endif @@ -2393,7 +2448,7 @@ void ThreadRPCServer2(void* parg) #endif ip::tcp::endpoint peer; - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; #ifdef USE_SSL acceptor.accept(sslStream.lowest_layer(), peer); #else @@ -2431,12 +2486,14 @@ void ThreadRPCServer2(void* parg) } if (!HTTPAuthorized(mapHeaders)) { - // Deter brute-forcing short passwords - if (mapArgs["-rpcpassword"].size() < 15) - Sleep(50); + printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str()); + /* Deter brute-forcing short passwords. + If this results in a DOS the user really + shouldn't have their RPC port exposed.*/ + if (mapArgs["-rpcpassword"].size() < 20) + Sleep(250); stream << HTTPReply(401, "") << std::flush; - printf("ThreadRPCServer incorrect password attempt\n"); continue; } @@ -2657,7 +2714,7 @@ int CommandLineRPC(int argc, char *argv[]) string s = params[1].get_str(); Value v; if (!read_string(s, v) || v.type() != array_type) - throw runtime_error("addmultisigaddress: type mismatch "+s); + throw runtime_error("type mismatch "+s); params[1] = v.get_array(); }