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

时间:2022-06-16 15:11:21

基本原理这里就不写了,只写一个简单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\n", block.PreBlockHash)
        fmt.Printf("Hash: %x\n", block.Hash)
        fmt.Printf("TimeStamp: %x\n", block.TimeStamp)
        fmt.Printf("Nonce: %x\n", block.Nonce)
        fmt.Printf("MerkelRoot: %x\n", block.MerkelRoot)
        fmt.Printf("Data: %s\n", block.Data)
    }
}