Go语言实现区块链(二)

一、引入PoW

(1)定义Pow结构体

// 工作量证明
type ProofOfWork struct {
	Block Block //
	Target big.Int // 挖矿难度目标值
}

(2)提供创建函数

// 创建方法
func NewProofOfWork(block Block) * ProofOfWork {
	pow := ProofOfWork{
		Block: block,
	}
	// 目标值,用于设置挖矿的难度,先设置为固定值
	target := "0000100000000000000000000000000000000000000000000000000000000000"
	// 把target转换成big.Int类型
	bigInt := big.Int{}
	bigInt.SetString(target, 16)
	pow.Target = bigInt
	return &pow
}

(3)提供挖矿方法

// 挖矿方法
// 返回值一:挖到区块的hash
// 返回值二:随机数
func (pow *ProofOfWork) Run() ([]byte, uint64) {
	var hash []byte
	var nonce uint64
	for {
		// 根据不同随机数对block计算hash,然后再使用sha256算法加密,得到目标hash
		hash = pow.PrepareData(nonce)
		// 把hash转换成bigInt,然后与pow的target字段比较
		bigInt := big.Int{}
		bigInt.SetBytes(hash)
		// 如果hash比pow的target小,就代表挖矿成功
		if bigInt.Cmp(&pow.Target) == -1 {
			return hash, nonce
		}
		nonce++
	}
}

(4)定义PrepareData函数

// 根据nonce生成区块哈希,该方法与SetHash方法类似
func (pow *ProofOfWork) PrepareData(nonce uint64) []byte {
	block := pow.Block
	tmp := [][]byte{
		block.PrevHash,
		block.Data,
		block.MerKleRoot,
		uint64ToByte(block.Version),
		uint64ToByte(block.TimeStamp),
		uint64ToByte(block.Difficulty),
		uint64ToByte(nonce),
	}
	blockInfo := bytes.Join(tmp, []byte{})
	// 2.使用sha256加密
	hash := sha256.Sum256(blockInfo)
	return hash[:]
}

(5)修改NewBlock函数,将setHash()注释掉,使用ProofOfWork进行替换。

// 创建方法
func NewBlock(data []byte, prevHash []byte) *Block {
	block := Block{
		Version:    00,
		PrevHash:    prevHash,
		MerKleRoot: []byte{},
		TimeStamp:  uint64(time.Now().Unix()),
		Difficulty: 1,
		Nonce:      1,
		Data: []byte(data)}

	//提供一个设置哈希的方法
	//block.SetHash()
	pow := NewProofOfWork(block)
	hash, nonce := pow.Run()
	block.Hash = hash
	block.Nonce = nonce
	return &block
}

 

 

猜你喜欢

转载自blog.csdn.net/zhongliwen1981/article/details/89636202