github.com/NebulousLabs/Sia@v1.3.7/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 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  }