gitlab.com/SiaPrime/SiaPrime@v1.4.1/types/target.go (about) 1 package types 2 3 // target.go defines the target type and implements a few helper functions for 4 // manipulating the target type. 5 6 import ( 7 "errors" 8 "math/big" 9 10 "gitlab.com/SiaPrime/SiaPrime/build" 11 "gitlab.com/SiaPrime/SiaPrime/crypto" 12 ) 13 14 type ( 15 // A Target is a hash that a block's ID must be "less than" in order for 16 // the block to be considered valid. Miners vary the block's 'Nonce' field 17 // in order to brute-force such an ID. The inverse of a Target is called 18 // the "difficulty," because it is proportional to the amount of time 19 // required to brute-force the Target. 20 Target crypto.Hash 21 ) 22 23 var ( 24 // ErrNegativeTarget is an error when a negative value used when converting 25 // to target 26 ErrNegativeTarget = errors.New("negative value used when converting to target") 27 ) 28 29 // AddDifficulties returns the resulting target with the difficulty of 'x' and 30 // 'y' are added together. Note that the difficulty is the inverse of the 31 // target. The sum is defined by: 32 // sum(x, y) = 1/(1/x + 1/y) 33 func (x Target) AddDifficulties(y Target) (t Target) { 34 sumDifficulty := new(big.Rat).Add(x.Inverse(), y.Inverse()) 35 return RatToTarget(new(big.Rat).Inv(sumDifficulty)) 36 } 37 38 // Cmp compares the difficulties of two targets. Note that the difficulty is 39 // the inverse of the target. The results are as follows: 40 // -1 if x < y 41 // 0 if x == y 42 // +1 if x > y 43 func (x Target) Cmp(y Target) int { 44 return x.Int().Cmp(y.Int()) 45 } 46 47 // Difficulty returns the difficulty associated with a given target. 48 func (x Target) Difficulty() Currency { 49 if x == (Target{}) { 50 return NewCurrency(RootDepth.Int()) 51 } 52 return NewCurrency(new(big.Int).Div(RootDepth.Int(), x.Int())) 53 } 54 55 // Int converts a Target to a big.Int. 56 func (x Target) Int() *big.Int { 57 return new(big.Int).SetBytes(x[:]) 58 } 59 60 // IntToTarget converts a big.Int to a Target. Negative inputs trigger a panic. 61 func IntToTarget(i *big.Int) (t Target) { 62 // Check for negatives. 63 if i.Sign() < 0 { 64 if build.DEBUG { 65 panic(ErrNegativeTarget) 66 } 67 } else { 68 // In the event of overflow, return the maximum. 69 if i.BitLen() > 256 { 70 return RootDepth 71 } 72 b := i.Bytes() 73 offset := len(t[:]) - len(b) 74 copy(t[offset:], b) 75 } 76 return 77 } 78 79 // Inverse returns the inverse of a Target as a big.Rat 80 func (x Target) Inverse() *big.Rat { 81 return new(big.Rat).Inv(x.Rat()) 82 } 83 84 // MulDifficulty multiplies the difficulty of a target by y. The product is defined by: 85 // y / x 86 func (x Target) MulDifficulty(y *big.Rat) (t Target) { 87 product := new(big.Rat).Mul(y, x.Inverse()) 88 product = product.Inv(product) 89 return RatToTarget(product) 90 } 91 92 // Rat converts a Target to a big.Rat. 93 func (x Target) Rat() *big.Rat { 94 return new(big.Rat).SetInt(x.Int()) 95 } 96 97 // RatToTarget converts a big.Rat to a Target. 98 func RatToTarget(r *big.Rat) (t Target) { 99 if r.Num().Sign() < 0 { 100 if build.DEBUG { 101 panic(ErrNegativeTarget) 102 } 103 } else { 104 i := new(big.Int).Div(r.Num(), r.Denom()) 105 t = IntToTarget(i) 106 } 107 return 108 } 109 110 // SubtractDifficulties returns the resulting target with the difficulty of 'x' 111 // is subtracted from the target with difficulty 'y'. Note that the difficulty 112 // is the inverse of the target. The difference is defined by: 113 // sum(x, y) = 1/(1/x - 1/y) 114 func (x Target) SubtractDifficulties(y Target) (t Target) { 115 sumDifficulty := new(big.Rat).Sub(x.Inverse(), y.Inverse()) 116 return RatToTarget(new(big.Rat).Inv(sumDifficulty)) 117 }