【阿菜做实践】利用go语言写一个简单的Pow样例

时间:2023-03-09 03:54:22
【阿菜做实践】利用go语言写一个简单的Pow样例

本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简单demo。开发IDE用的是JB Golang。

整个项目的文件结构如下:

PoWdemo
│ main.go

├─Block
│ block.go

└─BlockChain
blockChain.go

首先是block.go文件,这个文件记录了有关区块的结构体以及对应的操作函数,详细代码如下:

package Block

import (
"crypto/sha256"
"encoding/hex"
"strconv"
"strings"
"time"
) //
// Block
// @Description: Block information
//
type Block struct{
Index int
TimeStamp string
Diff int
PreHash string
HashCode string
Nonce int
Data string
} //
// GenerateFirstBlock
// @Description : generating the genesis block
// @param data : data of genesis block
// @return Block : genesis block
//
func GenerateFirstBlock(data string) Block{
var firstBlock Block
firstBlock.Index = 1
firstBlock.TimeStamp = time.Now().String()
firstBlock.Diff = 4
firstBlock.Nonce = 0
firstBlock.Data = data
firstBlock.HashCode = generateBlockHashValue(firstBlock) return firstBlock
} //
// generateBlockHashValue
// @Description : calculate the hash of a block
// @param block : the aim block
// @return string : hash of the aim block
//
func generateBlockHashValue(block Block) string{
var hashData = strconv.Itoa(block.Index) + block.TimeStamp + strconv.Itoa(block.Diff) + strconv.Itoa(block.Nonce) +
block.Data
var hash = sha256.New()
hash.Write([]byte(hashData))
hashed := hash.Sum(nil)
return hex.EncodeToString(hashed)
} //
// GenerateNextBlock
// @Description : generating the next block
// @param data : data of next block
// @param preBlock : the previous block
// @return : Block
//
func GenerateNextBlock(data string, preBlock Block) Block{
var newBlock Block
newBlock.Data = data
newBlock.Index = preBlock.Index + 1
newBlock.TimeStamp = time.Now().String()
newBlock.Nonce = 0
newBlock.Diff = 6
newBlock.PreHash = preBlock.HashCode
newBlock.HashCode = PoW(newBlock.Diff, &newBlock) return newBlock
} //
// PoW
// @Description : calculate the hash value that meets the diff conditions
// @param diff : number of 0 in the prefix of the hash value
// @param block : aim block
// @return string : the hash of the aim block that meets the diff conditions
//
func PoW(diff int, block *Block) string{
for{
hash := generateBlockHashValue(*block)
if strings.HasPrefix(hash, strings.Repeat("0",diff)){
return hash
} else{
block.Nonce++
}
}
}

其次是blockChain.go文件,该文件记录了区块链所包含的信息,以及生成新区块的函数,详细代码如下:

package BlockChain

import (
"../Block"
"fmt"
) //
// Node
// @Description: blockchain
//
type Node struct{
NextNode *Node
BlockDate *Block.Block
} // the head node of the blockchain
var HeadNode *Node //
// CreatHeadNode
// @Description : creat the head node of blockchain
// @param block : the head block
// @return *Node : the pointer of head node
//
func CreatHeadNode(block *Block.Block) *Node{
var headNode *Node = new(Node)
headNode.NextNode = nil
headNode.BlockDate = block
HeadNode = headNode
return headNode
} //
// AddNode
// @Description : add a new node into the blockchain
// @param blockDate : block of the node
// @param preNode : the previous node
// @return *Node : the pointer of new node
//
func AddNode(blockDate *Block.Block, preNode *Node) *Node{
var newNode *Node = new(Node)
blockDate.PreHash = preNode.BlockDate.HashCode
newNode.BlockDate = blockDate
newNode.NextNode = nil
preNode.NextNode = newNode
fmt.Println(blockDate.HashCode)
return newNode
} //
// ShowBlockChain
// @Description : print the information of each block
// @param headNode : the pointer of head node
//
func ShowBlockChain(headNode *Node){
for node := headNode; node != nil; node = node.NextNode{
fmt.Println(node.BlockDate)
}
}

最后是main.go文件,对区块链进行初始化,并生成新的区块。

package main

import (
"./Block"
"./BlockChain"
"strconv"
) func main(){
var headBlock = Block.GenerateFirstBlock("This is the first block!")
var blockChain = BlockChain.CreatHeadNode(&headBlock) NodePtr := blockChain
for i := 0; i<10; i++{
var newBlock = Block.GenerateNextBlock("This is the " + strconv.Itoa(i) +" block!", headBlock)
NodePtr = BlockChain.AddNode(&newBlock, NodePtr)
} //BlockChain.ShowBlockChain(blockChain) }

以上就是本篇文章实现的简易Pow样例