golang開發區塊鏈


go開發區塊鏈

代碼地址 https://github.com/brady-wang/chain1

文件目錄

Block.go 區塊相關信息

BlockChain 區塊鏈

Bloak.go

定義區塊結構體
type Block struct {
	Index int // 區塊高度 創世區塊為0
	BMP int // 區塊存的值 就比如比特幣存的交易信息 
	Nonce int // 隨機值
	MyHash string // 本區塊的隨機值
	PreHash string // 上一區塊的隨機值
	TimeStamp string // 時間戳
	Difficult int // 挖礦難度
}

定義個方法 創建出創世區塊 也就是第一個區塊


// CreateFirstBlock 創世區塊
func CreateFirstBlock() *Block {
	var block = Block{
		Index:     0,
		BMP:       0,
		Nonce:     0,
		PreHash:   "",
		TimeStamp: time.Now().String(),
		Difficult: difficult,
	}
	block.MyHash = CalculateHash(&block)

	return &block
}

定義計算hash方法 就是把當前區塊的幾個字段鏈接后加密


// CalculateHash 計算hash
func CalculateHash(block *Block) string  {
	hashData := strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce)+block.PreHash
	hash := hashx.Sha256(hashData)
	return hash
}

定義方法獲取下一個區塊


// NextBlock 下一個區塊
func NextBlock(BMP int,preBlock Block) *Block{
	var block = Block{
		Index:     preBlock.Index+1,
		BMP:       BMP,
		PreHash:   preBlock.MyHash,
		Nonce: preBlock.Nonce,
		TimeStamp: time.Now().String(),
		Difficult: difficult,
	}
	for {
		block.Nonce++  // 無限循環 讓隨機值不斷自增 
		hash := CalculateHash(&block)
		fmt.Println(hash)
		if strings.HasPrefix(hash,strings.Repeat("0",block.Difficult)) { // 如果計算的hash前面幾個都為0 那么就是合法的hash
			block.MyHash = hash
			fmt.Println("挖礦成功 " + hash)
			break
		}
	}
	return &block
}

完整代碼 Block.go

package Block

import (
	"fmt"
	"github.com/brady-wang/go-tools/hashx"
	"strconv"
	"strings"
	"time"
)

const difficult = 4


type Block struct {
	Index int
	BMP int
	Nonce int
	MyHash string
	PreHash string
	TimeStamp string
	Difficult int
}


// CreateFirstBlock 創世區塊
func CreateFirstBlock() *Block {
	var block = Block{
		Index:     0,
		BMP:       0,
		Nonce:     0,
		PreHash:   "",
		TimeStamp: time.Now().String(),
		Difficult: difficult,
	}
	block.MyHash = CalculateHash(&block)

	return &block
}

// NextBlock 下一個區塊
func NextBlock(BMP int,preBlock Block) *Block{
	var block = Block{
		Index:     preBlock.Index+1,
		BMP:       BMP,
		PreHash:   preBlock.MyHash,
		Nonce: preBlock.Nonce,
		TimeStamp: time.Now().String(),
		Difficult: difficult,
	}
	for {
		block.Nonce++
		hash := CalculateHash(&block)
		fmt.Println(hash)
		if strings.HasPrefix(hash,strings.Repeat("0",block.Difficult)) {
			block.MyHash = hash
			fmt.Println("挖礦成功 " + hash)
			break
		}
	}
	return &block
}

// CalculateHash 計算hash
func CalculateHash(block *Block) string  {
	hashData := strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce)+block.PreHash
	hash := hashx.Sha256(hashData)
	return hash
}

BlockChain.go

區塊鏈 區塊生成后,要上到區塊鏈里面 ,可以用鏈表,也可以直接用切片

var BlockChain []Block.Block

定義方法 將當前區塊加入到鏈里面


func AddChain(block *Block.Block) []Block.Block {
	// 判斷當前塊的preHash和上一個的hash是否一致
	if isValidBlock(block) {
		mutex.Lock()
		BlockChain = append(BlockChain, *block)
		mutex.Unlock()
	}
	return BlockChain
}

// 是否是合法的區塊
func isValidBlock(block *Block.Block) bool  {
	if len(BlockChain) == 0 { // 創世區塊
		return true
	}
	if block.PreHash != BlockChain[len(BlockChain)-1].MyHash {
		return false
	}

	return true
}
// 現實所有
func Show() []Block.Block {
	return BlockChain
}

完整代碼 BlockChain.go

package BlockChain

import "test3/Block"
import "sync"

var BlockChain []Block.Block
var mutex sync.Mutex


func AddChain(block *Block.Block) []Block.Block {
	// 判斷當前塊的preHash和上一個的hash是否一致
	if isValidBlock(block) {
		mutex.Lock()
		BlockChain = append(BlockChain, *block)
		mutex.Unlock()
	}
	return BlockChain
}

func isValidBlock(block *Block.Block) bool  {
	if len(BlockChain) == 0 { // 創世區塊
		return true
	}
	if block.PreHash != BlockChain[len(BlockChain)-1].MyHash {
		return false
	}

	return true
}

func Show() []Block.Block {
	return BlockChain
}

main.go

通過類似gin框架 建立http web服務 提供查看區塊鏈總的 挖礦兩個路由

package main

import (
	"fmt"
	"github.com/brady-wang/gee/gee"
	"log"
	"net/http"
	"strconv"
	"test3/Block"
	"test3/BlockChain"
)
var first *Block.Block

var preBlock *Block.Block

func main() {
	go func() {
		first = Block.CreateFirstBlock()
		preBlock = first
		BlockChain.AddChain(first)
		fmt.Printf("%#v\n",first)
	}()

	r := gee.New()
	r.GET("/chain",chainList)
	r.GET("/next",nextChain)
	log.Fatal(r.Run(":8080"))
}

func nextChain(c *gee.Context) {
	var bmpStr = c.Query("bmp")
	bmp,_ := strconv.Atoi(bmpStr)
	next := Block.NextBlock(bmp,*preBlock)
	BlockChain.AddChain(next)
	preBlock = next
	c.JSON(http.StatusOK,next)

}

func chainList(c *gee.Context) {
	chain := BlockChain.Show()
	fmt.Printf("區塊長度%d",len(chain))
	c.JSON(http.StatusOK,chain)
}

╭─deepin@deepin-PC ~/go/go-tools ‹master*› 
╰─$ curl -i http://localhost:8080/next\?bmp\=14
HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 28 Jul 2021 01:54:58 GMT
Content-Length: 274

{"Index":11,"BMP":14,"Nonce":897121,"MyHash":"0000aaffc283d870b860bc13c816b02b1e385fe6f8014a07bad2df62ec30a4c3","PreHash":"000064669fe20a980bac3ebacf4be676602223b96a7feed9fb8286eb301ef3d5","TimeStamp":"2021-07-28 09:54:57.583441976 +0800 CST m=+98.626058388","Difficult":4}
╭─deepin@deepin-PC ~/go/go-tools ‹master*› 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM