叔块(uncle blocks)奖赏

GHOST 协议是一项不起的创新,由 Yonatan Sompolinsky 和 Aviv Zohar 在 2013 年 10 月首次提出的。它是处理快速出块伴生问题的第一个仔细尝试。

GHOST 的意图是处理这样一个难题:更短的出块时刻(因而承认速度会更快)会导致有更多区块 “过期” 因而安全性会下降 —— 由于区块在网络中传达需求必定时刻,假如矿工 A 挖到一个区块并向全网播送,在播送的路上,B 也挖出了区块,那么 B 的区块是过期的,且 B 的本次挖矿对网络的安全没有奉献。

此外,还有一个中心化问题:假如 A 是一个矿池,有 30% 的算力,B 有 10% 的算力。A有 70% 的时刻发生过期的区块(由于其他的 30% 时刻会发生最新区块,能够为 TA “当即” 得到了最新块的数据而无需等候区块传达),而 B 有 90% 的时刻发生过期区块。假如区块的产出时刻间隔很短,那么过期率就会变高,则 A 凭借其更大的算力使挖矿功率也更高。所以,区块生成过快,简略导致网络算力大的矿池在事实上独占挖矿进程。

根据 Sompolinsky 和 Zohar的描绘,GHOST 处理了在核算哪个链是最长的链的进程中,因发生过期区块而形成的网络安全性下降的问题。也便是说,不仅是父区块和更早的区块,一起过期的旁支区块(在以太坊中,咱们称之为 “叔块”)也被增加到核算哪个块具有最大的总工作量证明中去。

为了处理第二个问题:中心化问题,咱们采用了另一种策略:对过期区块也供给区块奖赏:挖到过期区块的奖赏是该区块基础奖赏的 7/8;而包括过期区块的侄子区块将收到 1/32 的基础奖赏作为赏金。可是,买卖费不会奖赏给叔块和侄块。

在以太坊中,过期区块只能被其兄弟区块的 7 代以内的直系子孙区块包括为叔块。之所以这样约束是由于,首要,GHOST 协议若不约束过期区块的代际间隔,将会花费大量开支在核算过期区块的有用性上;其次,无约束的过期区块鼓励方针会让矿工失掉在主链上挖矿的热情;终究,核算标明,过期区块奖赏方针约束在 7 层内供给了大部分所需的效果,而且不会带来负面效应。

  • 度量中心化危险的一个模仿器可见此处:https://github.com/ethereum/economic-modeling/blob/master/ghost.py

  • 一个更高层次的评论可见此处:https://blog.ethereum.org/2014/07/11/toward-a-12-second-block-time/

校正注:此处的 “包括” 在技术上的形式是:侄块在区块头中引用叔块的区块哈希值,然后把叔块的区块头包括在区块体内。

区块时刻算法的规划决策包括:

  • 区块时刻 12s:挑选 12 秒是由于这现已是善于网络推迟的最短时刻间隔了。在 2013 年的一份关于丈量比特币网络推迟的论文中,确认了 12.6 秒是新发生的区块传达到 95% 节点的时刻;可是,该论文还指出传达时刻与区块巨细成比例,因而在更快的钱银中,咱们能够期待传达时刻大大减少。传达间隔时刻是稳定的,约为 2 秒。可是,为了安全起见,在咱们的分析中,咱们假定区块的传达需求 12 秒

  • 7 代先人以内的约束:这样规划的意图是期望只保存少数区块,而将更早之前的区块铲除。现已证明 7 代的可引用规模就能够供给大部分所需的效果。

  • 1 代后裔的约束:(例如,设 c = child 且 p = parent,则 c(c(p(p(p(head))))) 是无效的):这也是出于简练性的规划方针,而且上述的模仿器显示这不会带来很大的中心化危险。(校正注:此句难解;一种或许的意思是:叔块的子孙不能作为叔块,即只有主链的一代旁支能作为叔块。)

  • 叔块有必要是有用的 :叔块有必要是有用的 header,而不是有用的区块。这样做也是为了简化,将区块链模型保持为线性数据结构(而不会变成 DAG)。不过,要求叔块是有用的区块也是有用的办法。

  • 奖金分配:7/8 的挖矿基础奖赏分配给叔块,1/32 分给侄块,它们买卖费用都是 0%。假如费用占多数,从中心化的角度看,这会使叔块鼓励机制无效;可是,这也是为什么只需咱们持续运用 PoW,以太坊就会不断发行以太币的原因。

难度更新算法

目前以太坊经过以下规矩进行难度更新:

难度更新规矩的规划方针如下:

  • 快速更新:区块间的时刻应该随着 hash 算力的增减而快速调整;

  • 低波动性:假如挖矿算力稳定,那么难度不应剧烈波动;

  • 简略:算法的完成应相对简略;

  • 低内存:算法不应依靠于过多的前史区块,要尽或许少的运用 “内存变量”。假设有最新的十个区块,将存储在这十个区块头部的内存变量相加,这些区块都可用于算法的核算;

  • 不可爆破:算法不应让矿工有过多篡改时刻戳或许矿池重复增加或删去算力的鼓励

咱们当时的算法在低波动性和抗爆破性上并不抱负。最近,咱们计划把时刻戳参数改为与父区块和祖父区块比较,所以矿工只有在连续挖 2 个区块时,才有动力去修正时刻戳。另一个更强壮的模仿公式: 

https://github.com/ethereum/economic-modeling/blob/master/diffadjust/blkdiff.py 

Gas 和费用

比特币中所有买卖大体相同,因而它们的网络本钱用单一一种单位来模仿。以太坊中的买卖要更杂乱,所以买卖费用需求考虑到账户的许多方面,包括网络带宽费用、存储费用和核算费用。尤其重要的是,以太坊编程言语是图灵完备的,所以买卖会运用恣意数量的宽带、存储和核算本钱;而终究会运用多少数量是无法可靠预测的(由于所谓的 “图灵停机问题”)(校正注:即不存在一个可靠的办法,能够断语恣意可在图灵机上履行的程序会不会在有限步内终止)。防止有人运用无限循环来施行拒绝服务式进犯是咱们的一个关键方针。

以太坊买卖费用的根本机制如下

  • 每笔买卖有必要指明自身乐意耗费的 gas 数量(即指定 startgas 的值),以及乐意为每单元 gas 付出的费用(即 gasprice ),在买卖履行开始时,startgas * gasprice 价值的以太币会从发送者账户中扣除;(校正注:此处的 startgas 便是咱们现在惯用的 gaslimit 。)

  • 买卖履行期间的所有操作,包括读写数据库、发送音讯以及每一步的核算都会耗费必定数量的 gas;

  • 假如买卖履行完毕,耗费的 gas 值小于指定的约束值,则买卖履行正常,并将剩余的 gas 值赋予变量 gas_rem ; 在买卖完成后,发送者会收到返回的 gas_rem * gasprice 价值的以太币,而给矿工的奖赏是(startgas - gas_rem)* gasprice 价值的以太币;

  • 假如买卖履行中,gas耗费殆尽,则所有的履行康恢复样,但买卖仍然有用,仅仅买卖的唯一成果是将 startgas * gasprice 价值的以太币付出给矿工,其他不变;

  • 当一个合约发送音讯给另一个合约,能够对这个音讯引起的子履行设置一个 gas 约束。假如子履行耗尽了 gas,则子履行康恢复样,但 gas 仍然耗费。(校正注:截至本文校正之时(2021 年 7 月 9 日),这一点还未改动,但它在未来有或许会改动。

上述说到的几点都是有必要满意的,例如

  • 假如买卖不需求指定 gas 约束,那么歹意用户就会发送一个有数十亿步循环的买卖。没有人能够处理这样的买卖,由于处理这样的买卖花的时刻或许很长很长;可是谁也无法预先奉告网络上的矿工,这就会导致拒绝服务的缝隙发生。

  • 一种替代严厉 gas 计数的办法是时刻约束,但它不或许有用,由于它们太主观了(某些核算机比别人的更快,即便大家的核算机都一样也仍然有或许呈现差池)。

  • startgas * gasprice 的整个值,在开始时就应该设置好,这样不至于在买卖履行中形成该账户 “破产”、无力持续付出 gas 费用。一边履行一边检查余额也不行,由于账户能够把余额放到其他当地。

  • 假如在 gas 不行的情况下,买卖履行不会彻底恢复(回滚),合约就有必要采用强有力的安全措施来防止合约发生改变。

  • 假如子约束不存在,则歹意账户能够对其他合约施行拒绝服务进犯。进犯者能够先与受害合约达到一致意见,然后在核算进程开始时插入一个无限循环,那么发送音讯给受害合约或许受害合约的任何补救尝试,都会使整个买卖死锁。(校正注:此句亦难解。)

  • 要求买卖发送者而不是合约来付出 gas,这样大大增加了开发人员的可操作性。以太坊前期的版本是由合约来付出gas的,这导致了一个相当严重的问题:每个合约有必要完成 “门卫” 代码,保证每个传入的音讯为合约供给了满足的以太币供其耗费。

gas 耗费核算有以下特点

  • 关于任何买卖,都将收取 21000 gas 的根本费用。这些费用可用于付出运转椭圆曲线算法所需的费用(该算法旨在从签名中康复发送者的地址)以及存储买卖所花费的硬盘和带宽空间。

  • 买卖能够包括无限量的 “数据” 。虚拟机中的某些操作码,能够让收到这样买卖的合约拜访这些数据。数据的 “固定耗费量” 规矩是:每个零字节 4 gas,非零字节 68 gas。这个公式的发生是由于用户向合约发送的买卖中,大部分的买卖数据由一系列的 32 字节的参数组成,其间多数参数具有许多前导零字节。该结构看起来似乎功率不高,但由于压缩算法的存在,实践上还是很有功率的。咱们期望此结构能够替代其他更杂乱的机制:这些机制根据预期字节数严厉包装参数,然后导致编译阶段杂乱性大增。这是三明治杂乱模型的一个破例,但由于本钱效益比,这也是合理的模型。

  • 用于设置账户存储项的操作码 SSTORE 的耗费是:1)将零值改为非零值时,耗费 20000 gas;2)将零值变成零值,或非零值变非零值,耗费 5000 gas;3)将非零值变成零值,耗费 5000 gas;此外,买卖履行成功(即未耗尽 gas 买卖就履行完了)后会退回 15000 gas。退款金额上限是买卖耗费 gas 总额的 50%。这给了人们小小鼓励去铲除存储项。咱们注意到,正由于缺少这样的鼓励,许多合约的存储空间没有被有用运用,然后导致了存储数据的快速胀大。这一规划既能供给 “为存储项持续收取租金” 形式的大部分优点,又不会失掉合约一旦建立就能够永久存在的保证。推迟退款机制是必要的,由于能够阻挠拒绝服务进犯:进犯者能够发送一笔含有少数 gas 的买卖,循环铲除大量的存储项,直到用光 gas,这样耗费了大量的验证算力,但实践并没有真正铲除存储,也不需求付出许多 gas。50% 的上限的是为了保证打包买卖的矿工依然能够确认履行买卖的核算时刻的上限。

  • (校正注:首要,SSTORE 等状况拜访操作码的 gas 耗费量现已随着以太坊的硬分叉而屡次更改。截至 2021 年 7 月,最新的数值可见《柏林晋级内容概览》;在可预见的未来,这个操作码的数值还会持续改变;其次,这里的 gas refund 机制,过后证明并没有启动缓解状况数据的胀大问题,反而恶化了该问题,由于人们能够在 gas price 较低时写入大量垃圾数据,在 gas price 较高时铲除这些数据来取得 gas,这便是 “GasToken” 的原理。当时已确认,在 “伦敦” 分叉中会改动 gas refund 机制。

  • 合约供给的音讯数据是没有本钱的。由于在音讯调用期间不需求实质复制任何数据,调用数据(call data)能够简略地视为指向父合约 memory 的指针,该指针在子进程履行时不会改动。

  • Memory 是一个能够无限扩展的数组,可是,每扩展 32 字节的 memory 就会耗费 1 gas 的本钱,缺少 32 字节以 32 字节计。(校正注:memory 一般译为内存,但在以太坊的语境下,它是 EVM 由于存储数据的三种类型之一,因而都不译,以示其特别性。)

  • 某些操作码的核算时刻极度依靠参数,gas 开支核算是动态改变的。例如,EXP 的的开支是指数级其他(10 gas + 10 gas/字节,即,x^0 = 1 gas、x^1 … x^255 = 2 gas、x^256 … x^65535 = 3 gas,等等)。复制操作码(如:CALLDATACOPY, CODECOPY, EXTCODECOPY)的开支是 1 gas + 1 gas/32 字节(四舍五入;LOG 操作码的规矩也类似)。Memory 扩展的开支不包括在这里。如若包括,会变成一个平方进犯向量(50000 次的 CALLDATACOPY,每次耗费 50000 gas,则其核算量应是 50000^2,但假如不运用动态收费规矩,就只需付出 ~50000 gas)。

  • 假如值不是零,操作码 CALL(以及 CALLCODE)会额定耗费 9000 gas。这是由于任何值传输都会引起归档节点的前史存储显著增大。请注意,操作的 实践耗费 是 6700;可是此基础上,咱们强制增加了一个自动给予接收者的 gas 值,这个值最小 2300。这样做是为了让承受买卖的钱包至少有满足的 gas 来生成 log。

Gas 机制的另一个重要部分是 gas 价格自身体现出的经济学原理。比特币中,默认的办法是采纳朴实自愿的收费办法,矿工扮演守门人的角色而且动态设置收费的最小值。以太坊中答应买卖发送者设置恣意数意图 gas。这种办法在比特币社区十分受欢迎,由于它是 “市场经济” 的体现:答应矿工和买卖者之间根据供需联系来决定价格。可是,这种办法的问题是,买卖处理并不遵从市场原则。尽管能够将买卖处理看作是矿工向发送者供给的服务(这听起来很直观),但实践上矿工所处理的每个买卖都有必要由网络中的每个节点处理,所以买卖处理的大部分本钱都由第三方机构承担,而不是决定是否处理它的矿工。因而,“公地悲惨剧” 问题很有或许发生。

当时,由于缺少矿工在实践中的行为的清晰信息,所以咱们将采纳一个十分简略公平的办法:投票体系,来设定单个区块可耗费的 gas 总额。矿工有权将在最新区块的 gas 上限基础上变更 0.0975% (1/1024),作为当时区块的 gas 上限。所以终究的 gas 上限应该是矿工们设置的中间值。咱们期望将来能够采用软分叉的办法来运用愈加准确的算法。

虚拟机

以太坊虚拟机是履行买卖代码的引擎,也是以太坊与其他体系的核心差异。请注意,虚拟机应该同 “合约与音讯模型” 分开考虑。例如,SIGNEXTEND 操作码是虚拟机的一个功能,但实践上 “某个合约能够调用其他合约并指定子调用的 gas 限定值” 是 “合约与音讯模型” 的一部分。

EVM的规划方针如下:

  • 简略:操作码尽或许的少而且低级;数据类型尽或许少;虚拟机的结构尽或许少;

  • 成果清晰:在 VM 规范中,没有任何或许发生歧义的空间,成果应该是彻底确认的。此外,核算步骤应该是准确的,以便能够丈量 gas 的耗费量;

  • 节约空间:EVM 组件应尽或许紧凑;

  • 为预期用途而特化:在 VM 上构建的运用应能处理 20 字节的地址,以及 32 位的自定义加密值,拥有用于自定义加密的模数运算、读取区块和买卖数据与状况交互等才能;

  • 简略安全:为了让 VM 不被利用,应该能够简略地让建立一套 gas 耗费本钱模型的操作;

  • 优化友爱:应该易于优化,以便即时编译(JIT)和 VM 的加速版本能够构建出来。

一起 EVM 也有如下特别规划

  • 暂时/永久存储的差异:咱们先来看看什么是暂时存储和永久存储。暂时存储:存在于 VM 的每个实例中,并在 VM 履行完毕后消失。永久存储:存在于区块链状况层。假设履行下面的树(S 代表永久存储,M 代表暂时存储):

  1. A调用 B;

  2. B 设置 B.S[0]=5,B.M[0]=9 ;

  3. B 调用 C;

  4. C 调用 B。

    此刻,假如B企图读取 B.S[0] ,它将得到B前面存入的数据,也便是 5;但假如 B 企图读取 B.M[0] ,它将得到 0,由于 B.M 是暂时存储,读取它的时分是虚拟机的一个新的实例。在一个内部调用(inner call)中,假如设置 B.M[0] = 13 和 B.S[0] = 17 ,然后内部调用和 C 的调用都终止、回到了 B 的外部调用(outer call),此刻读取 M,将会看到 B.M[0] = 9 (此值是在上一次同一 VM 履行实例中设置的), B.S[0] = 17 。假如 B 的外部调用完毕,然后 A 再次调用 B,将看到 B.M[0] = 0,B.S[0] = 17 。这个区其他意图是:1.每个履行实例都分配有内存空间,不会由于循环调用而减损,这让安全编程愈加简略。2.供给一个能够快速操作的内存形式:由于需求修正树,所以存储更新必定很慢。

  • 栈/memory 形式:前期,核算状况(除了指向下一个指令的程序计数器)有三种:栈(stack,一个 32 字节规范的 LIFO 栈),内存(memory,可无限延长的暂时字节数组),存储项(storage,永久存储)。在暂时存储端,栈和内存的替代计划是 memory-only 范式,或许是寄存器和内存的混合体(两者差异不大,寄存器本质上也是一种内存)。在这种情况下,每个指令都有三个参数,例如: ADD R1 R2 R3: M[R1] = M[R2] + M[R3] 。挑选栈范式的原因很明显,它使代码缩小了 4 倍。

  • 单词巨细 32 字节:在大多数结构中,如比特币,单词巨细是 4 或 8 字节。4 或 8 字节对存储地址和加密核算来说局限性太大了。而不对巨细作约束又很难建立相应安全的 gas 模型。32 字节是一个抱负巨细,由于它满足存储下许多密码算法所需求的大数值以及地址,又不会由于太大而导致功率低下。

  • 咱们有自己的虚拟机:咱们的虚拟机运用 java、Lisp 和 Lua 等言语开发。咱们以为开发一款专业的虚拟机是值得的,由于:1)咱们的 VM 规范比其他许多虚拟机简略的多,由于其他虚拟机为杂乱性付出的价值更小,也便是说它们更简略变得杂乱;可是,在咱们的计划中每额定增加一点杂乱性,都会给集约化开展带来妨碍,并带来潜在的安全缺陷,比如一致错误,这就让咱们的杂乱性本钱很高;2)咱们的 VM 愈加专业化,如支持 32 字节;3)咱们不会有杂乱的外部依靠,杂乱的外部依靠会导致咱们安装失败;4)完善的审查机制,能够详细到特别的安全需求;即便运用外部 VM,也无法节约太多工作量。

  • 运用了可变、可扩展的 memory 巨细:固定 memory 的巨细是不必要的约束,太小或太大都不合适。假如内存巨细是固定的,每次拜访内存都需求检查拜访是否超出边界,显然这样的功率并不高。

  • 1024 调用深度约束:许多编程言语在内存还没有溢出时,就由于调用深度太深而崩溃了。所以仅运用区块 gas 上限一种约束是不行的。

  • 无类型:仅仅为了简练。不过,DIV、SDIV、MOD、SMOD 会运用有符号(signed)或无符号的操作码(事实证明,关于操作码 ADD 和 MUL,有符号和无符号是对等的);转换成定点运算在所有情况下都很简略,例如,在 32 位长度下,a * b -> (a * b) / 2^32, a / b -> a * 2^32 / b ,+、- 和 * 在整数下不变。

  • 校正注:在原译本中还有如下一段,但其对应段落在当时版本的原文中现已删去了: 栈巨细没有约束:没什么特别理由!许多情况下,该规划不是肯定必要的;由于,gas 的开支和区块 gas 上限总是会充任每种资源耗费的上限。

    这个 VM 中某些操作码的功能和意图很简略了解,但也有一些不太好了解,以下是一些特别的原因:

    • ADDMOD, MULMOD:大多数情况下, mulmod(a, b, c) = a * b % c ,但在椭圆曲线算法中,运用的是 32 字节模数运算,直接履行 a * b % c 实践上是在履行 ((a * b) % 2^256) % c ,会得到彻底不同的成果。在 32 字节的空间中履行 32 字节数值的 a * b % c 核算的一致十分困难且繁琐。

    • SIGNEXTEND:SIGNEXTEND操作码的效果是为了方便从大的有符号整数到小的有符号整数的类型转换。小的有符号整数是很有用的,由于未来的即时编译虚拟机或许有才能检测首要处理 32 字节整数又长时刻运转的代码块,小的有符号整数能加速处理。

    • SHA3:在以太坊代码中,SHA3 作为安全的、高强度的、不定长数据哈希映射办法,运用十分广泛。一般,在运用存储器时,需求运用 Hash 函数来防止歹意抵触,在验证默克尔树和类似的以太坊数据结构时也需求运用到 Hash 函数。重要的是,与 SHA3 的类似的哈希函数,如 SHA256、ECRECVOR、RIPEM160,不是以操作码的形式包括在里面,而是以伪合约的形式。这样做的意图是将它们放在一个独自的类别中,假如当咱们以后提出恰当的 “原生插件” 体系时,能够增加更多这样的合约,而不需求扩展操作码。

    • ORIGIN:ORIGIN 操作码由买卖的发送者供给,首要的效果是答应合约退回付出的 gas。

    • COINBASE:COINBASE 的首要效果是:1)答应子钱银对网络安全作出奉献;2)使矿工能够作为一个去中心化的经济体,来设置根据子一致的运用,如 Schellingcoin。

    • PREVHASH:PREVHASH 可用作一个半安全的随机来源。此外,答应合约求值(evalute)上一个区块的默克尔树状况证明,而不需求高度杂乱的 “以太坊轻客户端” 递归结构 。

    • EXTCODESIZE, EXTCODECOPY:首要的效果是让合约根据模板检查其他合约的代码,乃至是在与其他合约交互前,模仿它们。见:https://lesswrong.com/lw/aq9/decision_theories_a_less_wrong_primer/

    • JUMPDEST:当跳转(jump)意图地约束在几个索引时(尤其是,动态意图跳转的核算杂乱度是 O(log(有用应战意图数量)),而静态跳转总是稳定的),JIT 虚拟机完成起来更简略。所以,咱们需求:1)对有用变量跳转意图地做约束;2)鼓励运用静态而不是动态跳转。为了达到这两个方针,咱们定下了以下规矩:1)紧接着 push 后的跳转能够跳到任何当地,而不仅是另一个 jump;2)其他的 jump 只能跳转到 JUMPDEST。对跳转的约束是有必要的,这样就可经过检查代码中的前一个操作来确认当时是一个静态跳转还是动态跳转。缺少对静态跳转的需求是鼓励运用它们的原因。禁止跳转进入 push 数据也会加速 JIT 虚拟机的编译和履行。

    • LOG:LOG是事件的日志。

    • CALLCODE:该操作码答应合约运用自己的存储项,在独自的栈空间和 memory 中调用其他合约的 “函数” 。这样能够在区块链上灵活完成规范库代码。

    • SELFDESTRUCT:答应合约删去它自己,条件是它现已不需求存在了。SELFDESTRUCT 并非当即履行,而是在买卖履行完之后履行。这是由于假如答应 SELFDESTRUCT 在履行之后回滚,将会极大地进步缓存的杂乱度,不利于高效的 VM 完成。

    • PC:尽管理论上不需求 PC 操作码,由于所有 PC 操作码的实例都能够根据将 push 操作的索引参加实践程序计数器来替代完成,但运用 PC 能够创立独立代码的方位(可复制粘贴到其他合约的编译函数,假如它们以不同索引完毕,不会被打断)。

    原文链接:

    https://eth.wiki/en/fundamentals/design-rationale

    作者: Vitalik

    翻译&校正: kim & 阿剑

视野开拓

就其重要性而言,商业在思想和道德上所起的作用超越了其在经济方面的好处。在如今人类进步的低水平下,让人们与不同于自己的人接触,了解与自己迥然不同的思想和行为方式,这样的价值是很难被高估的......商业首先教会各个国家用好的意愿去看待他国的富足与繁荣。-《伟大的贸易》

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注