最近一直忙于伏羲也没怎么学别的东西···今天更一点东西,一起来看看一条最简单的区块链是如何实现的。
本文转载自:Wuman’s Blog
区块结构体
我们把一个区块看成一个结构体,用结构体来存储区块所需要的信息。
// 创建区块链结构体
type Block struct {
Timer int64 // 时间戳
Data []byte // 数据
prevHash[]byte // 前一个区块的Hash
Hash []byte // 本区块的Hash
}
在一个最简单的区块中,我们需要的最基本的属性有:
- 时间戳
- 区块数据
- 前一个区块的Hash值
- 本区块的Hash值
其中,除了时间戳外,我们均使用字节类型来定义。
创建一个区块
我们需要一些数据来创建一个区块(创世块会稍稍有区别)。
//创建区块
func NewBlock(data string, prevhash []byte) *Block {
// 创建一个区块链结构体
block1 := Block{}
// 获取时间
block1.Timer = time.Now().Unix()
// 传入数据参数
block1.Data = []byte(data)
// 传入前一个Hash
block1.prevHash = prevhash
// setHash方法加密获得自己的Hash
block1.setHash()
// 返回区块指针
return &block1
}
首先,我们需要区块所存储的数据内容data,还需要上一个区块的Hash,在创建完成之后,我们返回一个结构体类型的指针。
其中,我们使用的setHash方法是用来获取本区块Hash的。下面我们来看一看这个函数。
setHash函数
setHash用来给区块加密,来获取本区块的Hash值。
// 进行加密设置Hash
func (block *Block) setHash() {
// 首先将区块的时间转化为字符切片类型,便于加密
time := []byte(strconv.FormatInt(block.Timer, 10))
// 将数据,时间,前一个区块的Hash进行拼接
heards := bytes.Join([][]byte{time, block.Data, block.prevHash}, []byte{})
// sha256加密
hash := sha256.Sum256(heards)
// 加密后的Hash直接赋给本Hash
block.Hash = hash[:]
}
在这里,我们通过sha256加密,对由时间戳、区块数据、上一个区块Hash组成的信息进行加密,将得到的Hash赋给本区块的Hash。
创世区块
创世区块由于没有前一个区块,我们就不需要使用前一个区块的Hash值了。
// 创建创世块
func Firstblock() *Block {
// 传入参数,返回结构体指针
firstblock := NewBlock("This is firstblock", []byte{})
// 返回结构体指针类型
return firstblock
}
main函数
我们在main函数里打印出区块的Hash
func main() {
firstblock := Firstblock()
// 按照16进制打印
fmt.Printf("%x",string(firstblock.Hash))
}
代码
package main
import (
"bytes"
"crypto/sha256"
"fmt"
"strconv"
"time"
)
// 创建区块链结构体
type Block struct {
Timer int64 // 时间戳
Data []byte // 数据
prevHash[]byte // 前一个区块的Hash
Hash []byte // 本区块的Hash
}
// 进行加密设置Hash
func (block *Block) setHash() {
// 首先将区块的时间转化为字符切片类型,便于加密
time := []byte(strconv.FormatInt(block.Timer, 10))
// 将数据,时间,前一个区块的Hash进行拼接
heards := bytes.Join([][]byte{time, block.Data, block.prevHash}, []byte{})
// sha256加密
hash := sha256.Sum256(heards)
// 加密后的Hash直接赋给本Hash
block.Hash = hash[:]
}
// 创建创世块
func Firstblock() *Block {
// 传入参数,返回结构体指针
firstblock := NewBlock("This is firstblock", []byte{})
// 返回结构体指针类型
return firstblock
}
//创建区块
func NewBlock(data string, prevhash []byte) *Block {
// 创建一个区块链结构体
block1 := Block{}
// 获取时间
block1.Timer = time.Now().Unix()
// 传入数据参数
block1.Data = []byte(data)
// 传入前一个Hash
block1.prevHash = prevhash
// setHash方法加密获得自己的Hash
block1.setHash()
// 返回区块指针
return &block1
}
func main() {
firstblock := Firstblock()
// 按照16进制打印
fmt.Printf("%x",string(firstblock.Hash))
}
打印结果
GOROOT=D:\Goland\Go #gosetup
GOPATH=D:\Goland\Gowork;D:\Goland\Go #gosetup
D:\Goland\Go\bin\go.exe build -o C:\Users\HP\AppData\Local\Temp\___go_build_running_go.exe D:/Goland/Gowork/src/main/running.go #gosetup
C:\Users\HP\AppData\Local\Temp\___go_build_running_go.exe #gosetup
0d00bc4d9ef291f3e0fe6ac36fa2a1a62e6f6e1939b191688bc18817bb96f1e9
Process finished with exit code 0