diff options
| author | Ross Nicoll <[email protected]> | 2017-11-19 22:09:03 +0000 |
|---|---|---|
| committer | Ross Nicoll <[email protected]> | 2018-09-19 19:23:29 +0100 |
| commit | fcde8643344a3a7baadf31d97dd3e1b47aa8cff9 (patch) | |
| tree | e3f8540c7060b29b848a9964c6b6f08fe3b64b5b /src/rpc/mining.cpp | |
| parent | Merge AuxPoW support from Namecore (diff) | |
| download | discoin-fcde8643344a3a7baadf31d97dd3e1b47aa8cff9.tar.xz discoin-fcde8643344a3a7baadf31d97dd3e1b47aa8cff9.zip | |
Sync mining code from Namecore to resolve unit test failures (#1385)
Diffstat (limited to 'src/rpc/mining.cpp')
| -rw-r--r-- | src/rpc/mining.cpp | 323 |
1 files changed, 120 insertions, 203 deletions
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 70192686b..b355ccdc9 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -98,6 +98,8 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { + // Dogecoin: Never mine witness tx + const bool fMineWitnessTx = false; static const int nInnerLoopCount = 0x10000; int nHeightStart = 0; int nHeightEnd = 0; @@ -113,7 +115,7 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript)); + std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript, fMineWitnessTx)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -319,6 +321,8 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) { UniValue getblocktemplate(const JSONRPCRequest& request) { + // Dogecoin: Never mine witness tx + const bool fMineWitnessTx = false; if (request.fHelp || request.params.size() > 1) throw runtime_error( "getblocktemplate ( TemplateRequest )\n" @@ -549,7 +553,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // Create new block CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit); + pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fMineWitnessTx); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); @@ -930,148 +934,6 @@ UniValue estimatesmartpriority(const JSONRPCRequest& request) /* ************************************************************************** */ /* Merge mining. */ -/** - * The variables below are used to keep track of created and not yet - * submitted auxpow blocks. Lock them to be sure even for multiple - * RPC threads running in parallel. - */ -static CCriticalSection cs_auxblockCache; -static std::map<uint256, CBlock*> mapNewBlock; -static std::vector<std::unique_ptr<CBlockTemplate>> vNewBlockTemplate; - -static -void AuxMiningCheck() -{ - if(!g_connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, - "Error: Peer-to-peer functionality missing or disabled"); - - if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0 - && !Params().MineBlocksOnDemand()) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, - "Dogecoin is not connected!"); - - if (IsInitialBlockDownload() && !Params().MineBlocksOnDemand()) - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, - "Dogecoin is downloading blocks..."); - - /* This should never fail, since the chain is already - past the point of merge-mining start. Check nevertheless. */ - { - LOCK(cs_main); - if (chainActive.Height() + 1 < Params().GetConsensus().nAuxpowStartHeight) - throw std::runtime_error("mining auxblock method is not yet available"); - } -} - -static -UniValue AuxMiningCreateBlock(const CScript& scriptPubKey) -{ - AuxMiningCheck(); - - LOCK(cs_auxblockCache); - - static unsigned nTransactionsUpdatedLast; - static const CBlockIndex* pindexPrev = nullptr; - static uint64_t nStart; - static CBlock* pblock = nullptr; - static unsigned nExtraNonce = 0; - - // Update block - { - LOCK(cs_main); - if (pindexPrev != chainActive.Tip() - || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast - && GetTime() - nStart > 60)) - { - if (pindexPrev != chainActive.Tip()) - { - // Clear old blocks since they're obsolete now. - mapNewBlock.clear(); - vNewBlockTemplate.clear(); - pblock = nullptr; - } - - // Create new block with nonce = 0 and extraNonce = 1 - std::unique_ptr<CBlockTemplate> newBlock - = BlockAssembler(Params()).CreateNewBlock(scriptPubKey); - if (!newBlock) - throw JSONRPCError(RPC_OUT_OF_MEMORY, "out of memory"); - - // Update state only when CreateNewBlock succeeded - nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - pindexPrev = chainActive.Tip(); - nStart = GetTime(); - - // Finalise it by setting the version and building the merkle root - IncrementExtraNonce(&newBlock->block, pindexPrev, nExtraNonce); - newBlock->block.SetAuxpowFlag(true); - - // Save - pblock = &newBlock->block; - mapNewBlock[pblock->GetHash()] = pblock; - vNewBlockTemplate.push_back(std::move(newBlock)); - } - } - - // At this point, pblock is always initialised: If we make it here - // without creating a new block above, it means that, in particular, - // pindexPrev == chainActive.Tip(). But for that to happen, we must - // already have created a pblock in a previous call, as pindexPrev is - // initialised only when pblock is. - assert(pblock); - - arith_uint256 target; - bool fNegative, fOverflow; - target.SetCompact(pblock->nBits, &fNegative, &fOverflow); - if (fNegative || fOverflow || target == 0) - throw std::runtime_error("invalid difficulty bits in block"); - - UniValue result(UniValue::VOBJ); - result.pushKV("hash", pblock->GetHash().GetHex()); - result.pushKV("chainid", pblock->GetChainId()); - result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); - result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue); - result.pushKV("bits", strprintf("%08x", pblock->nBits)); - result.pushKV("height", static_cast<int64_t> (pindexPrev->nHeight + 1)); - result.pushKV("_target", HexStr(BEGIN(target), END(target))); - - return result; -} - -static -bool AuxMiningSubmitBlock(const std::string& hashHex, - const std::string& auxpowHex) -{ - AuxMiningCheck(); - - LOCK(cs_auxblockCache); - - uint256 hash; - hash.SetHex(hashHex); - - const std::map<uint256, CBlock*>::iterator mit = mapNewBlock.find(hash); - if (mit == mapNewBlock.end()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "block hash unknown"); - CBlock& block = *mit->second; - - const std::vector<unsigned char> vchAuxPow = ParseHex(auxpowHex); - CDataStream ss(vchAuxPow, SER_GETHASH, PROTOCOL_VERSION); - CAuxPow pow; - ss >> pow; - block.SetAuxpow(new CAuxPow(pow)); - assert(block.GetHash() == hash); - - submitblock_StateCatcher sc(block.GetHash()); - RegisterValidationInterface(&sc); - std::shared_ptr<const CBlock> shared_block - = std::make_shared<const CBlock>(block); - bool fAccepted = ProcessNewBlock(Params(), shared_block, true, nullptr); - UnregisterValidationInterface(&sc); - - return fAccepted; -} - UniValue getauxblock(const JSONRPCRequest& request) { if (request.fHelp @@ -1114,75 +976,132 @@ UniValue getauxblock(const JSONRPCRequest& request) if (!coinbaseScript->reserveScript.size()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); - /* Create a new block */ + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + + if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0 && !Params().MineBlocksOnDemand()) + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Dogecoin is not connected!"); + + if (IsInitialBlockDownload() && !Params().MineBlocksOnDemand()) + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, + "Dogecoin is downloading blocks..."); + + /* This should never fail, since the chain is already + past the point of merge-mining start. Check nevertheless. */ + { + LOCK(cs_main); + if (chainActive.Height() + 1 < Params().GetConsensus().nAuxpowStartHeight) + throw std::runtime_error("getauxblock method is not yet available"); + } + + /* The variables below are used to keep track of created and not yet + submitted auxpow blocks. Lock them to be sure even for multiple + RPC threads running in parallel. */ + static CCriticalSection cs_auxblockCache; + LOCK(cs_auxblockCache); + static std::map<uint256, CBlock*> mapNewBlock; + static std::vector<std::unique_ptr<CBlockTemplate>> vNewBlockTemplate; + + /* Create a new block? */ if (request.params.size() == 0) - return AuxMiningCreateBlock(coinbaseScript->reserveScript); + { + static unsigned nTransactionsUpdatedLast; + static const CBlockIndex* pindexPrev = nullptr; + static uint64_t nStart; + static CBlock* pblock = nullptr; + static unsigned nExtraNonce = 0; + + // Update block + // Dogecoin: Never mine witness tx + const bool fMineWitnessTx = false; + { + LOCK(cs_main); + if (pindexPrev != chainActive.Tip() + || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast + && GetTime() - nStart > 60)) + { + if (pindexPrev != chainActive.Tip()) + { + // Clear old blocks since they're obsolete now. + mapNewBlock.clear(); + vNewBlockTemplate.clear(); + pblock = nullptr; + } + + // Create new block with nonce = 0 and extraNonce = 1 + std::unique_ptr<CBlockTemplate> newBlock(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript, fMineWitnessTx)); + if (!newBlock) + throw JSONRPCError(RPC_OUT_OF_MEMORY, "out of memory"); + + // Update state only when CreateNewBlock succeeded + nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); + pindexPrev = chainActive.Tip(); + nStart = GetTime(); + + // Finalise it by setting the version and building the merkle root + IncrementExtraNonce(&newBlock->block, pindexPrev, nExtraNonce); + newBlock->block.SetAuxpowFlag(true); + + // Save + pblock = &newBlock->block; + mapNewBlock[pblock->GetHash()] = pblock; + vNewBlockTemplate.push_back(std::move(newBlock)); + } + } + + arith_uint256 target; + bool fNegative, fOverflow; + target.SetCompact(pblock->nBits, &fNegative, &fOverflow); + if (fNegative || fOverflow || target == 0) + throw std::runtime_error("invalid difficulty bits in block"); + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", pblock->GetHash().GetHex())); + result.push_back(Pair("chainid", pblock->GetChainId())); + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); + result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue)); + result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); + result.push_back(Pair("height", static_cast<int64_t> (pindexPrev->nHeight + 1))); + result.push_back(Pair("_target", HexStr(BEGIN(target), END(target)))); + + return result; + } /* Submit a block instead. Note that this need not lock cs_main, since ProcessNewBlock below locks it instead. */ - assert(request.params.size() == 2); - bool fAccepted = AuxMiningSubmitBlock(request.params[0].get_str(), - request.params[1].get_str()); - if (fAccepted) - coinbaseScript->KeepScript(); - return fAccepted; -} + assert(request.params.size() == 2); + uint256 hash; + hash.SetHex(request.params[0].get_str()); -UniValue createauxblock(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - "createauxblock <address>\n" - "\ncreate a new block and return information required to merge-mine it.\n" - "\nArguments:\n" - "1. address (string, required) specify coinbase transaction payout address\n" - "\nResult:\n" - "{\n" - " \"hash\" (string) hash of the created block\n" - " \"chainid\" (numeric) chain ID for this block\n" - " \"previousblockhash\" (string) hash of the previous block\n" - " \"coinbasevalue\" (numeric) value of the block's coinbase\n" - " \"bits\" (string) compressed target of the block\n" - " \"height\" (numeric) height of the block\n" - " \"_target\" (string) target in reversed byte order, deprecated\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("createauxblock", "\"address\"") - + HelpExampleRpc("createauxblock", "\"address\"") - ); + const std::map<uint256, CBlock*>::iterator mit = mapNewBlock.find(hash); + if (mit == mapNewBlock.end()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "block hash unknown"); + CBlock& block = *mit->second; - // Check coinbase payout address - CBitcoinAddress coinbaseAddress(request.params[0].get_str()); - if (!coinbaseAddress.IsValid()) - throw JSONRPCError(RPC_INVALID_PARAMETER, - "Invalid coinbase payout address"); - const CScript scriptPubKey - = GetScriptForDestination(coinbaseAddress.Get()); + const std::vector<unsigned char> vchAuxPow + = ParseHex(request.params[1].get_str()); + CDataStream ss(vchAuxPow, SER_GETHASH, PROTOCOL_VERSION); + CAuxPow pow; + ss >> pow; + block.SetAuxpow(new CAuxPow(pow)); + assert(block.GetHash() == hash); - return AuxMiningCreateBlock(scriptPubKey); -} + submitblock_StateCatcher sc(block.GetHash()); + RegisterValidationInterface(&sc); + std::shared_ptr<const CBlock> shared_block + = std::make_shared<const CBlock>(block); + bool fAccepted = ProcessNewBlock(Params(), shared_block, true, nullptr); + UnregisterValidationInterface(&sc); -UniValue submitauxblock(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( - "submitauxblock <hash> <auxpow>\n" - "\nsubmit a solved auxpow for a previously block created by 'createauxblock'.\n" - "\nArguments:\n" - "1. hash (string, required) hash of the block to submit\n" - "2. auxpow (string, required) serialised auxpow found\n" - "\nResult:\n" - "xxxxx (boolean) whether the submitted block was correct\n" - "\nExamples:\n" - + HelpExampleCli("submitauxblock", "\"hash\" \"serialised auxpow\"") - + HelpExampleRpc("submitauxblock", "\"hash\" \"serialised auxpow\"") - ); + if (fAccepted) + coinbaseScript->KeepScript(); - return AuxMiningSubmitBlock(request.params[0].get_str(), - request.params[1].get_str()); + return fAccepted; } +/* ************************************************************************** */ + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- @@ -1192,8 +1111,6 @@ static const CRPCCommand commands[] = { "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} }, { "mining", "submitblock", &submitblock, true, {"hexdata","parameters"} }, { "mining", "getauxblock", &getauxblock, true, {"hash", "auxpow"} }, - { "mining", "createauxblock", &createauxblock, true, {"address"} }, - { "mining", "submitauxblock", &submitauxblock, true, {"hash", "auxpow"} }, { "generating", "generate", &generate, true, {"nblocks","maxtries"} }, { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} }, |