区块链学习Day04(Pow算法)

前面实现了区块的一个产生,还有新区块的产生,现在还没有体现链的问题,区块链区块链,有区块就有链
上次笔记内容
用Pow完成了上链的操作
在这里插入图片描述
新建几个文件用来存放,把之前Main.go的内容复制一部分到新建的Block.go中

package Block

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 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++

		}
	}
}

这也就完成了一部分,接下来写Blockchain里面的内容,创建Blockchain.go

package Blockchain

import (
	"fmt"
	"project/pow/Block"
)

// 通过链表的形式,维护区块链中的业务
// 链表大家都知道,每一个链表的元素,都会有一个指针域和数据域
// 指针域指向每一个数据域,然后形成一个链表,那么我们把区块链的每个节点当作是一个结构体
type Node struct {
	//指针域
	NextNode *Node
	//数据域
	Data *Block.Block
}

// 创建头节点,用头节点来保存创世区块,让它添加到链表上
// 返回*Node,最终保存创世区块,最终返回,以便下次添加,还需要有个PerHash
func CreateHeaderNode(data *Block.Block) *Node {
	//创建一个头节点
	headerNode := new(Node)
	//头节点指针域指向Nil
	headerNode.NextNode = nil
	//把创世区块保存到当前的链表的头节点当中
	//数据域保存传入的data
	headerNode.Data = data
	//返回头节点
	return headerNode
}

// 添加节点,当我们挖到成功的时候才添加区块
// 这是后面的节点,还要和前面的节点产生关系,需要把前面节点加进入node
func AddNode(data *Block.Block, node *Node) *Node {
	//先创建新节点
	var newNode *Node = new(Node)
	//指针域指向Nil
	newNode.NextNode = nil
	//数据域是传入的data
	newNode.Data = data
	node.NextNode = newNode
	return newNode
}

// 查看链表中的数据
func ShowNodes(node *Node) {
	n := node
	for {
		//没有下个节点,则结束循环
		if n.NextNode == nil {
			fmt.Println(n.Data)
			break
		} else {
			//有下一个节点,n是不断变化的
			fmt.Println(n.Data)
			n = n.NextNode
		}
	}
}

在这里插入图片描述
写完以后,在Pow文件夹下创建main

package main

import (
	"project/pow/Block"
	"project/pow/Blockchain"
)

func main() {
	//先创建创世区块
	first := Block.GenerateFirstBlock("创世区块")
	//生成下一个区块
	second := Block.GenerateNextBlock("第二个区块", first)

	//把节点加入链表里面
	//创建链表,链表当中首先保存的是头节点
	header := Blockchain.CreateHeaderNode(&first)

	//将第二个区块加入链表,还需要NOde参数,就是上一个节点
	Blockchain.AddNode(&second, header)

	//查看链表中的数据,从头去查,
	Blockchain.ShowNodes(header)
}

运行结果

.....省略
a5d9a1fa6515874db0a4e79c6fa27403dda63f3898d12df98132cb1fea732b93
e2ac75c5720ca233508ec7580f768a4ce00cc18fce2805075dab893c5e414f34
0000a67fbdb320da5a7e7712a9d03c9229ce8155b9ca7e14f4728964a8e02f3b
挖矿成功
&{0 b2adb75843ca635ea1493783164958301b69fe92d3b17ff3d890147cb277ae99 2023-12-23 
10:29:53.5140454 +0800 CST m=+0.002049101 4 创世区块 1 0}
&{b2adb75843ca635ea1493783164958301b69fe92d3b17ff3d890147cb277ae99 0000a67fbdb32
0da5a7e7712a9d03c9229ce8155b9ca7e14f4728964a8e02f3b 2023-12-23 10:29:53.5248877 
+0800 CST m=+0.012891401 4 第二个区块 2 11572}

验证一下,可以看到第一个区块,PreHash为0,
第二个区块的PreHash是上一个区块的哈希值,而且自己的哈希值是前导0为4的哈希值,则验证数据没有问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值