工作量证明pow / go实现简易区块链 #3
混迹币圈的人一般都知道工作量证明pow,它就是计算一组数据的哈希值,这个哈希值要达到一定的要求,这也就是所谓的难度。比特币和以太坊都是使用工作量证明的方法,在理论和实际层面都经受了严酷的考验,到目前为目,是最为成功的算法了。
下面就是在前面的基础上加上工作量证明的方法,如下:
package main
import (
"bytes"
"crypto/sha256"
"fmt"
"math"
"math/big"
)
type ProofOfWork struct {
block *Block
target *big.Int
}
const targetBits = 6 //难度值
func NewProofOfWork(block *Block) *ProofOfWork {
target := big.NewInt(1)
target.Lsh(target, uint(256-targetBits))
pow := ProofOfWork{block: block, target: target}
return &pow
}
func (pow *ProofOfWork) PrepareData(nonce int64) []byte {
block := pow.block
tmp := [][]byte{
IntToByte(block.Version),
block.PrevBlockHash,
block.MerKelRoot,
IntToByte(block.TimeStamp),
IntToByte(targetBits),
IntToByte(nonce),
block.Data}
data := bytes.Join(tmp, []byte{})
return data
}
func (pow *ProofOfWork) Run() (int64, []byte) {
var hash [32]byte
var nonce int64 = 0
var hashInt big.Int
for nonce < math.MaxInt64 {
data := pow.PrepareData(nonce)
hash = sha256.Sum256(data) //计算哈希值
hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 {
fmt.Printf("fond nonce,%d,%x", nonce, hash)
break
} else {
nonce++
}
}
return nonce, hash[:]
}
//验证
func (pow *ProofOfWork) IsValid() bool {
var hashInt big.Int
data := pow.PrepareData(pow.block.Nonce)
hash := sha256.Sum256(data)
hashInt.SetBytes(hash[:])
return hashInt.Cmp(pow.target) == -1
}
工作量证明就是:穷举nonce值,计算出符合条件(前面是几个零)的哈希。因为哈希是一种随机运算,没有规律,只能穷举。所以,挖矿就要比拼算力啰!