• [GO]用go语言实现区块链工作原理


    基本原理这里就不写了,只写一个简单demo的实现

    首先得有一个区块用来存储区块头和区块体

    type Block struct {
        Version      int64
        PreBlockHash []byte
        Hash         []byte //区块体内是不存储HASH值的,这是网络中某个节点在计算时存储在息本地的,这里是为了方便实现最终的功能做的
        TimeStamp    int64
        TargetBits   int64 //难度值
        Nonce int64
        MerkelRoot []byte
        Data []byte //区块体信息
    }

    还得有一个方法用于实现区块体

    func NewBlock(data string, prevBlockHash []byte) *Block {
        //initial block data
        block := &Block{
            Version:1,
            PreBlockHash:prevBlockHash,
            //Hash:[]
            TimeStamp:time.Now().Unix(),
            TargetBits:10,
            Nonce:5,
            MerkelRoot:[]byte{},
            Data:[]byte(data),
        }
        block.SetHash() //get block hash
        return block
    }

    那区块体的hash值计算就得使用另外一个方法来实现

    func (block *Block)SetHash()  {
        tmp := [][]byte{
            IntToByte(block.Version),
            block.PreBlockHash,
            IntToByte(block.TimeStamp),
            block.MerkelRoot,
            IntToByte(block.Nonce),
            block.Data,
        }
        data := bytes.Join(tmp, []byte{})//join接收两个参数,第一个二维数组,第二个这里设置为空的连接符
        hash := sha256.Sum256(data)
        block.Hash = hash[:]
    }

    区块有了,那么得一个能实现把区块连接起来的文件,blockchain.go

    package main
    
    import "os"
    
    type BlockChain struct {
        blocks []*Block
    }
    
    func NewBlockChain() *BlockChain {
        return &BlockChain{[]*Block{NewGensisBlock()}} //添加了创世块
    }
    
    func (bc *BlockChain)AddBlock(data string)  {
        if len(bc.blocks) <= 0{
            os.Exit(1)
        }
        lastBlock := bc.blocks[len(bc.blocks)-1] //还没取呢,如果取要取前一个块的HASH值,即取当前链最后一个块的HASH值
        prevBlockHash := lastBlock.Hash
        block := NewBlock(data, prevBlockHash)//取前一个块的hash值
        bc.blocks = append(bc.blocks, block)
    }

    上面两个文件涉及到的工具写在另外一个文件

    package main
    
    import (
        "bytes"
        "encoding/binary"
        "fmt"
        "os"
    )
    
    func IntToByte(num int64) []byte {
        var buffer bytes.Buffer
        err := binary.Write(&buffer, binary.BigEndian, num)//将int类型的num使用binary的方法传递到buffer里去
        CheckError(err)
        return buffer.Bytes()
    }
    
    func CheckError(err error)  {
        if err != nil {
            fmt.Println("err occur: ", err)
            os.Exit(1)
        }
    }
    
    func NewGensisBlock() *Block { //创建创世块
        return NewBlock("Gensis Block!", []byte{})
    }

    最后主函数的实现

    package main
    
    import "fmt"
    
    func main()  {
        bc := NewBlockChain{}
        bc.AddBlock("班长转给老师一枚BTC")
        bc.AddBlock("班长又转给老师一枚BTC")
        for i, block := range bc.blocks {//完成区块的遍历
            fmt.Println("============= block num : ", i)
            fmt.Println("Version", block.Version)
            fmt.Printf("PreBlockHash: %x
    ", block.PreBlockHash)
            fmt.Printf("Hash: %x
    ", block.Hash)
            fmt.Printf("TimeStamp: %x
    ", block.TimeStamp)
            fmt.Printf("Nonce: %x
    ", block.Nonce)
            fmt.Printf("MerkelRoot: %x
    ", block.MerkelRoot)
            fmt.Printf("Data: %s
    ", block.Data)
        }
    }
  • 相关阅读:
    数据查询表,列名对比
    Oracle ORA06550:错误
    设计模式——单例模式
    MS SQL 建表SQL的脚本
    WinForm 清空界面控件值的小技巧
    WinForm系列——控件的输入限制
    C++学习笔记——常量定义
    PLSQL 调试触发器
    static类为什么不能用sealed关键字修饰
    C++虚函数解析(转)
  • 原文地址:https://www.cnblogs.com/baylorqu/p/9761564.html
Copyright © 2020-2023  润新知