BitCoin全攻略七_工作量证明
我们已经把最简单的区块链的大体框架写好了
现在我们来写工作量证明
也就是俗称的挖矿
挖矿的原理就是根据自身的数据
计算出一个哈希值
每次计算Nonce值加一
一直算到比目标值小的时候
挖矿就成功了
我们创建一个proofofwork.go文件
来个结构体
type ProofOfWork struct{
block Block
target big.Int
}
然后我们写一个函数创建
我们这里暂时先写死一个难度值
0001000000000000000000000000000000000000000000000000000000000000
func NewProofOfWork(block Block) (*ProofOfWork){
targetStr = "0001000000000000000000000000000000000000000000000000000000000000"
bigIntTemp := big.Int{}
bigIntTemp.setString(targetStr, 16)
pow := ProofOfWork{
block: block,
target: bigIntTemp,
}
return &pow
}
然后我们写一个计算的方法
这里我们先写个TODO
等下再来完善Run方法
func (pow *ProofOfWork) Run() (nonce uint64, hash []byte) {
return 100,[]byte{}
}
然后我们想一下,工作量证明应该在哪里进行呢
应该是在创建区块的时候
因为我们挖矿成功了
才能得到Nonce,才能得到区块
所以我们改一下NewBlock
func NewBlock(data []byte, prevBlockHash []byte) *Block {
timeStamp := uint64(time.Now().Unix())
block := Block{
PrevBlockHash: prevBlockHash,
Hash: nil,
Data: data,
Version: version,
MerkleRoot: nil,
TimeStamp: timeStamp,
Bits: 0,
Nonce: 0,
}
pow := NewProofOfWork(block)
nonce, hash := pow.Run()
block.Nonce = nonce
block.Hash = hash
return &block
}
我们看下完整代码
先看下block.go文件
package main
import (
"crypto/sha256"
"bytes"
"encoding/binary"
"time"
)
const version = 1
type Block struct {
//1.前区块哈希值
PrevBlockHash []byte
//2.当前区块的哈希
Hash []byte
//3.数据
Data []byte
//4.版本
Version uint64
//5.梅克尔根哈希
MerkleRoot []byte
//6.时间戳
TimeStamp uint64
//7.难度值
Bits uint64
//8.随机数Nonce
Nonce uint64
}
func NewBlock(data []byte, prevBlockHash []byte) *Block {
timeStamp := uint64(time.Now().Unix())
block := Block{
PrevBlockHash: prevBlockHash,
Hash: nil,
Data: data,
Version: version,
MerkleRoot: nil,
TimeStamp: timeStamp,
Bits: 0,
Nonce: 0,
}
pow := NewProofOfWork(block)
nonce, hash := pow.Run()
block.Nonce = nonce
block.Hash = hash
return &block
}
func getHash(block *Block) []byte {
version := Uint64ToBytes(block.Version)
timeStamp := Uint64ToBytes(block.TimeStamp)
bits := Uint64ToBytes(block.Bits)
nonce := Uint64ToBytes(block.Nonce)
var info []byte
info = append(info, block.PrevBlockHash...)
info = append(info, block.Data...)
info = append(info, version...)
info = append(info, block.MerkleRoot...)
info = append(info, timeStamp...)
info = append(info, bits...)
info = append(info, nonce...)
hash := sha256.Sum256(info)
return hash[:]
}
func Uint64ToBytes(i uint64) []byte {
var buffer bytes.Buffer
err := binary.Write(&buffer, binary.BigEndian, i)
if err != nil {
panic(err)
}
return buffer.Bytes()
}
然后proofofwork.go文件
package main
import (
"math/big"
"fmt"
"crypto/sha256"
)
type ProofOfWork struct {
//1.区块
block Block
//2.目标值
target big.Int
}
func NewProofOfWork(block Block) (*ProofOfWork) {
targetStr := "0001000000000000000000000000000000000000000000000000000000000000"
bigIntTemp := big.Int{}
bigIntTemp.SetString(targetStr, 16)
pow := ProofOfWork{
block: block,
target: bigIntTemp,
}
return &pow
}
func (pow *ProofOfWork) Run() (nonce uint64, hash []byte) {
}