sha256算法_Go语言实现Pow共识算法

650c5c438c1ef99fd670ad706e77eea7.png

作者: 张详,闫思

来源: IDCU

PoW呢...Proof of Work ,工作量证明机制,可能这个名字大家不熟悉,说比特币的话,大家就熟悉了。没错,PoW就是比特币所使用的共识机制。

通过计算一个数值( nonce ),使得拼揍上交易数据后内容的 Hash 值满足规定的上限。在节点成功找到满足的Hash值之后,会马上对全网进行广播打包区块,网络的节点收到广播打包区块,会立刻对其进行验证。

如果验证通过,则表明已经有节点成功解迷,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争猜谜。 网络中只有最快解谜的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。

假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保了整个系统的安全。

举个例子,给定的一个基本的字符串”Hello, world!”,我们给出的工作量要求是,可以在这个字符串后面添加一个叫做nonce的整数值,对变更后(添加nonce)的字符串进行SHA256哈希运算,如果得到的哈希结果(以16进制的形式表示)是以”0000”开头的,则验证通过。为了达到这个工作量证明的目标。我们需要不停的递增nonce值,对得到的新字符串进行SHA256哈希运算。按照这个规则,我们需要经过4251次计算才能找到恰好前4位为0的哈希散列。

如图所示

ea2b2fcd0cbef69e094192c88beb0e17.png

然后我们今天呢,就用Go语言来实现它。

话不多说,首先从环境搭建教起,对,没错,就这个网址(https://www.golangtc.com/download)

3ea112c20fc0a1fa031258545b1b700e.png

选择你需要的,笔者话,选择的是go1.9.2windows-amd64.msi,不用配置环境,这里展示一下。

ab0dd96682e04d0b1768edcf6e51cfd6.png

这样的话就妥了,然后呢,下载git,(https://git-scm.com/downloads)这个网址。

下载后打开,安装我们本次所需要的三个第三方库,spew,gorilla/mux,godotenv

spew 在控制台中格式化输出相应的结果。

gorilla/mux 是编写web处理程序的流行软件包。

godotenv 可以从我们项目的根目录的 .env 文件中读取数据。

事实上如果你打算做公链开发相关,这三个依赖是一直都要用的。

在git里分别输入

$ go get github.com/davecgh/go-spew/spew

$ go get github.com/gorilla/mux

$ go get github.com/joho/godotenv

友情提示这里会遇到一个很尴尬的问题,bash: $'Âgo‘: command not found,这个错误是这样的

只是因为你多加了一个空格在前面,删掉空格就好了,亲测有效。

cc94a99859f038df6a65845deef0a8e5.png

好了我们继续,安装后环境之后呢,新建一个文件,叫.env,里面输入ADDR=8080,这是调用8080端口的意思,win环境下的话,会提示你必须键入文件名,所以我们将文件名修改成.env. 就可以创建.env这种.开头的文件了。

再建一个文件叫,mian.go。这就是咱们的“源码”了,打开它开始编程。

新建一个文件,叫.env,里面输入ADDR=8080,这是调用8080端口的意思,win环境下的话,会提示你必须键入文件名,所以我们将文件名修改成.env. 就可以创建.env这种.开头的文件了。

再建一个文件叫,mian.go。这就是咱们的“源码”了,打开它开始编程。

首先是引入相应的包 ,来咱们逐个解释一下

package main /*定义报名,package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包 */

import( //导入包(的函数或者其他元素)

"crypto/sha256"/* 软件包sha256 实现 FIPS 180-4 中定义的 SHA224 和 SHA256 哈希算法。*/

"encoding/hex"//包十六进制实现十六进制编码和解码。

"encoding/json" /* 包json实现了RFC 4627中定义的JSON的编码和解码。JSON和Go值之间的映射在Marshal和 Unmarshal函数的文档中进行了描述。有关此包的介绍,请参阅“JSON和Go”:https://golang.org/doc/articles/json_and_go.html */

"fmt" /* fmt 包使用函数实现 I/O 格式化(类似于 C 的 printf 和 scanf 的函数), 格式化参数源自C,但更简单 */

"io" /* Package io 为 I/O 原语提供基本接口。它的主要工作是将这些原语的现有实现(例如包 os 中的那些原语)包装到抽象功能的共享公共接口中,以及一些其他相关原语中 */

"log"/* Log包实现了一个简单的日志包。它定义了一个类型,记录器,用于格式化输出的方法。它还有一个预定义的“standard”记录器,可以通过帮助函数 Printf|ln,Fatalf|ln 和 Panicf|ln 访问,比手动创建记录器更易于使用。该记录器写入标准错误并打印每条记录的消息的日期和时间。每条日志消息都在一个单独的行上输出:如果正在打印的消息不以换行符结尾,则记录器将添加一条。写入日志消息后,致命函数调用 os.Exit(1) 。写入日志消息后, Panic 函数调用 panic */

"net/http" //http包提供HTTP客户端和服务器实现

"os"/* Package os为操作系统功能提供了一个平台无关的接口。虽然错误处理类似于 Go,但设计类似 Unix,失败的调用返回类型错误的值而不是错误号 */

"strconv"//包strconv实现了对基本数据类型的字符串表示的转换

"strings"//打包字符串实现简单的函数来操纵 UTF-8 编码的字符串

"sync"/* 程序包 sync 提供基本的同步原语,如互斥锁。除了 Once 和 WaitGroup 类型之外,大多数类型都是供低级库例程使用的。通过 Channel 和沟通可以更好地完成更高级别的同步 */

"time"//打包时间提供了测量和显示时间的功能。日历计算总是假定公历,没有闰秒

"github.com/davecgh/go-spew/spew"//这三就是刚才那三个倒霉孩子

"github.com/gorilla/mux"

"github.com/joho/godotenv"

)

定义一下区块中有的

const difficulty = 1/*difficulty 代表难度系数,如果赋值为 1,则需要判断生成区块时所产生的 Hash 前缀至少包含1个 0 */

type Block struct //Block 是我们定义的结构体,它代表组成区块链的每一个块的数据模型

{

Index int //区块链中数据记录的位置

Timestamp string //时间戳,是自动确定的,并且是写入数据的时间

Bike int /*假定我们现在做的是一个共享单车的区块链,Bike就是一定区域内的自行车数量*/

Hash string //是代表这个数据记录的SHA256标识符

PrevHash string //是链中上一条记录的SHA256标识符

Difficulty int //挖矿的难度

Nonce string //PoW中符合条件的数字

}

var Blockchain []Block // 存放区块数据

type Message struct{ // 定义结构体,请求的数据

Bike int

}

var mutex = &sync.Mutex{}//用sync防止同一时间产生多个区块

定义完成之后,就是该生成区块了

func generateBlock(oldBlock Block, Bike int) Block { //定义函数

var newBlock Block //新区块

t := time.Now()

newBlock.Index = oldBlock.Index + 1 //区块的增加,index也加一

newBlock.Timestamp = t.String() //时间戳

newBlock.Bike = Bike

newBlock.PrevHash = oldBlock.Hash //新区块的PrevHash存储上一个区块的Hash

newBlock.Difficulty = difficulty

for i := 0; ; i++ {//通过循环改变 Nonce

hex := fmt.Sprintf("%x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值