查看原文
其他

为何多家公链纷纷使用 Wasm 合约?

橙汁 Patract开放平台 2021-10-13
本文发表于2019年8月,转自 CSDN。作者:单鹏飞,区块链研发工程师。原文标题:「Wasm 学习」。原文链接:https://blog.csdn.net/Pnfy__Shan/article/details/98494865


01
认识 Wasm

最近越来越多的项目开始转向 VNT 使用的 Wasm,像 EOS、Ontology,包括最初引入虚拟机 EVM 运行智能合约环境的以太坊,最近也开始转向使用Wasm。

除以太坊外,一些其他项目 EOS(C++)、Polkadot(Rust)、 Cardano(Haskell,Rust)已经或者计划开发支持 Wasm 的虚拟机。目前 Wasm 在以太坊下一代虚拟机(eWasm)以及 EOS、Dfinity 项目中被使用。

什么是 Wasm?


Wasm 全称 WebAssembly ,是一个可移植、体积小、加载快并且兼容 Web 的全新格式,可以使用非 Java 编程语言编写代码并且能在浏览器上运行的技术方案,也是自 Web 诞生以来首个 Java 原生替代方案。

Wasm 是一种新的编码方式,一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如 C/C++/Rust 等语言提供一个编译目标,以便它们可以在 Web 上运行。Wasm 的开发团队分别来自 Mozilla、Google、Microsoft、Apple 等公司,标准由 W3C 组织制定,目前 Wasm 在以太坊下一代虚拟机(eWasm)以及 EOS、Dfinity 项目中被使用。

Wasm 的特点


高效
  
Wasm 有一套完整的语义,实际上 Wasm 是体积小且加载快的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率。

安全

Wasm 运行在一个沙箱化的执行环境中,甚至可以在现有的 JavaScript 虚拟机中实现。在 Web 环境中,Wasm 将会严格遵守同源策略以及浏览器安全策略。

开放

Wasm 设计了一个非常规整的文本格式用来、调试、测试、实验、优化、学习、教学或者编写程序。可以以这种文本格式在 Web 页面上查看 Wasm 模块的源码。

标准

Wasm 在 Web 中被设计成无版本、特性可测试、向后兼容的。Wasm 可以被 JavaScript 调用,进入 JavaScript 上下文,也可以像 Web API 一样调用浏览器的功能。当然,Wasm 不仅可以运行在浏览器上,也可以运行在非 Web 环境下。

Wasm 的优势


EVM 虽然有着较高的兼容性,但需要预编译,同时需要付出 Gas 作为代价,有着很高的编程成本,这种程序本质上都是脚本程序,即由程序翻译指令并执行,而不是由本地机器 CPU 读取指令并执行,因此效率非常低。

而 Java 的操作相对重复繁琐,在执行过程中耗时较长。

和 EVM 及 Java 相比,Wasm 是谷歌、苹果、微软三大竞争公司同时支持的一种中间代码(字节码), 被所有主流浏览器支持。同时其他语言(C,C++,Java)编写的程序都可以编译成 Wasm 字节码,基于此建立的应用层生态不仅可以让开发人员有着非常低的学习成本, 而且有着高性能的标准。

由于 EVM 需要预编译,同时需要付出 Gas 作为代价,实际上在 EVM 上编程成本很高,同时对于 EVM 的臃肿毫无帮助。最后,Solidity 相比其语言基础 C 比较难学。

而 Wasm 是内存安全的、平台独立的,并且可以有效地映射到所有类型的 CPU 架构。其指令集效率高,同时保有足够的可移植性。此外,Wasm 指令集可以很容易地通过移除浮点指令来确定化,这将使它适合于替换 EVM 语言。

同时,Wasm 在不增加内存消耗的情况下,可以达成无信任编程,通过在 Wasm 上进行堆栈分析与计量进行精确计算。

目前 ETH 打算将 DApp 也用基于 ETH、Wasm 的智能合约,而 EOS、Polkadot 和 Ontology 则是用于虚拟机,其余涉及 Wasm 的项目似乎并没有真正理解 Wasm 是做什么的。

Wasm 有哪些对开发者友好的特点?


无疑,Wasm 拓展了智能合约开发者可用的编程语言,这意味着你可以使用任何你熟悉的编程语言开发智能合约,并有着诸多对开发者友好的特点,例如:

1.性能高效:Wasm 采用二进制编码,在程序执行过程中的性能优越;
2.存储成本低:相对于文本格式,二进制编码的文本占用的存储空间更小;
3.多语言支持:用户可以使用 C/C++/Rust/Go 等多种语言编写智能合约并编译成 Wasm 格式的字节码。

VNT Chain(维特链)基于 Wasm 有哪些创新?


VNT Chain 采用的是由 VNT_P(公有链)+VNT_C(联盟链)+VNT_I(跨链)的聚合链技术架构,其中 VNT_P 可运行被编译为 Wasm 格式的智能合约,而无需关心智能合约的编写语言。

正是因为看到 Wasm 的诸多优势及未来前景,VNT 技术支撑方云象在 VNT Chain 设计之初,就确定了基于 Wasm 开发 VNT Chain 虚拟机的技术方案。基于原生的 Wasm,VNT Chain 进行了以下创新及改进:

1.改造原生 Wasm 中多线程、浮点数、异常处理等导致计算非确定性的设计,确保计算的确定性;
2.扩展对 String、Address、Hash 等数据类型的支持;
3.扩展 Opcode 以支持标准库的方法;
4.增加燃料(Gas)机制,解决了智能合约中的停机问题;
5.提供沙箱运行环境,实现资源隔离,保障系统的安全性;
6.提供编写智能合约所需的各种语言的类库;
7.支持合约调试功能;
8.兼容 Q 语言,该语言为自主设计智能合约编写语言 。

基于对 Wasm 语言的应用以及优化改造,VNT Chain 的智能合约模块具备更高的兼容性与性能,同时拥有更强的安全性与灵活性。尤其是 VNT Chain 首创的形式化自我验证能力编程语言,将语言本身的类型系统与数学定理系统结合,并将语言的类型验证与形式化验证结合,为智能合约形式化安全验证提供强有力的支持。

Wasm 从最初公布时不被看好,到现在被广泛使用,我们可以肯定未来它将作为分布式应用开发的基础层被运用到越来越多项目中。

Wasm 在大型项目中的应用 

  
在这里能够举的例子还是很多,比如 AutoCAD、GoogleEarth、Unity、Unreal、PSPDKit、WebPack 等等。拿其中几个来简单说一下。

AutoCAD

这是一个用于画图的软件,在很长的一段时间是没有Web的版本的,原因有两个:其一,是 Web 的性能的确不能满足他们的需求。其二,在 Wasm 没有面世之前,AutoCAD 是用 C++ 实现的,要将其搬到 Web 上,就意味着要重写他们所有的代码,这代价十分的巨大。

而在 Wasm 面世之后,AutoCAD 得以利用编译器,将其沉淀了30多年的代码直接编译成 Wasm,同时性能基于之前的普通 Web 应用得到了很大的提升。正是这些原因,得以让 AutoCAD 将其应用从 Desktop 搬到 Web 中。

Google Earth

Google Earth 也就是谷歌地球,因为需要展示很多3D的图像,对性能要求十分高,所以采取了一些 Native 的技术。最初的时候就连 Google Chrome 浏览器都不支持 Web 的版本,需要单独下载 Google Earth 的 Destop 应用。而在 Wasm 之后呢,谷歌地球推出了 Web 的版本。而据说下一个可以运行谷歌地球的浏览器是 FireFox。

什么时候使用 Wasm 


说了这么多,那么到底什么时候该使用它呢?总结下来,大部分情况分两个点:

a.对性能有很高要求的 App/Module/游戏
b.在 Web 中使用 C/C++/Rust/Go 的库

举个简单的例子。如果你要实现的 Web 版本的 Ins 或者 Facebook, 你想要提高效率。那么就可以把其中对图片进行压缩、解压缩、处理的工具,用 C++ 实现,然后再编译回 Wasm。

Wasm 的几个开发工具


AssemblyScript。支持直接将 TypeScript 编译成 Wasm。这对于很多前端同学来说,入门的门槛还是很低的。

Emscripten。可以说是 Wasm 的灵魂工具不为过,上面说了很多编译,这个就是那个编译器。将其他的高级语言,编译成WebAssembly。

WABT。是个将 Wasm 在字节码和文本格式相互转换的一个工具,方便开发者去理解这个 Wasm 到底是在做什么事。

Wasm 的意义


 Wasm 并没有要替代 JavaScript,一统天下的意思。我总结下来就两个点。

  • 给了 Web 更好的性能
  • 给了 Web 更多的可能

关于 Wasm 的性能问题,之前也花了很大的篇幅讲过了。而更多的可能,随着 Wasm 的技术越来越成熟,势必会有更多的应用,从 Desktop 被搬到 Web 上,这会使本来已经十分强大的 Web 更加丰富和强大。

EOS 为何选择 Wasm


比特币的程序非常简单,由解锁脚本和锁定脚本构成。以太坊有智能合约,有图灵完备的虚拟机 EVM,但是指令也相对简单,且自成一套。这两种程序本质上都是脚本程序,即由程序翻译指令并执行,而不是由本地机器 CPU 读取指令并执行,效率不高。但选择解释性语言有它的合理性,就是他的高度兼容性,它对智能合约的执行设备(矿机)没有限制。

那 EOS 的智能合约语言 Wasm 有什么来头呢?它是谷歌、苹果、微软三大竞争公司同时支持的一种中间代码(字节码),是浏览器都支持的一种代码。所有其他语言(C,C++, Java)编写的程序都可以编程成 Wasm 字节码的程序。

看出这种设计的好处没?也就是说 EOS 兼容所有用 C,C++ 等高级语言编写的程序,EOS 的应用层生态基于此就建立了,开发人员的学习成本非常低。

同时 Wasm 字节码既可以编译成机器码后执行,又可以使用解释器直接执行, 兼容性和性能兼有,EOS 选择了未来编程序语言,背靠 Wasm 生态, 至少在这方面它值得"区块链3.0”的称号。

当然,Wasm 作为年轻的正在发展的技术,它的不稳定性可能会给 EOS 带来不好的影响,但 EOS 也还在开发中,且 Wasm 本身具备柔性, 所以这个缺点并不重要了。



02
快速用 C 语言写的基于 Wasm 的 Demo

前置条件


想要编译成 Wasm,你首先需要先编译 LLVM,这是运行后续工具的先决条件。

Git。Linux 和 OS X 系统中好像已经默认装好了,在 Windows 上需要自行安装 Git。

CMake。在 Linux 和 OS X系统中,你可以使用包管理工具 apt-get 或 Brew 来安装。如果是 Windows 系统,你可以自行下载安装。

系统编译工具。Linux上,安装 GCC。OS X 上,安装 Xcode。Windows 上安装 Visual Studio 2015 Community with Update 3 或更新版本。

Python 2.7.x,在 Linux 和 OS X上,很可能已经装好了。

安装完毕后,确认 git,cmake 和 python 已经在你的环境变量里,可以使用。

编译 Emscripten


通过 Emscripten SDK 构建 Emscripten 是自动的,下面是步骤。
$ git clone https://github.com/juj/emsdk.git $ cd emsdk $ ./emsdk install sdk-incoming-64bit binaryen-master-64bit $ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
这些步骤完成以后,安装完成。将 Emscripten 的环境变量配置到当前的命令行窗口下。
$ source ./emsdk_env.sh
这条命令将相关的环境变量和目录入口将会配置在当前的命令行窗口中。

在 Windows中,./emsdk 使用 emsdk 代替,source ./emsdk_env.sh 使用 emsdk_env 代替。

编译并运行一个简单的程序


现在,我们已经有了一个完整的工具链,将简单的程序编译成 Wasm。不过,这里有一些值得提醒的地方:

在使用 emcc 命令时,要带着 -s WASM=1 参数(不然,默认将会编译成asm.js)。

如果我们想让 Emscripten 生成一个我们所写程序的 HTML 页面,并带有 Wasm 和 JavaScript 文件,我们需要给输出的文件名加 .html 后缀名。

最后,当我们运行程序的时候,我们不能直接在浏览器中打开 HTML 文件,因为跨域请求是不支持 File 协议的。我们需要将我们的输出文件运行在 HTTP 协议上。

下面这些命令可能让你创建一个简单的“hello word”程序,并且编译它。
$ mkdir hello $ cd hello $ echo '#include <stdio.h>' > hello.c $ echo 'int main(int argc, char ** argv) {' >> hello.c $ echo 'printf("Hello, world!\n");' >> hello.c $ echo '}' >> hello.c $ emcc hello.c -s WASM=1 -o hello.html
我们可以使用 Emrun 命令来创建一个 Http 协议的 Web Server 来展示我们编译后的文件。
$ emrun --no_browser --port 8080 .
HTTP 服务开启后,您可以在浏览器中打开。如果你看到了“Hello,word!”输出到了 Emscripten 的 控制面板,恭喜你!你的 Wasm 程序编译成功了!


03
快速用 Golang 写的基于 Wasm 的 Demo

1.编写一个 hello world 的 Golang 代码
package main import ( "fmt" )
func main() { fmt.Println("hello,wasm,go")

2.编译

注:Golang 版本 go1.11+,我电脑版本:go version go1.11.4 darwin/amd64
GOOS=js GOARCH=wasm go build -o test.wasm hello.go

3.把库中的 Html 和 js 文件复制过来

cp $GOROOT/misc/wasm/wasm_exec.{html,js} .我电脑用下面的命令cp /usr/local/Cellar/go/1.11.4/libexec/misc/wasm/wasm_exec.html .

4.写一个 Http 服务接口

package main
import ( "flag" "log" "net/http" "strings" )
var ( listen = flag.String("listen", ":8080", "listen address") dir = flag.String("dir", ".", "directory to serve") )
func main() { flag.Parse() log.Printf("listening on %q...", *listen) log.Fatal(http.ListenAndServe(*listen, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { if strings.HasSuffix(req.URL.Path, ".wasm") { resp.Header().Set("content-type", "application/wasm") }

http.FileServer(http.Dir(*dir)).ServeHTTP(resp, req) })))
这里也可以不写 Http 脚本,我电脑用的是 Caddy 这个现成工具,是 Golang 写的,Nginx 的升级版。

5.运行

go run http.go
在浏览器中打开 http://localhost:8080/wasm_exec.html,点击 Run 按钮,可以在控制台看到 Hello,Wasm,Go 字符串。这个字符串是 wasm_exec.js(库中复制过来的)文件中的第45行打印出来的。

6.另一种更加直接的方式

node wasm_exec.js test.wasm
可以直接在控制台看到该字符串。


04
eWasm 项目初探

为了改进EVM 1.0,以太坊的新一代虚拟机项目eWasm ( GitHub.com/ewasm)将支持 Wasm,Wasm 在性能、扩展性、开发工具、社区都更有优势。除以太坊外,一些其他项目 EOS,Polkadot, Cardano 已经或者计划开发支持 Wasm 的虚拟机。

以太坊基础设施的虚拟机(EVM)正准备进行一次彻底的重写。重写后,目前的 EVM 将被一个名为 eWasm 的新虚拟机所取代。eWasm 是以太坊的 Wasm 版本代码,由万维网联盟(W3C)创建,它将允许开发者使用多种编程语言进行编码 ,而不仅仅是 Solidity 语言 ,同时还增加了一些性能增强的功能。

eWasm 也存在技术问题。如,eWasm 支持多语言,因此代码很大程度上会依赖所谓的 “编译器” ,而这会成为攻击者的单点故障。

1.EVM2.0 对比 EVM1.0 的优势

  • 性能更好
  • 可扩展性好
  • 开发合约更容易,支持更多语言和工具

2.eWasm 项目目标和方案

以太坊 eWasm 项目目标是既要完成对 Wasm 的支持,又要兼容 EVM1.0 合约。要达到这个目标,eWasm 目前的设计方案如下:

3.VM 语义设计

执行合约前要能够判断出这个合约是 Wasm 合约还是 EVM1.0 合约,并可调用对应的 EVM 解析执行。

如果客户端没有支持 EVM1.0 的 EVM,需要将 EVM1.0 合约通过预编译合约( EVM to Wasm 项目)翻译成 Wasm 合约。

部署 Wasm 合约时,要有一个预编译内置合约(合约名称 Sentinel Contract)对合约进行检查,要求合约复合 EVM2.0 的要求,比如不能包括float类型,不能有限定外的操作。

4.eWasm 合约语义设计(Ewasm Contract Interface - ECI)

ECI 定义了 eWasm 合约的结构,通过 Wasm 的 Module 实现,可以认为 eWasm 是 Wasm 的子集 。

合约必须符合 Wasm 二进制格式。

合约 Import Module 只能 Import EEI,不能 Import 以太坊之外的 Module 保证了 EVM 是一个沙盒程序。

提供 Debug  Module,但 Debug 模式只能用于开发,在部署的时候需要去掉。

每个合约必须提供两个 Export 方法,一个是 Main,供 VM 执行调用,一个是 Memory,供 EEI 调用,保存结果。Wasm Module 中的 Start Function 需要被 Disable。

5.Ethereum Environment Interface (EEI) 定义

EEI 定义了 Wasm 程序如何与链进行交互,通过 EEI 将以太坊 API 暴露给e Wasm,使 eWasm 可以读写链上信息,意义是 Wasm 指令是 Low Level 的,High Level 功能留给客户端实现。

数据类型

  • bytes: 不确定长度的二进制数组
  • bytes32: 32字节的数组
  • address: 20字节的数组
  • u128: 128位的无符号整数
  • u256: 256位的无符号整数

API

  • useGas 减掉消耗的gas
  • getAddress 获得账户的地址
  • getBlockHash 获得区块哈希
  • call 将参数信息发送给某个地址
  • storageStore 保存一个256bit的值

更多 API 及详细信息参考:
https://github.com/ewasm/design/blob/master/eth_interface.md 

6.以太坊内置合约

一些功能接口可以通过内置合约的方式来完成,每个合约都会有固定地址,可以像调用其他合约一样调用内置合约。

Sentinel合约:执行 eWasm 检查,看合约是否符合 ECI 的要求;执行没Metering,将结果注入到 eWasm 合约中。

evm2wasm :将 EVM1.0 合约翻译成 Wasm 合约。

7.Metering

Metering 功能是计算每个指令消耗的 Gas,在合约执行之前,提前知道这个合约需要多少消耗 Gas,也就可以预计运行时间。

提前计算 Gas 消耗还可以避免因 Gas 不足导致操作回滚,避免了做无用功。详细可参考:https://github.com/ewasm/design/blob/master/metering.md

8.eWasm 子项目

根据 eWasm 项目设计方案,eWasm 创建了多个子项目分别实现模块功能,将这些项目组合到一起,共同实现支持 Wasm 合约并且兼容旧合约的目标。

EVM-C

EVM-C 的作用是分离客户端和 EVM,客户端在执行合约中只负责与链上信息的交互,把对合约的解析和执行任务交给 EVM,他们之间的通信接口就是 EVM-C。

客户端有多个版本的实现,Go,C++,Rust等。EVM 也有多种方式去解析和执行合约,比如 Interprter,JIT,AOT,现在又有了执行不同指令格式的合约的需求。所以通过接口将二者分离可以更方便的配置客户端。


EVMC 由 C++ 实现,可以直接与 Aleth 结合。EVMC 通过 Bind 的方式支持非 C++ 版本的客户端。目前只能支持 Aleth 和 Geth。

https://github.com/ethereum/evmc

Hera

Hera 是由 C++ 实现的尊从 EVMC 接口的 eWasm 虚拟机。Hera 内部包含了Wasm VM,目前 Wasm 的 VM 有多个实现版本,Hera 计划支持 Bineryen,Wabt,Wavm(EOS 也使用 Wavm),目前可以完全支持 Bineryen。

不管是哪个版本的客户端,只要是使用 EVMC 接口就可以与 Hera 进行交互。总之只要执行指令过程中有与链上的信息交互就通过接口与客户端通信,其他 low level  的 Wasm 指令由内置的 VM 执行。

对于 EVM1.0 的合约,Hera 将通过另一个项目 EVM 2 Wasm 提供的方法将 EVM1.0 合约翻译成 eWasm 合约。


https://github.com/ewasm/hera

9.项目现状

Parity 对 eWasm 合约的支持是最好的,但是它的实现方式是内置在客户端中,并没有使用 EVMC 和 Hera,Aleth 和 Geth 正在开发中。

目前的测试网络已经上线,但缺少工具支持,没有生成 ABI 文件的工具,也没有任何 hello world 教程或文档。

关于上线时间,根据 DevCon4 上的信息,以太坊会先发布 Casper 和 Sharding,然后发布 EVM2.0,至少要2020年左右甚至更久。


05
总结

1.越来越多的项目开始转向 Wasm,像 EOS(C++),Polkadot(Rust), Cardano(Haskell,Rust),VNT(Golang),Ontotogy 等,以太坊的下一代虚拟机是 eWasm。

2.该平台上做二次开发,开发人员可以使用其他语言(C,C++,Java,Golang)来编写智能合约,然后编译为 Wasm 字节码的程序。Wasm 字节码既可以编译成机器码后执行,又可以使用解释器直接执行, 兼容性和性能兼有。基于此建立的应用层生态不仅可以让开发人员有着非常低的学习成本, 而且有着高性能的标准。

3.Wasm 的特点:高效、安全、开放、标准。

4.Wasm 对开发者友好:性能高效、存储成本低、多语言支持、可扩展性好

5.由 W3C 领导,Google、Apple、MicroSoft 等大公司支持,更广阔的社区。

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)
 
2.对于将要集成 Wasm 合约功能的平行链项目方,或者使用 Wasm 合约开发的 DApp 项目方,商务合作欢迎联系 santry@patract.io
 
3.对于用户,欢迎加入:
Telegram(https://t.me/patract)
Twitter(https://twitter.com/PatractLabs)
 
4.对于求职者,我们在招聘区块链开发工程师、前端/全栈开发工程师、产品经理、开发者运营等岗位,可以联系 sean@patract.io

扫码加入Patract 微信开发群



往期精彩:
//Substrate 合约书之合约语言框架
//演示|inkBridge 介绍及 Wasm 合约开发
//Litentry基于Patract的Redspot和Europa产品进行ink!合约开发,拓展身份服务生态

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存