diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2011-09-08 12:51:43 -0400 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2011-12-01 23:20:32 -0500 |
commit | 5d901f1ba0b2f4444e484b9cb3db8d86c428af3f (patch) | |
tree | 4e4a49112ebe6ba6f2cfcc8442de1e410a13732a /src/main.cpp | |
parent | 0e6425da4a29d6944e7edce85535725e1f963e2c (diff) | |
download | bitcoin-5d901f1ba0b2f4444e484b9cb3db8d86c428af3f.tar.xz |
Orphan block fill-up-memory attack prevention
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src/main.cpp b/src/main.cpp index dad7d144e7..af00069d66 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -651,11 +651,32 @@ int64 static GetBlockValue(int nHeight, int64 nFees) return nSubsidy + nFees; } +static const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks +static const int64 nTargetSpacing = 10 * 60; +static const int64 nInterval = nTargetTimespan / nTargetSpacing; + +// +// minimum amount of work that could possibly be required nTime after +// minimum work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) +{ + CBigNum bnResult; + bnResult.SetCompact(nBase); + while (nTime > 0 && bnResult < bnProofOfWorkLimit) + { + // Maximum 400% adjustment... + bnResult *= 4; + // ... in best-case exactly 4-times-normal target time + nTime -= nTargetTimespan*4; + } + if (bnResult > bnProofOfWorkLimit) + bnResult = bnProofOfWorkLimit; + return bnResult.GetCompact(); +} + unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast) { - const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks - const int64 nTargetSpacing = 10 * 60; - const int64 nInterval = nTargetTimespan / nTargetSpacing; // Genesis block if (pindexLast == NULL) @@ -1317,6 +1338,26 @@ bool static ProcessBlock(CNode* pfrom, CBlock* pblock) if (!pblock->CheckBlock()) return error("ProcessBlock() : CheckBlock FAILED"); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + if (pcheckpoint && pblock->hashPrevBlock != hashBestChain) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime; + if (deltaTime < 0) + { + return error("ProcessBlock() : block with timestamp before last checkpoint"); + } + CBigNum bnNewBlock; + bnNewBlock.SetCompact(pblock->nBits); + CBigNum bnRequired; + bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); + if (bnNewBlock > bnRequired) + { + return error("ProcessBlock() : block with too little proof-of-work"); + } + } + + // If don't already have its previous block, shunt it off to holding area until we get it if (!mapBlockIndex.count(pblock->hashPrevBlock)) { |