3.POW挖矿验证算法实现

Pow(Proof Of Work)的中文翻译是:工作量证明,是区块链共识机制的一种。

我们都知道比特币系统是由全球无数个节点支撑着整个系统的正常运转。每打包一个区块(记一笔账),也就是把上一个区块和当前区块的所有的交易(上节中我们讲到区块结构的data)打包在一个区块链上并广播给其他的节点。

那么问题来了:
1.全球这么多节点中每个节点都有权利打包区块,区块由谁去打包。
2.我为什么要耗费我的电脑系统资源去参与到打包区块(记账)中去。

Pow简单点来说就是我随机出一个数,谁先猜到了就由谁来记账。当然因为你的积极参与,也会得到一笔比特币作为奖励。系统会自动通过当前全网的算力将区块产出的速度控制在10分钟左右,那么开辟一个新区块就叫做我们经常听到的挖矿下面我们就来实现这么一个算法

先来简单回顾一下我们上节中区块组成的基本结构

type Block struct {
    Height    int64
    Data      []byte
    Timestamp int64
    PrevHash  []byte
    Hash      []byte
}

本节中新增的属性

Nonce int64

还记得我之前讲的“谁先猜到了就由谁来记账”这句话吗?既然是猜,那么肯定是通过某个值,不断的去改变他的值然后进行判断看他是否符合我们需要的结果。

所以这个nonce就派上用场了。

block.info上查看到的区块信息,看到了吗?比特币区块中的nonce

image.png

每次创建区块,都要去验证。新创建一个对象,专门处理挖矿验证。

func NewBlock(height int64, data []byte, prev []byte) *Block {
    block := &Block{
        height,
        data,
        time.Now().Unix(),
        prev,
        nil,
        0,
    }
    //以前的Hash是这么来的
    //block.Hash = block.SetHash()

    //现在的Hash
    //1.创建pow的对象得到区块和难度值
    pow := NewProofOfWork(block)

    //2.开始挖矿验证区块
    hash, nonce  := pow.Run()

    //3.给区块进行赋值
    block.Nonce = nonce
    block.Hash = hash

    return block
}

工作量证明的结构

type ProofOfWork struct {
    Block  *Block   //当前要验证的区块
    diff *big.Int //大数据存储
}

创建新的工作量证明,设置难度值
原理:如果随机生成的Hash(二进制)小于难度值则挖矿成功
实现过程:
将1左移(256-20(由常量定义的targetBit值))位。然后转换成二进制格式如下

//前面有20个零
diff :`0000 0000 0000 0000 00010000...0000`

左移的方法:

diff := diffBig.Lsh(diffBig, 256-targetBit)

创建工作量证明的完整函数:

//创建新的工作量证明
const targetBit = 20
func NewProofOfWork(block *Block) *ProofOfWork {
    //设置好难度
    diffBig := big.NewInt(1)
    diff := diffBig.Lsh(diffBig, 256-targetBit)
    return &ProofOfWork{block, diff}
}

开始运行,用死循环去不断累积nonce当找到符合要求的就退出循环。满足条件(当随机到的值小于难度值算成功)

func (pow *ProofOfWork) Run() ([]byte, int64) {
    //1. 将Block的属性拼接成字节数组
    nonce := 0
    var hashInt big.Int //存储新生成的HASH
    var hash [32]byte
    for {
        //准备数据
        dataBytes := pow.prepareData(nonce)
        hash = sha256.Sum256(dataBytes)
        fmt.Printf("\r%x :", hash)
        //将hash存储到hashInt
        hashInt.SetBytes(hash[:])
        //fmt.Println(hashInt)
        //判断hashInt是否小于Block里面的target //3. 判断hash有效性,如果满足条件,跳出循环
        if pow.diff.Cmp(&hashInt) == 1 {
            break
        }

        //通过nonce值不断变化求结果
        nonce = nonce + 1
    }
    return hash[:], int64(nonce)
}

今天的内容你是否学会了呢?如果没有可以去下载源码自己进行编译,调试去跟踪一下执行过程。很快就明白了。
https://gitee.com/itgjz/blockchain_learn/tree/master/block_chain_learn3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 货币的演变——从贝壳到比特币 当社会分工产生之后,人类就产生了商品交换的需求。在货币被发明之前,人类是以以物换...
    longlee阅读 7,677评论 1 23
  • 一、快速术语检索 比特币地址:(例如:1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV)由一串...
    不如假如阅读 16,114评论 4 87
  • 辜负的时光, 敷衍的生活, 日后总有一天, 我们都得不回来, 我们都得偿还。 ………… 孩子,你不能这样 今天由于...
    西瓜vs开心果阅读 317评论 0 0
  • 满心以为,过去的2017年已是最糟糕的一年,可未曾想,2018年才是更加惆怅的日子。 一个失落彷徨迷惘寂静的夜晚
    钱先森森阅读 396评论 0 0
  • 我啊总觉得自己是不一样的一只,觉得应该很特殊,在这茫茫宇宙里我有我自己的思维,很神奇,注定不平凡,(可能所有人都是...
    酒香爱馒头阅读 240评论 0 0