虚拟机 抽象
通用高级的抽象的合约虚拟机设计规范
账户抽象
- 账户信息由字节码(Code)和存储(Storage)构成
- 使用 20 长度字节数组类型的值来唯一标识(ID)账户
- 以账户 ID 为键,以 Code 和 Storage 为值,构建 Verkle 树来保存所有账户的状态
- 任何账户都可以接收输入(Input),在虚拟机里执行代码并保存新的执行结果(比如转账)
- 如果账户的字节码为空,将使用具有默认接口功能的代码替代(这个代码可以采用硬编码的方式提供)
- 因为所有账户都可以有字节码和存储,所以账户都可以视为合约
- 预先部署一个代币合约,作为原生数字货币,用于矿工奖励发放和用户费用支付
- 预先部署一个共识合约,接收区块输入,并验证、执行和存储它
合约虚拟机
在虚拟机中,所有账户统称为合约,合约执行代码需要消耗燃料(Gas),按照代码的复杂度来收取
硬编码合约
将区块链的一些核心功能转化为硬编码的合约实现,有以下优势
- 相比字节码的方式合约调用能带来一致性的体验
- 有效减少字节码的数量
- 可以采用硬编码的方式实现,性能不会有太大影响
从账户 0x1 开始分配
特殊字节码
- 购买 Gas:共识合约会提供一个支付代币购买的接口,经过接口验证后内部调用此字节码为其增加 Gas,仅共识合约可以调用
- 重置合约:清空合约存储数据并使用新的字节码初始化(可以指定为空),类似以太坊合约部署,仅限重置账户自己
- 创建合约:使用指定的字节码去初始化一个随机的合约,类似以太坊 CREATE2 字节码
合约可以自定义代码来关闭重置功能,类似以太坊账户的合约销毁机制:不存在调用销毁字节码逻辑的合约是无法被销毁的
交易执行
- 用户指定一个目标合约和输入(符合一定规则的,一般会包含签名以及合约调用),发送到虚拟机中
- 加载合约对应的代码开始执行,初始时虚拟机会暂借一定量的 Gas(MinGas),这些 Gas 主要用调用购买 Gas 接口
- 交易可以在耗尽 MinGas 之前调用共识合约提供的 Gas 购买接口添加更多 Gas,否则交易会失败
- 失败的交易会回滚状态,但不返还消耗来购买 Gas 的代币;不管成功或失败,多余的 Gas 会进行返还处理
- 如果一笔交易没有购买过 Gas,则不应该打包进区块中(取决于矿工逻辑)
- 在交易结束(不管成功或失败)前都没有购买 Gas 的交易可以视为垃圾交易,理应直接丢弃
垃圾交易
为了避免无效交易的 DOS 攻击,需要在交易执行消耗少量 Gas 的时候就进行判断,如果还没有账户为这笔交易买单,则应该终止执行并将其视为垃圾交易。因为矿工激励规则,没有账户付 Gas 的交易矿工收益为零,所以矿工有权拒绝打包这类交易。
灵活收费
将 Gas 收费逻辑转移到虚拟机中实现,只要交易目标合约调用了共识合约的购买 Gas 接口即可,目标合约可以在购买 Gas 之前执行一些自定义代码(比如签名验证或其它一些检查),共识合约可以自定义购买 Gas 费的逻辑(比如某些账户免费或阶梯购买)
交易安全
合约有默认的接口,使用对应的私钥进行控制,用户可以更新代码实现自定义的规则,实现多签、托管、恢复等等功能,达到灵活控制账户的目的,后期还能采用升级默认的合约接口来提高安全性。
重放攻击由账户自行防御,可采用类似 nonce 的机制或其它方法
默认合约接口
链合约
- 存储区块(调用共识合约验证)
- 查询区块
- 参数配置查询
共识合约
- 验证一个新的区块
- 执行其中的交易
- 执行激励规则
- 验证一笔交易
系统合约
- 重置账户
- 创建账户
- 删除账户