前言
源於我對區塊鏈挖礦的好奇,最近沉迷於學習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值則表明挖礦成功,然後把這一個塊上傳更新到鏈上。