Alert Source Discuss

EIP-: ```md

Authors

```md

eip: 2678 title: 修订后的以太坊智能合约打包标准(EthPM v3) author: g. nicholas d’andrea (@gnidan), Piper Merriam (@pipermerriam), Nick Gheorghita (@njgheorghita), Christian Reitwiessner (@chriseth), Ben Hauser (@iamdefinitelyahuman), Bryant Eisenbach (@fubuloubu) discussions-to: https://ethereum-magicians.org/t/ethpm-v3-specification-working-group/4086 status: Final type: Standards Track category: ERC created: 2020-05-26 —

简述

一种描述智能合约软件包的数据格式。

摘要

本 EIP 定义了一种用于包清单文档的数据格式,该文档表示一个或多个智能合约的包,可以选择包括源代码和跨多个网络的任何/所有已部署实例。包清单是最小化的 JSON 对象,通过内容可寻址存储网络(如 IPFS)分发。然后,包被发布到链上 EthPM 注册表中,该注册表在 EIP-1319 中定义,可以从中自由访问。

本文档以自然语言描述了此格式版本 3 的正式规范。

动机

本标准旨在鼓励以太坊开发生态系统在代码重用方面采用软件最佳实践。通过定义开放的、社区驱动的包数据格式标准,这项工作旨在通过提供一种通用解决方案来支持包管理工具的开发,该解决方案的设计考虑了观察到的常见实践。

  • 更新了包清单的模式,以与编译器的 metadata 输出兼容。
  • 更新了 "sources" 对象定义,以支持更广泛的源文件类型,并用作编译器的 JSON input
  • 将编译器定义移动到顶级的 "compilers" 数组中,以便:
    • 简化编译器版本、源和已编译资产之间的链接。
    • 简化使用多个编译器版本的包。
  • 将键格式从 snake_case 更新为 camelCase,以与 JSON convention 更加一致。

指导原则

本规范对文档生命周期做出以下假设。

  1. 包清单旨在由包管理软件作为发布过程的一部分以编程方式生成。

  2. 包清单将在包管理器执行安装包依赖项或构建和部署新版本等任务期间被使用。

  3. 包清单通常不会与源代码一起存储,而是由包注册表存储由包注册表引用并存储在类似于 IPFS 的东西中。

  4. 包清单可用于验证源代码合约的公共部署。

用例

在创建此规范期间考虑了以下用例。

  • owned: 一个包含合约的包,这些合约本身不打算使用,而是作为基础合约,通过继承为其他合约提供功能。
  • transferable: 一个具有单个依赖项的包。
  • standard-token: 一个包含可重用合约的包。
  • safe-math-lib: 一个包含已部署的包合约实例的包。
  • piper-coin: 一个包含来自依赖项的可重用合约的已部署实例的包。
  • escrow: 一个包含本地合约的已部署实例的包,该本地合约链接到本地库的已部署实例。
  • wallet: 一个包含本地合约的已部署实例的包,该本地合约链接到来自依赖项的库的已部署实例。
  • wallet-with-send: 一个已部署实例链接到深度依赖项的包。
  • simple-auction: 编译器 "metadata" 字段输出。

包规范

约定

RFC2119

本文档中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 和 “OPTIONAL” 必须按照 RFC 2119 中的描述进行解释。

带前缀与不带前缀

带前缀 的十六进制值以 0x 开头。不带前缀 的值没有前缀。除非另有说明,否则所有十六进制值0x 前缀表示。

  • 带前缀: 0xdeadbeef
  • 不带前缀: deadbeef

文档格式

规范格式是单个 JSON 对象。包 必须 符合以下序列化规则。

  • 文档必须紧密打包,即没有换行符或多余的空格。

  • 所有对象中的键必须按字母顺序排序。

  • 同一个对象中的重复键无效。

  • 文档必须使用 UTF-8 编码。

  • 文档必须没有尾随换行符。

  • 为了确保向后兼容性,manifest_version 是一个被禁止的顶级键。

文档规范

为包定义了以下字段。可以包含自定义字段。自定义字段x- 为前缀,以防止与规范的未来版本发生名称冲突。

EthPM 清单版本

manifest 字段定义了此文档所符合的规范版本。

  • 必须 包含此字段。

  • 必需: 是
  • : manifest
  • 类型: 字符串
  • 允许的值: ethpm/3

包名

name 字段定义了此包的人类可读名称。

  • 包含此字段以便在 EthPM 注册表上发布。

  • 包名称必须以小写字母开头,并且只能包含小写字母 a-z、数字字符 0-9 和短划线字符 -

  • 包名称的长度不得超过 255 个字符。

  • 必需: 如果包含 version
  • : name
  • 类型: 字符串
  • 格式: 必须匹配正则表达式 ^[a-z][-a-z0-9]{0,255}$

包版本

version 字段声明此版本的版本号。

  • 包含此字段以便在 EthPM 注册表上发布。

  • 此值符合 semver 版本编号规范。

  • 必需: 如果包含 name
  • : version
  • 类型: 字符串

包元数据

meta 字段定义了有关包的元数据的位置,这些元数据本质上不是包安装所必需的,但可能因其他原因而重要或方便。

源代码

sources 字段定义了一个源代码树,该源代码树包含重新编译此版本中包含的合约所需的完整源代码树。

合约类型

contractTypes 字段托管了此版本中包含的 合约类型

  • 仅包含可以在此包的源文件中找到的合约类型。

  • 不应包含来自依赖项的合约类型。

  • 不应在版本的合约类型部分中包含抽象合约。

  • 必需: 否
  • : contractTypes
  • 类型: 对象(字符串: 合约类型对象
  • 格式: 键必须是有效的 合约别名
    必须符合 合约类型对象 定义。

编译器

compilers 字段保存了有关编译器及其设置的信息,这些编译器及其设置已用于生成此版本中包含的各种 contractTypes

部署

deployments 字段保存了有关此版本已部署 合约实例 的链的信息,以及这些已部署合约实例的 合约类型 和其他部署详细信息。此对象的 BIP122 URI 键定义的链集必须是唯一的。在部署字段中不能有两个不同的 URI 键表示相同的区块链。

  • 必需: 否
  • : deployments
  • 类型: 对象(字符串: 对象(字符串: 合约实例对象))
  • 格式: 键必须是有效的 BIP122 URI 链定义。
    必须是符合以下格式的对象:
    - 键必须是有效的 合约实例名称
    - 值必须是有效的 合约实例对象

构建依赖项

buildDependencies 字段定义了此项目依赖的 EthPM 包的键/值映射。

  • 必需: 否
  • : buildDependencies
  • 类型: 对象(字符串: 字符串)
  • 格式: 键必须是有效的 包名称
    必须内容可寻址 URI,该 URI 解析为符合与其父包相同的 EthPM 清单版本的有效包。

对象定义

包中使用的不同对象的定义。所有对象都允许包含自定义字段。自定义字段x- 为前缀,以防止与规范的未来版本发生名称冲突。

链接引用 对象

链接引用 对象具有以下键/值对。假定所有链接引用都与某些相应的 字节码 相关联。

偏移量:offsets

offsets 字段是一个整数数组,对应于链接引用在字节码中出现的每个起始位置。位置从相应字节码的字节表示形式的开头开始,从 0 开始索引。如果此字段引用的位置超出字节码的末尾,则此字段无效。

  • 必需: 是
  • 类型: 数组

长度:length

length 字段是一个整数,它定义了链接引用的字节长度。如果定义的链接引用的末尾超过字节码的末尾,则此字段无效。

  • 必需: 是
  • 类型: 整数

名称:name

name 字段是一个字符串,它必须是有效的 标识符使用相同的名称为任何与同一链接值链接的链接引用命名。

  • 必需: 否
  • 类型: 字符串
  • 格式: 必须符合 标识符 格式。

链接值 对象

描述单个 链接值

定义 链接值对象 具有以下键/值对。

偏移量:offsets

offsets 字段定义了在此链接值的 value 写入的相应字节码中的位置。这些位置从相应字节码的字节表示形式的开头开始,从 0 开始索引。

  • 必需: 是
  • 类型: 整数
  • 格式: 请参见下文。

格式

整数数组,其中每个整数必须符合以下所有条件。

  • 大于或等于零

  • 严格小于相应字节码的不带前缀的十六进制表示形式的长度。

类型:type

type 字段定义了用于确定在 链接 相应字节码时编码的内容的 value 类型。

  • 必需: 是
  • 类型: 字符串
  • 允许的值: 字节码文字的 "literal"
    命名引用特定 合约实例"reference"

值:value

value 字段定义了在 链接 相应字节码时应写入的值。

  • 必需: 是
  • 类型: 字符串
  • 格式: 根据 type 确定,请参见下文。

格式

对于静态值文字(例如,地址),值必须是以 0x 为前缀的十六进制字符串,表示字节。

要从此包中引用 合约实例 的地址,该值应为该合约实例的名称。

  • 此值必须是有效的 合约实例名称

  • 此链接值所属的合约实例下的链定义必须在其键中包含此值。

  • 此值可能不会引用此链接值所属的同一合约实例。

要从依赖项树中的某个位置引用 中的合约实例,值的构造方式如下。

  • [p1, p2, .. pn] 定义依赖项树中的路径。

  • p1p2pn 中的每一个必须是有效的包名称。

  • p1 必须存在于当前包的 buildDependencies 的键中。

  • 对于每个 pn,其中 n > 1pn 必须存在于 pn-1 的包的 buildDependencies 的键中。

  • 该值由字符串 <p1>:<p2>:<...>:<pn>:<contract-instance> 表示,其中所有 <p1><p2><pn> 都是有效的包名称,并且 <contract-instance> 是有效的 合约名称

  • <contract-instance>必须是有效的 合约实例名称

  • 在由 <pn> 定义的依赖项包中,必须满足以下所有条件:

    • deployments 键下必须定义 恰好 一个链,该链与此链接值嵌套下的链定义匹配。

    • <contract-instance>必须存在于匹配链的键中。

字节码 对象

字节码对象具有以下键/值对。

字节码:bytecode

bytecode 字段是一个字符串,包含字节码的 0x 前缀十六进制表示形式。

  • 必需: 是
  • 类型: 字符串
  • 格式: 0x 前缀的十六进制。

链接引用:linkReferences

linkReferences 字段定义了相应字节码中需要 链接 的位置。

  • 必需: 否
  • 类型: 数组
  • 格式: 所有值必须是有效的 链接引用对象。另请参见下文。

格式

如果应用到相应的 bytecode 字段时任何 链接引用 无效,或者任何链接引用相交,则此字段被视为无效。

相交定义为两个重叠的链接引用。

链接依赖项:linkDependencies

linkDependencies 定义了用于链接相应字节码的 链接值

  • 必需: 否
  • 类型: 数组
  • 格式: 所有值必须是有效的 链接值对象。另请参见下文。

格式

此字段的验证包括以下内容:

  • 两个链接值对象不得包含任何相同的 offsets 值。

  • 每个 链接值对象linkReferences 字段下必须具有相应的 链接引用对象

  • 已解析的 value 的长度必须等于相应 链接引用length

包元数据 对象

定义 包元数据 对象具有以下键/值对。

作者

authors 字段定义了此包作者的人类可读名称列表。包可以包含此字段。

  • 必需: 否
  • : authors
  • 类型: 数组(字符串)

许可证

license 字段声明与此包关联的许可证。此值符合 SPDX 格式。包包含此字段。如果文件 源代码对象 定义了自己的许可证,则该许可证对于该特定文件优先于此包范围的 meta 许可证。

  • 必需: 否
  • : license
  • 类型: 字符串

描述

description 字段提供了可能与包相关的其他详细信息。包可以包含此字段。

  • 必需: 否
  • : description
  • 类型: 字符串

关键字

keywords 字段提供了与此包相关的相关关键字。

  • 必需: 否
  • : keywords
  • 类型: 数组(字符串)

链接

links 字段提供了与此包关联的相关资源的 URI。如果可能,作者对以下常见资源使用以下键。

  • website: 包的主要网站。

  • documentation: 包文档

  • repository: 项目源代码的位置。

  • 必需: 否
  • : links
  • 类型: 对象(字符串: 字符串)

源代码 对象

定义 源代码 对象具有以下字段。

  • : 源代码文件的唯一标识符。(字符串)
  • : 源代码对象

源代码 对象

校验和:checksum

源代码文件的哈希。

  • 必需: 仅当缺少 content 字段且提供的 URL 均不包含内容哈希时。
  • : checksum
  • : 校验和对象

URL:urls

解析为同一源代码文件的 URL 数组。

  • URL存储在内容可寻址文件系统上。如果不是,则必须包含 contentchecksum 之一。

  • URL必须以方案为前缀。

  • 如果生成的文档是目录,则键解释为目录路径。

  • 如果生成的文档是文件,则键解释为文件路径。

  • 必需: 如果未包含 content
  • : urls
  • : 数组(字符串)

内容:content

内联合约源。如果同时提供了 urlscontent,则 content必须urls 中标识的文件的内容匹配。

  • 必需: 如果未包含 urls
  • : content
  • : 字符串

安装路径:installPath

源文件的文件系统路径。

  • 必须是以 ./ 开头的相对文件系统路径。

  • 必须解析为当前虚拟工作目录中的路径。

  • 必须在所有包含的源中是唯一的。

  • 不得包含 ../,以避免在不正确的实现中访问源代码文件夹之外的文件。

  • 必需: 要使包可写入磁盘,则必须包含此字段。
  • : installPath
  • : 字符串

类型:type

type 字段声明了源代码文件的类型。该字段为以下值之一:solidityvyperabi-jsonsolidity-ast-json

  • 必需: 否
  • : type
  • : 字符串

许可证:license

license 字段声明了与此源代码文件关联的许可证类型。定义后,此许可证将替代包范围的 元数据许可证

  • 必需: 否
  • : license
  • : 字符串

校验和 对象

定义 校验和 对象具有以下键/值对。

算法:algorithm

用于生成相应哈希的 algorithm。可能的算法包括但不限于 sha3sha256md5keccak256

  • 必需: 是
  • 类型: 字符串

哈希:hash

使用相应算法生成的源文件内容的 hash

  • 必需: 是
  • 类型: 字符串

合约类型 对象

定义 合约类型 对象具有以下键/值对。

合约名称:contractName

contractName 字段定义了此 合约类型合约名称

源代码 ID:sourceId

生成此合约类型的源文件的全局源代码标识符。

  • 必需: 否
  • 类型: 字符串
  • 格式: 必须匹配此包的 源代码对象 中包含的唯一源代码 ID。

部署字节码:deploymentBytecode

deploymentBytecode 字段定义了此 合约类型 的字节码。

  • 必需: 否
  • 类型: 对象
  • 格式: 必须符合 字节码对象 格式。

运行时字节码:runtimeBytecode

runtimeBytecode 字段定义了此 合约类型 的未链接的 0x 前缀运行时部分的 字节码

  • 必需: 否
  • 类型: 对象
  • 格式: 必须符合 字节码对象 格式。

ABI:abi

UserDoc:userdoc

  • 必需: 否
  • 类型: 对象
  • 格式: 必须符合 UserDoc 格式。

DevDoc:devdoc

  • 必需: 否
  • 类型: 对象
  • 格式: 必须符合 DevDoc 格式。

合约实例 对象

合约实例对象 表示一个已部署的 合约实例,并定义为具有以下键/值对。

合约类型:contractType

contractType 字段定义了此 合约实例合约类型。这可以引用此 中包含的任何合约类型包清单buildDependencies 部分中的任何包依赖项中找到的任何合约类型。

  • 必需: 是
  • 类型: 字符串
  • 格式: 请参见下文。

格式

此字段的值必须符合此处两种格式中的一种

要从此包中引用合约类型,请使用格式 <contract-alias>

  • <contract-alias>必须是有效的 合约别名

  • 该值必须存在于此包的 contractTypes 部分的键中。

要从依赖项中引用合约类型,请使用格式 <package-name>:<contract-alias>

  • <package-name>必须存在于此包的 buildDependencies 的键中。

  • <contract-alias>必须是有效的 合约别名

  • <package-name> 的已解析包必须在 contractTypes 部分的键中包含 <contract-alias> 值。

地址:address

address 字段定义了 合约实例地址

  • 必需: 是
  • 类型: 字符串
  • 格式: 十六进制编码的 0x 前缀以太坊地址,与正则表达式 ^0x[0-9a-fA-F]{40}$ 匹配。

交易:transaction

transaction 字段定义了在其中创建此 合约实例 的交易哈希。

  • 必需: 否
  • 类型: 字符串
  • 格式: 0x 前缀的十六进制编码的交易哈希。

区块:block

block 字段定义了挖掘创建此合约实例的交易的区块哈希。

  • 必需: 否
  • 类型: 字符串
  • 格式: 0x 前缀的十六进制编码的区块哈希。

运行时字节码:runtimeBytecode

runtimeBytecode 字段定义了此 合约实例 的字节码运行时部分。存在时,此字段中的值将取代此 合约实例合约类型 中的 runtimeBytecode

  • 必需: 否
  • 类型: 对象
  • 格式: 必须符合 字节码对象 格式。

此字节码的 linkReferences 中的每个条目必须linkDependencies 部分中具有相应的条目。

编译器信息 对象

compilers 字段定义了在编译此包中包含的任何 合约类型合约实例 期间使用的各种编译器和设置。

定义 编译器信息 对象具有以下键/值对。

名称:name

name 字段定义了在编译中使用的编译器。

  • 必需: 是
  • : name
  • 类型: 字符串

版本:version

version 字段定义了编译器的版本。该字段与操作系统无关(字符串中不包含操作系统),并且采用 semver 格式的稳定版本形式,或者如果在每晚版上构建,则应以 <semver>-<commit-hash> 的形式表示,例如:0.4.8-commit.60cc1668

  • 必需: 是
  • : version
  • 类型: 字符串

设置:settings

settings 字段定义了编译中使用的任何设置或配置。对于 "solc" 编译器,这符合 编译器输入和输出描述

  • 必需: 否
  • : settings
  • 类型: 对象

合约类型:contractTypes

在此包中,使用此编译器生成其输出的 合约别名合约类型 的列表。

  • 所有本地声明 runtimeBytecodecontractTypes 都应归因于编译器对象。

  • 单个 contractTypes 不得归因于多个编译器。

  • 必需: 否
  • : contractTypes
  • 类型: 数组(合约别名

BIP122 URI

BIP122 URI 用于通过 BIP-122 规范的子集定义区块链。

blockchain://<genesis_hash>/block/<latest confirmed block hash>

<genesis hash> 表示链上第一个区块的区块哈希,而 <latest confirmed block hash> 表示已可靠确认的最新区块的哈希(包管理器应可以自由选择所需的确认级别)。

词汇表

本词汇表中的术语已更新,以反映 V3 中所做的更改。

ABI

应用程序二进制接口的 JSON 表示形式。有关更多信息,请参见官方 规范

地址

特定链上帐户的公共标识符

字节码

编译器产生的 EVM 指令集。除非另有说明,否则应假定这是十六进制编码的,表示整数个字节,并且 带前缀0x

字节码可以是链接的或未链接的。(请参见 链接

  • 未链接的字节码:合约 EVM 指令的十六进制表示形式,其中包含需要 链接 才能使合约正常运行的代码段。
    未链接的代码段必须用零字节填充。
    示例0x606060405260e06000730000000000000000000000000000000000000000634d536f
  • 链接的字节码:合约 EVM 指令的十六进制表示形式,其中所有 链接引用 都已替换为所需的 链接值示例0x606060405260e06000736fe36000604051602001526040518160e060020a634d536f

链定义

此定义源自 BIP122 URI

格式为 blockchain://<chain_id>/block/<block_hash> 的 URI

  • chain_id 是链的创世哈希的不带前缀的十六进制表示形式。

  • block_hash 是链上区块的哈希的不带前缀的十六进制表示形式。

如果创世区块哈希与 chain_id 匹配,并且可以在该链上找到由 block_hash 定义的区块,则认为该链与链定义匹配。多个链可以匹配单个 URI,在这种情况下,所有链都被视为有效匹配项

内容可寻址 URI

任何包含加密哈希的 URI,该哈希可用于验证在 URI 处找到的内容的完整性。

URI 格式在 RFC3986 中定义

建议工具支持 IPFS 和 Swarm。

合约别名

这是一个用于引用特定 合约类型 的名称。合约别名在单个 必须是唯一的。

合约别名必须使用以下命名方案之一:

  • <contract-name>

  • <contract-name><identifier>

<contract-name> 部分必须与此合约类型的 合约名称 相同。

<identifier> 部分必须与正则表达式 ^[-a-zA-Z0-9]{1,256}$ 匹配。

合约实例

合约实例是 合约类型 的特定已部署版本。

所有合约实例在某些特定链上都具有 地址

合约实例名称

一个名称,该名称引用来自单个 部署的特定链上的特定 合约实例。此名称在给定链的所有其他合约实例中必须是唯一的。该名称必须符合正则表达式 ^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$

如果给定的 合约类型 只有一个已部署的实例,则包管理器使用该合约类型的 合约别名 作为此名称。

如果给定的合约类型有多个已部署的实例,则包管理器使用提供一些添加的语义信息的名称,以帮助以有意义的方式区分两个已部署的实例。

合约名称

在源代码中找到的用于定义特定 合约类型 的名称。这些名称必须符合正则表达式 ^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$

在项目的源文件中,可以有多个具有相同合约名称的合约。

合约类型

指包源中的特定合约。此术语可用于引用抽象合约、普通合约或库。如果两个合约具有相同的字节码,则它们属于同一合约类型。

示例:

contract Wallet {
    ...
}

Wallet 合约的已部署实例将属于 Wallet 类型。 ```#### 标识符 通常指 中的命名实体。

一个符合正则表达式的字符串 ^[a-zA-Z][-_a-zA-Z0-9]{0,255}$

链接引用

合约字节码中需要链接的位置。链接引用具有以下属性。

  • offset:定义链接引用开始的字节码中的位置。
  • length:定义引用的长度。
  • name:(可选)用于标识引用的字符串。

链接值

链接值是可以代替 链接引用 插入的值。

链接

在某些 字节码 中用 链接值 替换 链接引用 的行为。

应用程序的源代码或编译后的字节码的分发,以及与作者身份、许可证、版本控制等相关的元数据。

为简洁起见,术语 通常用作换喻,表示 包清单

包清单

包的机器可读描述。

已添加前缀

带有前导 0x字节码字符串。

  • 示例0xdeadbeef

未添加前缀

添加前缀

  • 示例deadbeef

理由

最小化

EthPM 包以字母顺序排列并最小化的 JSON 格式分发,以确保一致性。由于包发布在内容可寻址的文件系统(例如 IPFS)上,因此此限制保证任何给定的合约资产集将始终解析为相同的内容可寻址 URI。

包名

包名仅限于小写字符、数字和 -,以提高包名的可读性,从而提高包的安全性。用户更有可能使用这个受限制的字符集准确地识别他们的目标包,而不会混淆一个伪装成具有相似但不同字符(例如 O0)的受信任包的恶意包。

BIP122

自 EthPM v1 以来一直使用 BIP-122 标准,因为它是用于识别不同区块链和区分分叉的行业标准 URI 方案。

编译器

编译器现在在一个顶级数组中定义,简化了工具识别与合约资产交互或验证所需的编译器类型。如果多个 contractTypes 共享相同的编译器类型,这也消除了不必要地重复信息。

向后兼容性

为了提高对 EthPM 规范的理解和可读性,manifest_version 字段在 v3 中更新为 manifest。为了确保向后兼容性,v3 包必须定义一个值为 "ethpm/3" 的顶级 "manifest"。此外,"manifest_version" 是 v3 包中禁止的顶级键。

安全注意事项

使用 EthPM 包隐式地需要导入和/或执行由他人编写的代码。EthPM 规范保证了当使用正确构建和发布的 EthPM 包时,用户将拥有与包作者包含在包中的完全相同的代码。但是,无法保证此代码可以安全地进行交互。因此,最终用户仅与由他们信任包含非恶意代码的个人或组织编写和发布的 EthPM 包进行交互至关重要。

版权

通过 CC0 放弃版权和相关权利。

Citation

Please cite this document as:

, "EIP-: ```md," Ethereum Improvement Proposals, no. , . [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-.