go開發區塊鏈
文件目錄

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*›

