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