区块链行业将迎来首次技术标准之争:EOS-VM抢跑虚拟机赛道

EOS-VM 是 EOS.IO 成为通用区块链协议的重要基石,同时超越了 EOS.IO 自身,将会成为事实上的区块链虚拟机技术标准,甚至会将以太坊和波卡尚在起步阶段的虚拟机开发扼杀在襁褓中。

0、前言

EOS.IO 开发团队 Block.One 于 2019 年 6 月 1 日发布了全新的 EOS-VM。

EOS 原力团队在经过大规模测试后认为,EOS-VM 将成为区块链行业使用率最高的 VM,也将率先成为区块链行业 VM 的事实标准。

我们在《EOS.IO 将迎来史上最复杂硬分叉升级》一文中曾经讲过,多个重要的分支都在积极开发中,而 EOS-VM 就是一个重要性不亚于 1.8.0 的分支。该分支从 2018 年 7 月份就开始了,从提交记录上来看,早期的 EOS-VM 并没有特别紧凑的开发计划。然而从 2019 年开始,经过了一系列密集的开发,初步完成了今天我们所看到的 EOS-VM 项目。

如果说 EOSIO1.8.0 版本让我们看到了 Block.one 在 EOS.IO 上的决心,那么 EOS-VM 可以让我们一窥 Block.one 在区块链行业的野心。

1、什么是 VM

VM 全称为 Virtual Machine,在区块链语境下可以理解为智能合约的运行环境。

我们可以将智能合约类比于互联网中的 HTML,区块链系统可以看作操作系统,那么 VM 则是浏览器,各种基于智能合约的 DAPP 就是互联网中的各种网站。

以太坊完成了区块链系统中首个系统的智能合约支持,其 EVM 虚拟机也是早期智能合约开发者的主流开发环境,同时有非常多的项目都借鉴了以太坊的 VM,如 TRX 的 TVM。

但是 EVM 有其局限性,虚拟机效率相对成熟的虚拟机系统来说极其低下,难以支持更加复杂的应用和环境。

成熟的虚拟机系统是一个由一系列庞大的项目构成的体系,事实上,在目前的环境下,从零开始实现一个完整成熟的虚拟机系统是非常困难的,同时也是没有必要的,因为对于这样一个庞大的工程项目,从零开始意味着开发者和社区要承受大量的兼容和学习成本,最好的方式是基于现有成熟的虚拟机标准来开发适用于区块链项目的虚拟机实现。

因此,大多数区块链项目都选择使用现有成熟的虚拟机实现,目前可以说最适合的莫过于 WebAssembly 虚拟机,除了 EOS.IO 之外,polkadot 也选择基于 WebAssembly,而以太坊也在开发基于 WebAssembly 的 ewasm 项目。

对于区块链领域来说 , 无论是不是「The Lesser Evil」,WebAssembly 已经成为非常重要的一部分了。

作为一个高性能的去中心化智能合约平台,EOSIO 中所使用的虚拟机实现是整个项目中非常重要的一部分,在阅读早期的 EOSIO 实现代码时会发现,在调用虚拟机时,EOSIO 实现代码中少有的做了很严格的封装,以此来隐藏虚拟机实现的细节,可以见得 EOSIO 项目将会在虚拟机方面做持续重大的改进 。

 // EOSIO chain 实现中少有的接口封装
    
    class wasm_interface {
    
    public:
    
    enum class vm_type {
    
    wavm,
    
    wabt
    
    };
    
    ...
    
    private:
    
    unique_ptr my;
    
    ...
    
    };

从最早使用的 wavm 虚拟机,到后面支持的 wabt 虚拟机,Block.one 团队一直在改进虚拟机的支持,也在为多虚拟机兼容作准备,最终 EOSIO 发起了更高的挑战,开发出了全新的 EOS-VM,最为 EOSIO 使用的虚拟机实现。

如果说 EVM 是一个区块链虚拟机的话,那么 EOS-VM 则会是第一个可大规模商用的虚拟机。

2、EOS-VM 是什么

我们先来看看 EOS-VM 到底是什么,EOS-VM 是一个区块链系统专用的 wasm 运行时。

在区块链系统中,合约代码会被编译成字节码的形式,这些字节码不能直接在操作系统上运行,需要一个执行器来执行这些合约,在软件体系中,可以把这些执行器视为一个抽象的「机器」,EOS-VM 就是这样一个执行器。

EOS-VM 主要做四件事:

首先 ,EOS-VM 负责加载和解析编译后的智能合约字节码,也就是 wasm;

其次,EOS-VM 负责在字节码运行过程中为其分配资源,当然对于智能合约来说,可用的资源就是内存;

再次,EOS-VM 负责向智能合约的字节码提供虚拟机外的 API 调用功能;

最后,EOS-VM 负责执行字节码来计算智能合约运行的结果。

在 EOS-VM 中 eosio::vm::backend 类是整个虚拟机系统调用的入口,在 tools 目录下有两个使用 EOS-VM 虚拟机的测试工具,想要详细了解 EOS-VM 实现的读者可以通过这些作为入口来阅读 EOS-VM 的代码。

int main(int argc,char**argv) {

...

// 设置看门狗 , 限制运行时间为秒

watchdog wd;

wd.set_duration(std::chrono::seconds(3));

try {

...

// 加载 wasm 字节码

auto code = backend_t::read_wasm( argv[1] );

// 创建执行环境

backend_t bkend( code );

wd.set_callback([&](){

bkend.get_context().exit();

});

...

// 执行

bkend.execute_all(&wd);

} catch ( ... ) {

}

return 0;}

这里说的 EOS-VM 的主要工作,但如果只是这些的话,那其实和 wavm、wabt 没什么区别了,在完成基本的必要工作之外,EOS-VM 针对区块链应用场景做了一些重要的改进和优化,下面我们来结合 EOS-VM 的介绍文档以及代码实现来看看 EOS-VM 有哪些重要的改进。

3、EOS-VM 有哪些重要的改进

EOS-VM 针对区块链应用场景作了很多的改进,这些改进对于智能合约开发者来说是最好的礼物。

下面我们先结合 EOS-VM README 文档看看有哪些改进,再结合现有的 EOS-VM 代码具体看一下 EOS-VM 是如果做到的。

在早期 EOS-VM 的 README 中 ,Block.one 列举了以下的改进 :

  1. Satisfying the needs of a blockchain.
  2. Security built into the framework.
  3. Performance centric design.
  4. Light weight and easy to integrate solution.
  5. Effortless extendability.

目前的 README 中改为了对于非开发者更加易懂的描述 :

Extremely Fast Execution (6x faster than WABT)
Extremely Fast Parsing/Loading (20x faster than WABT)
Efficient Time Bound Execution
Deterministic Execution (Soft Float & Hardware Floating Point options)
Standards Compliant
Designed for Parallel Execution
C++ / Header Only
Simple API for integrating Native Calls

我们来逐条分析 :

3.1 满足区块链场景下的需求

首先 Block.one 对 EOS-VM 的定位是「A VM for Blockchain」,这意味着 EOS-VM 中在 WebAssembly 的基础上添加了很多区块链所需的特定功能。

目前主要是三方面:

首先是浮点数的支持。对于浮点数,很多开发者往往片面的认为其运算是不精确的,无法用于区块链系统。实际上并非如此,只是对于一些不同的硬件中,因为各种各样的历史原因,硬件中固化的浮点数运算有一些差异,解决这一点最好的方式是使用 softfloat 库,不使用机器硬件提供的浮点数,这样不同的硬件机器上,浮点数运算的结果都是相同的了。当然这里 Block.one 也提到,如果不在乎所有平台上保持浮点数运算的确定性,则可以使用基于硬件的浮点数运算,这样效率会比使用 softfloat 快很多,这种情况一般是节点硬件机器会保持统一的状态下使用的。

在 EOSIO 中其实也集成了 softfloat 库,但是之前的实现是在链中嵌入的,原生的虚拟机中本身不支持,现在并入虚拟机实现,可以降低其他区块链使用 EOS-VM 时的开发成本。

其次是 EOS-VM 增加了 watchdog 机制以确保运行字节码的运行时间限制,这个类似看门狗的机制,会在细粒度上对合约进行资源使用限制。

这一点很重要 , 以至于后期的介绍文档中要单独分出一节来描述。

如果看过 EOS 现在的代码,会发现有很多大量杂乱的代码在处理合约执行超时的问题,对于一个图灵完备的智能合约来说,最大的困难在于我们如果不执行一遍其合约,就无法知道其执行消耗,所以 EOS 中需要边执行智能合约边判定其消耗时间,对于 EOS 链的环境来说 VM 是个黑盒,所以如果在 VM 外来进行合约执行时间判定的话就会非常困难,而 EOS-VM 在这方面提供了内置支持,相关的实现就会非常简单,也会避免这方面出现的问题。

最后是一些虚拟机执行时的边界限制,这些边界限制乍看上去是一些功能的限制,但是在区块链应用场景下,这些限制不会带来实际功能的限制,反而基于这些断言,EOS-VM 可以得到极大的优化。

3.2 内置的安全性支持

支持智能合约的区块链系统可以视作一台公用的计算机,而公用意味着必须对使用者进行限制。如果使用者可以毫无限制的运行自己的代码,那么会带来很大的安全性问题,对于公链来说,这是不能接受的。

这里的安全性问题主要是两方面:代码行为的安全性和代码消耗的有界性。

首先,EOS-VM 通过内置类型来保证类型的安全性,并且通过可选的分配器来使用系统提供的机制来保证沙箱性。

另外,上文提到的 watchdog 机制以确保运行字节码的运行时间限制。对于公链来说,如果没有有效的机制,这一点往往会引起公链的安全问题。EOSIO 之前就出现过基于延迟交易引发的阻塞攻击问题,这个问题本质上就是没有有效细致的界定资源使用的问题。相应的以太坊也多次出现类似的问题,以太坊早期的数次硬分叉都是为了解决这类问题。

最后,EOS-VM 在任何时候都不会触发无限制的递归或循环,严格限制某些 WASM 有意或者无意导致的崩溃或无限挂起机器的情况。

这些内置的安全性支持将会大大提高链的安全性,同时也会提供一个可控的安全性保证。

3.3 面向高性能的设计

在很多时候,特化就是最好的优化。

实际上,如果完全兼容 WebAssembly,那么 EOS-VM 优化的空间并不大。但是对于区块链的需求场景,很多 WebAssembly 的设计并不需要,EOS-VM 基于这一点做了大量的特化,同时意味着性能上,EOS-VM 也得到了非常大幅度的优化。

EOS-VM 性能主要得益于对其内置化的类型的优化,EOS-VM 内置了绝大多数合约需要的数据类型,对于这些类型 EOS-VM 就可以对其一一优化,特别是 variant,这个类型其实并不是一个原生的功能。如果直接使用类似 union 的话,会造成很大的类型安全问题,使用 variant,虽然在实现时得到了很好的安全性和易用性保证。但是如果不将其集成入虚拟机层,那么其复杂的实现会带来很大的性能损耗。

类似的还有 vector,如果阅读现在的 EOS 系统合约,会发现大量使用了 vector,诚然对于合约设计来说,使用 vector 是非常便捷的,但是很多对性能特别敏感的开发者可能会对此感到非常「不安」,如今 VM 直接集成 vector,可以料想后续这些开发者就可以「更愉快的」使用 vector 了。

现在的 EOS 合约开发需要依赖一个规模不算小的基础库,这意味着每个使用这些基础功能的合约都要集成其实现代码,将大量的基础库代码带入 wasm 层,如今 EOS-VM 在虚拟机的实现层植入这些基础类型,性能优化空间自然得到很大提高。

3.4 轻量级易于植入的架构

EOS-VM 是纯头文件的,这意味着 EOS-VM 可以被嵌入进几乎所有的 C++项目中。

同时,EOS-VM 在设计做了特别的处理,使得 EOS-VM 可以很好的适应多线程环境,C++多线程编程一度是个「深坑」,构建一个可以在并发环境下安全运行的库很多时候需要避免很多问题,EOS-VM 在这个问题上做了很多准备,可以避免重蹈像 std::string 在多线程环境下那样的「覆辙」。

纯头文件的优势还有很多,在这个方面 EOS-VM 已经很像在很多方面得到广泛应用的 LUA,后者同样以轻量级的运行时著称,可以预见,未来会有更多的非 EOS 甚至非区块链项目使用 EOS-VM。

3.5 高度可扩展性

EOS-VM 拥有一套精细设计的结构,从某些方面上来讲,EOS-VM 要比 EOSIO 的代码结构好得多。

EOS-VM 的设计中充分考虑了其拓展性,对于一个 VM 来说其主干结构几乎没有什么需要拓展和修改的地方,因为其功能就是上面提到的四件事。

但是对于不同的应用场景,其字节码格式和功能必然需要拓展和修改,EOS-VM 在响应的地方都做了设计,其中深度应用了 visitor 模式,使得在不改变类架构的前提下也可以很容易的为整个 VM 添加功能。

在很多人眼里,一个良好的架构似乎没有什么作用,毕竟你并不能把「架构良好」看作一个「前无古人」的新特性,但是对于项目开发而言,良好的架构会决定着整个项目后续的潜力。

总的来说,阅读现在的 EOS-VM 项目,会有一种类似 lua 或者 redis 项目的感觉,整个项目规模不大,结构紧凑,代码很干净。

虽然大量使用 C++特性会让一些初学者感到困惑,但并不会影响到对功能的理解,我们认为 EOS-VM 在未来将会在更广泛的领域中发挥更大的作用。

4、EOS-VM 对 EOSIO 生态的影响

EOSIO 作为一个开源软件,社区基于 EOSIO 启动了不同功能和治理理念的 EOS 网络、EOS、EOS 原力、ENU、Telos、worbli,BOS 等网络均在 Block.one 的技术支持下发展,而本次 VM 的改革将使得所有基于 EOSIO 启动的公有链受益。

从现有的实现来看,EOS-VM 将会尽量与当前 EOSIO 虚拟机实现保持兼容,出现不兼容的地方,也可以基于 abi 中的 version 来进行区别。未来即使出现大量和 EOS 原力一样对 EOSIO 底层代码进行了大量改进的区块链,也可以轻松兼容。

未来一段时间之内,基于 EOSIO 链的公链的开发者可以集成 EOS-VM 到链中,同时保持原有 wasm 支持。

引入 EOS-VM 可以为链带来很多好处和影响。

4.1 节约用户资源消耗

如上文所述,使用 EOS-VM 可以提升链的性能,用户使用基于 EOS-VM 运行的智能合约可以节省大量的链上资源消耗。

在基于 EOSIO 的公链中往往主要有三类资源:CPU、NET 和 RAM,CPU 主要由合约运行消耗的实际时间来结算,NET 主要与交易的大小相关,而 RAM 主要是基于合约带来的状态变换所使用的内存大小来决定的。

其中,现阶段 EOS-VM 主要将会节省用户 CPU 资源,这方面也是现在 EOSIO 网络主要的资源限制,对于 EOSIO 网络来说,NET 资源消耗往往固定,而 RAM 可以通过不断的增发来激励节点升级,这样就可以在网络上增加 RAM 的供给。

从硬件的角度来说,目前的服务器性能所支持的 RAM 升级空间还是非常宽裕的,但是对于 CPU,目前的限制很大,正如 BM 在电报群中所发的「牢骚」,英特尔并没有给 EOS 造出 100 太赫兹的 CPU,当然这只是开的玩笑,但是确实当前服务器 CPU 性能限制还是比较大的,对于服务器来说,近几年主要是并行计算能力的提高,单核性能虽然也得到了一定程度上的提升,但依然显得不足。

为 EOSIO 添加并行计算支持是一个比较长的过程,即使 EOSIO 可以支持并行计算,也会受单核计算性能限制,因为对于合约来说,其计算过程依然是单线程的,提升虚拟机效率,对基于 EOSIO 的链来说非常有用。

4.2 使得链具有更强的拓展性

EOS-VM 无论是代码还是架构都十分简介明了,为了保持简单和纯头文件化,Block.one 甚至没有引入其「祖传」的 fc 库,多数开发者只要简单了解一下 wasm 字节码的定义文档,就可以没有障碍的阅读和理解 EOS-VM 的设计和代码。

这样,开发者可以很简单的在 EOS-VM 的基础之上进行二次开发,尤其对于一些基于 EOSIO 技术的链,开发者可以简单的添加新的类型以满足特定链的特殊需求。

4.3 更简单的开发外围工具

EOS-VM 是纯头文件的,这意味着 EOS-VM 可以被嵌入进几乎所有的 C++项目中,而且通过简单的处理,EOS-VM 也可以被基于其他语言开发的项目中。

如 EOS-VM 中 tools 中的 interp,只需要不到 100 行代码就可以构建起 EOS-VM 的运行时环境,这样对于开发用于开发 EOSIO 合约的工具非常有用。

很多 EOS 合约开发的初学者都会想要调试合约代码,在以往这是几乎不可能的,虽然新版的 cdt 中也提供了一个 native lib,但是这样也无法完美的模拟合约的运行环境。

虽然「好的代码不是调出来的」,但是缺乏一个调试环境也会带来一些麻烦。另一方面,我们也要考虑合约运行时与现有开发工具的集成问题,而 EOS-VM 可以很好的满足这一点。

通过 EOS-VM,未来 EOSIO 开发生态将会更加完善,开发效率将会大幅提高。

5、EOSIO 正在向真正的协议演进

不知不觉中,EOSIO 的官网 slogan 已经从「最强大的去中心化应用平台」改为「build on chang,build on EOSIO」。同样在 EOS-VM 的设计中,开发者已经无法明显感受到 EOSIO 和 DPOS 共识机制的存在,EOS-VM 的设计非常独立。

如果一直关注 EOSIO 发展的话,会发现 EOSIO 的合约层在逐渐的去 EOSIO 化,从像 eosio_assert 改为 check 这样的改名,到 cdt 中完全去除 capi 的调用这样的重构,目前的 EOS 合约开发中,开发者会越来越少的碰到「EOS」。

一个典型的例子就是不同 EOSIO 姊妹链间的合约移植,现在基于 cdt 的合约在不同的项目间的差别已经越来越少,早期社区曾经对像 enu 这样由于大量不必要的改名所引发的不兼容表示非常困扰,但现在如果使用 cdt 工具,开发者几乎感受不到 enu 改名所带来的不兼容。

这一切都在意味着 EOSIO 正在向真正的协议演进。

Block.one 团队在早期并不像其他项目一样,急于构建抽象的协议和形式化的黄皮书,而是以非常务实的态度进行 EOS 的开发,这也在一定方面上使得 EOSIO 这一公链的主网启动要远远早于其他的「第三代」区块链项目。

我们认为 Block.one 团队不会一直在「埋头造车」, 而是采用自底向上的思路,不断的发展 EOSIO 生态,使其向真正的协议演进,最终成为一个极具竞争力的区块链协议事实标准。

6、Block.one 打响区块链标准之争的第一枪

长久以来,任何一个软件的细分领域都在谋求技术标准的整合和统一,这样的统一并非是由中心话组织去强制推行,而是通过软件本身逐渐得到主流市场的认可,最后成为事实上的技术标准。

而在区块链 VM 领域,旧的虚拟机如 EVM 性能低下,单一功能的虚拟机无法承载复杂的智能合约,基于通用设计虚拟机将会成为未来主流区块链项目的必需品,而这样的区块链项目目前唯一可选的只有 EOS-VM,EOS-VM 领跑行业一年多,将会成为最好的智能合约运行环境的标准,其行业地位将会类似于 ARM 在手机芯片行业的地位,甚至未来 ETH 的智能合约有望在 EOS-VM 上运行。

甚至我们也可以大胆的假设,EOS-VM 不会限于区块链行业,由于其优异的设计和实现,甚至会被用于像游戏引擎、数据库、Web 框架这样的传统软件开发领域。

7、加密社区的开源与技术标准垄断

我们都知道,Block.one 在向社区募资时一直强调自己是一个开源组织,所募集的钱也均要用于开发开源的 EOSIO 软件回馈社区,也为加密经济社区带来了大量的贡献。

但 EOS-VM 与 Block.one 以往任何一个开源项目都不同 ,Block.one 罕见地对 EOS-VM 项目保留了其权利 , 这意味着这个项目不会像其他开源库一样仅仅是一个开源库。保留权利这一动作与其募资时纯粹的开源组织定位产生了一定的偏差,甚至可能会通过商业性质的授权来限制其使用场景。

与传统互联网行业不同,加密经济的大部分技术都是开源的,无论是扩容之争和治理理念之争均未涉及到技术标准层面,在开源的加密经济市场中出现一个志在垄断的 VM 将带来什么样的影响,我们拭目以待。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能合约虚拟赋予了区块链运行去中心化应用(Dapp)的能力。它让区块链演化为“操作系统”,孕育出繁荣的Dapp生态。一款优秀的VM不仅仅是要完成确定、高效、安全地执行合约字节码的功能,它应该足够通用,能最大化节省开发者的成本,甚至能形成独立的开发者生态。从架构上来说,VM为智能合约提供计算资源和运行容器,区块链的共识、执行模块与VM是完全解耦的。在区块链2.0项目中,我们看到大部分项目将VM作为区块链项目的一个子模块,一同编译进二进制中;Fabric更进一步,链码被编译成独立的程序,运行于独立的docker容器中,通过grpc与节点交互。如此,可将数据与逻辑彻底分离;在未来,VM可能以硬件的形式安装在“矿”中,通过更底层的如PCIe接口与区块链进行通信。业界的Nervos CKB使用RISC-V实现VM,为演化成硬件模块做准备。架构设计验证层验证层会对合约字节码及传参进行一些验证,包含ABI验证,环境检查与版本检查三个环节。ABI验证:利用合约ABI对用户发送的合约调用及参数进行校验。环境检查:检查虚拟执行环境是否符合预期检查Config字段。字节码是否合法。exports是否包含apply与memory,以及类型是否正确;是否包含start(被禁用);是否包含import,import的模块是否合法。解释器模块是否ready。版本检查:检查合约版本,选择对应版本的解释器。注入层注入层主要对合约字节码注入一些必要的代码,以及构建相应的执行上下文。Gas MeteringGas metering是用于统计每一个操作所须花费的Gas。原理非常简单:实现Env_api方法useGas。将wasm字节码恢复成易于解析的格式化文本(如JSON)。将useGas注入到格式化文本中将格式化文本重新恢复成wasm字节码。这里有一个值得考虑的问题:**Gas Metering能否放到编译期去做?**在编译器做Gas metering注入的好处是只须要注入一次,节省了执行时的开销。但这样的弊端也很明显:Gas Table本属于区块链协议的一部分,但却被放到合约编译器中,恶意用户只须要更改编译器的Gas Table即可完成作恶,作恶成本大大降低。若Gas Table需要修改,无法再对已部署的旧合约更新Gas Metering,导致新老合约的Gas收费标准不一致。在每次执行时进行一次Gas Metering注入,虽然牺牲了一些执行效率,但换来了Gas灵活变更的特性,这对于不断调整、迭代的公链项目是至关重要的。一种更好的方案,是将Gas Table以合约形式部署,无须硬分叉便可更改Gas Table的参数。Env API 注入Env_api是区块链提供给合约层用于与区块链进行交互的接口。注入原理如下:合约字节码(wast)中包含形如(import env getAddress (func ...))的代码段。意为从env模块中导入getAddress函数。env模块从哪来呢?由虚拟利用解释器的API构建原生模块,并实现预先设计的Env_api。这里的Env_api都须要用原生语言实现。利用解释器的moduleResolver在执行代码前注入。经以太坊基金会Go-team的gary推荐,这里隆重介绍下EVMC这个项目。它提供了一套虚拟和客户端之间的通用交互接口。不同的VM只需要实现这些接口,即可为以太坊客户端提供交互功能。如此将客户端与虚拟实现相互分离,更能够根据实际情况灵活切换底层虚拟实现。上下文构建我们还需要给合约执行构建合理的上下文环境,提供必要的内部模块和数据以供合约使用,包括:区块链账本实例,提供区块、交易等信息的调用接口。状态数据库实例,提供状态数据的增删改查的调用接口。当前Transaction与Action的相关数据。当前区块高度和区块时间。执行层执行层是虚拟的核心模块,负责执行合约字节码并返回结果。它必须具备以下几个特性:确定性:即相同入参和上下文,无论在什么设备上运行,何时运行,运行几次,都必须获得相同结果。高效执行:虚拟的执行时间不大于共识算法给于交易执行的最大时间。停与回滚:须要有相应停制。在执行失败时须要对本次执行涉及的所有状态变更进行回滚。沙箱环境:即保证合约与合约之间、合约与宿主系统之间的资源隔离。能够防备恶意和故障合约的不良影响。Apply执行合约字节码,实际是调用合约代码中的apply函数。合约上下文,包括用户指定调用的合约方法名和对应入参,通过Env_api在实际apply实现中获取,最终调用相应的合约方法。栗子详见系列第二篇。Memory合约除了应导出apply函数外,还须要导出memory对象。memory对象是wasm编译器在合约编译时自动注入,通常会开辟一页内存(64KB) (memory $0 1)。解释器会初始化一个线性字节数组作为内存供wasm使用,wasm与区块链数据交互是依靠内存共享的形式,通过该字节数组进行传递。(这也是为何在Env_api设计里,很多数值的传参是offset与length的组合)Wasm的内存数组是按照| static memory | dynamic memory |的次序划分,static memory中存放编译期的字符串或数组,dynamic memory用于运行期的数据存储,并且可以动态扩容。为了防止dynamic memory无限制地扩容,需要有合理的收费制与内存分配上限。AssemblyScript提供了一个额外的位于static memory之前的预留空间,称为reserved memory。这使得我们在运行期可以将一些变长数据(如字符串,数组等)以Global的形式导入wasm。这样wasm无须调用Env_api即可直接使用上下文的变量,如发送方、接收方、合约地址、当前调用的合约方法名等。状态存储对VM最本质的需求是对状态存储的需求,这种存储是达成共识的、不可逆的,从而实现了去中心化应用中数据的信任存储。Ethereum1出现的状态爆炸问题给我们敲响了警钟——只收取每一次读写操作的费用,而不收取占用存储的费用,是不合理的。如果不对占用存储收费,则用户可以无限制地占用区块链的稀缺存储资源;且由于没有好的数据清理制,区块链的状态就会不断增长,即所谓“爆炸”。状态存储付费是很自然想到的方案。如何设计合理的状态存储付费方案,有两个底层逻辑需要考虑:用户应当为占用链上的稀缺存储资源付出成本。这里的成本是广义的,可以是代币价值、会成本与承担额外风险等形式。状态存储的使用属性最大化,投资属性最小化。须要避免出现用户大量囤积存储资源,提高资源利用率。EOS使用【RAM】来解决状态收费的问题。开发者须要使用代币向系统合约购买RAM,存储状态数据须要消耗对应大小的RAM资源,当数据删除时RAM资源也会相应释放,并且可以卖回给系统拿回代币。但开发者须要承担RAM和代币价值波动风险。如何对RAM定价呢?EOS创新性地引入了Bancor算法对RAM进行模拟市场定价。Bancor算法有两个特点:数字货币价格取决于存储金金额和代币流通量,真实模拟了市场供需关系;人交易,无须对手盘,这使得“巨鲸”可轻易做多或做空,导致价格波动剧烈。也正因为上面两个特性,EOS主网刚上线时,出现了大量RAM资源被囤积,RAM价格被瞬间拉至高位,又在随后的一周内快速下降,造成了“割开发者韭菜”的情况。V神在2018年曾提出过使用【状态租金】来解决状态爆炸问题。状态租金很像当前云计算服务的商业模式,用户不仅花费购买占用空间大小,还须购买占用时间。对于状态租金方案的具体设计,我们仍然须要考虑以下几个问题:用户体验:当状态出租时间快到期时,如何提醒用户续费?时间到期后状态数据是否立马清除?不同级别的数据是否有区别的对待?(云服务厂商都会提供到期后的赎回期,以防止关键数据被意外删除)支付对象:哪些数据需要支付租金?除了合约的状态数据必然要支付租金以外,账户本身的元数据(balance, nonce等)是否也要付租金?如果需要,时间到期后清零,势必损害用户的资金安全(与区块链保护数字资产的理念相背),同时nonce为0后可能会遭受重放攻击。如果不需要,仍然无法抑制因新账户的创建而产生的状态爆炸问题。定价:链上存储资源的稀缺程度,与区块链的生态价值及当下的市场需求密切相关。如何建立一个合理定价模型便是个非常重要的问题。Ethereum Research中有大神对状态租金的方案进行了细化,引入了激励制用于租赁过期的发现和确认,并且允许在状态数据删除后申请恢复。Nervos CKB结合了状态买卖和状态租金的长处,利用原生代币代表占用全局状态的权利,且汇率恒定,即1 CKB代表1 Bytes的存储空间。同时巧妙地利用【二级发行】制为代币持有者(存储空间占有者)设置了【通胀税】,以作为支付给矿工的状态租金。靠通胀收取租金的方式既保留了RAM方案的买断存储空间的使用模式,解决了上面所提到的用户体验的问题,又将定价转移到了通胀部分对应的法币价值,完全由二级市场进行价值发现。但这使得状态空间的上限严格等同于当前代币流通量,在初期可能会限制生态的发展。合约安全我们在第一篇中有提到,合约安全分为编译期安全和执行期安全。本篇主要阐述执行期安全的设计思路。执行期安全也成为运行期安全,主要由VM针对以下两方面提供保障:数据安全:不能随意篡改其他用户或其他合约的状态数据。资源安全:CPU、内存、硬盘资源的分配与回收。数据安全加密数字资产真正实现了人类梦寐以求的“私有财产神圣不可侵犯”,它象征着真正的自由。为了捍卫这份“自由”,数据安全是重中之重。VM需要为以下两个方面提供安全保障:用户数据的安全,即利用密码学算法判断是否有修改状态数据的权限。合约状态数据的隔离,即任何合约都不能直接修改其他合约的状态数据,即使该用户拥有权限。第一个维度很好理解,合约会提供根据用户地址和交易签名进行身份权限审查的功能(甚至可提供基于多密钥对的权限管理),以判断本次合约调用是否有权限修改相应的数据。这也是“私有财产神圣不可侵犯”的根源。第二个维度需要特别解释一下。这里的不能直接修改其他合约的状态数据,是指不能在合约A的方法中直接修改合约B的数据。为什么?因为这会导致状态变更无法追溯,带来不确定性。我们知道,区块链环境中只能通过交易(Transaction)来触发状态变更,交易本身就是状态变更的日志。若允许在合约A中直接修改合约B的状态数据,则这次修改是并未生成相关日志的,使得状态修改无法追溯,与区块链“可追溯”的特性相违背。以太坊中跨合约调用也是没有保留日志的。笔者认为这是因为以太坊合约是不可升级的,一旦部署后地址和代码都是不可变更的,因此可结合交易和代码具体片段来追踪状态变更记录。但以太坊并没有提供相关的索引,这导致对状态修改的记录追踪基本不可能,因此我认为这是一个设计上的重大缺陷。在EOS中,我们看到跨合约调用是生成了新的action,并被加入到原action列表中,在链上保留了状态修改的日志。能否利用静态代码分析的方式确定跨合约的对方地址和相关合约方法,从而追溯到状态变更的细节?当然是可行的,但如果有多层调用(合约A -> 合约B -> ... -> 合约Z),这种方案显然开销是非常大的。尽管以太坊提供了tracer,可以在执行交易的过程中追踪跨合约调用的对象,但如果我想查找导致合约X某状态变更的所有历史操作,上述方案必须遍历并模拟执行所有的历史交易,显然是不可取的。我们认为,跨合约交易正确的做法,是通过内联交易的形式调用合约B的方法从而间接修改合约B数据。即生成一个新的交易来触发目标合约的状态变更。该交易也会应放入区块中,视为由原交易生成的日志。这样可为状态变更保留操作记录,也符合“可追溯”的特征。资源安全智能合约通常运行在由虚拟提供的沙箱环境,我们需要对其能够使用的资源进行适度的把控。这些资源包括三类:CPU、内存、硬盘。下面我们以QA的形式对涉及到的问题进行解答——CPU资源Q1: 合约运行最大能占用多少个进程,多少个线程?一个;一个或多个。Q2: 是否允许合约内开辟新线程?不允许。合约不应有操作系统级别的调用,而应由虚拟层来确定性地分配CPU资源(线程数)。Q3:多线程下如何保证线程安全?多线程下,不应通过加锁来保证线程安全,原因是加锁无法保证执行顺序,带来不确定性。正确的做法是在执行前通过静态分析、注解等手段对合约调用进行归类。互斥资源的调用顺序遵循交易发送的顺序;非互斥资源的合约调用可以并行执行。Q4: 如何控制执行时间?利用Gas制控制合约执行时间(在本系列第一篇已提到),避免过度占用CPU时间。Q5: 如何捕捉错误与处理?合约执行的错误不应导致虚拟的进程终止,虚拟应当提供错误捕获和处理的制。常规的做法时合约运行时的错误以error的形式抛出,虚拟层捕获后做失败处理,包括终止交易执行、状态回滚、资源回收等。内存资源Q1:合约运行最大能占用多少内存?节点能分配多大的内存给虚拟,是由矿工决定。这本质上经济学问题:扩大内存分配无疑会增加成本,而这部分提升的执行效率能为矿工带来多少收益。若可用内存过少,部分交易执行失败,可能导致分叉;若可用内存过多,又会造成资源浪费,降低矿工收益。Q2: 内存能否动态扩张?可以,但须要付费。为了防止内存无限制扩张,虚拟还应对合约的内存占用设置上限。Q3: 如何避免内存泄漏?不应交由合约开发者控制内存回收,虚拟应当实现GC制。Q4: 如何避免内存溢出?Wasm虚拟中内存实则为字节数组,本身带有边界控制,能有效防止内存溢出。磁盘资源Q1: 单个合约最多能够存储多少数据?这也是经济学问题,应该设置合理的硬盘占用计费。Q2: 能否修改其他合约的持久化数据?不能直接修改,因为这会影响到【数据安全】章节中提到的确定性。虚拟为合约创建的上下文环境中,包含相互隔离的数据空间。可以通过创建新的上下文环境进行数据修改,这样的操作视为一次新的合约调用(保留日志)。Q3: 如何防止未知的数据丢失(如磁盘损毁)?当发生数据丢失时,节点执行合约会得到不同的状态结果,导致区块被认定为非法,区块链无法延长。这里需要区块链系统具备状态一致性的检测制,在解决硬盘故障后采用同步主链块并重放交易的方式进行恢复。系统合约系统合约是指区块链系统在启动时预先部署的,可升级、可治理的合约,提供如权限控制、资源租赁、代币质押等基础服务。系统合约通常有以下三个特点:公开透明,无暗箱操作。可通过Env_api被用户合约调用。合约通过治理进行代码变更,无须硬分叉。系统合约可采用普通合约的实现方式,并在系统预定的合约地址部署。未来优化方向智能合约的并行执行合约并行执行是提升智能合约执行效率的一大思路。这里的并行执行并不是指单个合约方法内部的并行,而是合约间的并行。实现合约并行执行,我们需要考虑两个重要的问题:如何检测本次合约执行所访问的资源对象?如读写状态数据、读取账户余额等互斥操作。如何做合约执行的合理调度?即哪些合约能够并行执行,哪些必须串行?一种容易想到的思路是这样的:通过静态代码分析检测出合约方法可能访问到的资源,对会访问相同资源的合约调用归为同一个组。每个组的执行可以并行化,组内执行则串行化(根据交易发送顺序)。然而,实际设计时需要考虑的因素就复杂很多:如何设计一个完备的算法,准确地检测合约方法可能访问到的资源(包括跨合约调用中的资源访问)?如何设计一个高效的调度算法,将合约调用准确分组?合约并行执行后所带来的性能提升,是否能够追回以上两个算法所带来的开销?预言预言是智能合约获取链外数据的桥梁。这些数据通常由第三方可信数据源提供,如天气数据、赛事数据、数字货币价格等。在传统的互联网应用中,我们可以简单地通过HTTP API获取到这些数据。但在智能合约却不行,原因是HTTP调用通常是异步的,时间不可预估且不具备确定性。因此,需要一个专门的基础设施来为智能合约提供这些链外数据。预言的设计原则中需要考虑三个要点:获取链外数据并保证数据的真实可用。以确定性、同步的方式被智能合约调用获取。预言网络本身的安全性和可用性。隐私保护密码学的研究推动了隐私领域的创新。隐私研究主要涉及零知识、多方计算、全同态加密等领域。多方计算 MPC 允许一组人基于他们的输入进行联合计算,而不需要每个人显示其输入值。 例如,Alice 和 Bob 想要知道谁拥有的比特币更多,那么在不需要他们披露自己拥有多少比特币的情况下就能达到这个目的。遗憾的是,目前多方计算的局限性在于它在实践中使用效率极低。全同态加密 (Fully homomorphic encryption) 则允许人们在加密的数据上计算。几十年来,这一直是密码学领域中的一个未解决的问题,直到 2009 年,斯坦福大学博士生克雷格·詹特利 Craig Gentry 使用「理想格」构建了第一个全同态加密方案。如果 Bob 想在 Alice 的数据上执行任意计算,比如训练器学习模型,同时不必要求 Alice 显示明文数据,理想格加密方案就能派上用场。全同态加密和多方计算一样,目前仍然基本上停留在理论阶段,在实践中的使用效率太低。 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值