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值則表明挖礦成功,然後把這一個塊上傳更新到鏈上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章