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

  • 相关阅读:
    考勤助手——基于CS三层结构的子系统设计
    淘宝网架构分析——反向代理
    软件架构风格——解释器风格详析
    软件架构风格
    考勤助手类图的设计
    任课教师管理考勤子系统之用例图
    考勤助手ER图2.0版本所存在的问题
    关于“考勤助手”体系架构风格的选取
    浅谈CDN技术的性能与优势
    软件体系结构——解释器风格的浅解
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/9225223.html
Copyright © 2011-2022 走看看