From 6a2b1cce6da438f9690c516cc6023799105c88fe Mon Sep 17 00:00:00 2001 From: MD Islam Date: Tue, 25 May 2021 18:23:36 -0400 Subject: [PATCH] Add functionality to generate auxpow blocks in regtest This roughly reverts the work done here that disabled auxpow generation in regtest: https://github.com/dogecoin/dogecoin/pull/1431/files\#diff-ccc24453c13307f815879738d3bf00eec351417537fbf10dde1468180cacd2f1R127-R137 This is a pretty severe functionality change since auxpow is critical to Dogecoin and wallet integrators need to be able to parse the extra data in auxpow blocks. For future wallet integrators: Dogecoin follows similar schemes as Namecoin for the merged mining support and the spec is here: https://en.bitcoin.it/wiki/Merged_mining_specification pr review: GetHash -> GetPoWHash --- .gitignore | 1 + src/rpc/client.cpp | 2 ++ src/rpc/mining.cpp | 65 ++++++++++++++++++++++++++++++------------ src/test/rpc_tests.cpp | 6 ++++ 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 3ad8af3b4..1437f65e5 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,4 @@ libbitcoinconsensus.pc contrib/devtools/split-debug.sh .idea/ +.vscode/* diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 0ad6c3ef2..9f0e0f1d2 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -34,8 +34,10 @@ static const CRPCConvertParam vRPCConvertParams[] = { "setmocktime", 0, "timestamp" }, { "generate", 0, "nblocks" }, { "generate", 1, "maxtries" }, + { "generate", 2, "auxpow" }, { "generatetoaddress", 0, "nblocks" }, { "generatetoaddress", 2, "maxtries" }, + { "generatetoaddress", 3, "auxpow" }, { "getnetworkhashps", 0, "nblocks" }, { "getnetworkhashps", 1, "height" }, { "sendtoaddress", 1, "amount" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index e0c6708d2..0637d6b33 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -97,7 +97,7 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1); } -UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) +UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript, int nMineAuxPow) { // Dogecoin: Never mine witness tx const bool fMineWitnessTx = false; @@ -124,22 +124,40 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG LOCK(cs_main); IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); } - // Dogecoin: Don't mine Aux blocks in regtest - //CAuxPow::initAuxPow(*pblock); - //CPureBlockHeader& miningHeader = pblock->auxpow->parentBlock; - while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus(nHeight))) { - ++pblock->nNonce; - --nMaxTries; + if (!nMineAuxPow) { + while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus(nHeight))) { + ++pblock->nNonce; + --nMaxTries; + } + } else { + CAuxPow::initAuxPow(*pblock); + CPureBlockHeader& miningHeader = pblock->auxpow->parentBlock; + while (nMaxTries > 0 && miningHeader.nNonce < nInnerLoopCount && !CheckProofOfWork(miningHeader.GetPoWHash(), pblock->nBits, Params().GetConsensus(nHeight))) { + ++miningHeader.nNonce; + --nMaxTries; + } } if (nMaxTries == 0) { break; } - if (pblock->nNonce == nInnerLoopCount) { - continue; + if (!nMineAuxPow) { + if (pblock->nNonce == nInnerLoopCount) { + continue; + } + } else { + CPureBlockHeader& miningHeader = pblock->auxpow->parentBlock; + if (miningHeader.nNonce == nInnerLoopCount) { + continue; + } } std::shared_ptr shared_pblock = std::make_shared(*pblock); if (!ProcessNewBlock(Params(), shared_pblock, true, NULL)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); + if (nMineAuxPow) { + continue; + } + else { + throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); + } ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -154,13 +172,14 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG UniValue generate(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw runtime_error( - "generate nblocks ( maxtries )\n" + "generate nblocks ( maxtries auxpow )\n" "\nMine up to nblocks blocks immediately (before the RPC call returns)\n" "\nArguments:\n" "1. nblocks (numeric, required) How many blocks are generated immediately.\n" "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n" + "3. auxpow (numeric, optional) If the block should include the auxpow header (default = 0).\n" "\nResult:\n" "[ blockhashes ] (array) hashes of blocks generated\n" "\nExamples:\n" @@ -173,6 +192,10 @@ UniValue generate(const JSONRPCRequest& request) if (request.params.size() > 1) { nMaxTries = request.params[1].get_int(); } + int nMineAuxPow = 0; + if (request.params.size() > 2) { + nMineAuxPow = request.params[2].get_int(); + } boost::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); @@ -185,19 +208,21 @@ UniValue generate(const JSONRPCRequest& request) if (coinbaseScript->reserveScript.empty()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); - return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true); + return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true, nMineAuxPow); } + UniValue generatetoaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) throw runtime_error( - "generatetoaddress nblocks address (maxtries)\n" + "generatetoaddress nblocks address (maxtries auxpow)\n" "\nMine blocks immediately to a specified address (before the RPC call returns)\n" "\nArguments:\n" "1. nblocks (numeric, required) How many blocks are generated immediately.\n" "2. address (string, required) The address to send the newly generated dogecoin to.\n" "3. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n" + "4. auxpow (numeric, optional) If the block should include the auxpow header (default = 0).\n" "\nResult:\n" "[ blockhashes ] (array) hashes of blocks generated\n" "\nExamples:\n" @@ -210,6 +235,10 @@ UniValue generatetoaddress(const JSONRPCRequest& request) if (request.params.size() > 2) { nMaxTries = request.params[2].get_int(); } + int nMineAuxPow = 0; + if (request.params.size() > 3) { + nMineAuxPow = request.params[3].get_int(); + } CBitcoinAddress address(request.params[1].get_str()); if (!address.IsValid()) @@ -218,7 +247,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request) boost::shared_ptr coinbaseScript(new CReserveScript()); coinbaseScript->reserveScript = GetScriptForDestination(address.Get()); - return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); + return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false, nMineAuxPow); } UniValue getmininginfo(const JSONRPCRequest& request) @@ -1127,8 +1156,8 @@ static const CRPCCommand commands[] = { "mining", "submitblock", &submitblock, true, {"hexdata","parameters"} }, { "mining", "getauxblock", &getauxblock, true, {"hash", "auxpow"} }, - { "generating", "generate", &generate, true, {"nblocks","maxtries"} }, - { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} }, + { "generating", "generate", &generate, true, {"nblocks","maxtries","auxpow"} }, + { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries","auxpow"} }, { "util", "estimatefee", &estimatefee, true, {"nblocks"} }, { "util", "estimatepriority", &estimatepriority, true, {"nblocks"} }, diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 8539a9a52..5c7b5b0fe 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -341,6 +341,12 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); + + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9")("1"))); + BOOST_CHECK_EQUAL(result[0].get_int(), 1); + BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); + BOOST_CHECK_EQUAL(result[2].get_int(), 9); + BOOST_CHECK_EQUAL(result[3].get_int(), 1); } BOOST_AUTO_TEST_SUITE_END()