首页 区块技术正文

无版本区别的EVM

无版本区别的EVM


如果我们有机会重新设计EVM,提高其向后兼容性,使其在功能上更加友好,而不必担心我们现有的历史负担,我们该怎么办?


在本文中,我将探讨这个问题,并记录从中发展而来的技术描述和设计理念。


目标


Web不是特定于版本的,并且已经存在了几十年。所以我在这里假设我们想要制作一个也没有版本差异的EVM。


我们还希望确保此虚拟机具有良好的向后兼容性(这是必需属性)。换句话说,至少我们可以很好地兼容我们现有的合同(在当前的EVM中,即使单个操作码的燃气消耗变化也会损坏现有合同),并且很容易添加新功能。


操作码无效


设计弹性EVM的最简单和最重要的变化是为合同部署添加验证过程。并非所有字节序列都是有效的EVM代码,并且不应将任何无效的操作码部署到链中,因为将来可能会为这些代码分配具有不同功能的新操作码。


这种检查的技术细节首先在EIP-1712中找到。简而言之,在执行合同创建的状态转换功能(或将合同代码添加到状态)之前执行以下检查:


遍历代码的字节码


如果代码是PUSH(n)操作码,则跳过下n个字节


如果字节码是有效的操作码,或者指定了无效指令(0xfe),则继续


否则,赶上陷阱


上面的检查有点类似于跳转目的地检查。请注意,对于例外,我们在这里使用“陷阱”,我们将在下面详细解释。


专题调查


如果EVM要消除版本差异,基于EVM的代码执行应该能够调查底层环境是否支持特定功能。鉴于EVM的作用,我们总是希望已定义的操作码的功能保持不变,并且可以引入新的操作码来添加功能。在引入某些功能之前,可能已部署了某些合同。当EVM不支持某项功能时,这些合同可以安排备用子程序运行子程序,并在激活硬分叉后立即开始使用新功能。功能测量组件就像这里使用的跳线一样。因此,我们正式定义了一个新的操作码HAS_FEATURE。


操作码接收堆栈参数。它检查参数是否介于0和2 ^ 8之间,如果不是,则捕获错误。


如果不支持参数(解释为操作码),则将0x0推回堆栈;否则按0x1


例外和陷阱


耗气量


过去的经验证明,我们总是希望调整燃气消耗量。因为我们想要这样做,我们不希望合约开发商对交易的燃气消耗甚至任何操作码的燃气消耗做出任何假设。为此,只需删除EVM中有关气体消耗的所有公共信息。通过这种方式,Gas的消耗成为从EVM隐藏的“实现细节”并被隐藏,并且仅需要在块层执行中正确处理。正式删除Gas操作码为0x5a。此外,重新定义CALL,CALLCODE和DELEGATECALL,而不是使用气体堆栈参数,而是在现有执行框架中获取所有可用的Gas。


评论