区块链 ❤️ WASM 之 Arbitrum Stylus
Arbitrum 最近发布了 Stylus VM 升级。 Stylus VM 将带入一些新功能:
支持更多语言
低费用,低内存消耗
自定义预编译器
与 EVM 的互操作性
所有这些功能都是通过集成 WASM 带来的。WASM 有很多优势,并且在云原生场景中得到了广泛应用。我们将在后面的部分详细介绍 WASM 的故事。
先驱者
Arbitrum 并非第一个将 WASM 引入链上的项目。在 Arbitrum 之前,Polkadot 已经允许用户编写 WASM 智能合约。它提供了两种编写 WASM 智能合约的语言,一种类似嵌入式 DSL 的汇编脚本,另一种是类似 Rust 的语言 ink!。
Cosmos 也采用了 CosmWasm 作为其智能合约运行时。开发者可以使用 Rust 来编写智能合约。
在深入探讨为什么区块链 ❤️ WASM 之前,让我们看看 Cosmos 和 Polkadot 是如何解释他们选择 WASM 的。
Cosmos 声称 WASM 可以带来以下好处:
与 Rust 库兼容
多样化的开发社区
安全性,防止重入攻击
容易测试
高性能
Polkadot 的 WASM 运行时具有以下特点:
高性能
与 EVM 的互操作性
平台无关
体积小
支持 Rust 和 Assembly Script(Typescript 风格)
Polkadot、Cosmos 和 Arbitrum 由 WASM 带来的一些优势是共享的,但 Arbitrum 有一些独特之处。我们将在最后一部分详细介绍 Arbitrum 和 Cosmos 的更多细节。
WASM
什么是 WASM
为了理解为什么区块链 x WASM,我们需要理解 WASM 是什么以及 WASM 背后的初衷。
WebAssembly(WASM)是一种二进制格式,允许代码在网络浏览器中以接近本地速度运行。它是 C 和 Rust 等语言的编译目标,旨在快速、高效且安全。WASM 弥合了网络和系统级编程之间的鸿沟,增强了网络性能和功能。
WASM 之所以被称为 Web,是因为它可以在 JS 中运行,通常是在浏览器环境中。在 JS 中,开发者可以访问完整的 WASM API。WASM 也得到了完整的 Web API 支持。在 WASM 中,开发者可以控制 Web 的行为。
WASM 历史
WASM 是根据“一次编写,到处运行”的原则设计的。
早在 2016 年,许多程序通过领域特定语言(DSL)发布新功能。制作 DSL 需要在维护、效率和安全性之间进行权衡。然而,人们正在寻找一种新的方式来向无数需要维护、效率和安全性的服务器交付新功能。
他们从上到下检查了不同的解决方案。以下是人们对这些解决方案的关注点:
系统虚拟机
频繁启动/关闭的开销太大
缺乏对代码的可视性以确保安全性
对性能需求来说太抽象/高级
容器
缺乏对代码的可视性以确保安全性
对性能需求来说太抽象/高级
频繁启动/关闭的开销太大
语言级虚拟机
为了安全性需要频繁修改 VM
嵌入像 V8 这样的 VM 的开销
将新语言适应 VM 的安全模型的速度较慢
仍然很高级
指令集架构(ISA)
高效地修改 ISA 代码以进行沙箱化非常困难
Google 的先前项目从 ISA 转向 WASM
缺乏成熟的实现可供使用
这是 WASM 成为现实的背景。人们开始从 2018 年开始开发 WASM 编译器。WASM 开发者扩展了“一次编写,到处运行”的理念。他们希望在不同的架构上运行,在服务器和嵌入式硬件上运行,甚至在其他语言上运行。他们不想再制造一个 Java,牺牲安全性。
到了 2019 年,组件模型被创建出来,用于包装 WASM 模块并将其接口提升到更高的层次,实现了组件之间的跨语言互操作性。例如,这使他们能够编写一次 HTTP 库并在多种语言之间共享。组件模型以一种新颖的方式解决了长期存在的问题。
到目前为止,WASM 拥有很多酷炫的功能。现在,WASM 在云原生场景中被大量使用。区块链在某种程度上也是云原生的一个应用案例。WASM 有以下优势:
高性能
二进制文件体积小
可移植性:WASM 在指令集级别提供可移植性,允许相同的字节码在任何 WASM 运行时上运行。
支持 C/C++、Rust、AssemblyScript、C#、Dart、F#、Go、Kotlin、Swift、D、Pascal、Zig、Grain 等语言。
在 JS 引擎中运行
沙箱:WASM 默认提供更强大的沙箱,通过限制内存、CPU 等来防止访问沙箱之外的内容。
WASM 启动非常快,通常在几毫秒或更短的时间内。
WASM 社区仍在努力为更多的集成和跨语言性能而努力。
Stylus
在思考 WASM 的倡议和其他区块链上的 WASM 应用后,让我们回过头来思考 Arbitrum Stylus 的限制。
Stylus 的工作原理
开发者使用现成的 WASM 编译器(如 Clang 或 Rustc)将其智能合约编译为 WASM。
将 WASM 字节码以压缩形式上传到 Arbitrum 链上。
合约所有者调用
ArbWasm
预编译的compileProgram
方法,该方法对WASM进行安全工具检查、计量气体成本,并将其编译为针对验证者硬件优化的本机代码。当调用合约时,它在类似 Wasmer 的 WASM 运行时上运行,比 EVM 快得多,节省了气体成本。
第三步看起来多余,但为了性能和安全原因,它是必要的。将 WASM 代码编译为本机机器代码可以加快执行速度。添加额外的编译步骤也可以避免编译炸弹。
"编译炸弹" 是一种恶意代码,旨在在编译过程中消耗过多的资源,导致编译器崩溃或挂起。它是一种可以用来中断软件开发过程的拒绝服务攻击。
关于 Stylus 的普遍关注
语言支持
Stylus 可以帮助 Arbitrum 扩展到 C++ 和 Rust 的开发社区,但它仍然无法触及目前最流行的开发社区。它为在浏览器环境中执行的智能合约打开了大门,但 JS 和 Python 仍然不受支持。
有一些早期项目将 Python 和 JS 带到 WASM,但由于垃圾收集对象的实现和性能问题,它还没有准备好进行大规模的采用。
语言兼容性
Stylus 目前支持 C/C++ 和 Rust SDK。它与这些语言工具协作良好。开发者还可以引入一些第三方库,比如在构建智能合约时使用一些原生的加密实现。对于这些的唯一限制是 gas 成本。
Rust SDK 仍处于早期阶段。Rust 和 C SDK 还有一些缺失的特性。C SDK 不支持 ABI 导出函数。在两个 SDK 中都不支持修饰符。
本地的 Stylus 测试环境尚未支持,但开发者可以直接在 SDK 中运行测试。在 Stylus 中运行智能合约,测试网是唯一的方式。测试网尚未支持智能合约验证。
人们正在将不同的 ERC 代币和 Uniswap V2 引入 Stylus。
语言选择
使用 DSL、嵌入式 DSL 还是通用编程语言是一个难题。开发者需要在接近底层控制与使用更高级别抽象之间做出权衡,后者更易于使用但限制了灵活性。
构建全新的 DSL 也需要时间来开发工具链和生态系统。eDSL 是通用编程语言的子语言,共享相同的语义和语法。使用 eDSL,可以利用现有的语言和工具,降低学习新 DSL 的学习曲线,DSL 与通用代码之间具有良好的互操作性。例如,为了吸引最多的开发者,制作一个 JS、Python eDSL 是有意义的。通用编程语言要求开发者使用 SDK 进行开发。这引入了额外的工具,更多的冗长表述,减少了表达性,以及长的 API 调用和对象操作。
选择合适的语言并制作一个 eDSL 可能是一个正确的混合。它吸引了来自受欢迎的开发社区的人,并提供易于使用的工具。从下面的数据中,我们可以看到最大的加密开发者社区仍然是以太坊。使用 Rust 进行智能合约的 Polkadot、Cosmos 和 Solana 也吸引了相当数量的人。他们在总开发者数量上也有非常快的增长速度。
性能
WASM 可以大大提高执行速度并减小打包大小。虽然 Stylus 还没有上主网,但我们可以参考其他网络的基准测试。
执行时间缩短了 4-8 倍。编译后的大小减少了 2 倍。
(相关图片已省略)
目前,Stylus 合约的大小有限制,大约为 128KB 未压缩。从其他语言如 Solidity 迁移非常大的智能合约将会很困难。你可以在 Stylus 代码库中找到。
// arbos/programs/programs.go
const MaxWasmSize = 128 * 1024
const initialFreePages = 2
const initialPageGas = 1000
const initialPageRamp = 620674314 // 目标是 8MB 的成本为 3200 万 gas,减去线性项
const initialPageLimit = 128 // 拒绝内存大于 8MB 的 wasm
const initialInkPrice = 10000 // 1 evm gas 可购买 10k ink
const initialCallScalar = 8
请注意,WASM 在启动和关闭时有一些开销。如果你编写的是非常轻量级的东西,EVM 可能比 WASM 更便宜。
与 EVM 的互操作性
EVM 和 WASM 共享相同的存储槽和状态树。Stylus 与 EVM 具有互操作性,因为在 WASM 中实现了 EVM API。这是通过 WASM 中流行的 Host I/O 模式完成的。这里是 EVM API 在 WASM 中的完整支持列表。看起来互操作性得到了完全支持。
read_args
write_result
storage_load_bytes32
storage_store_bytes32
call_contract
delegate_call_contract
static_call_contract
do_call
create1
create2
do_create
read_return_data
return_data_size
emit_log
account_balance
account_codehash
evm_gas_left
evm_ink_left
block_basefee
block_coinbase
block_gas_limit
block_number
block_timestamp
chainid
contract_address
msg_reentrant
msg_sender
msg_value
native_keccak256
tx_gas_price
tx_ink_price
tx_prigin
memoery_grow
console_log_text
console_log
console_tee
自定义预编译
这个更令人兴奋。没有人之前做过这样的事。我们可以将更多的加密原语以更低的执行成本引入链上。对于链上机器学习,我们可以将张量计算作为预编译内容引入,以降低推理成本。然而,我没有看到关于自定义预编译的相关代码。我们看到了 EVM 部分的预编译,但它不是热可交换的。
我相信这些部分仍然在利用 WASM 的力量进行实现。EVM 可以调用编译为机器代码的 WASM 编写的函数。
可重入性
不像 CosmWasm 使用演员模型提供合约调用并且不提供可重入功能,Stylus Rust SDK 将重入性设置为一个功能标志,并且默认设置为关闭。开发者可以手动启用重入功能。
默认启用重入性功能标志会稍微改变 API,因为开发者在进行调用时必须小心地刷新存储缓存,以及其他安全考虑。
结论
WASM 是一个新兴技术,在云原生领域获得了关注。许多区块链正在集成 WASM 作为它们智能合约的运行时。虽然 Arbitrum 不是第一个这样做的,但它可能是最重要的。WASM 不能完全改变区块链世界并取代 EVM,但 WASM 有潜力增强 Arbitrum 对抗即将出现的 zk-rollups 的竞争力。我喜欢 Arbitrum 称这为 EVM+。EVM 是智能合约运行时的基础,WASM 可以为 Arbitrum 带来一些额外的能力。