Blockchain Learning Day03 (Pow Algorithm)

Generate new block

Disclaimer: The notes are for self-study. I am not very clear about it, so please forgive me.
Insert image description here
Generating a new block and returning the new block will also contain the above attributes, and the previous hash will also become preHash: the hash of the previous node.
The code continues to follow the previous chapter article, if you don’t know how to read
the link below: Blockchain Learning Day02 (Pow Algorithm)

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// 通过代码实现挖矿
// 1.声明区块的结构体
type Block struct {
    
    
	//上一个区块的哈希
	PreHash string
	//当前区块的哈希
	HashCode string
	//时间戳
	TimeStamp string
	//当前网络的难度系数
	//控制哈希值有几个前导0
	Diff int
	//存交易信息
	Data string
	//区块高度
	Index int
	//随机值
	Nonce int
}

// 创建区块链首先要有第一个节点,写一个方法生成第一个节点,当然第一个区块是中本聪做的,我们做一个本地即可
// 创建创世区块(链中的第一个区块)
// 需要交易信息参数,最终返回一个区块
func GenerateFirstBlock(data string) Block {
    
    

	//创建第一个区块
	var firstblock Block
	//第一个哈希值是前一个哈希,但是根据基本的数据结构来说,链表来说前一个指向Nil,没有值,用0代表
	firstblock.PreHash = "0"
	//区块的产生时间,用系统当前时间即可 ,我们定义的是string,要转换一下
	firstblock.TimeStamp = time.Now().String()
	//前导0的个数,暂时设置为4 比如 0000
	firstblock.Diff = 4
	firstblock.Data = data
	//因为是创世区块,所以高度是固定为1
	firstblock.Index = 1
	//随机值 暂时为0
	firstblock.Nonce = 0
	//当前块的哈希,
	//通过用sha256算一个真正的哈希
	firstblock.HashCode = GenerationHashValue(firstblock)
	return firstblock
}

// 生成区块的哈希值
// 计算的哈希值,把整个Block传进去
func GenerationHashValue(block Block) string {
    
    
	var hashdata = strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce) + strconv.Itoa(block.Diff) + block.TimeStamp
	//对这个串求哈希算法
	var sha = sha256.New()
	//需要传入数组类型
	sha.Write([]byte(hashdata))
	hashed := sha.Sum(nil)
	//将字节转换为字符串
	return hex.EncodeToString(hashed)
}

// 测试一下
func main() {
    
    
	//创建创世区块
	firstBlock := GenerateFirstBlock("创世区块")
	fmt.Println(firstBlock)
	fmt.Println(firstBlock.Data)

	//产生第二个区块,要传上一个区块
	GenerateNextBlock("第二个区块", firstBlock)
}

// 产生新的区块
func GenerateNextBlock(data string, oldBlock Block) Block {
    
    
	//产生一个新的区块
	var newBlock Block
	newBlock.TimeStamp = time.Now().String()
	//可以自己修改难度系数,越大越慢
	newBlock.Diff = 4
	//区块高度 认为第二个区块 ,一般认为高度应该是上一个区块的Index+1,但是我们认为是第二个区块,先挖出来,先写死 2
	newBlock.Index = 2
	newBlock.Data = data
	//上一个哈希就是传进来的oldBlock
	newBlock.PreHash = oldBlock.HashCode
	//先设置为0,这个Noce是由矿工进行调整的
	newBlock.Nonce = 0
	//利用pow进行挖矿
	//当前节点的哈希,这是第二个区块了,要有要求,不是谁都可以根据Diff规矩去取,比如Diff=0,那么哈希前导0就必须满足0000开头
	//用到Pow的思想去做
	newBlock.HashCode = pow(newBlock.Diff, &newBlock)
	return newBlock
}

// Pow工作量证明算法进行哈希碰撞
// 要传指针的Block,因为要修改原来的值Nonce,要不断去修改
// 传指针保证操作的是同一对象
func pow(diff int, block *Block) string {
    
    
	//不停的去挖矿
	for {
    
    
		hash := GenerationHashValue(*block)
		//每挖一次,打印一次哈希值
		//并不是每次打印的哈希值都是正确的,要符合前导0,Diff个数
		fmt.Println(hash)
		//判断哈希值前缀是否为4个0
		if strings.HasPrefix(hash, strings.Repeat("0", diff)) {
    
    
			fmt.Println("挖矿成功")
			return hash
		} else {
    
    
			//没有挖到正确的
			//再重新去计算,修改原来的值,让随机值去自增,
			block.Nonce++

		}
	}
}

结果:
省略…
4b5ffc524ced8f17059a8d2df1c997842facc81c1aba5fdba9631ea8e974fc9e
aebf6bd16cc615cd89c5b7642a9ba659a8a8eb3175a94a0f7b0ab89f2210f76b
d95a5302617aee8d675e7fc727ccd2c2618d44086dde0048893ba58b3eeebf78
0000ac3053583197868461c6dbaebd96521015635349bbc55a015889b460850f
挖矿成功
满足了挖矿条件的Diff就可以,4个前导0,diff越大计算越慢。

Guess you like

Origin blog.csdn.net/weixin_44774466/article/details/135147443