OSDN Git Service

Merge pull request #24 from Blockmeta/master
[bytom/bytom.git] / consensus / general.go
1 package consensus
2
3 import (
4         "math/big"
5
6         "github.com/bytom/protocol/bc"
7 )
8
9 const (
10         subsidyReductionInterval = uint64(560640)
11         baseSubsidy              = uint64(624000000000)
12 )
13
14 // HashToBig converts a *bc.Hash into a big.Int that can be used to
15 // perform math comparisons.
16 func HashToBig(hash *bc.Hash) *big.Int {
17         buf := hash.Byte32()
18         blen := len(buf)
19         for i := 0; i < blen/2; i++ {
20                 buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]
21         }
22
23         return new(big.Int).SetBytes(buf[:])
24 }
25
26 // CompactToBig converts a compact representation of a whole number N to an
27 // unsigned 64-bit number.  The representation is similar to IEEE754 floating
28 // point numbers.
29 //
30 //      -------------------------------------------------
31 //      |   Exponent     |    Sign    |    Mantissa     |
32 //      -------------------------------------------------
33 //      | 8 bits [63-56] | 1 bit [55] | 55 bits [54-00] |
34 //      -------------------------------------------------
35 //
36 //      N = (-1^sign) * mantissa * 256^(exponent-3)
37 func CompactToBig(compact uint64) *big.Int {
38         // Extract the mantissa, sign bit, and exponent.
39         mantissa := compact & 0x007fffffffffffff
40         isNegative := compact&0x0080000000000000 != 0
41         exponent := uint(compact >> 56)
42
43         var bn *big.Int
44         if exponent <= 3 {
45                 mantissa >>= 8 * (3 - exponent)
46                 bn = big.NewInt(int64(mantissa))
47         } else {
48                 bn = big.NewInt(int64(mantissa))
49                 bn.Lsh(bn, 8*(exponent-3))
50         }
51
52         if isNegative {
53                 bn = bn.Neg(bn)
54         }
55
56         return bn
57 }
58
59 // BigToCompact converts a whole number N to a compact representation using
60 // an unsigned 64-bit number
61 func BigToCompact(n *big.Int) uint64 {
62         if n.Sign() == 0 {
63                 return 0
64         }
65
66         var mantissa uint64
67         exponent := uint(len(n.Bytes()))
68         if exponent <= 3 {
69                 mantissa = uint64(n.Bits()[0])
70                 mantissa <<= 8 * (3 - exponent)
71         } else {
72                 tn := new(big.Int).Set(n)
73                 mantissa = uint64(tn.Rsh(tn, 8*(exponent-3)).Bits()[0])
74         }
75
76         if mantissa&0x0080000000000000 != 0 {
77                 mantissa >>= 8
78                 exponent++
79         }
80
81         compact := uint64(exponent<<56) | mantissa
82         if n.Sign() < 0 {
83                 compact |= 0x0080000000000000
84         }
85         return compact
86 }
87
88 func CheckProofOfWork(hash *bc.Hash, bits uint64) bool {
89         if HashToBig(hash).Cmp(CompactToBig(bits)) <= 0 {
90                 return true
91         }
92         return false
93 }
94
95 func CalcNextRequiredDifficulty() uint64 {
96         return uint64(2161727821138738707)
97 }
98
99 func BlockSubsidy(height uint64) uint64 {
100         return baseSubsidy >> uint(height/subsidyReductionInterval)
101 }