详解POW工作量证明原理
算法简介
发送方签名:
counter = 0;
while(1) {
result = SHA1(mailAdress + time + counter);
if (result.substring(0, 20) == "00000000000000000000") {
break;
}
counter++;
}
sig = mailAdress + time + counter;
服务端验签:
if (SHA1(sig).substring(0, 20) == "00000000000000000000") {
return true;
}
散列函数如SHA-1是基本均匀分布的,对于我们生成的每一个邮件签名来说,对应的的哈希值在每一位上出现0和1的概率应该是相同的,SHA-1生成的160-bit哈希结果,其所有的可能是 2^160 种,而前20位固定为0的情况有 2^140 种,所以每次生成的邮件签名符合条件的概率为: 2^140 / 2^160 = 1/2^20
问题一,解空间必然存在,解空间的大小为2^140。
问题二,每一次生成邮件签名命中的概率为 1/2^20 ,客户端平均需要运算 2^20 次就能找到正确答案,运算时间为: PerSHA1Time*2^20 。
问题三,服务器端需要丢弃掉已经出现过的答案,同时需要对收件人地址和时间戳做合法性校验即可。
工作量证明系统主要特征是客户端需要做一定难度的工作得出一个结果,验证方却很容易通过结果来检查出客户端是不是做了相应的工作。这种方案的一个核心特征是不对称性:工作对于请求方是适中的,对于验证方则是易于验证的。它与验证码不同,验证码的设计出发点是易于被人类解决而不易被计算机解决。
下图表示的是工作量证明的流程:
举个例子,给定的一个基本的字符串"Hello, world!",我们给出的工作量要求是,可以在这个字符串后面添加一个叫做nonce的整数值,对变更后(添加nonce)的字符串进行SHA256哈希运算,如果得到的哈希结果(以16进制的形式表示)是以"0000"开头的,则验证通过。为了达到这个工作量证明的目标。我们需要不停的递增nonce值,对得到的新字符串进行SHA256哈希运算。按照这个规则,我们需要经过4251次计算才能找到恰好前4位为0的哈希散列。
"Hello, world!0" => 1312af178c253f84028d480a6adc1e25e81caa44c749ec81976192e2ec934c64
"Hello, world!1" => e9afc424b79e4f6ab42d99c81156d3a17228d6e1eef4139be78e948a9332a7d8
"Hello, world!2" => ae37343a357a8297591625e7134cbea22f5928be8ca2a32aa475cf05fd4266b7
...
"Hello, world!4248" => 6e110d98b388e77e9c6f042ac6b497cec46660deef75a55ebc7cfdf65cc0b965
"Hello, world!4249" => c004190b822f1669cac8dc37e761cb73652e7832fb814565702245cf26ebb9e6
"Hello, world!4250" => 0000c3af42fc31103f1fdc0151fa747ff87349a4714df7cc52ea464e12dcd4e9
通过这个示例我们对工作量证明机制有了一个初步的理解。有的人会认为如果工作量证明只是这样的一个过程,那是不是只需要记住nonce为4521计算能通过验证就行了?当然不是的,这只是一个个例。
下面,我们将输入简单的变更为"Hello, world+整数值",整数值取1到1000,也就是说,将输入变成一个由1000个值组成的数组:“Hello, world!1、Hello, world!2……Hello, world!1000”。然后对数组中的每一个输入依次进行上面例子中要求的工作量证明——找到前导为4个0的哈希散列。
容易算出,预期大概要进行216次尝试(哈希值的伪随机特性使得我们可以做概率估算),才能得到4个前导0的哈希散列。而统计一下刚才进行的1000次计算的实际计算结果,我们会发现,进行计算的平均次数为66958次,十分接近216(65536)。在这个例子中,数学期望的计算次数,就是我们要求的“工作量”,重复多次进行的工作量证明会是一个符合统计学规律的概率事件。
统计输入的字符串与对应得到目标结果实际使用的计算次数列表如下:
Hello, world!1 => 42153
Hello, world!2 => 2643
Hello, world!3 => 32825
Hello, world!4 => 250
Hello, world!5 => 7300
...
Hello, world!995 => 164819
Hello, world!996 => 178486
Hello, world!997 => 22798
Hello, world!998 => 68868
Hello, world!999 => 46821
比特币体系里的工作量证明机制与上述示例类似,但要比它更复杂一些,以后会另起文章说明