GO语言简单实现POW挖矿原理

前言

源于我对区块链挖矿的好奇,最近沉迷于学习GO语言,并用它简单实现了pow挖矿的原理。

代码实现过程

定义块信息结构体:

type Block struct {
	//当前区块的Hash值.
	HashCode string
	//当前时间戳.
	TimeStamp string
	//当前长度.
	Index int
	//网络难度系数,若前导0个数符合难度系数,则挖矿成功,根据挖矿人数不断变化.
	Diff int
	//下一个区块的Hash值
	PreHashCode string
	//随机数
	Nonce int
	//交易信息.
	Data string
}

创建创世块

func initFirstBlock() *Block{
	var firstBlcok = new(Block)
	firstBlcok.TimeStamp = string(time.Now().UnixNano())
	firstBlcok.Diff = 3
	firstBlcok.Nonce = 1
	firstBlcok.PreHashCode = "0"
	firstBlcok.Data = "创世块"
	firstBlcok.Index = 1
	for ; ;  {
		hashCode := generateHashCode(*firstBlcok)
		fmt.Println(hashCode)
		if strings.HasPrefix(hashCode, strings.Repeat("0", firstBlcok.Diff)) {
			firstBlcok.HashCode = hashCode
			break
		}else {
			firstBlcok.Nonce++
		}
	}
	fmt.Println("创世模块初始化完毕")
	return firstBlcok
}

生成hash值的工具

用于生成Block块中的HashCode 

//计算hash值.
func generateHashCode(block Block) string {
    //生成规则.
	record := strconv.Itoa(block.Index) + block.TimeStamp +
		strconv.Itoa(block.Nonce) + strconv.Itoa(block.Diff) + block.PreHashCode
	hash := sha256.New()
	hash.Write([]byte(record))
	sum := hash.Sum(nil)
	hashCode := hex.EncodeToString(sum)
	return hashCode
}

有了块以后,开始创建链

type Node struct {
	block Block
	nextBlock Block
	index int
}

func initFirstChain(block *Block) *Node {
	node := new(Node)
	node.index = 1
	return node
}

func createNextNode(block Block,node *Node) *Node {
	nextNode := new(Node)
	nextNode.index = node.index + 1
	node.nextBlock = block
	return nextNode
}

POW挖矿

func calNextBlock(diff int, block *Block) Block {
	nextBlock := new(Block)
	nextBlock.Index = block.Index + 1
	nextBlock.TimeStamp = string(time.Now().UnixNano())
	marshal, _ := json.Marshal(block)
	nextBlock.Data = string(marshal)
	nextBlock.Diff = diff
	nextBlock.PreHashCode = block.HashCode

	for ; ;  {
		hashCode := generateHashCode(*nextBlock)
		fmt.Println(hashCode)
		if strings.HasPrefix(hashCode, strings.Repeat("0", nextBlock.Diff)) {
			nextBlock.HashCode = hashCode
			break
		}else {
			nextBlock.Nonce++
		}
	}
	fmt.Println("挖矿成功!!!")
	return *nextBlock
}

主函数

func main() {
	now := time.Now()
	//初始化创世模块
	firstBlock := initFirstBlock()
	//初始化链表
	chain := initFirstChain(firstBlock)
	//开始挖坑
	block := calNextBlock(6, firstBlock)
	node := createNextNode(block, chain)
	fmt.Println(node)
	elapsed := time.Since(now)
	fmt.Println("用时:", elapsed)
}

测试结果

总结

diff的值决定了挖矿的难度系数,系统会根据diff的值,不断地进行hash碰撞,直到碰撞出符合条件的hash值则表明挖矿成功,然后把这一个块上传更新到链上。

猜你喜欢

转载自blog.csdn.net/weixin_39886135/article/details/112984367