「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」。
一个基于web服务器的PoW案例
本文收录于我的专栏:细讲区块链
本专栏会讲述区块链共识算法以及以太坊智能合约、超级账本智能合约、EOS智能合约相关知识,还会详细的介绍几个实战项目。如果有可能的话,我们还能一起来阅读以太坊的源码。有兴趣的话我们一起来学习区块链技术吧~
五、区块校验
1 | go复制代码func isHashValid(hash string, difficulty int) bool { |
这个我们本专栏之前的文章介绍了,在此简单说一下,这里我们就校验一下哈希值前面的零的数量是不是和难度值一致。
六、启动HTTP服务器
1 | go复制代码func run() error { |
我们先从.env文件中获取PORT的值。然后监听获取的端口号。http.Server是设置http服务器的参数,其中Addr是地址,ReadTimeout、WriteTimeout分别是读写超时时间,然后是设置请求头的数据大小的最大值,1 << 20是位运算,算出来就是1MB。!!!最重要的就是回调函数了,这里需要我们自己编写来处理Get和Post请求。
然后我们就来监听事件并且根据监听到的事件来服务。
七、回调函数的编写
1 | go复制代码func makeMuxRouter() http.Handler { |
mux.NewRouter()是用来创建路由,muxRouter.HandleFunc(“/“,handGetBlockchain).Methods(“GET”)是根据你访问的目录和请求类型来调用指定的方法。这里是使用Get方法访问根目录就调用handGetBlockchain方法。同样的,muxRouter.HandleFunc(“/“,handWriteBlock).Methods(“POST”)就是使用Post请求访问根目录时就调用handWriteBlock方法。
八、处理Get请求
1 | go复制代码func handGetBlockchain(w http.ResponseWriter, r *http.Request) { |
我们需要将数据转换为json格式,便于与前端进行交互。
同样我们的参数分别是响应和请求。然后处理错误,当出现500错误时,也就是http.StatusInternalServerError,我们将err.Error()写入w:
如果没出错,就将json数据写入w。
九、处理POST请求
1 | go复制代码func handWriteBlock(writer http.ResponseWriter, request *http.Request) { |
因为需要服务器响应结果为json,先设置响应头的”Content-Type”为”application/json”。然后从request中读取JSON数据,将JSON数据转成Message。如果转换失败,就交给下一步处理异常,如果成功就创建新的区块。
这里使用defer,说明我们要记得关闭请求哦~
然后添加区块时要记得上锁,可以防止同个时间点多个POST请求生成区块。
接下来就要校验生成的区块是否正确,如果正确就加入区块链中。
十、处理异常
1 | go复制代码func responseWithJSON(writer http.ResponseWriter, request *http.Request, |
如果将传入的inter转换为json格式的数据没有出现错误就往响应头写入响应码,并将数据写入。
十一、校验区块是否正确
1 | go复制代码func isBlockValid(newBlock, oldBlock Block) bool { |
这里校验了新区块的index是否等于原来最后一个区块的index加一,新区块的PreHash应该等于之前区块链最后一个区块的HashCode。然后还需要再一次计算区块的哈希值,进行比对。
十二、主逻辑
然后我们现在用Go实现通过http请求来完成区块链。
1 | go复制代码func main() { |
godotenv.Load()加载一个文件,如果不填写参数,就默认是加载.env文件。
这个.env文件我们这里就只需要填写一个端口号。
这里我们先将创世区块加入区块链。然后用spew.Dump()将其格式化输出到命令行。
最后我们会要用run来启动http服务器。
十三、运行结果
我们可以使用curl来进行get和post请求。
这是get请求,得到区块链。
这是进行post请求,新建一个区块加到了区块链。
可以看到再次get请求,已经有新的区块在区块链中了。
本文转载自: 掘金