-
Notifications
You must be signed in to change notification settings - Fork 16
/
cuckaroo.go
125 lines (115 loc) · 4.43 KB
/
cuckaroo.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
118
119
120
121
122
123
124
125
// Copyright (c) 2017-2020 The qitmeer developers
// license that can be found in the LICENSE file.
// Reference resources of rust bitVector
package pow
import (
"errors"
"fmt"
"github.com/Qitmeer/qng/common/hash"
"github.com/Qitmeer/qng/crypto/cuckoo"
"github.com/Qitmeer/qng/log"
"math/big"
)
type Cuckaroo struct {
Cuckoo
}
const MIN_CUCKAROOEDGEBITS = 24
const MAX_CUCKAROOEDGEBITS = 32
func (this *Cuckaroo) Verify(headerData []byte, blockHash hash.Hash, targetDiffBits uint32) error {
targetDiff := CompactToBig(targetDiffBits)
baseDiff := CompactToBig(this.params.CuckarooMinDifficulty)
h := this.GetSipHash(headerData)
nonces := this.GetCircleNonces()
edgeBits := this.GetEdgeBits()
if edgeBits < MIN_CUCKAROOEDGEBITS {
return fmt.Errorf("edge bits:%d is too short! less than %d", edgeBits, MIN_CUCKAROOEDGEBITS)
}
if edgeBits > MAX_CUCKAROOEDGEBITS {
return fmt.Errorf("edge bits:%d is too large! more than %d", edgeBits, MAX_CUCKAROOEDGEBITS)
}
err := cuckoo.VerifyCuckaroo(h[:], nonces[:], uint(edgeBits))
if err != nil {
log.Debug("Verify Error!", err)
return err
}
//The target difficulty must be more than the min diff.
if targetDiff.Cmp(baseDiff) < 0 {
str := fmt.Sprintf("block target difficulty of %d is "+
"less than min diff :%d", targetDiff, this.params.CuckarooMinDifficulty)
return errors.New(str)
}
if CalcCuckooDiff(this.GraphWeight(), blockHash).Cmp(targetDiff) < 0 {
return errors.New("difficulty is too easy!")
}
return nil
}
func (this *Cuckaroo) GetNextDiffBig(weightedSumDiv *big.Int, oldDiffBig *big.Int, currentPowPercent *big.Int) *big.Int {
oldDiffBig.Lsh(oldDiffBig, 32)
nextDiffBig := oldDiffBig.Div(oldDiffBig, weightedSumDiv)
targetPercent := this.PowPercent()
if targetPercent.Cmp(big.NewInt(0)) <= 0 {
return nextDiffBig
}
currentPowPercent.Mul(currentPowPercent, big.NewInt(100))
nextDiffBig.Mul(nextDiffBig, currentPowPercent)
nextDiffBig.Div(nextDiffBig, targetPercent)
return nextDiffBig
}
func (this *Cuckaroo) GetSafeDiff(cur_reduce_diff uint64) *big.Int {
minDiffBig := CompactToBig(this.params.CuckarooMinDifficulty)
if cur_reduce_diff <= 0 {
return minDiffBig
}
newTarget := &big.Int{}
newTarget = newTarget.SetUint64(cur_reduce_diff)
// Limit new value to the proof of work limit.
if newTarget.Cmp(minDiffBig) < 0 {
newTarget.Set(minDiffBig)
}
return newTarget
}
//calc scale
//the edge_bits is bigger ,then scale is bigger
//Reference resources https://eprint.iacr.org/2014/059.pdf 9. Difficulty control page 6
//while the average number of cycles found increases slowly with size; from 2 at 2^20 to 3 at 2^30
//Less times of hash calculation with the same difficulty
// 24 => 48 25 => 100 26 => 208 27 => 432 28 => 896 29 => 1856 30 => 3840 31 => 7936
//assume init difficulty is 1000
//24 target is 0c49ba5e353f7ced000000000000000000000000000000000000000000000000
//(The meaning of difficulty needs to be found 1000/48 * 50 ≈ 1000 times in edge_bits 24, and the answer may be obtained once.)
// why * 50 , because the when edge_count/nodes = 1/2,to find 42 cycles the probality is 2.2%
//29 target is db22d0e560418937000000000000000000000000000000000000000000000000
//(The difficulty needs to be found 1000/1856 * 50 ≈ 26 times in edge_bits 29, and the answer may be obtained once.)
//so In order to ensure the fairness of different edge indexes, the mining difficulty is different.
func (this *Cuckaroo) GraphWeight() uint64 {
//45 days
bigScale := MainHeight(1)
if this.params.AdjustmentStartMainHeight > this.mainHeight && int(this.GetEdgeBits()) != MIN_CUCKAROOEDGEBITS {
bigScale = this.params.AdjustmentStartMainHeight - this.mainHeight
bigScale = bigScale * 40
}
scale := (2 << (this.GetEdgeBits() - MIN_CUCKAROOEDGEBITS)) * uint64(this.GetEdgeBits()) / uint64(bigScale)
if scale <= 0 {
scale = 1
}
return scale
}
//solve solution
func (this *Cuckaroo) FindSolver(headerData []byte, blockHash hash.Hash, targetDiffBits uint32) bool {
this.SetEdgeBits(uint8(cuckoo.Edgebits))
sipH := this.GetSipHash(headerData)
c := cuckoo.NewCuckoo()
cycleNonces, isFound := c.PoW(sipH[:])
if !isFound {
return false
}
this.SetCircleEdges(cycleNonces)
//cpuminer need recalc blockhash
// this.bytes() contains (nonce 4 bytes + powtype 1 byte + 169 proofdata) 174 bytes
copy(headerData[len(headerData)-POW_LENGTH:], this.Bytes())
blockHash = hash.DoubleHashH(headerData)
if err := this.Verify(headerData, blockHash, targetDiffBits); err == nil {
return true
}
return false
}