全链游戏101:预编译合约

  • 预编译合约定义:EVM中用于高效执行复杂库函数(如加密/哈希)的特殊合约,通过节点客户端代码实现,相比EVM运行速度更快且成本更低,适合高频调用或计算量大的固定逻辑。

  • 技术实现示例:以太坊代码中的run函数通过预编译索引优先调用预编译合约,否则转入EVM解释器执行,其逻辑可通过流程图直观展现。

  • 现有预编译合约局限

    • 以太坊仅支持8个预编译合约(如签名恢复、哈希计算、椭圆曲线运算等),主要受限于:
      • 去中心化削弱:依赖全节点执行,全球仅4000-6000个全节点,远少于验证节点数量。
      • 升级不灵活:新增需硬分叉并通过漫长EIP流程(如EIP-196/197为隐私功能引入)。
      • 扩展性差:合约间难以交互组合。
  • 全链游戏中的应用

    • 通过预编译合约跳过EVM直接执行核心游戏逻辑(如高频状态查询),显著提升性能,但需权衡去中心化程度。
    • 专用游戏链可定制预编译合约组合,针对特定游戏类型优化,迭代中逐步筛选最优方案。
总结

什么是预编译合约?

预编译合约是 EVM 中用于提供更复杂库函数(通常用于加密、散列等复杂操作)的一种折衷方法,也可以理解为一种特殊的合约,这些函数不适合编写操作码。 它们适用于简单但经常调用的合约,或逻辑上固定但计算量很大的合约。 预编译合约是在使用节点客户端代码实现的,因为它们不需要 EVM,所以运行速度很快。 与使用直接在 EVM 中运行的函数相比,它对开发人员来说成本也更低。

如下代码可以看到, evm.go的合约中run函数有两个分支:第一个分支是通过预编译索引来实例化索引参数从而指定预编译合约,第二个分支是如果它不是预编译合约那evm将会被调用。

// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
   if contract.CodeAddr != nil {
      precompiles := PrecompiledContractsHomestead
      if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
         precompiles = PrecompiledContractsByzantium
      }
      if p := precompiles[*contract.CodeAddr]; p != nil {
         return RunPrecompiledContract(p, input, contract)
      }
   }
   for _, interpreter := range evm.interpreters {
      if interpreter.CanRun(contract.Code) {
         if evm.interpreter != interpreter {
            // Ensure that the interpreter pointer is set back
            // to its current value upon return.
            defer func(i Interpreter) {
               evm.interpreter = i
            }(evm.interpreter)
            evm.interpreter = interpreter
         }
         return interpreter.Run(contract, input, readOnly)
      }
   }
   return nil, ErrNoCompatibleInterpreter
}

用图形来表示的话,具体的逻辑如下图:

全链游戏101:预编译合约

那么预编译合约的瓶颈在哪里?

以太坊目前有八个预编译的合约:

  1. ECRecover - 通过签名恢复对应地址
  2. SHA256 - 计算SHA256哈希
  3. RIPEMD160 - 计算RIPEMD160哈希
  4. Identity - 返回输入数据的原值
  5. ModExp - 进行模数指数运算
  6. ECAdd - 椭圆曲线点加法
  7. ECMul - 椭圆曲线点乘法
  8. ECPairing - 配对运算,验证椭圆曲线点

可以看到第一到第四个预编译合约提供的基础的签名,哈希等加密功能,第五个到第八个提供了椭圆曲线运算,这些和zk-snark相关。

那么问题来了,为什么以太坊预编译只支持了八个预编译合约,预编译合约不是降低了gas消耗吗?而且为什么不直接把ECS(全链游戏的框架)植入以太坊预编译合约中呢?

其实主要是以下三个原因:

1.过度依赖预编译合约会降低整个平台的去中心化程度:

首先,预编译合约的代码需要集成在客户端节点代码中,增加了客户端的复杂性。第二,验证节点可能因为安全原因可能会过滤掉预编译合约的计算,所以大部分预编译合约的请求是由全节点完成的,目前全球的以太坊全节点的数量只有4000-6000个,而且验证节点有50万个,确实比起非预编译合约要中心化很多。

2.预编译合约的新增和修改需要硬分叉升级,不易灵活演进。

预编译合约的支持需要进行EIP流程,举个例子:EIP-196增加了在alt_bn128曲线上的ECADD()和ECMUL()两个预编译合约。EIP-197增加了在alt_bn128曲线上的配对Pairing函数。基本都是为了让隐私在以太坊上可用进行支持,而且整个EIP的流程是漫长和考究的,等待EIP通过也不是一个现实的问题。

3.预编译合约之间难以进行交互和组合,扩展性差。

这点就不多做解释了,很直观。

预编译合约在全链游戏扮演什么角色?

预编译合约跳过EVM直接通过节点执行,可以提升运算效率,但同时降低了全链的去中心化程度。将高频使用的游戏核心逻辑置于预编译中,可以优化该类游戏的性能。不同的游戏类型,其关键逻辑也不尽相同。因此,针对某一类游戏的专用链上,其预编译设计可以高度优化该类型游戏的需求。在游戏迭代过程中,最具效率的预编译合约组合也会逐步优化出来。

分享至:

作者:Gametaverse

本文为PANews入驻专栏作者的观点,不代表PANews立场,不承担法律责任。

文章及观点也不构成投资意见

图片来源:Gametaverse如有侵权,请联系作者删除。

关注PANews官方账号,一起穿越牛熊
推荐阅读
2025-01-13 02:24
2024-12-20 06:07
2024-03-19 09:00
2024-03-19 09:00
2024-03-19 08:00
2024-03-19 07:00

热门文章

行业要闻
市场热点
精选读物

精选专题

App内阅读