本篇博客的主要内容是用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样例