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