作者:黄武汉
4 区块链的难度设计
戈登.摩尔(Intel创始人)曾说过:集成电路上可容纳的电晶体数目,约每隔24个月便会增加一倍。翻译成通俗的说法:计算机的性能,每隔18个月会提高一倍(18个月是大卫.豪斯提出的)。在第三章中,我们了解到,挖矿所需要的时间,主要体现在算力上。当计算机的计算性能不断提升时,如果不做任何处理,那挖矿需要的时间会越来越短。难度设计就是为了平衡摩尔定律产生的影响,将挖矿时间维持在10分钟左右。
区块链的工作量证明,是寻找一个幸运数,让一些输入和幸运数的双SHA256数值小于难度目标(DIFF_TARGET,区块头部的一个字段,具体参见第二章的区块链结构)。所以难度目标越大,难度越小,符合要求的幸运数越容易找到,所需要尝试的次数越少。创世区块存储着最大的难度目标(DIFF_TARGET_MAX):0x1d00ffffff,这是一种特殊的浮点压缩格式,真正的数值是后三个字节为底,前一个字节为指数的一个字符串,即:0x00ffff*2^(8*(0x1d-3)),计算结果是一个前面有32个0的256位二进制数字,一般我们也简单的以前面有几个0来表示难度目标。
区块链中决定难度目标的是难度系数(DIFF),难度目标的计算公式为:
DIFF_TARGET=DIFF_TARGET_MAX/DIFF
创世区块的DIFF=1,所以难度目标等于最大难度目标值。DIFF每隔2016区块调整一次,记调整前的难度系数为DIFF_OLD,调整后的难度系数为DIFF_NEW,那:
DIFF_NEW=DIFF_OLD*(20160/最近2016区块计算所需的分钟数)
可以看出,如果最近2016区块的产生时间变短,那相应的难度系数会增大,难度目标值就会减小,通过这种方式,区块链动态调节着难度目标,保证10分钟的计算时间。最新的难度系数为
2,874,674,234,415。下图展示了难度系数的变化历史:
5 比特币算力问题
5.1 算力及增长
算力代表一个节点的计算能力,以hash速率来衡量。通常用hash/s表示,简写为H/S。目前全网算力大概为:20.70EH/S(1E=1000P,1P=1000T,1T=1000G,1G=1000M,1M=1000K,1K=1000),下图是目前全网算力的具体分布:
算力的增长,一方面受益于比特币的挖矿奖励递减设计。由于奖励越来越少,越早进入的矿工收益越大,所以比特币在早期吸引了一大堆矿工参与,扩充全网算力,一定程度上维护了区块链的稳定。另一方面,从最早的全能CPU,到专门支持简单计算的GPU,再到后来的ASIC,矿池等硬件设备的迭代更新,也使得算力呈指数增长。
5.2 算力作弊
通常用全网算力占比来衡量节点取得记账权的概率,如上图中的BTC.com就有33.6%的概率优先取得记账权。目前矿工的主要收入来自挖矿奖励,单个矿工的算力占比极低,能够争取到记账权的概率几乎为0。这使得单个矿工的投入产出比极不稳定,绝大部分的投入将毫无产出。为了解决这个问题,一些矿工加入了矿池,矿池算力占比高,挖到矿的概率也大。矿工加入矿池后,由矿池统一分配任务争取记账权,当池挖到矿时,会根据算力占比,将奖励分配到各个矿工。这样一来,虽然每次挖矿能得到的奖励变少,但是投入产出比变得稳定,所以许多矿工选择了这种方式进行投资。因为矿池的存在,算力出现了中心化,使得一些恶意攻击成为了可能,这里讨论两种常见的恶意攻击:
5.2.1 封堵交易
一条交易只有被封装到一个区块并记录到最长链时,才会被承认。如果一个组织不想承认某类交易,当发现这些交易被包含在最新的第n个区块时,可以进行恶意封堵。在第n-1区块之上,创建一个新的分支,自行挖矿。当恶意分支的长度大于正常分支时,正常分支上的所有区块便会失效,第n个区块之上交易也就得不到确认。理论上,不管一个组织掌握多少算力,都能发动这种攻击,只是成功概率不同罢了。如果失败,那恶意分支上的所有工作量都会被认定为无效,造成损失。
5.2.2 逆转交易
当一笔交易记录到第n个区块,并被6次确认后,交易双方完成了物质交换。此时交易发起方从n-1区块开始生成恶意分支,将之前的交易抹掉,并自行维护分支。在经过多个区块的生成博弈后,恶意分支长于原始分支,交易被逆转。这种攻击的代价比封堵更大,因为要追上6个区块。如果一个组织掌握了51%的算力,这种攻击完全是有可能进行的,从概率上讲,最终一定会成功。但在追赶的过程中,不会得到任何其他组织的承认,也得不到奖励,与需要逆转的交易收入相比,往往得不偿失。
5.2.3 作弊成本
假设全网算力为:ALL(算力)=20EH/S,目前较先进的蚂蚁S9矿机单矿机的算力大约为E(算力)=13.5TH/S,要掌握51%的算力,则需要的矿机数量:
N(矿机)=ALL(算力)*0.51/E(算力)
蚂蚁S9矿机的成本单台为CE(矿机) = 10900元,故矿机总成本为:
CA(矿机) = CE(矿机) * N(矿机) ≈ 82 亿(元)
蚂蚁S9矿机的功耗在1300w,1KWh的电费是0.35元,按照24小时计算,单台矿机24小时需要的电费:
CE(电费) = 1.3*24*0.35 = 10.92(元)
24小时,所有矿机的电费为:
CA(电费) = N(矿机) * CE(电费) ≈ 825万(元)
当前10分钟12.5BTC的产出,24小时能够生产1800BTC。每个BTC的价格PE(BTC) = 60000元。51%的算力在24小时能产生的BTC大约为:1800*51% = 918 BTC。那收益约为:
P(BTC) = 918 *60000 = 5508万
对于矿工而言:
挖矿的成本 = 矿机成本 + 电费 + 维护费及人工成本+ 矿场折旧费等
不去计算维护费,折旧费等,一个占有51%算力的组织,每天维护矿机的电费需要825万,前期投入为82亿,每天正常工作收益为5508万。假如不老实工作,想着逆转交易,那每天要承受着825万的电费消耗,多少天赶上正常分支,就要承受多少天的电费消耗,还有可能使得82亿的投入血本无归。所以作弊虽然可能,但基本不会去实施,成本难以支撑。
网上有很多利润计算工具,下图是其中一个,可以看出,目前投资一台蚂蚁S9矿机,设备投入为CE(矿机) = 10900元,每日电费为10.92元,大约需要216天才能回本,这种计算及其依赖BTC的价格波动和全网算力:
6 区块链脚本设计
6.1 脚本介绍
比特币网络中,没有账户余额的概念。交易主要由输入和输出构成(参考第二章的数据结构)。每一个输入的数据分为两个部分,一部分是用来说明对应UTXO位置的哈希地址及索引号,一部分用来解锁对应的UTXO的脚本;每一个输出的数据也可以分为两个部分,一部分是说明此UTXO包含的币值,一部分是用于加锁UTXO的脚本。当需要花费一笔UTXO时,需要提供一个输入脚本,将输入脚本与UTXO的输出脚本相连,执行脚本语言。如果结果不为0,则通过验证。
比特币的脚本语言是一种基于逆波兰表示法(后缀表示法)的基于堆栈的执行语言,包括256个指令(因为是一个字节表示的,0X00-0XFF,最多能表示256种意思),这些指令虽然可以进行丰富多样的编程,但却没有循环或者复杂的条件控制等
。这种脚本设计,主要是出于安全性考虑,可以避免一些逻辑炸弹的攻击,是一种图灵非完备的语言,在以太坊中,已经做了升级。下表展示了一些比较常见的指令以及下面要用到的变量含义:
6.2 脚本分类
从描述中可以看出,交易输出中的加锁脚本是可编程的,任何能够使得脚本运行结果不为0(false)的解锁脚本,都能使用这笔UTXO。一般加锁脚本,都是要求数字签名验证解锁的,针对的是明确的授予方,可以是一人(P2PK),也可能是多人(MS)。有些加锁脚本会设置一个难题,网络中的所有参与者都可以通过解决难题来争取这笔UTXO。有些加锁脚本不设置门槛,就像在天台撒钱一样,谁都能用。有些加锁脚本用来销毁UTXO,任何人都无法解锁使用。有些加锁脚本会设置时间限制,延时使用....下表整理了这些常用的脚本信息,可以结合上面的指令变量信息理解:
6.3 实例解析
这里拉取比特币网络的第一笔实物交易-披萨交易的原数据,对这种基于逆波兰表示法(后缀表示法)的基于堆栈的执行语言做一个实例讲解,它是一个典型的P2PHK交易。
首先从任意的节点拉取哈希值为:cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79的交易数据:
01000000018dd4f5fbd5e980fc02f35c6ce145935b11e284605bf599a13c6d415db55d07a1000000008b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabbffffffff0200719a81860000001976a914df1bd49a6c9e34dfa8631f2c54cf39986027501b88ac009f0a5362000000434104cd5e9726e6afeae357b1806be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce3388fa1abd0fa88b06c44ce81e2234aa70fe578d455dac00000000
按照第二章的数据结构,进行如下的解析:
将解锁脚本与加锁脚本链接,形成这样的执行流程:
由于栈顶非0,所以解锁成功,花了10000BTC(现在近7亿RMB了),买了2块披萨,真是人才!!!
7 分布式共识问题
分布式一致性问题,可以简单描述为如何保证分布式网络中的所有节点对于某个提案达成一致的意见,即达成共识的问题。分布式网络中,造成不一致的原因,大致分成两类:拜占庭错误和非拜占庭错误。非拜占庭错误指节点发生停机,延迟响应等这类能够预料结果的问题。而拜占庭错误,是指节点会发生信息伪造等无法预料结果的问题,非拜占庭问题是拜占庭问题的一个子集。区块链是一个去中心化的产品,在比特币网络中,没有一个中心化的权威机构能够对网络中的货币归属或交易顺序做检测,每个节点都可能伪造信息,所以区块链要解决的是拜占庭错误产生的分布式共识问题。
非拜占庭错误产生的分布式一致性问题,有Paxos、Raft等算法,不详述。区块链的共识问题,目前主要有PoW、PoS、DPoS等方法。
7.1 PoW
Proof of Work,工作量证明。在区块链中每产生一个区块,需要耗费一定的计算工作量,寻找一个合法的随机数来争取记账权,同时约定全网只承认最长的链条。当网络中存在恶意节点伪造数据时,需要耗费一定的工作量,这种作弊成功的概率与恶意节点拥有的算力占比相关,之前文章已经详细解释过。
随着全网算力的不断增长,作弊成本会越来越高。但这种算力密集型的工作,会使得算力越来越集中,目前全网算力基本已经被几大矿池占有,这种现状违背了去中心化的设计初衷。另外,除了最长链路上的区块,其他分支区块上的算力都将浪费,这种损耗随着算力增长,会越来越严重。为了解决这些问题,有人提出了PoS。
7.2 PoS
Proof of Stake,权益证明。在区块链中,通过一定数量的代币证明来争取记账权。代币与持有的货币数量及持有时间有关,拥有代币越多的人越容易获得记账权。网络中的恶意节点想要作弊,就必须拥有相当数量的代币。作弊被发现后,会被罚处相当量的货币,以提高作弊的代价。由于记账权与拥有的货币数量息息相关,系统的稳定健康对于那些货币占有量大的矿工而言更为重要。所以按照利益导向,财富越多的人,即越有记账权的人,越不会作弊。
相比PoW而言,PoS不会浪费算力。在作弊成本上,需要占有大量的货币。与PoW的算力对比,作弊的门槛更高,作弊的可能性更小。但是PoS会导致记账权被少数富裕的矿工控制,一定程度上也违背了去中心化的设计初衷。
为此,有人提出了改进的DPoS。
7.3 DPoS
Delegated Proof of Stake,股份授权证明机制。与PoS相比,只有成功竞选为受托人的矿工才拥有记账权。持有货币的矿工,可以参与投票,投票的权重与矿工持有的货币数量成正比,矿工可以随时投票或者撤销投票。矿工通过一定的机制成为候选人,在全网拉票,通过一定的得票率,竞选成为所托人。区块链网络可以决定受托人数量,受托人之间没有权重差异,竞选之后会打乱顺序,轮询获得记账权参与区块搭建。一定时效后,全网会进行新一轮的选举,确定新的受托人。
在这种机制中,投票比重越大的矿工,持有的货币数量越多,从利益导向来看,越希望区块健康发展。竞选成为受托人的矿工,如果不称职就会被剔除,从而损失成为受托人后创建区块所能得到的收益。虽然创建区块在一个中心化的区域进行,但是这种中心化是受到控制的。网络中的每个节点都有能力决定受托人,所以又能保证一定的去中心化。
相关阅读:
走进区块链(一)
走进区块链(二)
走进区块链(三)
走进区块链(四)
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者黄武汉授权发布。