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:
commit
d1062e32fa
35
src/main.cpp
35
src/main.cpp
@ -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
|
||||||
|
15
src/main.h
15
src/main.h
@ -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 };
|
||||||
|
@ -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:
|
||||||
|
48
src/pow.cpp
48
src/pow.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user