mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00

* [NOD-1006] Make CompactToBig take an out param so that we can reuse the same big.Int in averageTarget. * [NOD-1006] Fix merge errors. * [NOD-1006] Use CompactToBigWithDestination only in averageTarget. * [NOD-1006] Fix refactor errors. * [NOD-1006] Fix refactor errors. * [NOD-1006] Optimize averageTarget with a big.Int pool. * [NOD-1006] Defer releasing bigInts. * [NOD-1006] Use a pool for requiredDifficulty as well. * [NOD-1006] Move the big int pool to utils. * [NOD-1006] Remove unnecessary line.
62 lines
2.4 KiB
Go
62 lines
2.4 KiB
Go
// Copyright (c) 2013-2017 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package blockdag
|
|
|
|
import (
|
|
"github.com/kaspanet/kaspad/util/bigintpool"
|
|
"time"
|
|
|
|
"github.com/kaspanet/kaspad/util"
|
|
)
|
|
|
|
// requiredDifficulty calculates the required difficulty for a
|
|
// block given its bluest parent.
|
|
func (dag *BlockDAG) requiredDifficulty(bluestParent *blockNode, newBlockTime time.Time) uint32 {
|
|
// Genesis block.
|
|
if bluestParent == nil || bluestParent.blueScore < dag.difficultyAdjustmentWindowSize+1 {
|
|
return dag.powMaxBits
|
|
}
|
|
|
|
// Fetch window of dag.difficultyAdjustmentWindowSize + 1 so we can have dag.difficultyAdjustmentWindowSize block intervals
|
|
timestampsWindow := blueBlockWindow(bluestParent, dag.difficultyAdjustmentWindowSize+1)
|
|
windowMinTimestamp, windowMaxTimeStamp := timestampsWindow.minMaxTimestamps()
|
|
|
|
// Remove the last block from the window so to calculate the average target of dag.difficultyAdjustmentWindowSize blocks
|
|
targetsWindow := timestampsWindow[:dag.difficultyAdjustmentWindowSize]
|
|
|
|
// Calculate new target difficulty as:
|
|
// averageWindowTarget * (windowMinTimestamp / (targetTimePerBlock * windowSize))
|
|
// The result uses integer division which means it will be slightly
|
|
// rounded down.
|
|
newTarget := bigintpool.Acquire(0)
|
|
defer bigintpool.Release(newTarget)
|
|
windowTimeStampDifference := bigintpool.Acquire(windowMaxTimeStamp - windowMinTimestamp)
|
|
defer bigintpool.Release(windowTimeStampDifference)
|
|
targetTimePerBlock := bigintpool.Acquire(dag.targetTimePerBlock)
|
|
defer bigintpool.Release(targetTimePerBlock)
|
|
difficultyAdjustmentWindowSize := bigintpool.Acquire(int64(dag.difficultyAdjustmentWindowSize))
|
|
defer bigintpool.Release(difficultyAdjustmentWindowSize)
|
|
|
|
targetsWindow.averageTarget(newTarget)
|
|
newTarget.
|
|
Mul(newTarget, windowTimeStampDifference).
|
|
Div(newTarget, targetTimePerBlock).
|
|
Div(newTarget, difficultyAdjustmentWindowSize)
|
|
if newTarget.Cmp(dag.dagParams.PowMax) > 0 {
|
|
return dag.powMaxBits
|
|
}
|
|
newTargetBits := util.BigToCompact(newTarget)
|
|
return newTargetBits
|
|
}
|
|
|
|
// NextRequiredDifficulty calculates the required difficulty for a block that will
|
|
// be built on top of the current tips.
|
|
//
|
|
// This function is safe for concurrent access.
|
|
func (dag *BlockDAG) NextRequiredDifficulty(timestamp time.Time) uint32 {
|
|
difficulty := dag.requiredDifficulty(dag.virtual.parents.bluest(), timestamp)
|
|
return difficulty
|
|
}
|