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

posted @ 2021-07-28 10:11  brady-wang  阅读(1787)  评论(0编辑  收藏  举报