ERC-1900: dType - EVM 的去中心化类型系统
Authors | Loredana Cirstea (@loredanacirstea), Christian Tzurcanu (@ctzurcanu) |
---|---|
Created | 2019-03-28 |
Discussion Link | https://github.com/ethereum/EIPs/issues/1882 |
简单总结
EVM 和相关的语言(如 Solidity)需要一个可扩展的类型系统共识,以便进一步发展成为单例操作系统(世界计算机)。
摘要
我们提出了一个以太坊的去中心化类型系统,以引入数据定义(以及 ABI)的一致性。这个 ERC 专注于定义一个链上的类型注册表(命名为 dType
)和一个基于 struct
创建类型的通用接口。
动机
为了在以太坊上构建一个可互操作的协议网络,我们需要数据标准化,以确保链上信息的顺畅流动。链下,类型注册表将允许更好地分析区块链数据(例如,对于区块链浏览器)并创建智能合约开发工具,以便在新智能合约中轻松使用现有类型。
然而,这仅仅是第一阶段。正如本文档和未来基于本文档的提案中所定义的,我们正在提出更多内容:具有数据存储的去中心化类型系统 - ERC-2158。此外,开发人员可以创建 pure
函数库,这些函数知道如何交互和修改数据条目 - dType Functions Extension。这将有效地为以太坊上的一般函数式编程系统创建基础,开发人员可以在其中使用以前创建的构建块。
总结:
- 我们希望拥有一个良好的去中心化媒介,用于整合所有以太坊数据以及不同类型数据之间的关系。此外,还需要一种解决与每种数据类型相关的行为的方法。
- 函数式编程变得更容易。诸如
map
、reduce
、filter
之类的函数由每个类型库实现。 - Solidity 开发工具可以透明地扩展为包含创建的类型(例如在 Remix 等 IDE 中)。稍后,EVM 本身可以具有对这些类型的预编译支持。
- 该系统可以轻松扩展到与其它语言相关的类型。(在源文件中有类型定义(存储在 Swarm 中的相应语言的源代码))
- dType 数据库应成为世界计算机操作系统的系统注册表的一部分
规范
类型注册表可以具有对其 CRUD 操作的管理协议。但是,此提案不涵盖此内容和其他权限保护。
类型定义和元数据
dType 注册表应支持注册 Solidity 的基本类型和复杂类型。此外,它还应支持合约事件定义。在这个 EIP 中,重点将放在描述注册 Solidity 用户定义类型所需的最小链上类型定义和元数据上。
类型定义:TypeLibrary
类型定义由一个类型库组成,其中包含:
- 用于定义类型的标称
struct
- 附加函数:
isInstanceOf
:检查给定的变量是否是已定义类型的实例。可以为每个类型字段定义其它规则,例如,uint16 amount
具有特定范围。- 提供诸如
map
、filter
、reduce
之类的 HOF structureBytes
和destructureBytes
:提供类型结构化和解构。当导入合约接口不是一个有效的选择时,这对于底层调用或汇编代码可能很有用。它也可以用于类型检查。
一个简单的例子是:
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
library myBalanceLib {
struct myBalance {
string accountName;
uint256 amount;
}
function structureBytes(bytes memory data) pure public returns(myBalance memory balance)
function destructureBytes(myBalance memory balance) pure public returns(bytes memory data)
function isInstanceOf(myBalance memory balance) pure public returns(bool isInstance)
function map(
address callbackAddr,
bytes4 callbackSig,
myBalance[] memory balanceArr
)
view
internal
returns (myBalance[] memory result)
}
类型也可以在其组合中使用现有类型。但是,这总是会导致有向无环图。
library myTokenLib {
using myBalanceLib for myBalanceLib.myBalance;
struct myToken {
address token;
myBalanceLib.myBalance;
}
}
类型元数据:dType 注册表
类型元数据将在链上 dType 注册表合约中注册。它由以下组成:
name
- 类型的名称,因为它将在 Solidity 中使用;它可以存储为string
或编码为bytes
。该名称可以具有人类可读的部分和版本号。typeChoice
- 用于存储其它 ABI 数据,这些数据区分了类型在链上和链下的处理方式。它被定义为一个enum
,具有以下选项:BaseType
、PayableFunction
、StateFunction
、ViewFunction
、PureFunction
、Event
contractAddress
-TypeRootContract
的以太坊address
。对于此提案,我们可以将 Type Library 地址视为TypeRootContract
。未来的 EIP 将使其更加灵活,并提出其它 TypeStorage 合约,这些合约将修改contractAddress
的范围 - ERC-2158。source
- 一个bytes32
Swarm 哈希,类型库和合约的源代码可以在其中找到;在未来的 EIP 中,dType 将被扩展为支持其它语言(例如 JavaScript、Rust),由 Swarm 哈希标识的文件将包含该语言的类型定义。types
- 子类型的元数据:第一层深度的内部组件。这是一个对象(structs
)数组,具有以下字段:name
- 子类型名称,类型为string
,类似于上面的name
定义label
- 子类型标签dimensions
-string[]
,用于存储数组维度。例如:[]
->TypeA
[""]
->TypeA[]
["2"]
->TypeA[2]
["",""]
->TypeA[][]
["2","3"]
->TypeA[2][3]
简单值类型的元数据示例:
{
"contractAddress": "0x0000000000000000000000000000000000000000",
"typeChoice": 0,
"source": "0x0000000000000000000000000000000000000000000000000000000000000000",
"name": "uint256",
"types": []
}
{
"contractAddress": "0x0000000000000000000000000000000000000000",
"typeChoice": 0,
"source": "0x0000000000000000000000000000000000000000000000000000000000000000",
"name": "string",
"types": []
}
组合类型可以定义为:
{
"contractAddress": "0x105631C6CdDBa84D12Fa916f0045B1F97eC9C268",
"typeChoice": 0,
"source": <类型源代码文件的 SWARM 哈希>,
"name": "myBalance",
"types": [
{"name": "string", "label": "accountName", dimensions: []},
{"name": "uint256", "label": "amount", dimensions: []}
]
}
组合类型可以进一步组合:
{
"contractAddress": "0x91E3737f15e9b182EdD44D45d943cF248b3a3BF9",
"typeChoice": 0,
"source": <类型源代码文件的 SWARM 哈希>,
"name": "myToken",
"types": [
{"name": "address", "label": "token", dimensions: []},
{"name": "myBalance", "label": "balance", dimensions: []}
]
}
myToken
类型将具有最终的数据格式:(address,(string,uint256))
和带标签的格式:(address token, (string accountName, uint256 amount))
。
dType 注册表数据结构和接口
为了存储此元数据,dType 注册表将具有以下数据结构:
enum TypeChoices {
BaseType,
PayableFunction,
StateFunction,
ViewFunction,
PureFunction,
Event
}
struct dTypes {
string name;
string label;
string[] dimensions;
}
struct dType {
TypeChoices typeChoice;
address contractAddress;
bytes32 source;
string name;
dTypes[] types;
}
对于存储,我们提出一种模式,该模式将类型元数据与其它特定于存储的数据隔离开来,并允许对记录执行 CRUD 操作。
// key: identifier
mapping(bytes32 => Type) public typeStruct;
// array of identifiers
bytes32[] public typeIndex;
struct Type {
dType data;
uint256 index;
}
请注意,我们建议将类型的主标识符 identifier
定义为 keccak256(abi.encodePacked(name))
。如果该系统扩展到其它编程语言,我们可以将 identifier
定义为 keccak256(abi.encodePacked(language, name))
。
最初,可以禁止使用单个单词的英文名称,以避免抢注域名。
dType 注册表接口为:
import './dTypeLib.sol';
interface dType {
event LogNew(bytes32 indexed identifier, uint256 indexed index);
event LogUpdate(bytes32 indexed identifier, uint256 indexed index);
event LogRemove(bytes32 indexed identifier, uint256 indexed index);
function insert(dTypeLib.dType calldata data) external returns (bytes32 identifier);
function remove(bytes32 identifier) external returns(uint256 index);
function count() external view returns(uint256 counter);
function getTypeIdentifier(string memory name) pure external returns (bytes32 identifier);
function getByIdentifier(bytes32 identifier) view external returns(dTypeLib.dType memory dtype);
function get(string memory name) view external returns(dTypeLib.dType memory dtype);
function isRegistered(bytes32 identifier) view external returns(bool registered);
}
注意:
为了确保向后兼容性,我们建议不支持更新类型。
还可以从接口中删除 remove
函数,以确保不变性。保留它的一个理由是清除未使用的或已过时的类型的存储空间。但是,这可能会产生不良影响,并且应伴随可靠的权限系统、测试和治理流程。当收到足够的反馈后,将更新此部分。
理由
类型注册表必须存储最少的信息量,以重建类型 ABI 定义。这使我们能够:
- 支持链上互操作性
- 解码链下区块链副作用(对区块浏览器有用)
- 允许链下工具缓存和搜索集合(例如,用于编写类型化智能合约的编辑器插件)
随着以太坊等全局操作系统的出现,一个优势变得清晰:我们可以拥有一个全局类型系统,系统的各个部分可以通过它进行互操作。项目应该同意标准化类型和类型注册表,不断改进它们,而不是创建封装的项目,每个项目都有自己的类型。
对添加新类型或删除未使用的类型达成共识的工作留给治理系统。
在指定了这种系统的基础之后,我们可以基于存储在 dType 注册表中的类型定义和规则,在编译时构建一个静态类型检查系统。
类型库必须表达严格与其定义的类型相关的行为。各种项目的业务逻辑所需的附加行为可以在以后通过包含处理各自类型的函数的库来添加。这些也可以在 dType 中注册,但将在未来的 ERC 中详细说明。
这种方法将定义与存储的数据和行为分开,从而实现更轻松、更安全的细粒度升级。
向后兼容性
此提案不影响现有的以太坊标准或实现。它使用 ABIEncoderV2 的当前实验版本。
测试用例
将会添加。
实现
一个正在进行中的实现可以在 https://github.com/pipeos-one/dType/tree/master/contracts/contracts 找到。 当就规范达成共识时,该提案将使用适当的实现进行更新。
当前实现(此提案的更扩展版本)的视频演示可以在 https://youtu.be/pcqi4yWBDuQ 观看。
版权
版权及相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Loredana Cirstea (@loredanacirstea), Christian Tzurcanu (@ctzurcanu), "ERC-1900: dType - EVM 的去中心化类型系统 [DRAFT]," Ethereum Improvement Proposals, no. 1900, March 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1900.