aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2011-09-08 12:51:43 -0400
committerLuke Dashjr <luke-jr+git@utopios.org>2011-12-01 23:20:32 -0500
commit5d901f1ba0b2f4444e484b9cb3db8d86c428af3f (patch)
tree4e4a49112ebe6ba6f2cfcc8442de1e410a13732a /src/main.cpp
parent0e6425da4a29d6944e7edce85535725e1f963e2c (diff)
downloadbitcoin-5d901f1ba0b2f4444e484b9cb3db8d86c428af3f.tar.xz
Orphan block fill-up-memory attack prevention
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp47
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))
{