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 }