[lbry] blockchain: change the difficulty adjustment algorithm.
adjusted := target + (actual - target) / 8 max := target + (target / 2) min := target - (target / 8) if adjusted > max { adjusted = max } else if adj < min { adjusted = min } diffculty := lastDifficulty * adjusted / target
This commit is contained in:
parent
4bfd69e23d
commit
e63ede0311
2 changed files with 28 additions and 33 deletions
|
@ -1736,7 +1736,6 @@ func New(config *Config) (*BlockChain, error) {
|
||||||
params := config.ChainParams
|
params := config.ChainParams
|
||||||
targetTimespan := int64(params.TargetTimespan / time.Second)
|
targetTimespan := int64(params.TargetTimespan / time.Second)
|
||||||
targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second)
|
targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second)
|
||||||
adjustmentFactor := params.RetargetAdjustmentFactor
|
|
||||||
b := BlockChain{
|
b := BlockChain{
|
||||||
checkpoints: config.Checkpoints,
|
checkpoints: config.Checkpoints,
|
||||||
checkpointsByHeight: checkpointsByHeight,
|
checkpointsByHeight: checkpointsByHeight,
|
||||||
|
@ -1745,8 +1744,8 @@ func New(config *Config) (*BlockChain, error) {
|
||||||
timeSource: config.TimeSource,
|
timeSource: config.TimeSource,
|
||||||
sigCache: config.SigCache,
|
sigCache: config.SigCache,
|
||||||
indexManager: config.IndexManager,
|
indexManager: config.IndexManager,
|
||||||
minRetargetTimespan: targetTimespan / adjustmentFactor,
|
minRetargetTimespan: targetTimespan - (targetTimespan / 8),
|
||||||
maxRetargetTimespan: targetTimespan * adjustmentFactor,
|
maxRetargetTimespan: targetTimespan + (targetTimespan / 2),
|
||||||
blocksPerRetarget: int32(targetTimespan / targetTimePerBlock),
|
blocksPerRetarget: int32(targetTimespan / targetTimePerBlock),
|
||||||
index: newBlockIndex(config.DB, params),
|
index: newBlockIndex(config.DB, params),
|
||||||
hashCache: config.HashCache,
|
hashCache: config.HashCache,
|
||||||
|
|
|
@ -159,7 +159,6 @@ func CalcWork(bits uint32) *big.Int {
|
||||||
func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
||||||
// Convert types used in the calculations below.
|
// Convert types used in the calculations below.
|
||||||
durationVal := int64(duration / time.Second)
|
durationVal := int64(duration / time.Second)
|
||||||
adjustmentFactor := big.NewInt(b.chainParams.RetargetAdjustmentFactor)
|
|
||||||
|
|
||||||
// The test network rules allow minimum difficulty blocks after more
|
// The test network rules allow minimum difficulty blocks after more
|
||||||
// than twice the desired amount of time needed to generate a block has
|
// than twice the desired amount of time needed to generate a block has
|
||||||
|
@ -178,7 +177,8 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration)
|
||||||
// multiplied by the max adjustment factor.
|
// multiplied by the max adjustment factor.
|
||||||
newTarget := CompactToBig(bits)
|
newTarget := CompactToBig(bits)
|
||||||
for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 {
|
for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 {
|
||||||
newTarget.Mul(newTarget, adjustmentFactor)
|
adj := new(big.Int).Div(newTarget, big.NewInt(2))
|
||||||
|
newTarget.Add(newTarget, adj)
|
||||||
durationVal -= b.maxRetargetTimespan
|
durationVal -= b.maxRetargetTimespan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,47 +224,44 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
return b.chainParams.PowLimitBits, nil
|
return b.chainParams.PowLimitBits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the previous block's difficulty requirements if this block
|
// For networks that support it, allow special reduction of the
|
||||||
// is not at a difficulty retarget interval.
|
// required difficulty once too much time has elapsed without
|
||||||
if (lastNode.height+1)%b.blocksPerRetarget != 0 {
|
// mining a block.
|
||||||
// For networks that support it, allow special reduction of the
|
if b.chainParams.ReduceMinDifficulty {
|
||||||
// required difficulty once too much time has elapsed without
|
// Return minimum difficulty when more than the desired
|
||||||
// mining a block.
|
// amount of time has elapsed without mining a block.
|
||||||
if b.chainParams.ReduceMinDifficulty {
|
reductionTime := int64(b.chainParams.MinDiffReductionTime /
|
||||||
// Return minimum difficulty when more than the desired
|
time.Second)
|
||||||
// amount of time has elapsed without mining a block.
|
allowMinTime := lastNode.timestamp + reductionTime
|
||||||
reductionTime := int64(b.chainParams.MinDiffReductionTime /
|
if newBlockTime.Unix() > allowMinTime {
|
||||||
time.Second)
|
return b.chainParams.PowLimitBits, nil
|
||||||
allowMinTime := lastNode.timestamp + reductionTime
|
|
||||||
if newBlockTime.Unix() > allowMinTime {
|
|
||||||
return b.chainParams.PowLimitBits, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// The block was mined within the desired timeframe, so
|
|
||||||
// return the difficulty for the last block which did
|
|
||||||
// not have the special minimum difficulty rule applied.
|
|
||||||
return b.findPrevTestNetDifficulty(lastNode), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the main network (or any unrecognized networks), simply
|
// The block was mined within the desired timeframe, so
|
||||||
// return the previous block's difficulty requirements.
|
// return the difficulty for the last block which did
|
||||||
return lastNode.bits, nil
|
// not have the special minimum difficulty rule applied.
|
||||||
|
return b.findPrevTestNetDifficulty(lastNode), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the block node at the previous retarget (targetTimespan days
|
// Get the block node at the previous retarget (targetTimespan days
|
||||||
// worth of blocks).
|
// worth of blocks).
|
||||||
firstNode := lastNode.RelativeAncestor(b.blocksPerRetarget - 1)
|
firstNode := lastNode.RelativeAncestor(b.blocksPerRetarget)
|
||||||
|
if lastNode.height == 0 {
|
||||||
|
firstNode = lastNode
|
||||||
|
}
|
||||||
if firstNode == nil {
|
if firstNode == nil {
|
||||||
return 0, AssertError("unable to obtain previous retarget block")
|
return 0, AssertError("unable to obtain previous retarget block")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetTimeSpan := int64(b.chainParams.TargetTimespan / time.Second)
|
||||||
|
|
||||||
// Limit the amount of adjustment that can occur to the previous
|
// Limit the amount of adjustment that can occur to the previous
|
||||||
// difficulty.
|
// difficulty.
|
||||||
actualTimespan := lastNode.timestamp - firstNode.timestamp
|
actualTimespan := lastNode.timestamp - firstNode.timestamp
|
||||||
adjustedTimespan := actualTimespan
|
adjustedTimespan := targetTimeSpan + (actualTimespan-targetTimeSpan)/8
|
||||||
if actualTimespan < b.minRetargetTimespan {
|
if adjustedTimespan < b.minRetargetTimespan {
|
||||||
adjustedTimespan = b.minRetargetTimespan
|
adjustedTimespan = b.minRetargetTimespan
|
||||||
} else if actualTimespan > b.maxRetargetTimespan {
|
} else if adjustedTimespan > b.maxRetargetTimespan {
|
||||||
adjustedTimespan = b.maxRetargetTimespan
|
adjustedTimespan = b.maxRetargetTimespan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +272,6 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
// result.
|
// result.
|
||||||
oldTarget := CompactToBig(lastNode.bits)
|
oldTarget := CompactToBig(lastNode.bits)
|
||||||
newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan))
|
newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan))
|
||||||
targetTimeSpan := int64(b.chainParams.TargetTimespan / time.Second)
|
|
||||||
newTarget.Div(newTarget, big.NewInt(targetTimeSpan))
|
newTarget.Div(newTarget, big.NewInt(targetTimeSpan))
|
||||||
|
|
||||||
// Limit new value to the proof of work limit.
|
// Limit new value to the proof of work limit.
|
||||||
|
|
Loading…
Reference in a new issue