Go语言版本区块链第二部分:工作量证明

引入:

上一篇文章中,虽然我们只设计了一个简单的区块链原型,但它体现了区块链数据库的本质。我们可以向它里面添加区块,这些区块呈链状的,后一个区块指向前一个区块。然而,我们实现的区块链有一个非常明显的瑕疵:添加区块到这个链上特别容易。比特币或者其他区块链的一个要旨是向链中添加区块具有一定的困难性。今天我们就来修复这个瑕疵。

PoW(工作量证明):

区块链中一个关键的理念是你要想往里面添加数据需要完成一些艰难的工作(如解难题,或者叫挖矿)才行。这些艰难的工作保证着区块链安全和一致性。所以区块链会奖励这些完成艰难工作的人(这就是为什么人们挖矿会奖励比特币)。

这种机制与生活中的一个现象非常相似:一个人需要努力工作从而获得报酬去维持他的生活。在区块链中,一些网络参与者(矿工)努力工作从而维持此网络的运行,他们向链中添加区块,并且从中获得奖励(如比特币)。 他们的工作使得一个区块被安全的正确无误的添加到区块链中,这也维持着整个区块链数据库的稳定。值得注意的是,谁完成这件工作的必须有一个证明。

整个“解难题和证明”的机制称作“工作量证明”。说他难是因为“解难题”需要大量的计算:即使是性能很好的计算机也不能快速的完成。并且这个工作的难度会随着时间持续增大以保证大约6块/h的出块速度。在区块链中这种工作(挖矿工作)的目标是为一个区块找到一个满足一些要求的的hash值。并且这个hash值也起到证明的作用。因此,挖矿实际上就是寻找这种证明。

最需要强调的是,“工作量证明算法”必需满足一个需求:求解这个难题很困难,但是验证它很简单。

哈希:

在这一小节中,我们将讨论哈希。如果你对这一块很熟悉,请跳过这一部分。

哈希的过程就是给某一数据找到对应的一个hash值的过程。哈希函数可以接受任意大小的数据并生成固定大小的hash值。哈希有如下几个特性:

1.给定一个hash值,不能由此反推出原始数据。因此,哈希不是加密。

2.确定的数据只有一个hash值,并且这个hash值是唯一的。

3.仅仅改动数据中的一个字节,得到的hash值就完全不同。

哈希函数在数据一致性方面有着广泛的应用。一些软件提供商将软件的验证码印在软件的包装上面。

用户下载文件后可以用一个给定的哈希函数生成一个哈希值与软件提供商提供的hash对比一下,看是否一致。

在区块链中,哈希用来保证区块的(添加到区块链前后的)一致性。区块链中哈希算法的入参包含前一个区块的哈希值,这使得恶意修改一个区块变的不可能,或者至少非常困难。因为这需要重新计算这个区块的哈希值以及所有之后的区块的哈希值。

哈希现金:

比特币中使用了Hashcash算法,这是一个PoW算法,设计的初衷是用来防止垃圾邮件。该算法可分解为以下几个步骤:

1.准备公开的数据(data):在邮件系统中为接收方的地址;在比特币中为区块头

2.添加一个计数器(counter)。从0开始计数。

3.计算data+counter组合的hash值

4.校验hash值是否满足特定的要求

1).是,恭喜你成功了

2).否,counter++ 并且重复步骤3和4

所以,这是一个强制暴力计算的算法:改变counter,计算一个新的哈希值,检验它,不符合继续增加counter,继续计算一个新的哈希,等等,所以这是一个计算困难型的算法。

现在我们来看看目标哈希值需要满足的条件。在最早的Hashcash实现中,目标哈希值需要满足前20个比特都是0这样的要求。在比特币中,目标哈希满足的条件是随着时间变化的,因为在比特币的设计中,不管是计算能力随着时间推移的增长还是越来越多的员工加入到网络当中,出块的速度需要保持在每10分钟一个。

为了演示这一算法过程,我们使用前面例子中的数据("I like donuts") ,目标哈希满足前三个字节全部为0:

图中 ca07ca是十六进制表示的计数器(counter)的值,相当于十进制中的13240266。

实现:

上面我们分析了理论基础,现在我们来编写代码。首先,我们定义挖矿的难度:

比特币中,是在被挖出的区块的区块头中存储挖矿难度的。我们不打算实现一个目标哈希调整(挖矿难度的调整)的算法,现在我们仅仅定义一个全局的常量表示挖矿难度。

24是随意选取的,我们的目标是目标值占用内存空间在256个比特以内。并且我们希望这个"难度"足够有意义但是不能太大,因为"难度"越大就越难找到一个合适的哈希值。

创建一个ProofOfWork结构,它持有两个指针,一个指向区块,一个指向“目标值”。“目标值”就是算出的哈希满足的需求。我们之所以使用big.Int类型是因为我们需要比较哈希值和“目标值”:我们将哈希值转换为一个bigInt类型然后检验它是否比目标值小。

在NewProofOfWork函数中,我们初始化一个big.Int类型的变量,设置其值为1,然后左移256-targetBits 个比特位。256指的是SHA-256的比特位数,我的区块链中将使用SHA-256哈希算法。十六进制表示的“目标值”如下图所示:

它占用29个字节的内存空间。下面是之前计算的哈希与“目标值”的比较:

第一个哈希值("I like donuts"计算得出的哈希值)大于目标值,因此它是无效的。第二个哈希值("I like donutsca07ca"计算得出的哈希值)小于目标值,因此它是有效的。

你可以认为“目标值”是有效哈希的上边界:如果一个哈希值小于这个边界值,它是有效的,反之则反。降低这个边界值意味着有效值的减少,因此,找到一个有效值需要付出更多的工作。

现在,我们准备计算哈希的数据。

这段代码很简单:我们仅仅将区块中的字段与目标值及nonce合并。nonce就是上文Hashcash中描述的计数器,这是一个密码学上的名词。

好了,所有的准备工作都完成了,我们可以开始实现PoW算法的核心了。

首先,我们定义几个变量,hashInt:hash转换为整型后的值;nonce:计数器。接下来是一个(伪)"无限循环",循环的最大次数为maxNonce,它与math.MaxInt64相等;这样是为了防止nonce的溢出。尽管在我们的Pow算法实现中计数器的溢出很难,但是检查一下更好,以防万一。

在循环中执行的步骤:

1.准备数据

2.用SHA-256计算数据的hash

3.得到hash的big integer 类型

4.将hash的整型值与目标值比较

现在我们可以Block的SetHash方法删掉了并且我们将NewBlock方法修改如下:

如你所见nonce将作为Block的一个属性保存在其中。这样做是必需的,因为工作量证明需要用到noce。Block结构变为如下所示的样子:

让我们启动程序看看我们的程序是否能够很好的工作。

非常好!现在你可以看到所有区块的hash都是以三个字节的0开头,并且生成这些hash值需要一些时间。

事情还没完,我们还有一件事要做:验证工作量。

这就是我们使用区块中存储的nonce的地方。

再看看我们的代码是否能正常运行:

结果:

结论:

我们的区块链进一步接近它的真实架构了:添加区块需要一定的工作量证明,因此可以挖矿了。但是它依然缺少一些至关重要的特征:区块链数据没有持久化,缺少钱包,地址,交易以及共识机制。所有的这些特性,我们会在以后的文章中一一介绍。

-尽力而为-

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容