0.学习目的

goland作为开发工具,用go语言进行区块链系统的模拟运行与开发。

1.区块以及区块链的实现

区块链中的区块通常有以下几个基本属性:

Data:本身存储的数据

Hash:根据本身DataPrevhash由算法计算的来的哈希值

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()
}

我们将会得到以下结果:

至此搭建了一个我们自己的区块链作为我们实验的工具。

2.模拟区块链账本数据结构实现

3.POW:工作量证明机制