主页 > imtoken钱包苹果手机下载 > 比特币原理讲座1-区块链的基本原型

比特币原理讲座1-区块链的基本原型

imtoken钱包苹果手机下载 2023-01-18 11:37:19

工作证明

在上一节中,我们构建了一个非常简单的数据结构——区块,它也是整个区块链数据库的核心。完成的区块链原型已经可以通过链式关系将区块相互链接:每个区块都与前一个区块相关。

然而,目前实施的区块链有一个巨大的缺陷:向链中添加区块太容易且太便宜。而区块链和比特币的核心之一是,为了添加一个新区块,首先必须完成一些非常艰苦的工作。在本文中,我们将弥补这个缺点。

工作证明

区块链的一个关键点是,将数据放入区块链必须经过一系列艰巨的任务。正是由于这项艰巨的工作,区块链才能保持安全和一致。此外,完成这项工作的人还将获得相应的奖励(即通过挖矿获得硬币)。

这种机制与生命现象非常相似:一个人必须努力工作才能得到回报或奖励来支持他们的生活。在区块链中,整个网络是由网络中参与者(矿工)的持续工作支撑的。矿工不断向区块链添加新区块并获得相应的奖励。在这种机制的作用下,新生成的区块可以安全地加入到区块链中,从而维护了整个区块链数据库的稳定性。值得注意的是,完成工作的人必须证明这一点,即他必须证明他做了工作。

整个“努力工作和证明”机制称为工作量证明。完成这项工作并不容易,因为它需要大量的计算能力:即使是高性能计算机也无法在短时间内快速完成。此外,这项工作的难度随着时间的推移而增加,以保持每 10 分钟 1 个新块的速度。在比特币中,工作是找到满足一些必要条件的块的哈希值。这个哈希值也可以作为证明。因此,寻找证明(寻找有效的哈希)是矿工实际做的事情。

哈希计算

在本节中,我们将讨论散列。如果您已经熟悉此概念,则可以跳过。

获取指定数据的哈希值的过程称为哈希计算。哈希是计算数据的唯一表示。对于散列函数,输入任意大小的数据,它会输出一个固定大小的散列值。以下是哈希的一些关键属性:

原始数据无法从哈希值中恢复。也就是说,散列不是加密。

特定数据只能有一个散列,并且该散列是唯一的。

即使只更改输入数据中的一个字节,也会导致输出完全不同的哈希值。

散列函数被广泛用于检查数据的一致性。除了提供软件包之外,软件提供商通常还会发布校验和。下载文件后,可以使用hash函数计算下载文件的hash,并与作者提供的hash进行比较,保证文件下载的完整性。

在区块链中,散列用于保证区块的一致性。散列算法的输入数据包含前一个块的散列,因此不可能(或至少很难)修改链中的一个块:因为如果一个人想要修改前一个块的散列,那么他有重新计算该块和所有后续块的哈希值。

哈希现金

比特币使用 Hashcash,这是一种工作量证明算法,最初旨在防止垃圾邮件。它可以分解为以下几个步骤:

获取一些公共数据(例如,在电子邮件的情况下,它可能是收件人的电子邮件地址;在比特币中,它是块头)

向这个公开的数据添加一个计数器。计数器默认从 0 开始

结合数据和计数器得到一个哈希

检查哈希是否满足一定条件:

如果满足条件,结束

如果不是,请增加计数器并重复步骤 3-4

所以这是一个蛮力算法:改变计数器,计算一个新的哈希值,检查,增加计数器,计算哈希值,检查,等等。这就是为什么它的计算成本很高,因为这一步需要大量的计算和检查。

现在,让我们仔细看看哈希满足的必要条件。在最初的 Hashcash 实现中,它的要求是“哈希的前 20 位必须为 0”。在比特币中,这个要求会随着时间而改变。因为在设计上,必须保证每 10 分钟产生一个块,无论是算力会随着时间增长,还是越来越多的矿工进入网络,这个要求都需要动态调整。

为了说明该算法,我从上一个示例(“我喜欢甜甜圈”)中获取数据提币时哈希值什么时候生成,并找到一个前 3 个字节全为 0 的哈希值。

完成

好了,理论关卡完成了,我们来写代码吧!首先,定义挖矿的难度值:

在比特币中,当一个区块被挖出时,“目标比特”代表区块头中存储的难度,即开头有多少个 0。这里的24表示计算出来的hash的前24位必须为0。如果用十六进制表示提币时哈希值什么时候生成,前6位必须为0。这点从最终输出中可以看出。目前我们不会实现动态调整目标的算法,所以难度可以定义为一个全局常数。

24其实是一个可以任意取的数字,它的目的只是为了有个目标,占用不到256位的内存空间。同时,我们希望有足够的差异,但不要太多,因为差异越大,就越难找到合适的哈希。

在这里,我们构造了 ProofOfWork 结构,它存储了指向 block() 和 target() 的指针。这里的“目标”是上一节中描述的必要条件。这里使用大整数,我们将哈希与目标进行比较:首先将哈希转换为大整数,然后检查是否小于目标。

在 NewProofOfWork 函数中,我们将 big.Int 初始化为 1,然后左移。256 是 SHA-256 哈希中的位数,我们将使用 SHA-256 哈希算法。目标的十六进制形式是:

它在内存中占用 29 个字节。这是哈希与前面示例的正式比较:

第一个哈希(基于“我喜欢甜甜圈”计算)大于目标,因此它不是有效的工作量证明。第二个哈希(基于“我喜欢 donutsca07ca”计算)小于目标,因此是有效证明。

译者注:上述形式化有些“不真实”。其实应该不是出自“我喜欢甜甜圈”,但原文表达的意思是没有问题的,可能只是疏忽。这是我做的一个小实验:

输出:

您可以将目标视为一个范围的上限:如果一个数字(从哈希转换而来)小于上限,则它是有效的,否则它是无效的。因为要求小于上限,所以会导致有效数字不多。所以需要一些艰苦的工作(一系列迭代计算)才能找到一个有效的数字。

现在,我们需要对数据进行哈希处理,准备数据:

这部分更直观:只需合并 target、nonce 和 Block。这里,就是上面Hashcash提到的计数器,是一个密码学术语。

很好,到这里,所有的准备工作都完成了,我们来实现PoW算法的核心:

首先我们初始化变量:

是的整数表示;

是柜台。

然后开始一个“无限”循环:这个循环是有限的,它等于,这是为了避免可能的溢出。尽管我们的 PoW 的难度很小,实际上计数器不太可能溢出,但最好还是检查一下以防万一。

在这个循环中,我们执行以下操作:

准备数据

使用 SHA-256 散列数据

将哈希转换为大整数

将此大整数与目标进行比较

就像前面说的一样简单。现在我们可以删除方法并修改函数:

在这里,您可以看到另存为的属性。这是必要的,因为我们稍后会在验证此工作负载时使用它。现在的结构如下所示:

好的!现在让我们运行它,看看它是否有效:

有效!可以看到,每个散列都是从 0 开始的 3 个字节,获取这些散列需要一些时间。

还有一件事要做,以验证工作量证明:

在这里,我们使用上面的保存。

检查它是否再次工作:

输出:

从下图中可以看出,我们这次生成三个区块花了我们一分钟多的时间,这比没有工作量证明的情况下要慢很多(也就是成本要高很多):

总结

我们离真正的区块链又近了一步:现在添加新区块需要一些艰苦的工作,因此可以进行挖矿。但是,它仍然缺少一些关键特性:区块链数据库不是持久化的,没有钱包、地址、交易,也没有共识机制。但是,所有这些,我们将在下一篇文章中实现,现在,尽情享受挖矿吧!

参考:

完整的源代码

区块链哈希算法

工作证明

哈希现金

在 Go 中构建区块链。第 2 部分:工作量证明

第2部分

配套项目地址: