From 7fd7f7bc5268329fd6b29afe0292554726e9971b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 26 Nov 2019 22:20:50 -0600 Subject: [PATCH] blockchain: Remove easiest diff checkpoint checks. These checks are no longer necessary since they applied to orphans and blockchain no longer handles orphans. Further, orphans are currently otherwise limited by the block manager and this is another step towards the overall effort to decouple the connection code from the download logic. Ultimately, the goal is to remove orphan handling altogether. Finally, it also has the added benefit of further minimizing the reliance on trusted known good checkpoints. --- blockchain/difficulty.go | 37 --------------------------------- blockchain/process.go | 45 +--------------------------------------- 2 files changed, 1 insertion(+), 81 deletions(-) diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index 71b7562953..1dfa38b21a 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -22,43 +22,6 @@ var ( bigZero = big.NewInt(0) ) -// calcEasiestDifficulty calculates the easiest possible difficulty that a block -// can have given starting difficulty bits and a duration. It is mainly used to -// verify that claimed proof of work by a block is sane as compared to a -// known good checkpoint. -func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 { - // Convert types used in the calculations below. - durationVal := int64(duration) - adjustmentFactor := big.NewInt(b.chainParams.RetargetAdjustmentFactor) - maxRetargetTimespan := int64(b.chainParams.TargetTimespan) * - b.chainParams.RetargetAdjustmentFactor - - // The test network rules allow minimum difficulty blocks once too much - // time has elapsed without mining a block. - if b.chainParams.ReduceMinDifficulty { - if durationVal > int64(b.chainParams.MinDiffReductionTime) { - return b.chainParams.PowLimitBits - } - } - - // Since easier difficulty equates to higher numbers, the easiest - // difficulty for a given duration is the largest value possible given - // the number of retargets for the duration and starting difficulty - // multiplied by the max adjustment factor. - newTarget := standalone.CompactToBig(bits) - for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 { - newTarget.Mul(newTarget, adjustmentFactor) - durationVal -= maxRetargetTimespan - } - - // Limit new value to the proof of work limit. - if newTarget.Cmp(b.chainParams.PowLimit) > 0 { - newTarget.Set(b.chainParams.PowLimit) - } - - return standalone.BigToCompact(newTarget) -} - // findPrevTestNetDifficulty returns the difficulty of the previous block which // did not have the special testnet minimum difficulty rule applied. // diff --git a/blockchain/process.go b/blockchain/process.go index 87e617b660..958838363b 100644 --- a/blockchain/process.go +++ b/blockchain/process.go @@ -9,7 +9,6 @@ import ( "fmt" "time" - "github.com/decred/dcrd/blockchain/standalone" "github.com/decred/dcrd/dcrutil/v3" ) @@ -51,8 +50,6 @@ func (b *BlockChain) ProcessBlock(block *dcrutil.Block, flags BehaviorFlags) (in b.chainLock.Lock() defer b.chainLock.Unlock() - fastAdd := flags&BFFastAdd == BFFastAdd - blockHash := block.Hash() log.Tracef("Processing block %v", blockHash) currentTime := time.Now() @@ -74,48 +71,8 @@ func (b *BlockChain) ProcessBlock(block *dcrutil.Block, flags BehaviorFlags) (in return 0, err } - // Find the previous checkpoint and perform some additional checks based - // on the checkpoint. This provides a few nice properties such as - // preventing old side chain blocks before the last checkpoint, - // rejecting easy to mine, but otherwise bogus, blocks that could be - // used to eat memory, and ensuring expected (versus claimed) proof of - // work requirements since the previous checkpoint are met. - blockHeader := &block.MsgBlock().Header - checkpointNode, err := b.findPreviousCheckpoint() - if err != nil { - return 0, err - } - if checkpointNode != nil { - // Ensure the block timestamp is after the checkpoint timestamp. - checkpointTime := time.Unix(checkpointNode.timestamp, 0) - if blockHeader.Timestamp.Before(checkpointTime) { - str := fmt.Sprintf("block %v has timestamp %v before "+ - "last checkpoint timestamp %v", blockHash, - blockHeader.Timestamp, checkpointTime) - return 0, ruleError(ErrCheckpointTimeTooOld, str) - } - - if !fastAdd { - // Even though the checks prior to now have already ensured the - // proof of work exceeds the claimed amount, the claimed amount - // is a field in the block header which could be forged. This - // check ensures the proof of work is at least the minimum - // expected based on elapsed time since the last checkpoint and - // maximum adjustment allowed by the retarget rules. - duration := blockHeader.Timestamp.Sub(checkpointTime) - requiredTarget := standalone.CompactToBig(b.calcEasiestDifficulty( - checkpointNode.bits, duration)) - currentTarget := standalone.CompactToBig(blockHeader.Bits) - if currentTarget.Cmp(requiredTarget) > 0 { - str := fmt.Sprintf("block target difficulty of %064x "+ - "is too low when compared to the previous "+ - "checkpoint", currentTarget) - return 0, ruleError(ErrDifficultyTooLow, str) - } - } - } - // This function should never be called with orphans or the genesis block. + blockHeader := &block.MsgBlock().Header prevHash := &blockHeader.PrevBlock if !b.index.HaveBlock(prevHash) { // The fork length of orphans is unknown since they, by definition, do