加载中 ...

以太坊君士坦丁堡升级深入分析

2019-02-02 10:54 编辑:btc268.com 来源:区块链资讯

  以太坊即将在7080000高度升级到Constantinople(君士坦丁堡)版本,预计时间为1月16号。这是以太坊第三阶段Metropolis(大都会)的第2个版本,也是最后一个版本。在这之后,以太坊将步入最终阶段Serenity(宁静)。

  这次升级一共涉及5个EIP,改动不算大,网络上也已经有很多文章,但大多是一些语焉不详的简短翻译,笔者试图深入分析一下各项改动的具体细节。

EIP 145: 增加SHL/SHR移位指令

  注意这只是EVM层面的优化,和solidity没有关系,目的是减少移位操作消耗的gas(从35减小到3)

  比如我们执行一个移位操作:

   function hello() public {
       int x = 1;
       int y = x << 3;
   }

  以前会被编译成很多条指令:

  

  升级完成后,只需要1条指令就搞定了~

EIP 1014:增加CREATE2指令,支持“Counterfactual Instantiation”

  这项提案是V神亲自敲定的,不过估计真正能看懂的人少之又少。这个改动不是给普通智能合约用的,是为了支持状态通道

  首先简单介绍一下状态通道:状态通道是指把一部分区块链状态“锁定”到一个多签名的合约中,由所有参与者共同控制。这种“状态锁定”称之为“state deposit”,比方说锁定一定的ETH或者ERC20代币,甚至是锁定一只以太猫。

  然后通道中的所有人就可以进行链下交易了,由于交易数据不上链,因此就不需要消耗gas。但是,每笔交易必须由交易双方或者多方共同签名,这被称为“unanimous consent”。这样,虽然在当前时刻该笔交易没有上链,但是在将来的任意时刻,交易的任何一方都有权把这笔交易提交到链上,并通过验证。因此,和链上交易需要等待多个区块确认不同,链下交易可以被“即时确认”,这一特性被称之为“instant finality”。

  有了这些铺垫,现在就可以引入一个新的概念:Counterfactual,翻译过来叫“反现实”,是不是完全摸不着头脑?实际上,如果我们说一个事件X是“counterfactual”的,代表了下面3层含义:

  X可以在链上发生,但是目前还没有

  任何一方都可以单方面导致X在链上发生

  因此,参与者们可以假装认为X已经在链上发生了

  举个例子:Alice在状态通道中给Bob发送了4 ETH,他们俩都对该笔交易签名。这样,这笔交易可以在任意时刻被Alice或者Bob提交到链上,但是目前它还没有上链。我们就说在“counterfactual”的语境下,Alice给了Bob 4个ETH。

  讲了这么多,跟EIP 1014有什么关系呢?实际上,在状态通道里不仅可以交易,还可以部署合约!比如你开发了一个扑克或者下棋的游戏,你可以不用先部署到链上,而是部署到状态通道里,这样你连1分钱都不用花!这就叫做Counterfactual Instantiation,反现实实例化。那么这是怎么做到的呢?状态通道的所有参与者需要向多签名合约发送“确认”:如果将来这个游戏合约部署到链上了,可以按照通道里的合约状态,从“锁定”资金中转出相应的额度到该链上合约中。

  那么现在就变成“鸡生蛋蛋生鸡”的问题了:合约还没有部署到链上,怎么知道它的地址呢?

  之前以太坊的合约地址是这么生成的:

  keccak256(RLP(sender_address, nonce))[12:]

  账户的nonce是随着交易数递增的,因此合约地址取决于该账户何时部署合约。我们需要一种不依赖nonce的确定性的算法来生成合约地址,因此V神提出了EIP 1014:

  keccak256( 0xff sender_address salt keccak256(init_code)))[12:]

  其中init_code就是用于创建合约实例的字节码,salt是一个32字节的值,作为一个随机因子(比如你想部署多个形同的合约)。这样,我们就可以预先知道合约的链上地址并在状态通道中与之交互了。

EIP 1052:增加EXTCODEHASH指令

  这个改动目的比较明确:减少校验合约代码的gas消耗

  很多合约需要验证其他合约的字节码,确认其代码是否安全、合规。之前的做法是先通过EXTCODECOPY把目标合约的字节码拷贝一份,然后再计算、比对哈希值。EXTCODECOPY会消耗很多的gas,实际上我们并不需要目标合约的字节码,只需要字节码的哈希,EIP 1052就是为了满足这个需求诞生的。

EIP 1283:优化SSTORE指令的gas消耗计算

  大家都知道,SSTORE是一个比较昂贵的指令,因为它会修改StateDB(存储)。

  之前的gas消耗计算简单粗暴:每调用一次SSTORE,就扣一次gas。比如在同一笔交易中,如果我先执行x=1,再执行x=2,最后执行x=3,会被收3次钱!这显然是不合理的,EIP 1283就是为了优化gas的计算方式。

  以太坊底层使用的LevelDB是K-V型数据库,我们把每个键值对称为一个“存储槽”(Storage Slot)。每个存储槽可能有三种值:

  原始值:执行当前交易之前的初始值

  当前值:执行SSTORE指令之前的值

  新值:执行SSTORE指令之后的值

  因为可能会执行多条SSTORE指令,所以当前值不一定等于原始值。

  SSTORE的gas消耗可以分为3种情况:

  No-op:当前值等于新值,EVM不需要做任何事情

  Fresh:当前值等于原始值,而新值不等于当前值

  Dirty:当前值不等于原始值,而新值也不等于当前值

  No-op的情况比较简单,固定收取200 gas。一般情况下我们会从Fresh状态开始,然后进入Dirty,当然如果设回原来的值,又会重新回到Fresh状态,此时会触发refund(退费)。具体状态机参见下图:

  

  详细解释:

  No-op状态:收取200 gas

  Fresh状态:

  如果原始值是0,收取20000 gas

  否则,收取5000 gas。如果新值是0,退还15000 gas

  Dirty状态:收取200 gas,并检查下面2个条件:

  如果原始值是0,退还19800 gas

  否则,退还4800 gas

  如果当前值是0(说明新值不是0),收回退还的15000 gas

  如果新值是0(说明当前值不是0),退还15000 gas

  如果原始值不是0

  如果原始值等于新值(被reset回原始值了)

  所以退费会记录到一个refund计数器中,并确保退费金额不会减成负数。

  总结一下,EIP 1283修正了SSTORE指令重复计费的问题,新的计费机制更加合理,对dApp开发者是一个利好。

EIP 1234:延迟难度炸弹,调整出块奖励

  以太坊创立之初,就明确提出最终会使用PoS作为共识算法,PoW只是暂时地过渡。为了保证平稳过渡,代码中设置了一个“难度炸弹”,也就是挖矿难度会随着出块数量的增加而逐渐加大,最终进入“冰河世纪”,也就是矿工们无法挖出区块,或者挖矿成本远远高于收益,导致矿工们放弃PoW,转向PoS。

  然而现实总是不会尽如人意,以太坊Casper开发进度缓慢,不得不一再延期。EIP 1234会把难度炸弹延迟12个月,从代码实现层面来看,就是在计算难度时采用一个fake的区块高度,往前推500万个区块:

fake_block_number = max(0, block.number - 5_000_000) if block.number >= CNSTNTNPL_FORK_BLKNUM else block.number

  另外,出块奖励也从3 ETH减少到2 ETH,叔块奖励也相应减少。此举也是为了刺激矿工从PoW向PoS过渡。

关键词:比特币新闻 币牛牛

转载自比特币新闻网(www.btc268.com),提供比特币行情走势分析与数字货币投资炒币最新消息。

原文标题:以太坊君士坦丁堡升级深入分析

原文地址:http://www.btc268.com/ytf/xw/6385.html

本文来源:区块链资讯编辑:btc268.com

本文仅代表作者个人观点,与本网站立场无关。

本网站转载信息目的在于传递更多信息。请读者仅作参考,投资有风险,入市须谨慎!

'); })();