Yuque Archive
寻常的路

用Go语言实现简单的区块链结构

参考:https://www.imooc.com/learn/1011

简介

实现简单的区块链结构,分别在CMD和HTTP服务中测试。没有涉及共识机制。

区块结构

一个区块结构应该包含区块的编号(Index)、区块创建时的时间戳(Timestamp)、上一个区块的哈希值(PrevBlockHash)、当前区块的哈希值(Hash)以及当前区块的数据(Data)。

当前区块的哈希值应该根据当前区块的编号、时间戳、数据,以及上一个区块的哈希值,共同计算得到,保证区块哈希值的唯一。这里区块索引为整型数值,哈希值为16进制表示的32为字符串,区块数据简略为字符串。

新建工程名为demochain,并且将项目放在$GOPATH/src目录下,以保证自定义包可用。项目一共两个核心文件,Block.goBlockchain.go,分别对应区块和区块链操作。

首先定义区块结构体:

demochain/core/Block.go

然后需要一个方法,计算当前区块的哈希值:

这样就可以写生成新区块的方法,新区块的索引为上一个区块索引 + 1,上一个区块和数据为入参,当前区块哈希使用刚写的哈希计算函数进行计算:

最后缺的是创世区块,当区块链中没有区块,需要用这个区块来作为初始区块:

区块链结构

区块链由多个区块连接组成,基本的区块链结构简单表示为区块数组:

demochain/core/Blockchain.go

先写一个验证区块是否合法的功能性方法:

暂时从三个部分验证区块的合法性,区块索引、上一个区块的哈希和当前区块的哈希。

然后写append方法,用于将新区块添加到区块链:

如果区块链为空,则不验证有效性,直接添加。

类似创世区块,区块链也要有一个初始方法,生成新的区块链:

初始区块链需要将创世区块添加进去,作为第一个区块,以后的区块添加在其后。

最后一个方法是发送添加区块的请求,这个方法里创建一个新的区块,并执行将区块添加进链的操作:

此外还需要一个辅助方法,用于打印出区块的所有数据:

cmd测试

测试还是较简单的,创建区块链,添加区块,打印区块:

demochain/cmd/cmd.go

打印结果如:

HTTP服务测试

Go语言内置的http模块提供了便捷的启动HTTP服务的方法,先声明一个区块链变量,之后将对这个变量进行操作:

demochain/server/server.go

写一个run函数,用于处理http请求并启动监听端口的服务:

HandleFunc方法的第一个参数为请求路径,第二个参数是回调方法,用于处理请求。listenAndServe方法会在8023端口启动服务。

然后写两个回调函数的内容,这两个函数都接收两个参数,响应和请求,类似于Servlet的service方法:

最后写主方法运行程序,注意把包名改为main:

访问 http://localhost:8023/blockchain/get 查看区块链已有区块。

访问 http://localhost:8023/blockchain/write?data=smallyu 写入并读取所有区块链数据。