aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/auxpow_miner.cpp
diff options
context:
space:
mode:
authorMax K <[email protected]>2019-07-14 19:35:30 +0200
committerGitHub <[email protected]>2019-07-14 19:35:30 +0200
commitcee13699a5676355487f8eb2d91985f63438eae4 (patch)
treecf12be6180f950a25ee2ee7f3f2126542835d6e3 /src/rpc/auxpow_miner.cpp
parentCorrect build and test net seed (diff)
parentHandle legacy v2 block at #66064 (diff)
downloaddiscoin-1.17-dev.tar.xz
discoin-1.17-dev.zip
Merge pull request #1546 from rnicoll/1.17-auxpow1.17-dev
1.17 AuxPoW support
Diffstat (limited to 'src/rpc/auxpow_miner.cpp')
-rw-r--r--src/rpc/auxpow_miner.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/rpc/auxpow_miner.cpp b/src/rpc/auxpow_miner.cpp
new file mode 100644
index 000000000..3d6e93bac
--- /dev/null
+++ b/src/rpc/auxpow_miner.cpp
@@ -0,0 +1,165 @@
+// Copyright (c) 2018 Daniel Kraft
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <rpc/auxpow_miner.h>
+
+#include <arith_uint256.h>
+#include <auxpow.h>
+#include <chainparams.h>
+#include <net.h>
+#include <rpc/protocol.h>
+#include <utilstrencodings.h>
+#include <utiltime.h>
+#include <validation.h>
+
+#include <cassert>
+
+namespace
+{
+
+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);
+ const auto auxpowStart = Params ().GetConsensus ().nAuxpowStartHeight;
+ if (chainActive.Height () + 1 < auxpowStart)
+ throw std::runtime_error ("mining auxblock method is not yet available");
+ }
+}
+
+} // anonymous namespace
+
+const CBlock*
+AuxpowMiner::getCurrentBlock (const CScript& scriptPubKey, uint256& target)
+{
+ AssertLockHeld (cs);
+
+ {
+ LOCK (cs_main);
+ if (pindexPrev != chainActive.Tip ()
+ || (mempool.GetTransactionsUpdated () != txUpdatedLast
+ && GetTime () - startTime > 60))
+ {
+ if (pindexPrev != chainActive.Tip ())
+ {
+ /* Clear old blocks since they're obsolete now. */
+ blocks.clear ();
+ templates.clear ();
+ pblockCur = nullptr;
+ }
+
+ /* Create new block with nonce = 0 and extraNonce = 1. */
+ std::unique_ptr<CBlockTemplate> newBlock
+ = BlockAssembler (Params ()).CreateNewBlock (scriptPubKey);
+ if (newBlock == nullptr)
+ throw JSONRPCError (RPC_OUT_OF_MEMORY, "out of memory");
+
+ /* Update state only when CreateNewBlock succeeded. */
+ txUpdatedLast = mempool.GetTransactionsUpdated ();
+ pindexPrev = chainActive.Tip ();
+ startTime = GetTime ();
+
+ /* Finalise it by setting the version and building the merkle root. */
+ IncrementExtraNonce (&newBlock->block, pindexPrev, extraNonce);
+ newBlock->block.SetAuxpowFlag (true);
+
+ /* Save in our map of constructed blocks. */
+ pblockCur = &newBlock->block;
+ blocks[pblockCur->GetHash ()] = pblockCur;
+ templates.push_back (std::move (newBlock));
+ }
+ }
+
+ /* At this point, pblockCur 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 pblockCur in a previous call, as pindexPrev is
+ initialised only when pblockCur is. */
+ assert (pblockCur);
+
+ arith_uint256 arithTarget;
+ bool fNegative, fOverflow;
+ arithTarget.SetCompact (pblockCur->nBits, &fNegative, &fOverflow);
+ if (fNegative || fOverflow || arithTarget == 0)
+ throw std::runtime_error ("invalid difficulty bits in block");
+ target = ArithToUint256 (arithTarget);
+
+ return pblockCur;
+}
+
+const CBlock*
+AuxpowMiner::lookupSavedBlock (const std::string& hashHex) const
+{
+ AssertLockHeld (cs);
+
+ uint256 hash;
+ hash.SetHex (hashHex);
+
+ const auto iter = blocks.find (hash);
+ if (iter == blocks.end ())
+ throw JSONRPCError (RPC_INVALID_PARAMETER, "block hash unknown");
+
+ return iter->second;
+}
+
+UniValue
+AuxpowMiner::createAuxBlock (const CScript& scriptPubKey)
+{
+ auxMiningCheck ();
+ LOCK (cs);
+
+ uint256 target;
+ const CBlock* pblock = getCurrentBlock (scriptPubKey, target);
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV ("hash", pblock->GetHash ().GetHex ());
+ result.pushKV ("chainid", pblock->GetChainId ());
+ result.pushKV ("previousblockhash", pblock->hashPrevBlock.GetHex ());
+ result.pushKV ("coinbasevalue",
+ static_cast<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;
+}
+
+bool
+AuxpowMiner::submitAuxBlock (const std::string& hashHex,
+ const std::string& auxpowHex) const
+{
+ auxMiningCheck ();
+
+ std::shared_ptr<CBlock> shared_block;
+ {
+ LOCK (cs);
+ const CBlock* pblock = lookupSavedBlock (hashHex);
+ shared_block = std::make_shared<CBlock> (*pblock);
+ }
+
+ const std::vector<unsigned char> vchAuxPow = ParseHex (auxpowHex);
+ CDataStream ss(vchAuxPow, SER_GETHASH, PROTOCOL_VERSION);
+ std::unique_ptr<CAuxPow> pow(new CAuxPow ());
+ ss >> *pow;
+ shared_block->SetAuxpow (std::move (pow));
+ assert (shared_block->GetHash ().GetHex () == hashHex);
+
+ return ProcessNewBlock (Params (), shared_block, true, nullptr);
+}