github.com/dominant-strategies/go-quai@v0.28.2/consensus/progpow/poem.go (about)

     1  package progpow
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"github.com/dominant-strategies/go-quai/common"
     7  	"github.com/dominant-strategies/go-quai/core/types"
     8  	"github.com/dominant-strategies/go-quai/params"
     9  	"modernc.org/mathutil"
    10  )
    11  
    12  // CalcOrder returns the order of the block within the hierarchy of chains
    13  func (progpow *Progpow) CalcOrder(header *types.Header) (*big.Int, int, error) {
    14  	if header.NumberU64() == 0 {
    15  		return big0, common.PRIME_CTX, nil
    16  	}
    17  
    18  	// Verify the seal and get the powHash for the given header
    19  	powHash, err := progpow.verifySeal(header)
    20  	if err != nil {
    21  		return big0, -1, err
    22  	}
    23  
    24  	// Get entropy reduction of this header
    25  	intrinsicS := progpow.IntrinsicLogS(powHash)
    26  	target := new(big.Int).Div(common.Big2e256, header.Difficulty())
    27  	zoneThresholdS := progpow.IntrinsicLogS(common.BytesToHash(target.Bytes()))
    28  
    29  	// PRIME
    30  	// PrimeEntropyThreshold number of zone blocks times the intrinsic logs of
    31  	// the given header determines the prime block
    32  	totalDeltaSPrime := new(big.Int).Add(header.ParentDeltaS(common.REGION_CTX), header.ParentDeltaS(common.ZONE_CTX))
    33  	totalDeltaSPrime = new(big.Int).Add(totalDeltaSPrime, intrinsicS)
    34  	primeDeltaSTarget := new(big.Int).Div(params.PrimeEntropyTarget, big2)
    35  	primeDeltaSTarget = new(big.Int).Mul(zoneThresholdS, primeDeltaSTarget)
    36  
    37  	primeBlockEntropyThreshold := new(big.Int).Add(zoneThresholdS, common.BitsToBigBits(params.PrimeEntropyTarget))
    38  	if intrinsicS.Cmp(primeBlockEntropyThreshold) > 0 && totalDeltaSPrime.Cmp(primeDeltaSTarget) > 0 {
    39  		return intrinsicS, common.PRIME_CTX, nil
    40  	}
    41  
    42  	// REGION
    43  	// Compute the total accumulated entropy since the last region block
    44  	totalDeltaSRegion := new(big.Int).Add(header.ParentDeltaS(common.ZONE_CTX), intrinsicS)
    45  	regionDeltaSTarget := new(big.Int).Div(params.RegionEntropyTarget, big2)
    46  	regionDeltaSTarget = new(big.Int).Mul(zoneThresholdS, regionDeltaSTarget)
    47  	regionBlockEntropyThreshold := new(big.Int).Add(zoneThresholdS, common.BitsToBigBits(params.RegionEntropyTarget))
    48  	if intrinsicS.Cmp(regionBlockEntropyThreshold) > 0 && totalDeltaSRegion.Cmp(regionDeltaSTarget) > 0 {
    49  		return intrinsicS, common.REGION_CTX, nil
    50  	}
    51  
    52  	// Zone case
    53  	return intrinsicS, common.ZONE_CTX, nil
    54  }
    55  
    56  // IntrinsicLogS returns the logarithm of the intrinsic entropy reduction of a PoW hash
    57  func (progpow *Progpow) IntrinsicLogS(powHash common.Hash) *big.Int {
    58  	x := new(big.Int).SetBytes(powHash.Bytes())
    59  	d := new(big.Int).Div(big2e256, x)
    60  	c, m := mathutil.BinaryLog(d, mantBits)
    61  	bigBits := new(big.Int).Mul(big.NewInt(int64(c)), new(big.Int).Exp(big.NewInt(2), big.NewInt(mantBits), nil))
    62  	bigBits = new(big.Int).Add(bigBits, m)
    63  	return bigBits
    64  }
    65  
    66  // TotalLogS() returns the total entropy reduction if the chain since genesis to the given header
    67  func (progpow *Progpow) TotalLogS(header *types.Header) *big.Int {
    68  	intrinsicS, order, err := progpow.CalcOrder(header)
    69  	if err != nil {
    70  		return big.NewInt(0)
    71  	}
    72  	switch order {
    73  	case common.PRIME_CTX:
    74  		totalS := new(big.Int).Add(header.ParentEntropy(common.PRIME_CTX), header.ParentDeltaS(common.REGION_CTX))
    75  		totalS.Add(totalS, header.ParentDeltaS(common.ZONE_CTX))
    76  		totalS.Add(totalS, intrinsicS)
    77  		return totalS
    78  	case common.REGION_CTX:
    79  		totalS := new(big.Int).Add(header.ParentEntropy(common.REGION_CTX), header.ParentDeltaS(common.ZONE_CTX))
    80  		totalS.Add(totalS, intrinsicS)
    81  		return totalS
    82  	case common.ZONE_CTX:
    83  		totalS := new(big.Int).Add(header.ParentEntropy(common.ZONE_CTX), intrinsicS)
    84  		return totalS
    85  	}
    86  	return big.NewInt(0)
    87  }
    88  
    89  func (progpow *Progpow) TotalLogPhS(header *types.Header) *big.Int {
    90  	switch common.NodeLocation.Context() {
    91  	case common.PRIME_CTX:
    92  		totalS := header.ParentEntropy(common.PRIME_CTX)
    93  		return totalS
    94  	case common.REGION_CTX:
    95  		totalS := new(big.Int).Add(header.ParentEntropy(common.PRIME_CTX), header.ParentDeltaS(common.REGION_CTX))
    96  		return totalS
    97  	case common.ZONE_CTX:
    98  		totalS := new(big.Int).Add(header.ParentEntropy(common.PRIME_CTX), header.ParentDeltaS(common.REGION_CTX))
    99  		totalS.Add(totalS, header.ParentDeltaS(common.ZONE_CTX))
   100  		return totalS
   101  	}
   102  	return big.NewInt(0)
   103  }
   104  
   105  func (progpow *Progpow) DeltaLogS(header *types.Header) *big.Int {
   106  	intrinsicS, order, err := progpow.CalcOrder(header)
   107  	if err != nil {
   108  		return big.NewInt(0)
   109  	}
   110  	switch order {
   111  	case common.PRIME_CTX:
   112  		return big.NewInt(0)
   113  	case common.REGION_CTX:
   114  		totalDeltaS := new(big.Int).Add(header.ParentDeltaS(common.REGION_CTX), header.ParentDeltaS(common.ZONE_CTX))
   115  		totalDeltaS = new(big.Int).Add(totalDeltaS, intrinsicS)
   116  		return totalDeltaS
   117  	case common.ZONE_CTX:
   118  		totalDeltaS := new(big.Int).Add(header.ParentDeltaS(common.ZONE_CTX), intrinsicS)
   119  		return totalDeltaS
   120  	}
   121  	return big.NewInt(0)
   122  }