比特币价格·比特币行情
Ctrl+D收藏简单区块链

一文读懂Substrate的合约机制(一)

作者:

时间:2020/12/22 14:54:42

本期我们分享来自本体技术团队的一篇文章的第一部分,关于 Substrate 的合约机制分析。

概要

Substrate 把整个程序逻辑分为 Host 和 Runtime 部分,Host 功能是固定的,偏向于底层,是采用原生执行的方式,而 Runtime 部分是动态的,偏上层业务,编译成 Wasm 字节码,这样可以随时升级,其执行在 Wasm 虚拟机中。合约功能作为上层业务,放置在 runtime 中,由 contract pallet 模块负责。通过分析本文主要要搞清楚两个问题:

1. 合约设计的经济模型:交易执行收费和存储租金机制;

2. 合约的执行机制:本身跑在 Wasm 虚拟机里的 runtime 里是怎么跑用户 Wasm 合约的。

Runtime 的 contract pallet 扩展了 Currency trait 的账户系统,因此可以和其他基于 Currency 实现账户系统的模块一起使用。扩展的合约账户具有实例化合约和调用其他合约和非合约账户的功能。

为了合约代码的复用,将合约代码的上传部署和合约账户的实例化分成两部分,多个合约账户可以从同一份上传的 code 进行实例化。

合约的经济模型

为了避免垃圾交易和恶意合约占用计算和存储资源,合约的设计考虑了交易执行收费和合约存储收费逻辑。当合约账户的余额不够支付存储租金时,合约的存储会被清理并进入 tombstone 状态。

当合约处于正常工作状态,其主要有以下信息:

pub struct RawAliveContractInfo<CodeHash, Balance, BlockNumber> {    pub trie_id: TrieId, // 合约对应的trie 子树unique id.    pub storage_size: u32, // 总存储bytes,是所有key-value对的和。    pub empty_pair_count: u32, // 所有value长度为0的key-value pair数目。    pub total_pair_count: u32, // 所有key-value pair数目.    pub code_hash: CodeHash, // 关联的code hash    pub rent_allowance: Balance, // 支付的租赁费用上限。    pub deduct_block: BlockNumber, // 最近一次支付租金的区块号。    pub last_write: Option<BlockNumber>, // 最近一次child 存储写入数据的区块号}tombstone 状态的合约信息当合约进入 tombstone 状态后,合约的所有存储都会被清理,合约信息里只有一个对 storage_root+code_hash 进行 hash 的值。

pub struct RawTombstoneContractInfo<H, Hasher>(H, PhantomData<Hasher>);合约的复活合约进入 tombstone 状态后,技术上是可以进行恢复的。首先需要准备一本新临时合约T,往 T 合约的存储中插入原合约中的 key-value 对,使 storage root 和原合约完全一致,然后调用 restore_to 合约接口,这个接口会检查当前合约的 storage root 是否和要恢复的 tombstone 一致,如果满足要求那么就使原合约复活,并且将当前的临时合约的资产转移到复活合约,并销毁当前临时合约。

交易的 sender 必须在每个 call 中指定 gas limit,未使用完的 gas 会在调用结束后返还。当到达了指定的 gas limit 后,那么所有的 call 和相关的状态变更(包含转账)只会在当前调用的合约层进行回滚,比如,合约 A 调用 B,并且 B 执行时 gas 不够,那么所有 B 的调用将被回滚。如果 A 能对错误进行正确处理,那么 A 的其他调用和状态变更依然可以进行持久存储。初看起来这样做是一个极大的限制,但其实是底层增加了灵活性,因为并不是所有的调用都是灾难性的,因此给了调用方可以进行合理的判断和处理的机会;如果想要其他链那种出错就完全回滚的方式,那么可以在调用 B 出错后 A 也直接报错回滚 A 的变更。

对于 Wasm 的每一个指令和 host 函数都设置了对应的 Instruction Weight。

pub struct Schedule<T: Trait> {    /// 每个wasm指令执行的收费    pub instruction_weights: InstructionWeights<T>,    /// 每个导入函数调用的收费    pub host_fn_weights: HostFnWeights<T>,    // ...}runtime 会准备一个 gas(amount:u32)的计费函数,在 Wasm 合约上传后,立刻会对 Wasm 中的每一个函数进行计费函数的插入生成新的 code。后续合约的执行都以新的 code 为准。

pub struct RawAliveContractInfo<CodeHash, Balance, BlockNumber> {    pub trie_id: TrieId, // 合约对应的trie 子树unique id.    pub storage_size: u32, // 总存储bytes,是所有key-value对的和。    pub empty_pair_count: u32, // 所有value长度为0的key-value pair数目。    pub total_pair_count: u32, // 所有key-value pair数目.    pub code_hash: CodeHash, // 关联的code hash    pub rent_allowance: Balance, // 支付的租赁费用上限。    pub deduct_block: BlockNumber, // 最近一次支付租金的区块号。    pub last_write: Option<BlockNumber>, // 最近一次child 存储写入数据的区块号}tombstone 状态的合约信息当合约进入 tombstone 状态后,合约的所有存储都会被清理,合约信息里只有一个对 storage_root+code_hash 进行 hash 的值。

pub struct RawTombstoneContractInfo<H, Hasher>(H, PhantomData<Hasher>);合约的复活合约进入 tombstone 状态后,技术上是可以进行恢复的。首先需要准备一本新临时合约T,往 T 合约的存储中插入原合约中的 key-value 对,使 storage root 和原合约完全一致,然后调用 restore_to 合约接口,这个接口会检查当前合约的 storage root 是否和要恢复的 tombstone 一致,如果满足要求那么就使原合约复活,并且将当前的临时合约的资产转移到复活合约,并销毁当前临时合约。

pub struct Schedule<T: Trait> {    /// 每个wasm指令执行的收费    pub instruction_weights: InstructionWeights<T>,    /// 每个导入函数调用的收费    pub host_fn_weights: HostFnWeights<T>,    // ...}runtime 会准备一个 gas(amount:u32)的计费函数,在 Wasm 合约上传后,立刻会对 Wasm 中的每一个函数进行计费函数的插入生成新的 code。后续合约的执行都以新的 code 为准。

比特币期货日交易量创历史新高:Skew数据显示,昨天比特币期货交易量首度突破500亿美元,创历史新高。该成交量较原纪录提升20%以上。[2020/11/19 21:22:54]

JST成为JustLink联通链上与链下的核心纽带与计价工具:据官方消息显示,JUST基金会已于2020年10月30日正式上线去中心化预言机项目JustLink。JustLink能够以最安全的方式向链上的智能合约提供现实世界中产生的真实数据。作为JUST生态中的重要组成部分,JST是JustLink联动不同使用场景与不同生态之间的纽带与重要的计价工具。详情点击原文链接。[2020/10/30 11:16:35]

当前加密货币总市值约为3180.06亿美元:据金色财经数据显示,全球加密货币总市值约为3180.06亿美元。加密货币市场中占比排名第一的是BTC,市值约合2037.17亿美元,当前市值占比为64.06%; \nETH排名第二,市值约合401.84亿美元,当前市值占比为12.64%; \nXRP排名第三,市值约合111.58亿美元,当前市值占比为3.51%。[2020/10/9]

标签:

区块链热门资讯
首发 | DAO治理包治百病吗?去中心化保险的偿付反思

去中心化保险的偿付问题,真的适合用DAO投票去决定是否偿付吗? 首先我们来看一些通过投票来决定是否偿付的案例 我们从https://app.nexusmutual.io/claim-assessment查看老牌去中心化保险NXM的所有赔付案例,好家伙,65个赔付申请只有3个通过,还是最开始的3个,然后我们看看这3个赔付案例。

2020/12/22 14:54:55
Pickle的新代币机制

Pickle在上次在黑客事件之后,遭受重创,不过随着跟Yearn(YFI)的合并,事情出现了转机。在这次Yean的合并中,除了PJars跟 YFI的Vaults合并之外,对于PICKLE代币持有人来说,最关注的可能是其代币机制的变化。 DILL代币 在这次合并中,Pickle的代币机制出现了新的代币DILL。DILL类似于Curve协议中的VeCRV。

2020/12/22 14:54:50
ETH123.org:以太坊生态资源导航

哈喽,大家好。经过半个多月的努力,ETH123 终于和大家正式见面啦! 少废话,先看东西! 以太坊生态有些啥?我该从哪里开始?什么钱包好用?刚接触以太坊的新人们往往面临这样一堆问题。密码学货币对新手而言不算友好,晦涩难懂的概念,鱼龙混杂的信息,都可能成为登上这片新大陆的阻碍。每个人都曾是行业的萌新,这些疑惑,我们也深有感受。

2020/12/22 14:54:46
IPFS中MFS以及GC机制

 概 述 IPFS的介绍在《IPFS文件存储详解》已经详细介绍过,本文主要介绍IPFS中的文件系统MFS(Mutable File System)以及文件的GC机制。

2020/12/22 14:54:37
为你节省90% gas费:zkSync 使用教程

zkSync 是一个用于扩展以太坊支付及智能合约的 Layer2 协议,zkSync 称之为:加密支付的新标准。

2020/12/22 14:54:31
解放旧设备 Cypherium理性破壁

12月10日,国际货币金融机构官方论坛OMFIF发布了最新报告《支付的未来》,报告探索了传统支付提供商、科技公司和行业新进入者生态系统中正在进行的创新发展成果。 参与合作研究并联合发布报告的,既有花旗银行、万事达、Paypal、SWIFT等传统企业,也有互联网社交巨头Facebook旗下的数字钱包Novi。

2020/12/22 14:54:24
OKX