工作量证明

工作量证明

工作量证明计算复杂耗时,但验证简单快速。

工作量证明计算过程

工作量证明_第1张图片

  1. 使用sha256算法,对区块数据加上随机数Nonce进行哈希运算,得到哈希值。
  2. 将哈希值与目标值进行比较,若大于则重复第1步。
  3. 若小于目标值则挖矿成功,向全网广播。

go工作量证明demo

区块结构

type Block struct {
	//版本号
	Version uint64
	// 前区块哈希
	PrevHash []byte
	//交易的根哈希值
	MerkleRoot []byte
	//时间戳
	TimeStamp uint64
	//难度值, 系统提供一个数据,用于计算出一个哈希值
	Bits uint64
	//随机数,挖矿要求的数值
	Nonce uint64
	// 哈希, 为了方便,我们将当前区块的哈希放入Block中
	Hash []byte
	//数据
	Data []byte
}

工作量证明(挖矿)

type ProofOfWork struct {
	//区块
	block *Block
	//目标值:target,与生成哈希值比较
	target *big.Int
}

构造函数,这里目标值是假设值:

  1. sha256得到的哈希值是256位32字节
  2. 所以目标值也需要是256位32字节
  3. 这里每2个16进制数表示1个字节,需要64个16进制数
func NewProofOfWork(block *Block) *ProofOfWork {
	pow := ProofOfWork{
		block: block,
	}
	//sha256得到的哈希值是256位32字节
	//所以目标值也需要是256位32字节
	//这里每2个16进制数表示1个字节,需要64个16进制数
	targetStr :=
		"8000000000000000" +
		"0000000000000000" +
		"0000000000000000" +
		"0000000000000000"

	tmpBigInt := new(big.Int)
	//将难度值赋值给BigInt,16进制
	tmpBigInt.SetString(targetStr, 16)
	//得到目标值
	pow.target = tmpBigInt
	return &pow
}

准备数据,将区块数据转化为用于哈希计算的字节切片:

func (pow *ProofOfWork)PrepareData(nonce uint64) []byte {
	b := pow.block
	//拼接3个字节切片
	tmp := [][]byte{
		uintToByte(b.Version), //将uint64转换为[]byte
		b.PrevHash,
		b.MerkleRoot,
		uintToByte(b.TimeStamp),
		uintToByte(b.Bits),
		uintToByte(nonce),
		b.Data,
	}
	//Join接收2维切片,返回一维切片
	data := bytes.Join(tmp, []byte{})
	return data
}

工作量证明:寻找合适的随机数

伪代码:

for {
    1.拼接字符串
    2.哈希值=sha256(字符串+随机数)
if 当前哈希值 < 难度值 {
    break
}
    随机数++
}
return 哈希值, nonce

代码:

func (pow *ProofOfWork) Run() ([]byte, uint64) {
	var nonce uint64
	var hash [32]byte
	fmt.Println("正在挖矿")
	for  {
		//1.拼接字符串
		data := pow.PrepareData(nonce)
		//2.哈希值=sha256(字符串+nonce)
		hash = sha256.Sum256(data)
		//将hash转换为bigInt类型
		tmpInt := new(big.Int)
		tmpInt.SetBytes(hash[:])
		if tmpInt.Cmp(pow.target) == -1 {
			fmt.Printf("挖矿成功:%x\n", hash[:])
			break
		} else {
			nonce++
		}
	}
	return hash[:], nonce
}

验证区块

其他矿工验证区块有效性:

  1. 获得区块数据
  2. 计算区块哈希值
  3. 将哈希值与目标值进行比较
//其他矿工验证区块有效性
func (pow *ProofOfWork) IsValid() bool {
	//获得区块数据
	data := pow.PrepareData(pow.block.Nonce)
	//计算区块哈希值
	hash := sha256.Sum256(data)
	tmpInt := new(big.Int)
	//将哈希值转化成大数类型,用于和目标值比较
	tmpInt.SetBytes(hash[:])
	//和目标值比较
	return tmpInt.Cmp(pow.target) == -1
}

你可能感兴趣的:(比特币)