美文网首页
3.POW挖矿验证算法实现

3.POW挖矿验证算法实现

作者: J_zhe | 来源:发表于2018-07-07 17:46 被阅读0次

    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

    相关文章

      网友评论

          本文标题:3.POW挖矿验证算法实现

          本文链接:https://www.haomeiwen.com/subject/fsfguftx.html