github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/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 "github.com/NebulousLabs/Sia/build" 11 "github.com/NebulousLabs/Sia/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 = errors.New("negative value used when converting to target") 25 ) 26 27 // AddDifficulties returns the resulting target with the difficulty of 'x' and 28 // 'y' are added together. Note that the difficulty is the inverse of the 29 // target. The sum is defined by: 30 // sum(x, y) = 1/(1/x + 1/y) 31 func (x Target) AddDifficulties(y Target) (t Target) { 32 sumDifficulty := new(big.Rat).Add(x.Inverse(), y.Inverse()) 33 return RatToTarget(new(big.Rat).Inv(sumDifficulty)) 34 } 35 36 // Cmp compares the difficulties of two targets. Note that the difficulty is 37 // the inverse of the target. The results are as follows: 38 // -1 if x < y 39 // 0 if x == y 40 // +1 if x > y 41 func (x Target) Cmp(y Target) int { 42 return x.Int().Cmp(y.Int()) 43 } 44 45 // Difficulty returns the difficulty associated with a given target. 46 func (t Target) Difficulty() Currency { 47 if t == (Target{}) { 48 return NewCurrency(RootDepth.Int()) 49 } 50 return NewCurrency(new(big.Int).Div(RootDepth.Int(), t.Int())) 51 } 52 53 // Int converts a Target to a big.Int. 54 func (t Target) Int() *big.Int { 55 return new(big.Int).SetBytes(t[:]) 56 } 57 58 // IntToTarget converts a big.Int to a Target. Negative inputs trigger a panic. 59 func IntToTarget(i *big.Int) (t Target) { 60 // Check for negatives. 61 if i.Sign() < 0 { 62 if build.DEBUG { 63 panic(ErrNegativeTarget) 64 } 65 } else { 66 // In the event of overflow, return the maximum. 67 if i.BitLen() > 256 { 68 return RootDepth 69 } 70 b := i.Bytes() 71 offset := len(t[:]) - len(b) 72 copy(t[offset:], b) 73 } 74 return 75 } 76 77 // Inverse returns the inverse of a Target as a big.Rat 78 func (t Target) Inverse() *big.Rat { 79 return new(big.Rat).Inv(t.Rat()) 80 } 81 82 // Mul multiplies the difficulty of a target by y. The product is defined by: 83 // y / x 84 func (x Target) MulDifficulty(y *big.Rat) (t Target) { 85 product := new(big.Rat).Mul(y, x.Inverse()) 86 product = product.Inv(product) 87 return RatToTarget(product) 88 } 89 90 // Rat converts a Target to a big.Rat. 91 func (t Target) Rat() *big.Rat { 92 return new(big.Rat).SetInt(t.Int()) 93 } 94 95 // RatToTarget converts a big.Rat to a Target. 96 func RatToTarget(r *big.Rat) (t Target) { 97 if r.Num().Sign() < 0 { 98 if build.DEBUG { 99 panic(ErrNegativeTarget) 100 } 101 } else { 102 i := new(big.Int).Div(r.Num(), r.Denom()) 103 t = IntToTarget(i) 104 } 105 return 106 } 107 108 // SubtractDifficulties returns the resulting target with the difficulty of 'x' 109 // is subtracted from the target with difficulty 'y'. Note that the difficulty 110 // is the inverse of the target. The difference is defined by: 111 // sum(x, y) = 1/(1/x - 1/y) 112 func (x Target) SubtractDifficulties(y Target) (t Target) { 113 sumDifficulty := new(big.Rat).Sub(x.Inverse(), y.Inverse()) 114 return RatToTarget(new(big.Rat).Inv(sumDifficulty)) 115 }