6 "github.com/vapor/consensus"
7 "github.com/vapor/mining/tensority"
8 "github.com/vapor/protocol/bc"
9 "github.com/vapor/protocol/bc/types"
13 // bigOne is 1 represented as a big.Int. It is defined here to avoid
14 // the overhead of creating it multiple times.
15 bigOne = big.NewInt(1)
17 // oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid
18 // the overhead of creating it multiple times.
19 oneLsh256 = new(big.Int).Lsh(bigOne, 256)
22 // HashToBig convert bc.Hash to a difficulty int
23 func HashToBig(hash *bc.Hash) *big.Int {
24 // reverse the bytes of the hash (little-endian) to use it in the big
25 // package (big-endian)
28 for i := 0; i < blen/2; i++ {
29 buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]
32 return new(big.Int).SetBytes(buf[:])
35 // CalcWork calculates a work value from difficulty bits.
36 func CalcWork(bits uint64) *big.Int {
37 difficultyNum := CompactToBig(bits)
38 if difficultyNum.Sign() <= 0 {
42 // (1 << 256) / (difficultyNum + 1)
43 denominator := new(big.Int).Add(difficultyNum, bigOne)
44 return new(big.Int).Div(oneLsh256, denominator)
47 // CompactToBig converts a compact representation of a whole unsigned integer
48 // N to an big.Int. The representation is similar to IEEE754 floating point
49 // numbers. Sign is not really being used.
51 // -------------------------------------------------
52 // | Exponent | Sign | Mantissa |
53 // -------------------------------------------------
54 // | 8 bits [63-56] | 1 bit [55] | 55 bits [54-00] |
55 // -------------------------------------------------
57 // N = (-1^sign) * mantissa * 256^(exponent-3)
58 // Actually it will be nicer to use 7 instead of 3 for robustness reason.
59 func CompactToBig(compact uint64) *big.Int {
60 // Extract the mantissa, sign bit, and exponent.
61 mantissa := compact & 0x007fffffffffffff
62 isNegative := compact&0x0080000000000000 != 0
63 exponent := uint(compact >> 56)
67 mantissa >>= 8 * (3 - exponent)
68 bn = big.NewInt(int64(mantissa))
70 bn = big.NewInt(int64(mantissa))
71 bn.Lsh(bn, 8*(exponent-3))
81 // BigToCompact converts a whole number N to a compact representation using
82 // an unsigned 64-bit number. Sign is not really being used, but it's kept
84 func BigToCompact(n *big.Int) uint64 {
90 // Bytes() returns the absolute value of n as a big-endian byte slice
91 exponent := uint(len(n.Bytes()))
93 // Bits() returns the absolute value of n as a little-endian uint64 slice
95 mantissa = uint64(n.Bits()[0])
96 mantissa <<= 8 * (3 - exponent)
98 tn := new(big.Int).Set(n)
99 // Since the base for the exponent is 256, the exponent can be treated
100 // as the number of bytes to represent the full 256-bit number. And as
101 // the exponent is treated as the number of bytes, Rsh 8*(exponent-3)
102 // makes sure that the shifted tn won't occupy more than 8*3=24 bits,
103 // and can be read from Bits()[0], which is 64-bit
104 mantissa = uint64(tn.Rsh(tn, 8*(exponent-3)).Bits()[0])
107 if mantissa&0x0080000000000000 != 0 {
112 compact := uint64(exponent)<<56 | mantissa
114 compact |= 0x0080000000000000
119 // CheckProofOfWork checks whether the hash is valid for a given difficulty.
120 func CheckProofOfWork(hash, seed *bc.Hash, bits uint64) bool {
121 compareHash := tensority.AIHash.Hash(hash, seed)
122 return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0
125 // CalcNextRequiredDifficulty return the difficulty using compact representation
126 // for next block, when a lower difficulty Int actually reflects a more difficult
128 func CalcNextRequiredDifficulty(lastBH, compareBH *types.BlockHeader) uint64 {
129 if (lastBH.Height)%consensus.BlocksPerRetarget != 0 || lastBH.Height == 0 {
133 targetTimeSpan := int64(consensus.BlocksPerRetarget * consensus.TargetSecondsPerBlock)
134 actualTimeSpan := int64(lastBH.Timestamp - compareBH.Timestamp)
136 oldTarget := CompactToBig(lastBH.Bits)
137 newTarget := new(big.Int).Mul(oldTarget, big.NewInt(actualTimeSpan))
138 newTarget.Div(newTarget, big.NewInt(targetTimeSpan))
139 newTargetBits := BigToCompact(newTarget)