尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

EIP-1014 Skinny CREATE2 深度解读:确定性合约地址、Gas 计量与 Constantinople 落地

EIP-1014 Skinny CREATE2 深度解读:确定性合约地址、Gas 计量与 Constantinople 落地 EIP-1014 Skinny CREATE2 深度解读确定性合约地址、Gas 计量与 Constantinople 落地【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPsEIP-1014Skinny CREATE2是 Ethereum 核心协议层Core / Standards Track状态 Final中引入CREATE2操作码的规范由 Vitalik Buterin 于 2018-04-20 提出并在 Constantinople 硬分叉中正式激活。本文以 EIPS/eip-1014.md 为骨架结合仓库内 EIPS/eip-1013.mdConstantinople 元 EIP、EIPS/eip-684.md创建碰撞回退、EIPS/eip-161.mdnonce 前置递增与 EIPS/eip-3860.mdinitcode 计量等关联规范完整讲解地址计算公式、Gas 成本模型、碰撞语义、边界行为与官方测试向量帮助读者从规范到实现层面彻底理解确定性部署这一核心能力。一、背景与动机为什么要一个瘦的 CREATE2在 EIP-1014 之前以太坊只有CREATE0xf0一种合约创建方式其新合约地址由发送者地址 nonce经keccak256(rlp([sender, nonce]))推导而来。这种方案的结果是地址在链上执行之前无法被预先可靠计算——因为 nonce 是动态变化的你无法在不实际发送交易的情况下提前得知第 N 个由某地址创建的合约落在哪里。EIP-1014 的动机段落给出了核心场景Allows interactions to (actually or counterfactually in channels) be made with addresses that do not exist yet on-chain but can be relied on to only possibly eventually contain code that has been created by a particular piece of init code.也就是说CREATE2允许与链上尚不存在的地址进行交互真实交互或状态通道中的反事实 counterfactual 交互并且可以确信该地址未来只可能被某一段特定 init code 创建出来的代码占据。这正是状态通道state channel等反事实交互用例的关键前提——双方可以先在链下对某个尚未部署的合约地址达成约定、签名并交换承诺之后任何一方再实际部署该合约合约地址与当初约定的完全一致。二、规范详解操作码0xf5与确定性地址公式2.1 新增操作码与四个栈参数EIP-1014 在0xf5位置新增操作码CREATE2接收4 个栈参数参数说明endowment随创建调用转入新合约的 Wei 数额memory_startinit code 在内存中的起始偏移memory_lengthinit code 的长度字节数salt32 字节盐值一个完整的栈项除地址计算方式外CREATE2与CREATE0xf0行为完全一致它读取内存中[memory_start, memory_start memory_length)区间作为 init code在新地址上以endowment作为余额执行 init code最终将RETURN出来的运行时字节码写入状态。2.2 地址计算公式规范原文与传统的 sender-and-nonce-hash 不同CREATE2使用如下公式计算新合约地址keccak256( 0xff address salt keccak256(init_code) )[12:]其中0xff是单个字节address恒为20 字节发起创建的合约/账户地址即发送者salt恒为32 字节一个栈项keccak256(init_code)是 init code 的哈希恒为 32 字节。由于以上三段的长度全部固定最终哈希轮次的预映像preimage长度恒为 85 字节1 (0xff) 20 (address) 32 (salt) 32 (init_code hash) 85。EIP-1014 特别指出该公式是 2018-08-10 的 coredev核心开发者会议决议采用的。2.3 与CREATE的地址推导差异创建方式地址推导CREATE/ 创建交易keccak256(rlp([sender, nonce]))[12:]依赖动态 nonce不可预先确定CREATE20xf5keccak256(0xff sender salt keccak256(init_code))[12:]仅依赖 sender、salt 与 init code 本身完全确定、可离线预计算地址取哈希结果的后 20 字节[12:]与CREATE取法一致保证产出 160 位地址。三、Gas 成本模型hashcost 与扣除时机3.1 在CREATE计费之上增加 hashcostCREATE2采用与CREATE相同的气体计费模式gas schema但额外增加一项hashcosthashcost GSHA3WORD * ceil(len(init_code) / 32)其中GSHA3WORD即以太坊黄皮书中SHA3操作码每 32 字节字的气体常数值为6EIP-3860 的计量表中也明确写着Cost of address calculation (hashing of code) in case ofCREATE2only: 6 gas per word。因此hashcost 6 * ceil(len(init_code) / 32)例如init_code为 1 字节6 * ceil(1/32) 6init_code为 44 字节6 * ceil(44/32) 12init_code为空0 字节6 * 0 0。3.2 扣除时机早于地址求值与 init code 执行规范明确要求hashcost与内存扩展memory-expansion气体、CreateGas在同一时刻扣除即deducted at the same time as memory-expansion gas andCreateGasis deducted:beforeevaluation of the resulting address and the execution ofinit_code.换言之客户端必须先完成 init code 的哈希用于地址计算并足额扣除费用才能继续求值地址、执行构造函数。这与 EIP-3860 引入的 initcode 计费在时间点上是兼容的——EIP-3860 说明其第 4 条规则在计算合约地址和执行 initcode 之前扣除意味着在CREATE2中与哈希成本同时或更早应用。3.3 为什么必须收费防 DoSRationale 部分给出了设计理由地址计算依赖于对init_code的哈希而内存扩展只支付一次。如果执行可以反复对超大 init code 进行哈希而不额外收费客户端将暴露于 DoS 攻击——攻击者可以不断触发对大量 init code 的重复哈希。因此本 EIP 采用与SHA3操作码相同的每字成本让哈希工作的成本与 init code 长度成正比。这一思路在 EIPS/eip-3860.md 中被进一步强化该 EIP 将CREATE与CREATE2的 initcode 计量统一为每 32 字节 2 gas并明确指出CREATE2的总成本在激活前后分别为6与6 2gas/字即同一实现可复用于CREATE和CREATE2只是常数不同。四、设计原理Rationale逐条解析4.1 地址公式与 RLP 体系天然隔离采用0xff作为前缀字节有两个直接好处杜绝与传统地址碰撞传统地址由keccak256(rlp([sender, nonce]))推导而 RLP 编码以0xff开头只可能出现在数据长度达数 PB的场景——实际不可能因此两类公式产出的地址空间在结构上隔离预映像长度固定0xff1 字节address20 字节salt32 字节keccak256(init_code)32 字节恒为 85 字节便于实现与审计。4.2 关于Skinny瘦的含义EIP 标题中的 Skinny 指本方案刻意保持精简只新增一个操作码、只改变地址推导与额外哈希计费不引入状态通道协议、不规定 init code 的校验逻辑把反事实交互等上层能力留给应用层自行组合。这也是它作为 Core 类共识变更却实现面很小的原因。五、碰撞语义与边界行为Clarifications5.1 init code 的精确定义规范澄清init_code是执行后产生将被写入状态的运行时字节码runtime bytecode的那段代码高级语言通常用它实现构造函数constructor。5.2 地址碰撞由 EIP-684 规定CREATE2使碰撞成为可能不同 sender/salt/init_code 组合可能算出同一地址碰撞时的行为由 EIPS/eip-684.md 规定若因创建交易、CREATE或未来的CREATE2操作码尝试创建合约而目标地址已具有非零 nonce 或非空 code则创建立即抛错行为与 init code 首字节为无效操作码完全相同且自创世起追溯生效。具体而言只要目标地址的nonce 或 code 任一非零创建操作即失败。5.3 EIP-161 的 nonce 前置递增带来的副作用EIPS/eip-161.md 规定账户创建交易与CREATE操作应在执行初始化代码之前将 nonce 在正常起始值之上再递增 1。这意味着若合约由创建交易创建其 nonce 在交易内立刻变为非零副作用是——即使碰撞发生在init_code自身执行的后续步骤中同一笔交易内的碰撞也必然失败。5.4 SELFDESTRUCT 不改变 nonce 与 code还需注意SELFDESTRUCT0xff恰好与公式前缀字节数值相同但语义无关对 nonce 与 code没有即时影响因此一个合约无法在同一笔交易内自毁后再于原地址重建——销毁后地址上的 nonce/code 状态不会自动归零碰撞保护依旧生效。六、官方测试向量Examples 完整继承EIP-1014 提供了 7 组官方测试向量可直接用于验证任何实现的地址计算与 Gas 计费。以下地址、salt、init code、gas 与结果均取自 EIPS/eip-1014.md 原文gas 均在无内存扩展前提下给出CreateGas基础为 32000Example 0address0x0000000000000000000000000000000000000000salt 全零init_code0x00gas32006结果0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38Example 1address0xdeadbeef00000000000000000000000000000000salt 全零init_code0x00gas32006结果0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3Example 2address0xdeadbeef00000000000000000000000000000000salt0x000000000000000000000000feed000000000000000000000000000000000000init_code0x00gas32006结果0xD04116cDd17beBE565EB2422F2497E06cC1C9833Example 3address0x0000000000000000000000000000000000000000salt 全零init_code0xdeadbeef4 字节gas32006结果0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5eExample 4address0x00000000000000000000000000000000deadbeefsalt0x00000000000000000000000000000000000000000000000000000000cafebabeinit_code0xdeadbeefgas32006结果0x60f3f640a8508fC6a86d45DF051962668E1e8AC7Example 5address0x00000000000000000000000000000000deadbeefsalt0x00000000000000000000000000000000000000000000000000000000cafebabeinit_code 为0xdeadbeef重复 11 次共 44 字节gas32012即 32000 6×2两字哈希费结果0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854CExample 6address0x0000000000000000000000000000000000000000salt 全零init_code 为空0xgas32000无哈希费结果0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0对照可见Example 04 的 init code 均不超过 32 字节哈希费恒为 6 gas32006Example 5 为 44 字节、按两字计 12 gas32012Example 6 为空 init code、零哈希费32000。读者可自行以任意实现重算keccak256(0xff address salt keccak256(init_code))[12:]验证上述地址。七、落地Constantinople 硬分叉与激活参数CREATE2随 Constantinople 硬分叉上线。EIPS/eip-1013.mdHardfork Meta: Constantinople将 EIPS/eip-1014.md 列为该分叉包含的 EIP 之一激活参数如下主网MainnetBlock 7_280_000RopstenBlock 4,230,000KovanBlock 9_200_000RinkebyBlock 3_660_663同批分叉还包括 EIP-145移位指令、EIP-1052EXTCODEHASH、EIP-1234难度炸弹延迟与区块奖励调整、EIP-1283SSTORE净计量等。作为共识层变更CREATE2需要客户端在对应区块高度同步升级 EVM 实现。八、与后续规范的衔接从 initcode 计量到 EOFCREATE2并非孤立设计它与仓库内多个后续 EIP 相互咬合EIPS/eip-3860.mdLimit and meter initcode为CREATE/CREATE2的 initcode 引入每 32 字节 2 gas 的计量与 49152 字节上限与CREATE2原有 6 gas/字哈希费同点扣除、可复用同一实现形成完整的 initcode 成本体系EIPS/eip-684.mdRevert creation in case of collision将CREATE2碰撞回退行为正式规范化为目标地址已有非零 nonce 或非空 code 即抛错并追溯适用于所有历史区块EIPS/eip-3541.mdReject new contract code starting with the 0xEF byte其对新代码以0xEF开头即异常中止的约束同样作用于CREATE2部署路径测试用例中明确给出了CREATE2上下文的验证方式Yulcreate2(0, 0, calldatasize(), 0)EIPS/eip-7620.mdEOF 相关其地址计算讨论直接引用keccak256(0xff || sender || salt || keccak256(initcontainer))[12:]指出该方案与CREATE2公式相似但不完全相同EIPS/eip-8130.md在密钥库keystore部署场景中采用了keccak256(0xff || KEYSTORE_ADDRESS || effective_salt || keccak256(deployment_code))[12:]这一同构的确定性地址公式可见0xff前缀方案的扩展性。从源码结构看EIPS/eip-1013.md 的requires字段与上述各 EIP 的相互引用本仓库以规范间显式依赖的方式记录了CREATE2从提出、分叉激活到被后续 EIP 持续强化的完整演进链。九、总结EIP-1014 用最小的共识面一个新操作码0xf5换来了一个关键能力合约地址的完全确定性。通过keccak256(0xff address salt keccak256(init_code))[12:]公式任何一方都能离线预计算未来合约的地址并在链下反事实地与之交互而哈希费6 * ceil(len(init_code)/32)与先计费、后求值的扣除顺序则堵住了基于重复哈希的 DoS 漏洞。配合 EIPS/eip-684.md 的碰撞回退与 EIPS/eip-161.md 的 nonce 语义CREATE2的安全性边界被精确刻画而 EIPS/eip-3860.md、EIPS/eip-3541.md 等后续规范又在其基础上不断完善 initcode 计量与部署约束。对合约开发者而言理解CREATE2的地址公式与 Gas 模型是掌握确定性部署、状态通道反事实交互以及各类基于可预计算地址设计模式的前提。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表