Solidity合约元数据
飞儿506
发表于 2022-12-31 04:38:06
254
0
0
它可以用于查询编译器版本,所使用的源代码,|ABI| 和 |natspec| 文档,以便更安全地与合约进行交互并验证其源代码。
编译器会将元数据文件的 Swarm 哈希值附加到每个合约的字节码末尾(详情请参阅下文),
以便你可以以认证的方式获取该文件,而不必求助于中心化的数据提供者。# x1 t7 j1 w7 x
当然,你必须将元数据文件发布到 Swarm (或其他服务),以便其他人可以访问它。
该文件可以通过使用 solc --metadata 来生成,并被命名为 ContractName_meta.json 。+ L5 L" @3 c- G; S/ f% F
它将包含源代码的在 Swarm 上的引用,因此你必须上传所有源文件和元数据文件。& ~) R' R! B* \1 o$ Y
元数据文件具有以下格式。 下面的例子将以人类可读的方式呈现。& x7 v# ]5 c9 u% H
正确格式化的元数据应正确使用引号,将空白减少到最小,并对所有对象的键值进行排序以得到唯一的格式。/ A- T j9 F, s6 z
代码注释当然也是不允许的,这里仅用于解释目的。
{3 X. q1 i: F( e
// 必选:元数据格式的版本. u1 T9 A/ e. b5 Z/ _" f
version: "1",
// 必选:源代码的编程语言,一般会选择规范的“子版本”
language: "Solidity",
// 必选:编译器的细节,内容视语言而定。
compiler: {
// 对 Solidity 来说是必须的:编译器的版本
version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
// 可选: 生成此输出的编译器二进制文件的哈希值
keccak256: "0x123..."3 Y% K/ D4 \3 `: `# A# i% s N, r
}, h% }5 R/ M+ Z5 H2 S
// 必选:编译的源文件/源单位,键值为文件名% V; c4 i0 V3 Q& ?* M1 ^8 |
sources:; s. i! {! o8 J. F) k- j/ s/ B! i
{
"myFile.sol": {; \, v4 M5 _5 V$ f. w( B7 j1 T! M
// 必选:源文件的 keccak256 哈希值
"keccak256": "0x123...",
// 必选(除非定义了“content”,详见下文):
// 已排序的源文件的URL,URL的协议可以是任意的,但建议使用 Swarm 的URL
"urls": [ "bzzr://56ab..." ]
},
"mortal": {' I1 C1 ]$ c% \- w/ _ L0 z
// 必选:源文件的 keccak256 哈希值$ k* ?% D# W% Y. Y1 @
"keccak256": "0x234...",$ f( Y. ^! y y5 v( B# `
// 必选(除非定义了“urls”): 源文件的字面内容8 B- I0 N3 f5 H; t$ w5 r9 O! ]
"content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"4 C) z) d' ?# s- Y z
}
},
// 必选:编译器的设置; s B7 p& S% E$ P. h
settings:
{" n7 f* ^0 X9 t) B8 {
// 对 Solidity 来说是必须的: 已排序的重定向列表4 f8 m6 ]9 z1 I: I( v& R
remappings: [ ":g/dir" ],
// 可选: 优化器的设置( enabled 默认设为 false )
optimizer: {
enabled: true,
runs: 500( A" {; b2 h" c" U
},
// 对 Solidity 来说是必须的:用以生成该元数据的文件名和合约名或库名9 X" p; o0 ?1 r5 M8 M7 q& a
compilationTarget: {" b, x& n* ~) ~ h
"myFile.sol": "MyContract"4 ], d' r8 Q% V. }! f" g" b5 X
},
// 对 Solidity 来说是必须的:所使用的库的地址- D' i, a l) b9 e$ o2 J) u6 o" K
libraries: {
"MyLib": "0x123123..."+ i$ Q1 ^, q1 m- \, q
}
},
// 必选:合约的生成信息
output:
{
// 必选:合约的 ABI 定义& M# E' s, M- x* x
abi: [ ... ],* |2 [+ S3 _) h H
// 必选:合约的 NatSpec 用户文档
userdoc: [ ... ],# h- S5 @- E) [$ G. o2 `( f* o- K2 L
// 必选:合约的 NatSpec 开发者文档 ]; D- L# R! _: |3 B1 n
devdoc: [ ... ],
}( J6 N p6 P9 b- z& @! } P
}
… note::. T: t2 e) w7 x
需注意,上面的 ABI 没有固定的顺序,随编译器的版本而不同。2 z( K$ ~: [6 I7 I) W0 f
… note::
由于生成的合约的字节码包含元数据的哈希值,因此对元数据的任何更改都会导致字节码的更改。7 x% u( n+ Y% I$ K0 j8 N8 {8 |
此外,由于元数据包含所有使用的源代码的哈希值,所以任何源代码中的,5 W' i8 x2 G# E0 M/ w: K
哪怕是一个空格的变化都将导致不同的元数据,并随后产生不同的字节代码。% e5 A+ N* g7 ~
元数据哈希字节码的编码
由于在将来我们可能会支持其他方式来获取元数据文件,
类似 {"bzzr0":} 的键值对,将会以 CBOR _ 编码来存储。2 z; z/ o m% z7 Y5 A
由于这种编码的起始位不容易找到,因此添加两个字节来表述其长度,以大端方式编码。
所以,当前版本的Solidity编译器,将以下内容添加到部署的字节码的末尾::
0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 0x00 0x299 g/ o+ _$ D. Q; T9 X9 E8 }
因此,为了获取数据,可以检查部署的字节码的末尾以匹配该模式,并使用 Swarm 哈希来获取元数据文件。+ E% V- d4 h6 a: S% r
自动化接口生成和 |natspec| 的使用方法
元数据以下列方式被使用:想要与合约交互的组件(例如,Mist)读取合约的字节码,! I" q, k7 A0 N( w& O
从中获取元数据文件的 Swarm 哈希,然后从 Swarm 获取该文件。该文件被解码为上面的 JSON 结构。
然后该组件可以使用ABI自动生成合约的基本用户接口。- J: X% J0 G/ X0 v7 j0 l6 J: C% x
此外,Mist可以使用 userdoc 在用户与合约进行交互时向用户显示确认消息。+ l" Q0 J! Z, U2 X: O# y
有关 |natspec| 的其他信息可以在 这里 _ 找到。
源代码验证的使用方法 c* H. r3 J. \+ k# Z
为了验证编译,可以通过元数据文件中的链接从 Swarm 中获取源代码。. _- y2 Q# j) m1 W- m
获取到的源码,会根据元数据中指定的设置,被正确版本的编译器(应该为“官方”编译器之一)所处理。
处理得到的字节码会与创建交易的数据或者 CREATE 操作码使用的数据进行比较。
这会自动验证元数据,因为它的哈希值是字节码的一部分。. [( X) R3 t8 H
而额外的数据,则是与基于接口进行编码并展示给用户的构造输入数据相符的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人