原文地址  来自 微信公众号 区块链大师

POW工作量证明(英文全称为Proof of Work)早在比特币出现之前就已经有人探索,常见的是利用HASH运算的复杂度进行CPU运算实现工作量确定,当然你也可以利用卷积求导、大质数分解这些复杂的运算来达到工作量证明的目的(HASH只是pow采用一种算法而已,你可以使用大部分需要迭代运算的算法实现POW,其实稍微改一下pow算法就有可能诞生一种山寨币,然后大肆宣传欺骗小白,了解原理后就知道这并没有什么卵用),随着比特币成功后,POW为人们熟知,基于HASH的pow算法常被人误解为是pow的代名词,为了便于解释pow原理本文还是采用HASH算法作为举例。

定义

(Proof-of-work,工作量证明)最早是一个经济学名词,它是指系统为达到某一目标而设置的度量方法。简单理解就是一份证明,用来确认你做过一定量的工作。监测工作的整个过程通常是极为低效的,而通过对工作的结果进行认证来证明完成了相应的工作量,则是一种非常高效的方式

在1999年,Markus Jakobsson and Ari Juels两人将pow概念引入计算机体系,设计系统用以抵挡拒绝服务攻击和网络爬虫,后来在反垃圾邮件中被广泛使用。其设计理念是一个正常用户写一封邮件是需要一定的时间,而发送垃圾邮件者是无法接受这个等待的时间,如果pow系统能够使垃圾邮件发送者需要更多的时间来发送邮件,就可以增大他们的成本,起到抵挡攻击的作用。

pow系统中一定有两个角色,工作者和验证者,他们需要具有以下特点:

  • 工作者需要完成的工作必须有一定的量,这个量由工作验证者给出。

  • 验证者可以迅速的检验工作量是否达标。

  • 工作者无法自己"创造工作",必须由验证者发布工作。

  • 工作者无法找到很快完成工作的办法。

pow历史

工作量证明,是一种应对拒绝服务攻击和其他服务滥用的经济对策。它要求发起者进行一定量的运算,也就意味着需要消耗计算机一定的时间。这个概念由Cynthia Dwork 和Moni Naor 1993年在学术论文中首次提出。而工作量证明(POW)这个名词,则是在1999年 Markus Jakobsson 和Ari Juels的文章中才被真正提出。

哈希运算是一种最常见的工作量证明机制,它是亚当·贝克(Adam Back)在1997年发明的,用于抵抗邮件的拒绝服务攻击及垃圾邮件网关滥用。在比特币之前,哈希现金被用于垃圾邮件的过滤,也被微软用于hotmail/exchange/outlook等产品中(微软使用一种与哈希现金不兼容的格式并将之命名为电子邮戳)。

该机制主要利用HASH运算的复杂度,通过给定的初始值,通过简单的值递增规律,利用HASH碰撞原理,直到找到特定的碰值,可以通过调节碰撞值得长度,实现对于工作量的调节(碰撞值越长,所需要的运算量越大)

哈希现金也被哈尔·芬尼以可重复使用的工作量证明(RPOW)的形式用于一种比特币之前的加密货币实验中。另外,戴伟的B-money、尼克·萨博的比特金(Bit-Gold)这些比特币的先行者,都是在哈希现金的框架下进行挖矿的。

哈希现金扫盲

哈希现金HashCash是最典型的Solution-verification实现,HashCash也是目前应用最为广泛的反垃圾邮件的pow系统。

在HashCash系统中,发件方向邮箱服务器发送的邮件信息中必须包含一段邮件签名,邮件签名中包含有收件人地址、发件时间和一个数字counter,counter需要使邮件签名满足条件:

利用SHA-1散列算法对邮件签名生成一个160-bit长度的哈希值,该哈希值前20位全为0 。此算法利用了散列算法的不可预测性,SHA-1的碰撞概率决定了算法的安全性。

在目前的认知中,发件方除了穷举尝试,无法很快的找到满足条件的签名串。于是发件方在发送邮件之前的工作就是不断地counter++生成新的邮件签名,然后获取SHA-1哈希值,判断前20位是否全为0,如果不是的话重新生成。而对于邮件服务器而言,只需要做一次SHA-1判断生成的签名是否满足条件即可,完全符合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 。

问题三,服务器端需要丢弃掉已经出现过的答案,同时需要对收件人地址和时间戳做合法性校验即可。

HASH POW原理

工作量证明系统主要特征是客户端需要做一定难度的工作得出一个结果,验证方却很容易通过结果来检查出客户端是不是做了相应的工作。这种方案的一个核心特征是不对称性:工作对于请求方是适中的,对于验证方则是易于验证的。它与验证码不同,验证码的设计出发点是易于被人类解决而不易被计算机解决。

下图表示的是工作量证明的流程:

举个例子,给定的一个基本的字符串"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

比特币体系里的工作量证明机制与上述示例类似,但要比它更复杂一些,以后会另起文章说明

详解POW工作量证明原理的更多相关文章

  1. 淘宝JAVA中间件Diamond详解(2)-原理介绍

    淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...

  2. [转帖]万字详解Oracle架构、原理、进程,学会世间再无复杂架构

    万字详解Oracle架构.原理.进程,学会世间再无复杂架构 http://www.itpub.net/2019/04/24/1694/ 里面的图特别好 数据和云 2019-04-24 09:11:59 ...

  3. Go实现Pow工作量证明

    之前使用python编写了一段代码实现了工作量证明机制,近期由于参与以太坊智能合约开发钱包的工作接触到golang语言,所以借此以go来实现Pow(Proof of work). 实现代码如下: // ...

  4. SpringCloud 详解配置刷新的原理 使用jasypt自动加解密后 无法使用 springcloud 中的自动刷新/refresh功能

    之所以会查找这篇文章,是因为要解决这样一个问题: 当我使用了jasypt进行配置文件加解密后,如果再使用refresh 去刷新配置,则自动加解密会失效. 原因分析:刷新不是我之前想象的直接调用conf ...

  5. [转帖]详解Linux系统inode原理--硬链接、软链接、innodb大小和划分等

    详解Linux系统inode原理--硬链接.软链接.innodb大小和划分等 原创 波波说运维 2019-07-17 00:03:00 https://www.toutiao.com/i6713116 ...

  6. RocketMQ详解(一)原理概览

    专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...

  7. 详解PHP的执行原理和流程

    简介 先看看下面这个过程: • 我们从未手动开启过PHP的相关进程,它是随着Apache的启动而运行的: • PHP通过mod_php5.so模块和Apache相连(具体说来是SAPI,即服务器应用程 ...

  8. sed 增删改查详解以及 sed -i原理

    我为什么要详细记录sed命令:     sed 擅长取行.工作中三剑客使用频率最高,本篇文章将对sed命令常用的 增,删,改,查 进行详细讲解,以备以后工作中遗忘了查询,sed命令是作为运维人员来说, ...

  9. Android 异步通信:图文详解Handler机制工作原理

    前言 在Android开发的多线程应用场景中,Handler机制十分常用 今天,我将图文详解 Handler机制 的工作原理,希望你们会喜欢 目录 1. 定义 一套 Android 消息传递机制 2. ...

随机推荐

  1. 一个深拷贝方法的漏洞与一个javascript经典bug

    今天做某个项目,需要函数深拷贝. 在网上随便找了个代码粘上去,结果报错了. /** * * @desc 递归法 对象深拷贝 * @param {Object} * @return {new Objec ...

  2. PyQt样式设计

    QSS QSS(Qt Style Sheets)即PyQt样式表,是用来定义控件外观的一种机制.QSS内部实现大量参考了CSS,但是功能没有CSS强大,主要体现在选择器少,属性少等. 使用QSS 格式 ...

  3. Android Studio采坑记录

    折腾了几个月的Android Studio,终于在今天被我搞定了 ( ̄▽ ̄)~* 开贴记录下,免得下次再次采坑 先说下我之前电脑的环境配置吧,sdk是几年前在网上下载别人整理出来的包,一直没有更新过 ...

  4. 【Unity3D】简单常用的功能实现1——鼠标点击实现移动

    [鼠标点击实现移动] 第一步,在要移动的GameObject的Inspector面板中添加角色控制器组件并调整参数. 参数的调整可以依照Scene面板,如下图的绿色线框(角色控制器组件是一种胶囊形状的 ...

  5. js冒泡排序和数组去重

    1.冒泡排序 <script>//声明一个数组 var arr=[1,88,66,22,35,65,4,52];//自执行函数 (function maopao(){ for(var i= ...

  6. Shell变量的作用域:Shell全局变量、环境变量和局部变量

    Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他 ...

  7. 字符输入输出不一样!:什么情况下需要getchar()吃空格和回车

    今天一个很简单的题居然一直不对... 大概是用字符组成的一个方块..然后各种转换, 关键是我算法都写好了,然而输入进去的字符方块直接输出来都不太对... 后来想起吃空格问题,因为scanf了%c的话, ...

  8. C/C++编程笔记:C语言NULL值和数字 0 值区别及NULL详解

    在学习C语言的时候,我们常常会碰到C语言NULL值和数字 0 ,很多小伙伴搞不清楚他们之间的一个区别,今天我们就了解一下他们之间的区别,一起来看看吧! 先看下面一段代码输出什么: 输出<null ...

  9. 牛客练习赛64 如果我让你查回文你还爱我吗 线段树 树状数组 manacher 计数 区间本质不同回文串个数

    LINK:如果我让你查回文你还爱我吗 了解到了这个模板题. 果然我不会写2333... 考试的时候想到了一个非常辣鸡的 线段树合并+莫队的做法 过不了不再赘述. 当然也想到了manacher不过不太会 ...

  10. CF R630 div2 1332 E Height All the Same

    LINK:Height All the Same 比赛的时候 被这道题给打自闭了 还有1个多小时的时候开始想 想了30min 无果 放弃治疗. 心态炸了 F不想看了 应该要把题目全看一遍的 下次不能这 ...