经典共识PoW的原理及实现

经典共识PoW的原理及实现经典共识 PoW 的原理及实现 一 PoW 简介 PoW Proof of Work 是工作量证明的简称 最早使用在防止拒绝服务攻击以及过滤垃圾邮件 现在成为区块链公链中最常见也是最有效的共识算法之一 当下最流行的比特币 以太坊等公链目前均使用 PoW 共识 PoW 是通过对一个复杂难题的求解

大家好,我是讯享网,很高兴认识大家。

经典共识PoW的原理及实现

一、PoW简介

PoW(Proof of Work)是工作量证明的简称,最早使用在防止拒绝服务攻击以及过滤垃圾邮件,现在成为区块链公链中最常见也是最有效的共识算法之一,当下最流行的比特币、以太坊等公链目前均使用PoW共识。

​ PoW是通过对一个复杂难题的求解,来保证区块链交易打包出块的公平性,即最先解决难题的矿工,可以获得记账权,并将打包好的区块发送至其他节点验证上链,从而获得激励。在保证能够在不可信的环境下创造可信的同时,运用PoW还可以天然的防御女巫攻击等针对区块链的攻击。

​ 由于PoW要求所有矿工节点都解决无意义的复杂难题,导致了巨大的资源浪费,因此,最新的以太坊版本考虑使用PoS代替PoW成为其共识算法。

二、PoW原理及实现

​ 在介绍PoW原理之前,需要先了解一些知识。

2.1 区块头

​ 在区块链中,区块分为区块头和区块体两部分,区块体以默克尔树的数据结构存储了交易数据,区块头存储了上一个区块的Hash、默克尔树树根值、时间戳、难度值、区块高度等等非交易数据信息。

2.2 哈希计算

​ 哈希计算实际上就是使用哈希函数(散列函数)对不同长度的数据都能计算出等长的输出,而且对数据微小差距都十分敏感,比如"hello world"和"Hello world"的哈希值差距都是巨大的。

2.3 原理及实现

​ PoW的原理十分简单,实际上就是计算一个随机数Nounce,要求这个Nounce和区块头拼接后做的哈希值小于我们预设的值。具体实现如下:

​ 1.预设一个难度值targetBit,比如我们想PoW计算出的Hash值最前面开始有16个0,则设置该值为16。

​ 2.找到判断是否找出正确Nounce值的临界值target,在比特币中,PoW使用的是SHA256,输出的哈希值都是256位的,比如设置的难度值是16,那么我们最终应该得到的值的形式应该是 0000 0000 0000 0000 xxxx…xxxx(共256位),那么我们可以得知,当我得到的值小于0000 0000 0000 0001 0000…0000(共256位)时,该值合法,因为这个值已经小于了前面有15个0的最小值,那么其前面一定有16个0。


讯享网

​ 所以我们只要将临界值target先设置为1,二进制表示为0000 0000…0001(共256位),再将这个值左移256-targetBit = 256 - 16 = 240位,即可得到前面有15个0的最小值,即0000 0000 0000 0001 0000…0000(共256位)。

​ 3.将随机数Nounce置为0,再拼接上区块头的内容,计算其哈希值,如果大于了我们的目标值target,则将Nounce加1,再拼接区块头的内容计算哈希。重复上述过程,直到计算出小于target的哈希值,此时的Nounce就是最终的解。

三、PoW的go语言实现

1.首先定义工作量证明对象

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

讯享网

2.定义难度值

讯享网//256位hash里面至少有16个零 const targetBit = 16 

3.初始化工作量证明对象,计算出临界值target

func NewProofOfWork(block *Block) *ProofOfWork { 
    //创建一个初始值为1的target target := big.NewInt(1) //左移256-targetBit target = target.Lsh(target, 256-targetBit) return &ProofOfWork{ 
    block, target, } } 

4.拼接Nounce值和区块头中的内容

讯享网func (proofOfWork *ProofOfWork) prepareData(nonce int) []byte { 
    join := bytes.Join( [][]byte{ 
    proofOfWork.Block.PreBlockHash,//前一个区块的hash proofOfWork.Block.HashTransactions(),//默克尔树根 Utils.IntToHex(proofOfWork.Block.TimeStamp),//时间戳 Utils.IntToHex(int64(targetBit)),//难度值 Utils.IntToHex(int64(nonce)),//Nounce Utils.IntToHex(int64(proofOfWork.Block.Height)),//区块高度 }, []byte{ 
   }, ) return join } 

5.开始进行工作量证明计算

func (proofOfWork *ProofOfWork) Run() ([]byte, int64) { 
    nonce := 0 var hashInt big.Int //存储我们新生成的hash var hash [32]byte for { 
    // 将BLOCK属性拼接成字节数组 dataBytes := proofOfWork.prepareData(nonce) // 生成hash, sum256返回32位需要转换为64位 hash = sha256.Sum256(dataBytes) // 将hash存储到hashInt,采取hash[:]将切片转换为64位 hashInt.SetBytes(hash[:]) fmt.Printf("\r%x", hash) // 判断hashInt是否小于Block里面的target // x < y -1 // x == y 0 // x > y 1 if proofOfWork.target.Cmp(&hashInt) == 1 { 
    //判断有效性,如果满足条件,跳出循环 break } nonce = nonce + 1 } return hash[:], int64(nonce) } 

6.编写当需要验证Nounce值是否合法时的验证函数

讯享网func (proofOfWork *ProofOfWork) IsValid() bool { 
    var hashInt big.Int hashInt.SetBytes(proofOfWork.Block.Hash) //判断提供的hash是否小于target if proofOfWork.target.Cmp(&hashInt) == 1 { 
    return true } return false } 
小讯
上一篇 2025-03-18 22:22
下一篇 2025-02-23 23:49

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/119623.html