6 "github.com/vapor/mining/tensority"
7 "github.com/vapor/protocol/bc"
8 "github.com/vapor/protocol/bc/types"
12 // bigOne is 1 represented as a big.Int. It is defined here to avoid
13 // the overhead of creating it multiple times.
14 bigOne = big.NewInt(1)
16 // oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid
17 // the overhead of creating it multiple times.
18 oneLsh256 = new(big.Int).Lsh(bigOne, 256)
21 // HashToBig convert bc.Hash to a difficulty int
22 func HashToBig(hash *bc.Hash) *big.Int {
23 // reverse the bytes of the hash (little-endian) to use it in the big
24 // package (big-endian)
27 for i := 0; i < blen/2; i++ {
28 buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]
31 return new(big.Int).SetBytes(buf[:])
34 // CalcWork calculates a work value from difficulty bits.
35 func CalcWork(bits uint64) *big.Int {
36 difficultyNum := CompactToBig(bits)
37 if difficultyNum.Sign() <= 0 {
41 // (1 << 256) / (difficultyNum + 1)
42 denominator := new(big.Int).Add(difficultyNum, bigOne)
43 return new(big.Int).Div(oneLsh256, denominator)
46 // CompactToBig converts a compact representation of a whole unsigned integer
47 // N to an big.Int. The representation is similar to IEEE754 floating point
48 // numbers. Sign is not really being used.
50 // -------------------------------------------------
51 // | Exponent | Sign | Mantissa |
52 // -------------------------------------------------
53 // | 8 bits [63-56] | 1 bit [55] | 55 bits [54-00] |
54 // -------------------------------------------------
56 // N = (-1^sign) * mantissa * 256^(exponent-3)
57 // Actually it will be nicer to use 7 instead of 3 for robustness reason.
58 func CompactToBig(compact uint64) *big.Int {
59 // Extract the mantissa, sign bit, and exponent.
60 mantissa := compact & 0x007fffffffffffff
61 isNegative := compact&0x0080000000000000 != 0
62 exponent := uint(compact >> 56)
66 mantissa >>= 8 * (3 - exponent)
67 bn = big.NewInt(int64(mantissa))
69 bn = big.NewInt(int64(mantissa))
70 bn.Lsh(bn, 8*(exponent-3))
80 // BigToCompact converts a whole number N to a compact representation using
81 // an unsigned 64-bit number. Sign is not really being used, but it's kept
83 func BigToCompact(n *big.Int) uint64 {
89 // Bytes() returns the absolute value of n as a big-endian byte slice
90 exponent := uint(len(n.Bytes()))
92 // Bits() returns the absolute value of n as a little-endian uint64 slice
94 mantissa = uint64(n.Bits()[0])
95 mantissa <<= 8 * (3 - exponent)
97 tn := new(big.Int).Set(n)
98 // Since the base for the exponent is 256, the exponent can be treated
99 // as the number of bytes to represent the full 256-bit number. And as
100 // the exponent is treated as the number of bytes, Rsh 8*(exponent-3)
101 // makes sure that the shifted tn won't occupy more than 8*3=24 bits,
102 // and can be read from Bits()[0], which is 64-bit
103 mantissa = uint64(tn.Rsh(tn, 8*(exponent-3)).Bits()[0])
106 if mantissa&0x0080000000000000 != 0 {
111 compact := uint64(exponent)<<56 | mantissa
113 compact |= 0x0080000000000000
118 // CheckProofOfWork checks whether the hash is valid for a given difficulty.
119 func CheckProofOfWork(hash, seed *bc.Hash, bits uint64) bool {
120 compareHash := tensority.AIHash.Hash(hash, seed)
121 return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0
124 // CalcNextRequiredDifficulty return the difficulty using compact representation
125 // for next block, when a lower difficulty Int actually reflects a more difficult
127 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)