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\n", block.PrevBlockHash)
        fmt.Printf("Data: %s\n", block.Data)
        fmt.Printf("Hash: %x\n", 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

猜你喜欢

转载自www.cnblogs.com/hzhuxin/p/9225223.html