From 1ff115d7de994325ab496e37c6daef65f15ef8fe Mon Sep 17 00:00:00 2001 From: sairajzero Date: Sat, 19 Jun 2021 15:22:26 +0530 Subject: [PATCH] Max-Reorg-Depth --- src/chainparams.cpp | 6 ++++-- src/chainparams.h | 6 ++++++ src/consensus/validation.h | 2 ++ src/init.cpp | 2 ++ src/net_processing.cpp | 1 + src/validation.cpp | 8 ++++++++ 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 35139a011..c981085ae 100755 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -203,7 +203,9 @@ public: // (the tx=... number in the SetBestChain debug.log lines) 0.03 // * estimated number of transactions per second after that timestamp }; - + // Max-Reorg (51% attack prevention) + nMaxReorganizationDepth = 55; // 55 at 1 minute block timespan is +/- 55 minutes. + nMinReorganizationPeers = 3; } }; @@ -411,7 +413,7 @@ public: fDefaultConsistencyChecks = true; fRequireStandard = false; - fMineBlocksOnDemand = true; + fMineBlocksOnDemand = true; // checkpointData = (CCheckpointData) { // { diff --git a/src/chainparams.h b/src/chainparams.h index f4df46532..e0f2c4e73 100755 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -81,6 +81,9 @@ public: const CCheckpointData& Checkpoints() const { return checkpointData; } const ChainTxData& TxData() const { return chainTxData; } void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout); + // Max-Reorg (51% attack prevention) + int MaxReorganizationDepth() const { return nMaxReorganizationDepth; } + int MinReorganizationPeers() const { return nMinReorganizationPeers; } protected: CChainParams() {} @@ -99,6 +102,9 @@ protected: bool fMineBlocksOnDemand; CCheckpointData checkpointData; ChainTxData chainTxData; + // Max-Reorg (51% attack prevention) + int nMaxReorganizationDepth; + int nMinReorganizationPeers; }; /** diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 7577e09fb..80c9d274b 100755 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -22,6 +22,8 @@ static const unsigned char REJECT_NONSTANDARD = 0x40; // static const unsigned char REJECT_DUST = 0x41; // part of BIP 61 static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; static const unsigned char REJECT_CHECKPOINT = 0x43; +// Max-Reorg (51% attack prevention) +static const unsigned char REJECT_MAXREORGDEPTH = 0x44; /** Capture information about block/transaction validation */ class CValidationState { diff --git a/src/init.cpp b/src/init.cpp index f52086286..c9d7287c6 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -364,6 +364,8 @@ std::string HelpMessage(HelpMessageMode mode) if (showDebug) strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER)); strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file on startup")); + strUsage += HelpMessageOpt("-maxreorg=", strprintf(_("Set the Maximum reorg depth (default: %u)"), defaultChainParams->MaxReorganizationDepth())); //#51-Attk-prevention + strUsage += HelpMessageOpt("-minreorgpeers=", strprintf(_("Set the Minimum amount of peers required to not allow reorgs. Peers must be greater than. (default: %u)"), defaultChainParams->MinReorganizationPeers())); //#51-Attk-prevention strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=", strprintf(_("Keep the transaction memory pool below megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); strUsage += HelpMessageOpt("-mempoolexpiry=", strprintf(_("Do not keep transactions in the mempool longer than hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY)); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 53d6309a5..415a9bbd9 100755 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1009,6 +1009,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // best equivalent proof of work) than the best header chain we know about. send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) && + (chainActive.Height() - mi->second->nHeight < Params().MaxReorganizationDepth()) && //(51% attk prevention) (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, consensusParams) < nOneMonth); if (!send) { LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); diff --git a/src/validation.cpp b/src/validation.cpp index 5da8e7444..a8a0869bd 100755 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -42,6 +42,7 @@ #include "validationinterface.h" #include "versionbits.h" #include "warnings.h" +#include "net.h" #include #include @@ -2942,6 +2943,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta assert(pindexPrev != nullptr); const int nHeight = pindexPrev->nHeight + 1; + //If this is a reorg, check that it is not too deep (51% attack prevention) + int nMaxReorgDepth = gArgs.GetArg("-maxreorg", Params().MaxReorganizationDepth()); + int nMinReorgPeers = gArgs.GetArg("-minreorgpeers", Params().MinReorganizationPeers()); + bool fGreaterThanMaxReorg = chainActive.Height() - nHeight >= nMaxReorgDepth; + if (fGreaterThanMaxReorg && g_connman && (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) > nMinReorgPeers && !IsInitialBlockDownload()) + return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d), with connections (count %d), and (initial download %s)", __func__, nHeight, g_connman ? g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) : -1, IsInitialBlockDownload() ? "true" : "false"), REJECT_MAXREORGDEPTH, "bad-fork-prior-to-maxreorgdepth"); + // Check proof of work const Consensus::Params& consensusParams = params.GetConsensus(); if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))