Merge pull request #4377

654871d replace ComputeMinWork with CheckMinWork (jtimon)
b343c1a Move CBlockIndex::GetBlockWork() to pow::GetProofIncrement(nBits) (jtimon)
c2c02f3 Move UpdateTime to pow (jtimon)
This commit is contained in:
Pieter Wuille 2014-08-27 22:35:14 +02:00
commit d1062e32fa
No known key found for this signature in database
GPG Key ID: 8F653255C87992E0
7 changed files with 53 additions and 65 deletions

View File

@ -1420,25 +1420,6 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
} }
} }
void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
{
block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
// Updating time can change work required on testnet:
if (Params().AllowMinDifficultyBlocks())
block.nBits = GetNextWorkRequired(pindexPrev, &block);
}
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight) void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
{ {
bool ret; bool ret;
@ -2435,12 +2416,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
REJECT_CHECKPOINT, "time-too-old"); REJECT_CHECKPOINT, "time-too-old");
} }
bool fOverflow = false; if (!CheckMinWork(block.nBits, pcheckpoint->nBits, deltaTime))
uint256 bnNewBlock;
bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow);
uint256 bnRequired;
bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
if (fOverflow || bnNewBlock > bnRequired)
{ {
return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
REJECT_INVALID, "bad-diffbits"); REJECT_INVALID, "bad-diffbits");
@ -3297,15 +3273,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
return nLoaded > 0; return nLoaded > 0;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// CAlert // CAlert

View File

@ -14,6 +14,7 @@
#include "coins.h" #include "coins.h"
#include "core.h" #include "core.h"
#include "net.h" #include "net.h"
#include "pow.h"
#include "script.h" #include "script.h"
#include "sync.h" #include "sync.h"
#include "txmempool.h" #include "txmempool.h"
@ -163,8 +164,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b
bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL); bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL);
int64_t GetBlockValue(int nHeight, int64_t nFees); int64_t GetBlockValue(int nHeight, int64_t nFees);
void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
/** Create a new block index entry for a given block hash */ /** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash); CBlockIndex * InsertBlockIndex(uint256 hash);
/** Verify a signature */ /** Verify a signature */
@ -736,17 +735,7 @@ public:
uint256 GetBlockWork() const uint256 GetBlockWork() const
{ {
uint256 bnTarget; return GetProofIncrement(nBits);
bool fNegative;
bool fOverflow;
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
if (fNegative || fOverflow || bnTarget == 0)
return 0;
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
// as it's too large for a uint256. However, as 2**256 is at least as large
// as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
// or ~bnTarget / (nTarget+1) + 1.
return (~bnTarget / (bnTarget + 1)) + 1;
} }
enum { nMedianTimeSpan=11 }; enum { nMedianTimeSpan=11 };

View File

@ -307,7 +307,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// Fill in header // Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(*pblock, pindexPrev); UpdateTime(pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0; pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
@ -540,7 +540,7 @@ void static BitcoinMiner(CWallet *pwallet)
break; break;
// Update nTime every few seconds // Update nTime every few seconds
UpdateTime(*pblock, pindexPrev); UpdateTime(pblock, pindexPrev);
if (Params().AllowMinDifficultyBlocks()) if (Params().AllowMinDifficultyBlocks())
{ {
// Changing pblock->nTime can change work required on testnet: // Changing pblock->nTime can change work required on testnet:

View File

@ -8,6 +8,7 @@
#include "chainparams.h" #include "chainparams.h"
#include "core.h" #include "core.h"
#include "main.h" #include "main.h"
#include "timedata.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
@ -94,27 +95,58 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
} }
// //
// minimum amount of work that could possibly be required nTime after // true if nBits is greater than the minimum amount of work that could
// minimum work required was nBase // possibly be required deltaTime after minimum work required was nBase
// //
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) bool CheckMinWork(unsigned int nBits, unsigned int nBase, int64_t deltaTime)
{ {
bool fOverflow = false;
uint256 bnNewBlock;
bnNewBlock.SetCompact(nBits, NULL, &fOverflow);
if (fOverflow)
return false;
const uint256 &bnLimit = Params().ProofOfWorkLimit(); const uint256 &bnLimit = Params().ProofOfWorkLimit();
// Testnet has min-difficulty blocks // Testnet has min-difficulty blocks
// after Params().TargetSpacing()*2 time between blocks: // after Params().TargetSpacing()*2 time between blocks:
if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2) if (Params().AllowMinDifficultyBlocks() && deltaTime > Params().TargetSpacing()*2)
return bnLimit.GetCompact(); return bnNewBlock <= bnLimit;
uint256 bnResult; uint256 bnResult;
bnResult.SetCompact(nBase); bnResult.SetCompact(nBase);
while (nTime > 0 && bnResult < bnLimit) while (deltaTime > 0 && bnResult < bnLimit)
{ {
// Maximum 400% adjustment... // Maximum 400% adjustment...
bnResult *= 4; bnResult *= 4;
// ... in best-case exactly 4-times-normal target time // ... in best-case exactly 4-times-normal target time
nTime -= Params().TargetTimespan()*4; deltaTime -= Params().TargetTimespan()*4;
} }
if (bnResult > bnLimit) if (bnResult > bnLimit)
bnResult = bnLimit; bnResult = bnLimit;
return bnResult.GetCompact();
return bnNewBlock <= bnResult;
}
void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev)
{
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
// Updating time can change work required on testnet:
if (Params().AllowMinDifficultyBlocks())
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
}
uint256 GetProofIncrement(unsigned int nBits)
{
uint256 bnTarget;
bool fNegative;
bool fOverflow;
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
if (fNegative || fOverflow || bnTarget == 0)
return 0;
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
// as it's too large for a uint256. However, as 2**256 is at least as large
// as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
// or ~bnTarget / (nTarget+1) + 1.
return (~bnTarget / (bnTarget + 1)) + 1;
} }

View File

@ -17,7 +17,11 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool CheckProofOfWork(uint256 hash, unsigned int nBits);
/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ /** Check the work is more than the minimum a received block needs, without knowing its direct parent */
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); bool CheckMinWork(unsigned int nBits, unsigned int nBase, int64_t deltaTime);
void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev);
uint256 GetProofIncrement(unsigned int nBits);
#endif #endif

View File

@ -458,7 +458,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime // Update nTime
UpdateTime(*pblock, pindexPrev); UpdateTime(pblock, pindexPrev);
pblock->nNonce = 0; pblock->nNonce = 0;
Array transactions; Array transactions;

View File

@ -107,11 +107,7 @@ static bool CheckNBits(unsigned int nbits1, int64_t time1, unsigned int nbits2,
return CheckNBits(nbits2, time2, nbits1, time1); return CheckNBits(nbits2, time2, nbits1, time1);
int64_t deltaTime = time2-time1; int64_t deltaTime = time2-time1;
uint256 required; return CheckMinWork(nbits2, nbits1, deltaTime);
required.SetCompact(ComputeMinWork(nbits1, deltaTime));
uint256 have;
have.SetCompact(nbits2);
return (have <= required);
} }
BOOST_AUTO_TEST_CASE(DoS_checknbits) BOOST_AUTO_TEST_CASE(DoS_checknbits)