-
Notifications
You must be signed in to change notification settings - Fork 1
/
proofofwork.go
118 lines (96 loc) · 2.56 KB
/
proofofwork.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
package main
import (
"math/big"
"fmt"
"crypto/sha256"
"bytes"
)
//系统调节的难度值
const difficulty = 16
//1. 定义工作量证明, block, 难度值
type ProofOfWork struct {
//数据来源
block Block
//难度值
target *big.Int //一个能够处理大数的内置的类型,有比较方法
}
//2. 创建一个工作量证明
func NewProofOfWork(block Block) *ProofOfWork {
//填充两个字段
pow := ProofOfWork{
block: block,
}
////引用一个临时的big.int来接这个target
//var targetInt big.Int
//targetInt.SetString(targetStr, 16)
//初始值为1
targetInt := big.NewInt(1)
////left shift 左移256
//targetInt.Lsh(targetInt, 256)
////right shift 右移20
//targetInt.Rsh(targetInt, difficulty)
targetInt.Lsh(targetInt, 256 - difficulty)
pow.target = targetInt
return &pow
}
func (pow *ProofOfWork) prepareData(nonce uint64) []byte {
block := pow.block
//使用Join代替append
bytesArray := [][]byte{
Uint2Byte(block.Version),
block.PrevBlockHash,
block.MerkelRoot,
Uint2Byte(block.TimeStamp),
Uint2Byte(block.Difficulty),
Uint2Byte(nonce),
}
info := bytes.Join(bytesArray, []byte{})
return info
}
//3. 实现挖矿计算满足条件哈希值的函数 nonce
//计算完之后返回当前区块的哈希,和nonce
func (pow *ProofOfWork) Run() ([]byte, uint64) {
fmt.Printf("pow run...\n")
//1. 拿到区块数据
//block := pow.block
//区块的哈希值
var currentHash [32]byte
//挖矿的随机值
var nonce uint64
for {
info := pow.prepareData(nonce)
//2. 对数据做哈希运算
currentHash = sha256.Sum256(info)
//3. 比较
//引用big.int,将获取的[]byte类型的哈希值转成big.int
var currentHashInt big.Int
currentHashInt.SetBytes(currentHash[:])
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
//func (x *Int) Cmp(y *Int) (r int) {
if currentHashInt.Cmp(pow.target) == -1 {
//a. 比目标小,成功,返回哈希和nonce
fmt.Printf("找到了哈希值:%x, %d\n", currentHash, nonce)
break
} else {
//b. 比目标大,继续nonce++
nonce++
}
}
return currentHash[:], nonce
}
//4. 验证找到的nonce是否正确
//根据pow里的数据进行反向计算,验证一个下nonce和哈希是否匹配当前系统的难度需求
func (pow *ProofOfWork) IsValid() bool {
//nonce已经在block中了,我们就是要校验它
info := pow.prepareData(pow.block.Nonce)
//做哈希运算
hash := sha256.Sum256(info[:])
//引入临时变量
tmpInt := big.Int{}
tmpInt.SetBytes(hash[:])
// 比较
return tmpInt.Cmp(pow.target) == -1
}