zoukankan      html  css  js  c++  java
  • 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
    ",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*› 
    
    

  • 相关阅读:
    jquery 点击图片弹出遮罩层查看大图
    js 禁止复制粘贴
    如何设置ASP.NET页面的运行超时时间
    Asp.net中DataBinder.Eval用法的总结
    C#中DateTime的缺陷与代替品DateTimeOffset的对吧
    itextsharp html转成pdf 特殊符号异常处理
    C#中DateTime和DateTimeOffset的对比
    最新版本sublime text3注册码
    System.Web.Optimization找不到引用
    nodejs npm常用命令
  • 原文地址:https://www.cnblogs.com/brady-wang/p/15069157.html
Copyright © 2011-2022 走看看