difficulty.go raw

   1  package blockchain
   2  
   3  import (
   4  	"encoding/hex"
   5  	bits2 "github.com/p9c/p9/pkg/bits"
   6  	"github.com/p9c/p9/pkg/fork"
   7  	"math/big"
   8  	"strings"
   9  	"time"
  10  	
  11  	"github.com/p9c/p9/pkg/chainhash"
  12  )
  13  
  14  var (
  15  	// ScryptPowLimit is
  16  	ScryptPowLimit = scryptPowLimit
  17  	// ScryptPowLimitBits is
  18  	ScryptPowLimitBits = bits2.BigToCompact(&scryptPowLimit)
  19  	// bigOne is 1 represented as a big.Int. It is defined here to avoid the overhead of creating it multiple times.
  20  	bigOne = big.NewInt(1)
  21  	// oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid the overhead of creating it multiple times.
  22  	oneLsh256      = new(big.Int).Lsh(bigOne, 256)
  23  	scryptPowLimit = func() big.Int {
  24  		mplb, _ := hex.DecodeString(
  25  			"000000039fcaa04ac30b6384471f337748ef5c87c7aeffce5e51770ce6283137,",
  26  		)
  27  		return *big.NewInt(0).SetBytes(mplb) // AllOnes.Rsh(&AllOnes, 0)
  28  	}()
  29  )
  30  
  31  // CalcNextRequiredDifficulty calculates the required difficulty for the block after the end of the current best chain
  32  // based on the difficulty retarget rules. This function is safe for concurrent access.
  33  func (b *BlockChain) CalcNextRequiredDifficulty(algo string) (difficulty uint32, e error) {
  34  	b.ChainLock.Lock()
  35  	difficulty, e = b.CalcNextRequiredDifficultyFromNode(
  36  		b.BestChain.
  37  			Tip(), algo, false,
  38  	)
  39  	// F.Ln("CalcNextRequiredDifficulty", difficulty)
  40  	b.ChainLock.Unlock()
  41  	return
  42  }
  43  
  44  // calcEasiestDifficulty calculates the easiest possible difficulty that a block can have given starting difficulty bits
  45  // and a duration.
  46  //
  47  // It is mainly used to verify that claimed proof of work by a block is sane as compared to a known good checkpoint.
  48  func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
  49  	// Convert types used in the calculations below.
  50  	durationVal := int64(duration / time.Second)
  51  	adjustmentFactor := big.NewInt(b.params.RetargetAdjustmentFactor)
  52  	// Since easier difficulty equates to higher numbers, the easiest difficulty for a given duration is the largest
  53  	// value possible given the number of retargets for the duration and starting difficulty multiplied by the max
  54  	// adjustment factor.
  55  	newTarget := bits2.CompactToBig(bits)
  56  	for durationVal > 0 && newTarget.Cmp(b.params.PowLimit) < 0 {
  57  		newTarget.Mul(newTarget, adjustmentFactor)
  58  		durationVal -= b.maxRetargetTimespan
  59  	}
  60  	// Limit new value to the proof of work limit.
  61  	if newTarget.Cmp(b.params.PowLimit) > 0 {
  62  		newTarget.Set(b.params.PowLimit)
  63  	}
  64  	return bits2.BigToCompact(newTarget)
  65  }
  66  
  67  // CalcNextRequiredDifficultyFromNode calculates the required difficulty for the block after the passed previous block node
  68  // based on the difficulty retarget rules.
  69  //
  70  // This function differs from the exported CalcNextRequiredDifficulty in that the exported version uses the current best
  71  // chain as the previous block node while this function accepts any block node.
  72  func (b *BlockChain) CalcNextRequiredDifficultyFromNode(lastNode *BlockNode, algoname string, l bool,) (
  73  	newTargetBits uint32,
  74  	e error,
  75  ) {
  76  	nH := lastNode.height + 1
  77  	cF := fork.GetCurrent(nH)
  78  	newTargetBits = fork.GetMinBits(algoname, nH)
  79  	// Tracef("CalcNextRequiredDifficultyFromNode %08x", newTargetBits)
  80  	switch cF {
  81  	// Legacy difficulty adjustment
  82  	case 0:
  83  		// F.Ln("before hardfork")
  84  		return b.CalcNextRequiredDifficultyHalcyon(lastNode, algoname, l)
  85  	// Plan 9 from Crypto Space
  86  	case 1:
  87  		bits, ok := lastNode.Diffs.Load().(Diffs)
  88  		if bits == nil || !ok {
  89  			lastNode.Diffs.Store(make(Diffs))
  90  		}
  91  		version := fork.GetAlgoVer(algoname, lastNode.height+1)
  92  		if bits[version] == 0 {
  93  			bits, e = b.CalcNextRequiredDifficultyPlan9Controller(lastNode)
  94  			if e != nil {
  95  				E.Ln(e)
  96  				return
  97  			}
  98  			// D.Ln(bits, reflect.TypeOf(bits))
  99  			b.DifficultyBits.Store(bits)
 100  			// D.F("got difficulty %d %08x %+v", version, (*b.DifficultyBits)[version], *bits)
 101  		}
 102  		newTargetBits = bits[version]
 103  		return
 104  	}
 105  	return
 106  }
 107  
 108  // RightJustify takes a string and right justifies it by a width or crops it
 109  func RightJustify(s string, w int) string {
 110  	sw := len(s)
 111  	diff := w - sw
 112  	if diff > 0 {
 113  		s = strings.Repeat(" ", diff) + s
 114  	} else if diff < 0 {
 115  		s = s[:w]
 116  	}
 117  	return s
 118  }
 119  
 120  // CalcWork calculates a work value from difficulty bits.
 121  // Bitcoin increases the difficulty for generating a block by decreasing the
 122  // value which the generated hash must be less than.
 123  // This difficulty target is stored in each block header using a compact
 124  // representation as described in the documentation for CompactToBig.
 125  // The main chain is selected by choosing the chain that has the most proof
 126  // of work (highest difficulty).
 127  // Since a lower target difficulty value equates to higher actual difficulty,
 128  // the work value which will be accumulated must be the inverse of the
 129  // difficulty.  Also,
 130  // in order to avoid potential division by zero and really small floating
 131  // point numbers, the result adds 1 to the denominator and multiplies the
 132  // numerator by 2^256.
 133  func CalcWork(bits uint32, height int32, algover int32) *big.Int {
 134  	// Return a work value of zero if the passed difficulty bits represent a negative number. Note this should not
 135  	// happen in practice with valid blocks, but an invalid block could trigger it.
 136  	difficultyNum := bits2.CompactToBig(bits)
 137  	// To make the difficulty values correlate to number of hash operations, multiply this difficulty base by the
 138  	// nanoseconds/hash figures in the fork algorithms list
 139  	if difficultyNum.Sign() <= 0 {
 140  		return big.NewInt(0)
 141  	}
 142  	denominator := new(big.Int).Add(difficultyNum, bigOne)
 143  	r := new(big.Int).Div(oneLsh256, denominator)
 144  	return r
 145  }
 146  
 147  // HashToBig converts a chainhash.Hash into a big. Int that can be used to perform math comparisons.
 148  func HashToBig(hash *chainhash.Hash) *big.Int {
 149  	// A Hash is in little-endian, but the big package wants the bytes in big-endian, so reverse them.
 150  	buf := *hash
 151  	blen := len(buf)
 152  	for i := 0; i < blen/2; i++ {
 153  		buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]
 154  	}
 155  	// buf := hash.CloneBytes()
 156  	return new(big.Int).SetBytes(buf[:])
 157  }
 158