0.学习目的
以goland
作为开发工具,用go语言进行区块链系统的模拟运行与开发。
1.区块以及区块链的实现
区块链中的区块通常有以下几个基本属性:
Data
:本身存储的数据
Hash
:根据本身Data
和Prevhash
由算法计算的来的哈希值
Prevhash
:上一个区块的哈希值
Timestamp
:时间戳
其余数据有待补充,我们先根据这四个基本的属性来建立一个类Block
作为构筑区块链的基础区块。
package block
import (
"bytes"
"crypto/sha256"
"time"
)
type Block struct {
Hash []byte
Data []byte
PrevHash []byte
Timestamp int64
}
根据定义我们了解到,区块中最重要的数据是哈希值,需结合已有的数据来计算出来,我们可以将数据Data
,前一个块的哈希值PrevHash
,和当前块的时间戳Timestam
,连接在一起来构建一个字节数组info
。
使用SHA-256
哈希函数对info
进行哈希计算,使用sha256.Sum256()
函数将计算出的哈希值存储在hash
变量中。这个哈希值是一个长度为32字节的字节数组。
最后将计算出的哈希值切片赋值给当前块的Hash
字段,以便在后续使用。
func (b *Block) deriveHash() {
info := bytes.Join([][]byte{b.Data, b.PrevHash, []byte(string(b.Timestamp))}, []byte{})
hash := sha256.Sum256(info)
b.Hash = hash[:]
}
接下来写一个方法并调用derivehash()
方法以创建区块。
func CreateBlock(data string, prevHash []byte) *Block {
block := &Block{[]byte{}, []byte(data),prevHash ,time.Now().Unix()}
block.deriveHash()
return block
}
区块链就是一个集合了众多区块的结构体,构筑区块链就是在每个区块的第一个区块(”创世区块”)后面不断添加新的区块,我们先用上述的方法构建创世区块Genesis
。
func Genesis() *Block {
return CreateBlock("Genesis", []byte{})
}
接下来定义结构体区块链并将创世区块作为第一个区块,等待添加的区块以构建区块链。
type BlockChain struct {
Blocks []*Block
}
func InitBlockChain() *BlockChain {
return &BlockChain{[]*Block{Genesis()}}
}
现在需要一个方法帮助我们在创世区块后面添加新块,根据我们对于区块的定义,我们对该方法有这样的要求:它接收一个data
参数,该参数是要存储在新区块中的数据。首先获取区块链中的最后一个区块(即当前链的最新区块)作为prevBlock
。然后,使用CreateBlock()
函数创建一个新的区块,该区块的数据为传入的data
,前一个区块的哈希值为prevBlock.Hash
。最后,将新的区块追加到区块链的Blocks字段中,以实现向区块链添加新区块的功能。
func (chain *BlockChain) AddBlock(data string) {
prevBlock := chain.Blocks[len(chain.Blocks)-1]
new := CreateBlock(data, prevBlock.Hash)
chain.Blocks = append(chain.Blocks, new)
}
至此我们有了进行一系列后续实验的基础,现在来检验一下成果。
package main
import (
block "bcts"
"fmt"
)
func blockchainRun() {
chain := block.InitBlockChain()
chain.AddBlock("First Block after Genesis")
chain.AddBlock("Second Block after Genesis")
chain.AddBlock("Third Block after Genesis")
for _, block := range chain.Blocks {
fmt.Printf("Previous Hash: %x\n", block.PrevHash)
fmt.Printf("Data in Block: %s\n", block.Data)
fmt.Printf("Hash: %x\n", block.Hash)
fmt.Printf("time: %d\n",block.Timestamp)
}
}
func main() {
blockchainRun()
}
我们将会得到以下结果:
至此搭建了一个我们自己的区块链作为我们实验的工具。