Substrate 合约书之合约模型
前言
「Substrate 合约书」用于介绍 Substrate 中与 Wasm 合约体系相关的一系列知识。本书由 Patract (https://patract.io/)主导编写,由 Aten (https://github.com/atenjin)负责。本书仓库位于 https://github.com/patractlabs/substrate-contracts-book(opens new window),欢迎有志之士一起为本书做出贡献。
本书当前主要以 Pallet-Contracts (即 Wasm 合约)作为主体进行介绍。因此本书内容包含:
运行合约的合约平台(模块)
Pallet-Contracts
编写合约的语言
ink!
Ask!
Solang
帮助合约开发的工具们
Redspot
Europa
Elara
其中由于 Pallet-EVM(即 EVM/Solidity 体系的合约)在以太坊生态中已有比较丰富的资料,故不会在本合约书中当做重点讲解。而另外的合约体系如 Pallet-Actor,或 Libra 移植合约平台等皆处于比较早期的研究阶段,因此也不会作为本书的重点。
为了让合约开发者更好的理解 Pallet-Contracts 模块与 Wasm 合约的运行方式,本书也会涉及一些 Wasm 的介绍以及区块链合约模型的介绍。
合约模型
在已经具备合约及合约沙盒的概念后,我们就可以开始讨论合约模型的概念了。
合约沙盒只是代表运行合约的环境,而合约是以什么方式运行的,合约和合约是怎么交互的,合约是怎么与链的数据互动的,这些问题就归属于合约模型问题。
换句话说,合约模型就是合约是以什么模型运行在合约沙盒/虚拟机中的。
如图所示,合约模型与合约虚拟机本质上是可以解耦的,其中关系只存在合约虚拟机是否能支持上层所需要的合约模型,例如:
1.Bitcoin 的虚拟机就是比特币脚本的栈执行器,由于执行器设计是非图灵完备的 OP_CODE,因此对于上层的合约模型只能支持 Bitcoin 的脚本。
2.Ethereum 跟随 Bitcoin 的灵感,设计了具备图灵完备的 OP_CODE,即 EVM 虚拟机(Ethereum Virtual Machine)。但是 EVM 的 OP_CODE 比较简陋,且只有栈的设计,没有堆的概念。但是 EVM 引入了读写状态的 OP_CODE,因此从虚拟机机制上对合约模型可以支持状态模型。因此 EVM 也被看做一个执行状态转换的状态转换机(如 Gavin Wood 撰写的以太坊黄皮书中所描述的)。
状态模型实际上是比较通用的抽象模型,绝大多数模型都可以用状态模型模拟(如在状态模型中构建 UTXO 模型),因此从理论上来说,只要继续完善 EVM 的 OP_CODE,EVM 的上层同样可以构建出其他合约模型。
3.Libra 认为区块链的核心在于资产的处理,因此提出了 Move 的虚拟机模型(Move Virtual Machine <MVM>)来从虚拟机上限定合约的模型,可以理解为是一种特化逻辑过的 OP_CODE 集合。因此 MVM 的上层只能运行 Move 模型。
通过以上讨论,我们可以认识到合约模型的概念,并且理解到虚拟机对上层合约模型的限制,因此接下来就可以讨论 Wasm 虚拟机可以运行的合约模型以及 Pallet-Contracts 的合约模型构成。
Wasm 虚拟机
Wasm 是一种在基于栈的虚拟机上运行的二进制的指令格式(WebAssembly<abbreviated Wasm)>is a binary instruction format for a stack-based virtual machine, from https://webassembly.org/<opens new window>)。
因此 Wasm 的模型和主流计算机程序的模型结构比较相似。另一方面 Wasm 被设计成为了一种比较通用的形式,且设计了 WASI 并支持了运行环境自由定义 Host Function,因此虽然 Wasm 从浏览器发展而来,但是当前的使用场景已经不限于浏览器,开始在边缘计算,热更新,Serverless 平台等发挥效果。
若以指令的完备性来衡量一个虚拟机的能力,则 EVM 处于半成品的程度,限制多且不够灵活;而 JVM,Wasm 虚拟机则是比较完备的,限制少,功能性强。另一方面指令设计的合理性一定程度也会影响虚拟机的执行效率,同时虚拟机采用的实现方案也会对执行效率产生比较大的影响。
例如 EVM 当前只能以解释器(Interpreter)的形式运行,并且当前的实现过程体(Go, C++等版本)中没有看到针对解释器的优化,执行效率比较底下,而 JVM, Wasm 等虚拟机有采用 JIT 的模式的实现,执行效率相当高甚至逼近本地执行的性能。
注:Pallet-Contracts 当前只能使用 Wasmi(解释器)执行 Wasm 代码,因此合约的执行性能比不上使用 Wasmtime 的 Runtime 的执行性能。
而同时,Wasm 虚拟机相比于 JVM 等虚拟机,十分轻便(LightWeight),快速,可定制性强,且 Host Function 的功能给予了 Wasm 虚拟机与宿主之间交互的通道,因此和其他虚拟机相比,将 Wasm 虚拟机作为区块链合约沙盒与链的功能结合在一起比较容易。
另一方面在笔者看来,Wasm 是处于底层代码与上层代码之间比较好的一个抽象层,且其复杂性与完备性也远超于 EVM,因此比较适合区块链合约领域的需求。
因此 Wasm 虚拟机提供的沙盒环境在满足合约沙盒的前提下还满足以下 2 点要求:
指令完备,功能性丰富,执行效率高
有适合的接口能与宿主(这里指代运行 Wasm 的环境,即链)交互,方便宿主提供需要的功能。
EVM 的合约模型
由于 Ethereum 是存储状态的区块链,因此 EVM 的合约模型理所应当的需要基本读写状态的功能。如果把每次合约运行的过程看做一次程序的启动到执行结束的过程,那么状态数据的变化就对应着这个程序需要持久化数据的变化。
因此对于读写状态,以太坊的 EVM 提供了 SLOAD 和 SSTORE 两个指令。
另一方面以太坊描述一个账户使用了“账户模型”,即将合约和调用合约的用户都看做了一个账户,在这个账户下存在 Balance 等概念,因此 EVM 提供了 CALLER,ORIGIN,CALLVALUE 等等一系列指令来描述这种模型。
同时由于在 EVM 的抽象体系中,认为合约与用户是一致的,因此出现了“合约调用合约”的模型,即 CALL,DELEGATECALL 等指令,由此带来了合约的可组合性,造就了 Ethereum 繁荣的生态。而在 EVM 中,一个合约依托于一个 EVM 进行运行,因此合约调用合约是在一个 EVM 中启动了另一个 EVM 并加载指令进行执行。
当然 EVM 虚拟机设计的初衷就是为了解决比特币脚本的非图灵完备问题,为了解决这个问题并保证停机问题不发生,引入了指令的 Gas 计费模型,因此总结以上可以得到,EVM 的合约模型具备以下特性:
1.处理数据的模型是状态机模型,状态的变更靠外界调用触发(类比于调用了状态变更函数的过程);
2.合约模型中需要链相关的特性;
3.将合约与用户看做一致,允许合约调用合约;
4.引入指令计费模型。
Pallet-Contracts 的合约模型
这里直接下结论:Pallet-Contracts 虽然使用了 Wasm 虚拟机来执行代码,但是其合约模型基本与 EVM 合约模型一致。
也就是说 Pallet-Contracts 的合约模型同样具备以下 4 点特性:
处理数据的模型是状态机模型;
合约模型中需要链相关的特性;
将合约与用户看做一致,允许合约调用合约;
引入指令计费模型。
并且,在以上 4 种特性的基础上,增加了“存储租赁模型”:
Rent 存储租赁计费
在上文已经称述了合约执行的环境和合约模型是可以解耦的,EVM 由于设计的比较早还没有解耦这个层次的概念,因此在指令中 SLOAD,SSTORE 及类似和链相关的指令是与 EVM 其他指令合并一起的。而 Wasm 本来并非为区块链设计,因此一定不存在这些和链环境相关的指令。
因此 Wasm 的 Host Function 即是用来完成这件事情的。链作为 Host 宿主,只需要把他认为合约可能会用到的方法提供给 Wasm 虚拟机,让他导入这些函数对象,在合约的执行过程中即可以使用。因此通过 Host Function,Pallet-Contracts 合约模块就可以具备 1,2,4 功能,并将提供 3 需要的部分功能,同时第 5 点特性(租赁计费)也可以引入。
并且其中第 3 点功能的实现方式也与 EVM 一致,当出现合约调用合约的部分时,通过 Host Function 从 Wasm 回到了 Pallet-Contracts 模块,并启动了一个新的 Wasm 虚拟机去执行被调用的合约。(该部分在以后的文章中会描述)
因此总结而言,Pallet-Contracts 的合约模型具备如下特性:
1.合约模型与 EVM 的合约模型一致,并在此基础上增加了存储计费模型
2.与链交互的实现通过 Wasm 的 Host Function 特性实现
使用 Wasm 虚拟机实现其他合约模型
刚才简要描述了 Pallet-Contracts 是如何在 Wasm 虚拟机上实现合约模型的,由于前文已经解释了虚拟机与合约模型是可以解耦的,因此实际上在 Wasm 虚拟机上同样可以实现其他的合约模型。
例如我们可以考虑将 Move 虚拟机也移植到 Wasm 虚拟机中,其有两种可能的实现方式:
1.类比于将 EVM 的实现体在 Runtime 的 Wasm 环境运行,可以将 MVM 的实现体也编译成 Wasm 的形式(例如命名为 Pallet-MVM),在 Runtime Wasm 中运行。
基于这种实现,Move 依然可以按正常方式编译,并和 Solidity 的编译结果运行于 Pallet-EVM 一致,将 Move 的编译结果运行在例如 Pallet-MVM 的平台上。
2.将 MVM 与所有权,链相关的特性抽象一层,做成和 Pallet-Contracts 的形式,并设计将 Move 语言编译的中间码 IR 编译到 Wasm。
基于这种实现,可以将 Move 编译成为 Wasm,并在 Wasm 虚拟机中运行。
其他合约模型
EOS 的合约模型
EOS 的合约模型与 EVM 类似,同时强化了账户模型的概念。因此 EOS 使用 Wasm 的方式也是基于 Wasm 的执行,并通过 Host Function 引入与链相关的功能。
EOS 和 EVM 模型的主要区别在于,EOS 的合约调用合约的过程是以发交易的形态调用,并且 EOS 的资源模型是抵押模型。当前普遍认为正是 EOS 的抵押模型最后导致 EOS 没有走向成功。
异步合约模型
pallet-actor 是 Substrate 尝试实现异步合约模型的一个开端,当前没有什么进展。pallet-actor 的模型打算使用 Wasm 虚拟机作为运行环境,并在此基础上添加异步的功能以提升性能。
当前也有其他少数对异步合约模型的研究,但是皆处于比较初步的阶段。
About Patract
Patract 为波卡 Wasm 合约生态的平行链和 DApp 开发提供解决方案。我们帮助社区平行链设计和开发链上合约模块和 Runtime 支持,并且为 DApp 开发者提供覆盖开发、测试、调试、部署、监控、数据提供和前端开发等阶段的全栈工具和服务支持。
How to join Patract
1.对于合约开发者,可以访问官网 (https://patract.io),熟悉测试链和工具套件。欢迎加入官方开发群:
Element(https://app.element.io/#/room/#PatractLabsDev:matrix.org)
Discord(https://discord.gg/wJ8TnTfjcq)
搜索“Patract 开发平台”关注 Patract 微信公众号
2.对于将要集成 Wasm 合约功能的平行链项目方,或者使用 Wasm 合约开发的 DApp 项目方,商务合作欢迎联系 santry@patract.io
3.对于用户,欢迎加入:
Telegram(https://t.me/patract)
Twitter(https://twitter.com/PatractLabs)
4.对于求职者,我们在招聘区块链开发工程师、前端/全栈开发工程师、开发者运营等岗位,可以联系 sean@patract.io
评论