1. 上一版本问题
- 随机数和难度值随便填写的
- 区块的哈希值是无规则的
2. 本版本新加内容
- 添加POW共识算法
3. POW
3.1 POW简介
- Proof Of Work(POW), 即工作量证明,为一种共识算法。是一种确保数字交易安全,而不依赖第三方的协议。
3.2 POW本质
- 从本质上讲,工作量证明中的工作就是大家要共同解决的难题。要经过POW生成的数据是非常困难的、并且成本很高,但是一旦生产就很容易验证。
3.3 比特币中的POW
- 比特币中POW的难题就是验证和确认区块,使区块内的交易得以实现。具体来讲,POW算法主要是寻找一个随机数,使得区块头的哈希值小于规定的目标值。
- 下面是一个简单的验证区块的流程,以比特币的第二个区块为例。
//1.计算哈希值
//计算区块头的哈希需要以下六个参数,然后不断的修改nonce值,
// 并对区块头进行sha256
version: 000000001 --小端结尾--> 01000000
pre_hash(小端结尾后):6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000
merkle_root(小端结尾后): 982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e
timestamp:4966BC61--小端结尾-->61BC5549
bits:1D00FFFF ----> FFFF001D
nonce:9962E301 ----> 01E36299 //这个nonce值已经符合要求
header_hash=version+pre_hash+merkle_root+timestamp+bits+nonce
//对区块头进行两次sha256等运算并小端结尾得到:
header_hash=00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
//2. 比较
//把计算得到的区块头哈希与目标值进行比较,
// 如果得到的哈希值比目标值小,那么代表就解出了这道数学题
//但是,我不会算目标值。计算目标值的公式为:目标值=系数*2^(8*(指数-3))次方
//还望路过的大佬指点指点
4. 实现POW
4.1 定义POW结构
type ProofOfWork struct {
//a. 要挖矿的区块
block *Block
//b. 目标值
target *big.Int
}
4.2 创建POW函数
func NewProofOfWork(block *Block) *ProofOfWork{
pow := ProofOfWork{
block: block,
}
//目标值
targetStr := "0000f00000000000000000000000000000000000000000000000000000000000"
//引入辅助变量,将targetStr转换为big.int
//因为字符串无法比较大小
tmpInt := big.Int{
}
//把targetStr赋值给tmpInt, 格式为16进制
tmpInt.SetString(targetStr, 16)
pow.target = &tmpInt
return &pow
}
4.3 挖矿方法
func (pow *ProofOfWork) Run () ([]byte, uint64) {
//随机数
var nonce uint64
//要挖矿的区块
block := pow.block
var hash [32]byte
//不断循环,增加nonce,得到比目标值小的数
for{
//拼装数据
tmp := [][]byte{
Uint64ToByte(block.Version),
block.PrevHash,
block.MerkelRoot,
Uint64ToByte(block.TimeStamp),
Uint64ToByte(block.Difficulty),
Uint64ToByte(nonce),
block.Data,
}
blockInfo := bytes.Join(tmp, []byte{
})
//做hash运算
hash = sha256.Sum256(blockInfo)
tmpInt := big.Int{
}
tmpInt.SetBytes(hash[:])
//与目标值比较
//Cmp比较返回值的含义
// -1 if x < y
// 0 if x == y
// +1 if x > y
if tmpInt.Cmp(pow.target) == -1{
//找到了
fmt.Printf("挖矿成功! hash: %x, nonce: %d\n", hash, nonce)
return hash[:], nonce
}else {
//没到到 nonce加1
nonce ++
}
}
}
4.4 设置nonce和区块哈希
//添加区块函数
func NewBlock (data string, prevBlockHash []byte) *Block{
block := Block{
Version: 00,
PrevHash: prevBlockHash,
MerkelRoot: []byte{
},
TimeStamp: uint64(time.Now().Unix()),
Difficulty: 0,
Nonce: 0,
Hash: []byte{
},
Data: []byte(data),
}
//block.SetHash()
//创建一个pow对象
pow := NewProofOfWork(&block)
hash, nonce := pow.Run()
//根据挖矿结果对区块进行更新
block.Hash= hash
block.Nonce = nonce
return &block
}
源码:https://gitee.com/xiaoshengdada/go_bitcoin/tree/master/v2
自此,POW算法添加完成,功能相对简单,后续会继续完善POW共识算法。下一篇博客,实现区块的持久化。
如果有任何问题可以来微信群交流,一起学习进步。
最最后,推荐一位大佬的公众号:区块链技术栈。