一、引入PoW
(1)定义Pow结构体
// 工作量证明
type ProofOfWork struct {
Block Block //
Target big.Int // 挖矿难度目标值
}
(2)提供创建函数
// 创建方法
func NewProofOfWork(block Block) * ProofOfWork {
pow := ProofOfWork{
Block: block,
}
// 目标值,用于设置挖矿的难度,先设置为固定值
target := "0000100000000000000000000000000000000000000000000000000000000000"
// 把target转换成big.Int类型
bigInt := big.Int{}
bigInt.SetString(target, 16)
pow.Target = bigInt
return &pow
}
(3)提供挖矿方法
// 挖矿方法
// 返回值一:挖到区块的hash
// 返回值二:随机数
func (pow *ProofOfWork) Run() ([]byte, uint64) {
var hash []byte
var nonce uint64
for {
// 根据不同随机数对block计算hash,然后再使用sha256算法加密,得到目标hash
hash = pow.PrepareData(nonce)
// 把hash转换成bigInt,然后与pow的target字段比较
bigInt := big.Int{}
bigInt.SetBytes(hash)
// 如果hash比pow的target小,就代表挖矿成功
if bigInt.Cmp(&pow.Target) == -1 {
return hash, nonce
}
nonce++
}
}
(4)定义PrepareData函数
// 根据nonce生成区块哈希,该方法与SetHash方法类似
func (pow *ProofOfWork) PrepareData(nonce uint64) []byte {
block := pow.Block
tmp := [][]byte{
block.PrevHash,
block.Data,
block.MerKleRoot,
uint64ToByte(block.Version),
uint64ToByte(block.TimeStamp),
uint64ToByte(block.Difficulty),
uint64ToByte(nonce),
}
blockInfo := bytes.Join(tmp, []byte{})
// 2.使用sha256加密
hash := sha256.Sum256(blockInfo)
return hash[:]
}
(5)修改NewBlock函数,将setHash()注释掉,使用ProofOfWork进行替换。
// 创建方法
func NewBlock(data []byte, prevHash []byte) *Block {
block := Block{
Version: 00,
PrevHash: prevHash,
MerKleRoot: []byte{},
TimeStamp: uint64(time.Now().Unix()),
Difficulty: 1,
Nonce: 1,
Data: []byte(data)}
//提供一个设置哈希的方法
//block.SetHash()
pow := NewProofOfWork(block)
hash, nonce := pow.Run()
block.Hash = hash
block.Nonce = nonce
return &block
}