• Go语言模拟实现简单的区块链


    一.创建项目

      按照Go语言最佳实践的思路, 在工作空间下的src目录下创建 github.com/hangzhou-huxin/blokcchain目录作为我们的项目目录,然后用GoLand工具选中这个项目并打开:

    二.项目源码

     先在项目目录下添加block.go、blockchain.go这两个文件,分别封装了区块和区块链这两个类,当然在Go语言中是定义struct

    1.blokc.go源码

    package main
    
    import (
        "strconv"
        "bytes"
        "crypto/sha256"
        "time"
    )
    
    // Block keeps block headers
    type Block struct {
        Timestamp     int64
        Data          []byte
        PrevBlockHash []byte
        Hash          []byte
    }
    
    // SetHash calculates and sets block hash
    func (b *Block) SetHash() {
        timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
        headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
        hash := sha256.Sum256(headers)
    
        b.Hash = hash[:]  //初始化切片,是数组hash的引用
    }
    
    // NewBlock creates and returns Block
    func NewBlock(data string, prevBlockHash []byte) *Block {
        block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
        block.SetHash()
        return block
    }
    
    // NewGenesisBlock creates and returns genesis Block
    func NewGenesisBlock() *Block {
        return NewBlock("Genesis Block", []byte{})
    }

    代码说明:

        (1)   time.Now().Unix()  :返回从1970年1月1日开始的秒数

        (2)   bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{}) :bytes.Join函数可以把多个字节数组连接成一个新的切片返回bytes.Join的第一参数以[][]byte二维字节数组的方式提供要连接的字节数组,第二个参数的作用是生成的新的字节数组时,在每个字节数组中间插入的间隔符,当然这个间隔符也是以字节数组的形式来提供。

        (3)  timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))   : 字符串转字节数组

        (4)  b.Hash = hash[:]  //初始化切片,是数组hash的引用

        (5)  NewGenesisBlock() 和 NewBlock 都是构造性质的函数,按惯例一般以NewXxxx这样来命名 

    2. blockchain.go

    package main
    
    // Blockchain keeps a sequence of Blocks
    type Blockchain struct {
        blocks []*Block
    }
    
    // AddBlock saves provided data as a block in the blockchain
    func (bc *Blockchain) AddBlock(data string) {
        prevBlock := bc.blocks[len(bc.blocks)-1]
        newBlock := NewBlock(data, prevBlock.Hash)
        bc.blocks = append(bc.blocks, newBlock)
    }
    
    // NewBlockchain creates a new Blockchain with genesis Block
    func NewBlockchain() *Blockchain {
        return &Blockchain{[]*Block{NewGenesisBlock()}}  
    }

    下面是main函数:

    package main
    
    import "fmt"
    
    func main() {
        bc := NewBlockchain()
        bc.AddBlock("Send 1 BTC to Ivan")
        bc.AddBlock("Send 2 more BTC to Ivan")
    
        for _, block := range bc.blocks {
            fmt.Printf("Prev. hash: %x
    ", block.PrevBlockHash)
            fmt.Printf("Data: %s
    ", block.Data)
            fmt.Printf("Hash: %x
    ", block.Hash)
            fmt.Println()
        }
    }

    三.项目编译

     下面是当前在GoLand的工具下,项目的一个图:

    此时要编译这个代码,必须在blockchain上点右键,如图:

     而不能在main.go上点右键运行,因为main.go中会调用block.go 和 blockchain.go中的函数和struct ,直接在main.go进行编译,go build是看到block.go 和 blockchain.go的。

    以上项目的代码是参照该文所写:https://github.com/liuchengxu/blockchain-tutorial

  • 相关阅读:
    2013年工作中用到的10个命令:11-20
    2013年工作中用到的10个命令:11-20
    2013年工作中用到的10个命令:1-10
    OpenJDK源码研究笔记(十):枚举的高级用法,枚举实现接口,竟是别有洞天
    OpenJDK源码研究笔记(十):枚举的高级用法,枚举实现接口,竟是别有洞天
    Java实现 LeetCode 240 搜索二维矩阵 II(二)
    Java实现 LeetCode 239 滑动窗口最大值
    Java实现 LeetCode 239 滑动窗口最大值
    Java实现 LeetCode 239 滑动窗口最大值
    Java实现 LeetCode 238 除自身以外数组的乘积
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/9225223.html
Copyright © 2020-2023  润新知