主页 > imtoken平台 > 200行Go代码实现区块链-挖矿算法

200行Go代码实现区块链-挖矿算法

imtoken平台 2023-01-29 06:53:33

在本系列的前两篇文章[1][2]中,我们向您展示了如何通过精炼的 Go 代码实现一个简单的区块链。 包括生成区块、验证区块数据、广播通信等,本文让我们重点介绍如何实现PoW算法。

大家都在惊呼比特币、以太币等加密电子货币的持续狂热,尤其是刚接触这个领域的新手,不断听到张三、李四通过GPU“挖矿”积累了数万甚至数百万的加密币。 ”。 电子货币。 那么“挖矿”到底是什么? 它是如何工作的? 相信对于程序员来说,没有比自己动手实践“挖矿”算法更好的学习方式了。

在这篇文章中,让我们一一解读每一个问题哈希算法与比特币,最后写出自己的“挖矿”算法。 该算法称为工作量证明 [3],它是两种最流行的加密货币比特币和以太坊的基础。

什么是“挖矿”?

加密货币之所以有价值,是因为它们稀缺。 以今天的比特币为例。 如果任何人都可以随时随意“铸造”比特币,那么它作为电子货币就变得一文不值了。 比特币使用一种算法来控制输出速率,并在大约 122 年内达到最大值。 随着时间的推移,这种缓慢、稳定和渐进的产出有效地避免了通货膨胀。

比特币的产出是通过奖励“获胜矿工”来实现的,矿工之间会为了获得比特币奖励而进行竞争。 这个过程被称为“采矿”,因为它类似于“淘金热”[4],每个淘金者都辛苦工作并最终(希望)找到一点黄金。

“挖矿”是如何运作的?

如果你谷歌这个问题,你会得到大量的结果。 简单地说,“挖矿”就是“解决一个数学问题”的过程。 让我们从密码学和散列算法的一些知识开始。

密码学简介

单向加密以人类可读的文本(明文)作为输入,例如字符串“Hello world”,并通过数学函数将其传递以产生难以辨认的输出(密文)。 这些函数或算法在性质和复杂性上各不相同。 算法越复杂,逆向工程就越难。

以流行的 SHA-256 算法为例。 该网站 [5] 允许您计算任何给定输入的输出,即 SHA-256 哈希。 例如,让我们输入“Hello world”,看看我们得到了什么:

50哈希值能挖到多少比特币_哈希算法与比特币_比特币挖矿采用的算法

通过反复尝试计算“Hello world”的哈希值。 你会发现每次的结果都完全一样。 这个过程称为幂等性。

加密算法最基本的特性之一是很难对输入进行逆向工程,但很容易验证输出。 像上面的例子,你可以很容易地验证给定输入“Hello world”的 SHA-256 哈希值是否正确,但是很难从给定的哈希值判断它的输入是什么。 这就是为什么这种算法被称为单向加密。

比特币使用的是Double SHA-256,它将SHA-256得到的哈希值作为输入,重新计算SHA-256哈希值。 为简单起见,我们只使用一次 SHA-256。

矿业

回到加密电子货币,比特币是通过让参与者使用这样一种加密算法解出一个满足一定条件的哈希值来实现“挖矿”的过程。 具体来说,比特币要求参与者使用双SHA-256算法计算“前导0”超过数位的哈希值,第一个解决的参与者就是“获胜矿工”。

例如,让我们找到字符串“886”的 SHA-256 哈希值:

比特币挖矿采用的算法_哈希算法与比特币_50哈希值能挖到多少比特币

可以看出,它是一个“前导0”为3位的hash值(前三位为0)。

回想一下我们前面提到的“单向加密”的特点:

任何人都可以很容易地验证“886”产生了一个 3 位数的“前导 0”散列。 但是为了找到这样一个可以产生3个“前导0”(也就是这里的“886”)的输入,我们做了很多繁琐的计算工作:从一大堆数字中一个一个计算它们的哈希值和字母并判断是否满足上述条件。 如果我是第一个找到“886”的人,其他人就可以验证我做了这么多繁琐的工作。 在比特币和以太坊中,这样的过程被称为工作量证明算法。

“如果我非常幸运并且在第一次尝试时就找到了一个符合条件的(输入)值怎么办?” - 这种可能性很小,您可以尝试随意输入一些字母和数字。

比特币中的实际算法和约束比上述要求更复杂,当然也更难(需要更多“前导 0”)。 同时,它还可以动态调整难度。 目标是确保每 10 分钟产生比特币,无论有多少人参与“挖矿”。

马上就好了

了解足够的背景知识,然后我们使用 Go 语言在实践中编写工作量证明算法。

推荐阅读之前的《用200行Go代码实现你自己的区块链》系列文章,因为后面的工作量证明算法部分会涉及到之前的代码。

工作证明

在创建新块并将其添加到链中之前,需要一个“工作量证明”过程。 让我们首先编写一个简单的函数来检查给定的哈希值是否满足要求。

这是 isHashValid 函数:

func isHashValid(hash string, difficulty int) bool {
prefix := strings.Repeat("0", difficulty)
return strings.HasPrefix(hash, prefix)
}

Go 字符串包提供了方便的 Repeat 和 HasPrefix 函数。 我们设置前缀变量,代表“前导0”,然后检查哈希值是否有满足条件的“前导0”,然后返回True或False。

我们修改之前生成区块的generateBlock函数:

func generateBlock(oldBlock Block, BPM int) Block {
var newBlock Block

t := time.Now()

newBlock.Index = oldBlock.Index + 1
newBlock.Timestamp = t.String()
newBlock.BPM = BPM
newBlock.PrevHash = oldBlock.Hash
newBlock.Difficulty = difficulty

for i := 0; ; i++ {
hex := fmt.Sprintf("%x", i)
newBlock.Nonce = hex
if !isHashValid(calculateHash(newBlock), newBlock.Difficulty) {
fmt.Println(calculateHash(newBlock), " do more work!")
time.Sleep(time.Second)
continue
} else {
fmt.Println(calculateHash(newBlock), " work done!")
newBlock.Hash = calculateHash(newBlock)
break
}

}
return newBlock
}

新建一个区块newBlock,其中PrevHash包含前一个区块的哈希值,Timestamp是时间戳,BPM是心率数据,Difficulty是上面提到的难度,它的值决定了“前导0”的位数。

for 循环在这里很重要:

由于篇幅有限,我们将完整的代码发布在了Github上,可以从这里获取[6]。

跑上去看看

启动程序:

去运行 main.go

浏览器访问:8080

50哈希值能挖到多少比特币_哈希算法与比特币_比特币挖矿采用的算法

然后通过 Postman 发送带有心率数据的 POST 请求。

50哈希值能挖到多少比特币_比特币挖矿采用的算法_哈希算法与比特币

然后我们观察命令行窗口,不断计算哈希值。 如果不满足难度要求,我们会继续重试,直到找到满足要求的哈希值和Nonce。

50哈希值能挖到多少比特币_比特币挖矿采用的算法_哈希算法与比特币

可以看到最后的哈希值符合我们设置的难度要求(1位“前导0”)。 让我们再次刷新浏览器:

比特币挖矿采用的算法_哈希算法与比特币_50哈希值能挖到多少比特币

可以看到第二个区块创建成功并加入链中,其中Nonce是通过Proof-of-Work计算出来的满足难度要求的值。

下一步

在这里先恭喜你,以上内容很有价值。 虽然在我们的示例中使用了非常低的难度,但本质上,工作量证明算法是比特币和以太坊等区块链的重要组成部分。

至于下一步应该往哪个方向深入区块链哈希算法与比特币,建议学习如何通过IPFS访问大文件[7],打通区块链。

此外,与Proof-of-Work相比,Proof-of-Stake算法[8]越来越受到关注和青睐。 您还可以在本文中了解如何更改 PoW 算法以实现 PoS 算法。

参考链接

[1]

[2]

[3]

[4]%E6%B7%98%E9%87%91%E6%BD%AE

[5]

[6]

[7]

[8]