VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

以太坊账户与存储证明:验证账户、存储槽与实际含义

Three students in school uniforms work through open books at a classroom table, with textbooks and stationery nearby and study notes on the whiteboard behind them.

English version · 区块链学习导航 · 上一篇

区块链学习 · 延伸文章 BCX011

三名学生在教室桌旁一起阅读书本,身边放有课本和文具。
学习场景配图;不代表照片中的学生正在学习区块链。

存储值只有绑定到正确账户、正确状态根和正确存储键,才成为有用证据。响应字段看起来可信地写着“7”,并不够。验证者必须先检查账户证明,解码该账户内部经过认证的存储根,再在这个根下验证请求的存储槽。

本课用真实、本地生成的以太坊格式字节,完成这项两阶段调查。例子是一个合成状态,只有一个账户和一个非零存储槽。它不是真实区块、RPC响应或部署,也不主张任何真实网络地址的状态。

流程刻意限定范围,只练习完整单叶节点、RLP解码和安全键派生。它不是通用以太坊客户端或生产证明验证器,不覆盖全部字典树形状或畸形输入。

选择适合你的阅读路线

本篇目录

第1至3节定义可信前提与准确字节。第4至6节验证账户和槽。第7至10节区分改动数据、响应字段不一致、经过认证的不存在,以及缺少证据。第11至12节区分已证明存储和应用含义,并给出判断工作表。最后练习附答案。

返回目录 · 下一节

1. 单独提供状态根的权威来源

课堂请求提供一个经过认证的预期状态根R。其来源是可信练习记录,不是从证明本身推出来的。请求账户是二十字节值,每字节都为0x11。请求的直接存储槽是整数0,编码为三十二个零字节。

R为4bb4560f8e14f5b6d3aa1f69c110fd0b458bdcedaf910755f10fffbd474ceab7。除非案例明确改变它,每个独立案例都把该准确值作为接受的根。这是人为构造的状态数据,不是观察到的以太坊区块头字段。

真实调查中,选择经过认证的区块头及其状态根,需要独立的链、区块和最终性证据。在任意根下数学上正确的证明,不能补上缺失的权威来源。本课把这个选择作为已完成前提。

问题很准确:给定证据是否在R下建立了请求键的状态?它不询问提供者名声好不好、两个端点是否一致,或网页是否显示同一个值。

返回目录 · 下一节

2. 区分两层承诺和哈希输入

状态字典树把账户键绑定到账户值。解码后的账户值有四个字段:nonce、余额、存储根和代码哈希。存储字典树再在该账户经过认证的存储根下,把存储键绑定到存储值。

在本安全字典树模型中,账户路径是对准确二十个地址字节计算Keccak-256。存储路径是对直接槽编号的准确三十二字节编码计算Keccak-256。如果哈希的是显示的十六进制文本、单个零字节,或把账户填充到三十二字节,就回答了不同问题。

以太坊Keccak-256不是某些通用哈希库提供的标准SHA3-256。本题使用所需Keccak函数生成并独立核对字节。名称相似不能作为替换摘要算法的理由。

固定版本Geth安全字典树实现提供账户及存储键哈希处理的实现背景。它作为版本化资料被检查,没有作为客户端运行,也不被称为最新发布。

返回目录 · 下一节

3. 检查完整的小型证明包

账户证明包含一个108字节节点,准确十六进制字节如下:

f86aa120e2c07404b8c1df4c46226425cac68c28d27a766bbddce62309f36724839b22c0b846f8448080a0f258b1c6d5ee7f6f3549117fb0ac79118d5ad19b9c027f9b8e1471ca519b3b6ca0bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a

存储证明包含一个36字节节点,准确十六进制字节如下:

e3a120290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56307

两者都是完整的单叶节点。每个紧凑路径都以0x20开头,表示本题完整六十四个半字节键的偶数长度叶路径编码。这不是要求给每棵树的每个节点都加上该字节。

节点长度、紧凑路径、RLP字段和摘要均经过独立检查,没有省略中间内容或用省略号代替隐藏证明数据。证明包之所以小,是因为合成字典树各只有一个条目;一般状态证明可能需要不同节点类型的序列。

返回目录 · 下一节

4. 先验证账户,再相信字段

首先对完整108字节账户节点计算Keccak-256,与R比较。给定节点匹配。然后解码节点,核对其完整叶路径是否等于请求二十字节地址的哈希。

叶中的值本身是RLP编码账户,应继续解码内部值,不能直接把外层字典树节点当作账户元组。结果为nonce等于0、余额等于0、存储根为S、代码哈希为K。

S为f258b1c6d5ee7f6f3549117fb0ac79118d5ad19b9c027f9b8e1471ca519b3b6c。K为bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a,它是给定单字节代码00,即无进一步执行效果的STOP指令的哈希。

这个代码字节只用于让合成账户元组完整,不声称实现计数器、登记系统或稍后的假设布局卡。编码账户字段也不证明此状态来自真实可达的部署历史。

第一阶段通过R下的账户认证S。旁边一个标为storageHash的独立响应字段,并不会仅因与证明一起出现,就获得替换S的权威。

返回目录 · 下一节

5. 在解码得到的存储根下验证槽零

接着对完整36字节存储节点做哈希,与从账户解码出的S比较。给定节点匹配。解码紧凑叶路径,再与表示直接槽零的三十二个零字节的Keccak-256比较。

路径也匹配。叶中的存储值解码为整数7。在这个小型RLP案例中,单字节0x07表示整数的最短字节形式;在相关RLP层包裹这个单字节值,不会增加长字符串前缀。

成功的证据链是R到正确账户,账户到S,S到槽零的值7。它不是对十进制文本“7”做哈希,然后直接与状态根比较。

此时可以给出示范结果:“在给定、已认证的合成状态根下,请求账户存在,其直接槽零的值为七。”七代表已复核记录、标志还是其他含义,需要额外解释证据。

返回目录 · 下一节

6. 解码长度,而不是相信外观

账户节点以f8 6a开始,表示有效载荷106字节的RLP列表,加两字节前缀,总计108。路径项占34字节:一个字符串前缀,加三十三字节的紧凑路径标记和哈希键。

余下外层值项包含70字节账户编码,外加两字节字符串前缀,总计72。因此34+72=106。内部账户编码的68字节列表载荷,包含两个规范零整数,以及两个各带字符串前缀的三十二字节字段。

存储节点以e3开始,是35字节列表载荷的单字节前缀。路径项仍占34,编码值占一,总长36。这些检查让给定证明包可直接核对,但不能据此认为所有证明都具有这些长度。

以太坊RLP文档解释字节串、列表和整数约定。本地资料检查的是这些具体编码,不是针对所有畸形长度、嵌套或资源耗尽输入的加固解码器。

返回目录 · 下一节

7. 区分证明被改动与便捷字段错误

第一个独立变体把存储节点最后的值字节从07改成08,却保留原先预期S。改动节点的哈希不再为S,存储承诺检查失败。原账户证明可能仍有效,但修改后的存储证据没有绑定到其存储根。

另一个变体保留两个证明节点不变,只把便捷响应字段value设为8。密码学证明仍解码为7。正确判断是“经过认证的值为七,声称的响应值八与之不符”,而不是“所有证明计算都失败了”。

同样,伪造的独立storageHash字段不能覆盖认证账户元组中的S。如果字段不一致,应指出不一致,不能为了让另一份证明显得可接受,就改用另一个根。

这些区别保留了有用证据。误导性的摘要字段未必破坏本来有效的证明;反过来,证明字节变化导致承诺检查失败,也不能只当作显示笔误。

返回目录 · 下一节

8. 使用请求键,而不是拿到叶中哪个值就算哪个

在独立槽查询中,请求直接槽一,即三十一个零字节后接01。其Keccak路径不同于完整槽零叶路径。在认证过的单叶存储根下,这个完整叶因此建立槽一不存在。

叶包含槽零的七,并不让七成为槽一的值。按照给定以太坊存储语义,缺失槽的默认值为零。路径比较是决定证据支持哪句话的必要步骤。

类似地,查询另一个合成二十字节地址,每字节都是0x22。认证账户叶具有不同完整路径。在这个单叶状态字典树中,它证明另一个请求账户不存在,不能把原账户元组认证为属于这个不同地址。

所以,证明字节可以在密码学上有效,同时反驳请求键存在的主张。应区分经过认证的非成员关系、畸形密码学证据,以及提供者只回答了另一个身份的问题。

返回目录 · 下一节

9. 不要把缺失节点变成零

回到原先非空存储根S和请求槽零。这次省略必要存储节点,验证者无法完成存储检查。这是缺少证据,不是经过认证的零值。

此前不存在的结论依赖完整叶,并验证了其根绑定及分歧路径。空响应或超时没有提供这些。区别在证据:前者展示请求键为何不可能出现在认证结构中,后者根本没有提供必要结构。

固定版本Geth证明代码区分证明节点可用性与已经验证的不存在。本课缺节点结论明确针对非空根模型,不能概括成“每个空证明数组都无效”。

已经认证的空树根具有不同语义,按相关验证规则可能不需要普通叶证据。这超出本课具体结构。审查者应识别其独立条件,不能无差别套用单叶缺节点规则。

返回目录 · 下一节

10. 正确证明若基于错误根,就回答了错误问题

保留原证明节点,却把请求的预期状态根改成另一个不等于R的给定值。账户节点哈希不再匹配预期根,应在把内部存储根当成新请求权威之前停止。

另一种情况是,有人先在R下正确验证原包,却把结果标成某个未指定较晚区块的当前状态。证明没有提供这个时间跨越。它仍是R下的证据,不是对所有未来状态的普遍说法。

因此,证明验证与根选择必须分开。提供者不能建议验证者接受“刚好由本包算出来的根”,来修补不匹配。应用必须保留原先经过认证的目标上下文。

这个固定练习没有建立规范链成员关系、最终状态或RPC端点诚实性。它们是刻意给定或排除的前提,不是隐藏在成功摘要比较中的结论。

返回目录 · 下一节

11. 存储槽证据不会自带应用布局

考虑一张独立假设解释卡:“对于预期应用,reviewCount是在直接槽零中的无符号256位值。”如果该卡对相关应用与上下文具有独立依据,那么验证后的槽值支持有条件解释reviewCount=7。

卡片是额外证据。合成STOP代码并没有实现这个命名变量,本课证明也不认证Solidity编译或部署。我们展示的是,解释如何依赖另一份有依据的布局陈述。

移除卡片,证明仍建立槽零的值,却不建立reviewCount这个名称。如果把卡片改为reviewCount位于直接槽一,槽零成员证明就不能建立该变量。在给定单叶存储状态中,独立的槽一不存在检查会给出默认零。

真实存储可能涉及打包、映射、动态数组、继承和代理。Solidity 0.8.30布局资料说明布局规则。本课刻意使用声明的直接槽,不假装每个变量都能通过哈希名称或套用映射公式找到。

实现变化如何影响存储含义,可阅读代理状态与迁移。本课证明把字节绑定到根,不解决升级语义。

返回目录 · 下一节

12. 记录四项结论,而不是一个绿色标记

有用工作表包含四项:第一,根和上下文前提;第二,账户存在或不存在,存在时的认证元组;第三,存储存在、不存在或证据不可用;第四,应用解释及其布局依据,如果有的话。

对于主要证明包:根为合成练习给定并信任;请求账户存在;其解码存储根把直接槽零绑定到七;没有另一张有依据的解释卡,就没有建立任何真实应用变量。

对于修改响应字段的案例,应保留有效七并记录字段冲突。缺节点案例标为存储证据不可用。槽一分歧路径案例则记录认证不存在,以及给定语义下的默认零。它们不能全部压成一个含糊“失败”标签。

EIP-1186描述账户与存储证明RPC提案,但页面状态为Stagnant,创建于2018年6月24日。本课不称其为Final,不执行其历史示例,也不认证完整eth_getProof一致性。实际固定字节向量另外生成,并在本地核对。

返回目录 · 下一节

练习与答案

  1. 哪个根验证存储节点?从认证账户解码出的S,不是无关响应字段,也不是直接使用R。
  2. 账户键输入是什么字节?准确二十个地址字节,不是它们的十六进制文本字符。
  3. 直接槽零的键输入是什么?对准确三十二个零字节计算Keccak-256。
  4. 证明不变,旁边字段声称八,结论是什么?证明建立七,便捷字段与之不符。
  5. 存储节点自己把最后字节改成八,结论是什么?摘要不匹配原S。
  6. 完整认证单叶的完整路径不同于请求槽一,结论是什么?经过认证的不存在,在给定语义下对应默认零。
  7. 非空S下必要叶被省略,结论是什么?缺少证据,不是已证明不存在或为零。
  8. 证明槽零为七,是否证明存在命名Solidity计数器?不是,仍需要相关、有独立依据的布局及实现解释。

长度检查:外层账户叶34字节路径项加72字节值项,载荷106;加两字节列表前缀,共108。存储叶34加1为35,再加一字节前缀,共36。两项计算都不建立通用证明大小上限。

返回目录 · 下一节

来源与延伸阅读

可靠结果应追踪完整联系:从所选根到账户,从账户到请求槽,再把已证明值解释为现有布局证据真正支持的含义。

返回目录