本文介绍了Move语言的诞生背景,它旨在解决Solidity等现有编程语言在资产安全方面的不足。Move通过在语言设计、虚拟机和验证工具三个层面进行创新,例如引入Resource类型、Module系统和所有权系统,从而提高了数字资产的安全性。目前Move主要应用于Aptos、Sui和Starcoin等L1链项目,未来有望在DeFi、SocialFi和GameFi等领域得到更广泛的应用。
作者 [火币研究院] 陈思宇
继 Solidity 和 Rust 之后,Move 作为一种诞生于 Libra 残骸的新一代编程语言,因 Aptos 和 Sui 而再次受到关注。纵观区块链发展史,每条 L1 链的崛起往往意味着一定程度的开发范式转变。Move 的回归似乎表明,新的语言正在成为 L1 链领域竞争的新战场。
以太坊的编程语言 Solidity 已经见证了许多令人震惊的安全事件。仅在 2021 年,区块链生态系统中就发生了 200 多起公开的安全事件,损失超过 98 亿美元;绝大多数安全问题都是由智能合约中的漏洞引起的。由于 Libra 的愿景是成为全球货币体系的金融基础设施,因此 Move 必须将资产安全置于其设计目标的首位。
为了更好地实现资产安全,Move 在语言设计、虚拟机和验证工具三个层面进行了创新性变更。首先,Move 为数字资产定义了一种新的 Resource 类型,并抽象出两个基本属性:资源应同时满足稀缺性和访问控制。其次,Move 通过具有强数据抽象的 Module 系统来实现账户权限控制。第三,Move 继承了 Rust 的 Ownership 系统,以实现资产所有权的转移。此外,静态调用、形式化验证和字节码检查器等机制的引入也共同为数字资产的安全性提供了多重保障。
在语言接受度方面,Move 对开发者非常友好,其目的是降低开发者的安全门槛,使合约开发者能够专注于业务逻辑。它很容易上手,并且整体开发者迁移成本不高。从生态系统的角度来看,Move 的实际应用场景仍处于早期阶段,应用生态系统尚未大规模发展。目前,唯一用 Move 孵化的 L1 链项目是中国大陆的 Aptos、Sui 和 Starcoin。未来,Move 的金融特性和成熟度将培育第一批金融基础设施,如 DEX、DeFi 和钱包,随后是与金融相关的应用,如 Socialfi 和 Gamefi。
最近 L1 链领域异常活跃:两条新的 L1 链 Aptos 和 Sui 获得了市场的广泛关注,尽管总体市场状况不佳,但它们筹集了近 5 亿美元。除了大多数创始团队都是来自现已解散的稳定币 Libra(后来更名为 Diem)的专家之外,目前的成功更多地归功于对 Diem 遗留核心 Move 语言的继承。
每个 L1 链的崛起都伴随着一定程度的开发范式转变。目前,以 Move 为首的 Diem 家族的 L1 链似乎表明,新编程语言的叙事已成为 L1 链竞争的战场之一。
有这么多编码语言可用,为什么 Libra 还要“额外努力”来设计 Move?我们知道 Libra 的愿景是成为一个惠及数十亿人的全球货币金融基础设施。考虑到这一点,Move 必须将资产安全置于其设计目标的首位。然而,过去的编程语言并没有很好地满足这一要求。
根据 SlowMist Hacked 数据的不完全统计,仅在 2021 年,区块链生态系统中就发生了 200 多起公开的安全事件,损失超过 98 亿美元。其中,绝大多数安全问题出现在 DApp 或 DeFi 协议中。
此外,DApp 事件可分为前端事件、后端事件和合约事件。前端事件主要是由 DApp 客户端的安全漏洞引起的,涉及传统信息技术,导致用户账户信息、个人信息等被盗,从而导致加密资产损失;而后端事件通常涉及 DApp 服务器端的安全漏洞,导致 DApp 的后端服务和链上交互被劫持,从而导致用户加密资产被盗或丢失。合约事件通常是由于智能合约协议的漏洞导致资产损失造成的。大多数涉及链上协议的安全事件都是合约安全事件。
典型的合约安全攻击包括闪电贷攻击、重入攻击、双花攻击、溢出、交易重放、伪造收据等:这些都反映了以 Solidity 为代表的上一代编程语言,在语言特性、合约操作和虚拟机设计方面或多或少存在安全风险。
因此,Libra 决定放弃旧的智能合约编程语言,并开发更安全的 Move 语言。本文也将重点关注 Move 的安全特性。
Move 在资产安全方面优于以前的编程语言,很大程度上是因为它在前代不足的三个主要领域取得了进展:语言设计、虚拟机和链下验证工具。
Move 正在逐渐弱化“数字”属性,强调数字金融中的“资产”属性。为什么会这样?让我们看看图灵完备的智能合约语言是如何定义数字资产的。
众所周知,以太坊采用账户模型,它本身就是一个巨大的交易状态机:每笔交易都会改变以太坊区块链的状态,这些状态也打包在区块中。因此,以太坊一方面可以被认为是由区块中打包的交易形成的账户链,另一方面可以被认为是一个状态机,它随着区块的创建而不断地从区块链的一种状态跃迁到另一种状态。
此外,每个账户的信息总和由区块链在每个时刻的状态组成。同时,对于每个账户,它是从地址到账户状态的映射。例如,当你打开你的钱包时,每张银行卡都对应一个银行账户。银行卡的卡号相当于账户的地址,账户信息,包括资金余额、消费明细以及存储在卡号中的金融产品头寸都是账户的状态。每张卡对应于某个时间点的状态。你所有银行卡的集合对应于你的整体财务状况。当你使用你的银行卡进行交易或购买时,你的银行卡的状态会发生变化,你的财务状况也会相应地发生变化。
这种映射关系主要由以太坊账户中键字符串中的余额表示。直观地说,这是一个典型的 KV 键值对 (mapping (address => uint256) public balances),其中 Value 体现为账户的 Token 余额。因此,账户余额在 Solidity 中由整数数值变量 (uint) 表示,不同账户之间转移 Token 的过程通过数值加减运算来实现。
以下是 Solidity 实现的 ERC20 转账逻辑,其中“from user”(发送者)将 Value(token 数量)转账给“to user”(接收者),主要过程如下:
i. 将初始余额从发送者地址 (from) 映射到 oldFromVal 变量。
ii. 要求 oldFromVal 大于 value,即发送者余额充足。
iii. 初始余额从接收者地址 (to) 的映射中派生并分配给 oldToVal 变量。
iv. 使用 oldToVal 加上 value 并将其分配给 newToVal。
v. 使用 oldFromVal 减去 value 并将其分配给 newFromVal。
vi. 将 newFromVal 设置为发送者地址 (from) 的新 balance。
vii. 将 newToVal 设置为接收者 (to) 的新 balance 。
在一个简单的例子中,Alice 向 Bob 转账 10 美元,调用智能合约从 Alice 的账户地址中扣除 10 美元,并向 Bob 的地址增加 10 美元。修改余额的整个过程在中心化金融场景中是一种常见的借记逻辑。
然而,链上世界的情况却大不相同。例如,是否会出现 Bob 的余额增加 10 美元,但 Alice 的余额没有变化的情况?答案是肯定的。我们知道,链上操作主要依赖于智能合约,智能合约会根据预设规则自动执行。回到上面的例子,如果 from 和 to 地址相同,则相当于向自己发送 token。根据代码执行的顺序,虽然转账值首先从发送者地址中扣除,但 newToVal 的值稍后会被 newFromVal 的值覆盖,导致该账户的余额不断增加,但没有扣除。这就是我们常说的 token 无限增量漏洞。
从这个例子可以看出,用户之间的交易是通过执行编码程序来完成的,最终反映在地址下数字的更新上。可靠性取决于开发者,并且不保证人为偏差可能造成的错误。总而言之,Solidity 是一种用于区块链智能合约的语言,它不是一种面向资产的语言。数字资产仅仅是可以加减的数字,但在 Solidity 中没有类定义;而数字无法表达资产的类别。
为了解决上述问题,Move 为数字资产定义了一个新的数据类 First-class Resource,字面意思就是 Resource 是一等公民:在编码中,一等公民会优先被考虑,而资源是数量有限但可能产生价值的任何东西。Move 遵循这个概念,并为资源抽象出两个约束条件来进行编程,即稀缺性和访问控制。
稀缺性是贵重实物资产的一个重要属性,例如现实世界中的金条,无论经过多少次转手,数量都不会从一根变为两根,也不会突然消失;然而,数字资产并不具备这种固有的物理稀缺性。因此,Move 认为必须对数字资产计算规则进行编程,以强制执行这种稀缺性。它规定系统中资产的供应应受到限制,资产不应消失,应禁止复制现有资产,并且创建新资产应是一种特权操作。这里提到的编程方法指的是 Move 定义的语法结构 Ability。它包含 Move 为各种变量抽象出的四个属性:copy、key、drop 和 store;开发者可以使用这些字符串相互组合来启用变量的不同功能。值得注意的是,一旦变量被声明为 Resource,它只能使用 Key 和 Store 进行编辑,使用 Copy 和 Drop 无效。通过这种方式,Move 从编程语法结构上确保了资源类的稀缺性。
资产所有者应该能够使用访问控制策略来保护他们的资产。众所周知,以太坊主要依赖于公钥签名机制,而 Move 在此基础上提供了一个新的 Module 系统,我们将在后面详细介绍。
Move 使用 Resource 在底层逻辑上封装了资产的定义,将数字资产转换为真实的合约变量,不仅可以存储和分配,还可以作为函数/过程的参数和返回值参与运算。Ability 结构也在语法上反映了 Move 对 Resource 变量的强制规则,确保资产不会随意消失或被复制,从而有效地最大限度地减少了诸如上述无限增量漏洞之类的安全风险。
Module 类似于 Rust 中的 Mod 和 Solidity 中的 Contract,能够声明一系列数据类和函数,包括 Resource、Struct 和 Function。Struct 和 Resource 都被用来定义新的数据结构类型,Resource 有一些不同,因为它不能被复制和丢弃。Function 类似于大多数其他语言,并且被用来创建、销毁和更新 Module 中的声明类型。总的来说,Module 具有以下特点。
Module 是一种强数据抽象,因为它规定数据类在声明的 Module 内部是透明的,而在外部是不透明的;每个 Resource 对象都被封装在一个特定的 Module 中,由所有者的账户控制和更新,并提供外部函数来根据详细的命令创建、修改和销毁资产。如上所述,此功能还可以有效地控制对 Move 的访问,Module 外部的实体无法直接操作内部 Resource;它们必须遵循某些给定的函数,并且只能对 Resource 执行有限的操作。这反映在代码中,外部开发者只能调用 Module 中的 Public 函数,并根据模块的内部定义进行操作,从而避免了与意外调用相关的安全风险。
Module 保留了模块的公共套接字,供外部源启用合约间的组合和资源利用,这在功能上与 Solidity 的接口标准几乎没有区别。唯一最小的区别是 Move 中的模块是无状态的,并且状态存储在全局状态中。具体来说,在 Solidity 中发行 ERC-20 token 更像是保留一个账本,该账本通过账本的状态变化记录每个用户与合约交互的完整数据;另一方面,Move 通过 Module 封装资产,并以分布式方式将其存储在账户地址下,这更像是一个带有标签但独立的保险箱。
这个概念继承自 Rust,它对所有权的定义如下:
1. 每个 value 都有一个对应的变量,称为所有者。
2. value 在任何给定时刻都有一个且只有一个所有者。
3. 当所有者离开作用域时,value 将被丢弃。
简单来说,一个 value 只能有一个所有者;在这种情况下,所有者可以是 function 。当一个 value 被传递给一个新的函数时,这个新的函数就成为了新的所有者,将一个 value 传递给一个函数在语义上类似于将一个 value 赋值给一个变量。
这个特性在 Move 中是如何体现的呢?首先,所有的 Resource 必须存储在一个账户下——也就是说,Resource 只有在分配了一个账户后才能生成。其次,每个 Resource 一旦从账户中提取出来,就必须被标记为“已使用”:当资产通过内置的 Move_from 命令从账户中取出时,它要么作为返回值循环,要么流向一个新的账户,要么会被销毁。任何“自掏腰包”的东西,无论从账户中提取多少,都会被标记为“已使用”。这很好地阐述了交易的继承性:转移所有权。
回顾 Resource 的属性,虽然用户之间的 Resource 交易仍然是基于资产价值的大小进行加、减和索引,但与 Solidity 中的情况有明显的不同。后者强制执行编码逻辑,以减少一个的余额并增加另一个的余额,而 Resource 的转移过程更像是搬砖:将唯一的资源从一个账户移动到另一个账户,在转移过程中没有损失或重复,从而更好地保证了资产安全。
总的来说,Move 通过线性类的概念来明确数据所有权,强调资源的稀缺性、保护和访问控制。它还采用模块化系统来定义每个 Resource 的生命周期、存储和访问模式。这些特性共同确保了不会凭空创建或隐式丢弃数字资产,从而减少了双重支付和无限增量等安全问题的漏洞。
上一节介绍了 Move 的语言设计特性,这些特性使开发者能够编写满足特定需求的智能合约。然而,Move 和 Solidity 都是高级编程语言。计算机不会直接读取和执行这些源代码;合约的实现依赖于特定的执行器。
目前,虚拟机是智能合约的主流实现方法之一,也适用于 Move。它们为程序提供了一个对底层逻辑完全透明的执行环境,并且被设计为“一次编写,到处运行”。后者与开发者编写不同版本的程序以兼容不同的服务器形成了对比。这种设计的理由是,智能合约运行在一个需要拜占庭容错才能达成共识的分布式系统环境中,所有节点都必须按照智能合约中预设的规则产生相同的计算结果。否则,合约执行的结果无法被每个节点同意。然而,虚拟机可以忽略区块链节点上执行环境之间的差异,从而使节点上的一切都与其他节点保持一致,从而确保合约的确定性。
Move VM 是一个典型的基于堆栈的字节码解释器,其输入是字节码。再加上当前的世界状态,输出是对世界状态的改变。它有一组独立的内部指令来执行和处理系统的所有状态变化;用户可以在 Move 提供的字节码交叉引用表中找到命令对应的含义。
Move 虚拟机的具体工作流程如下。首先,源代码通过编译器转换为基本字节码,并传递给虚拟机。接收到字节码后,虚拟机必须首先调用字节码验证器进行验证,该验证器区分 Move 源代码中的各种类型的错误。最后,虚拟机解释器按顺序解释和执行脚本,从左到右遍历数据或字节码。运行时基于堆栈执行,当遇到数据时将数据压入堆栈,当遇到字节码时弹出相应的数据,基于字节码进行计算,然后在计算后将计算结果压回堆栈,直到退出。
在此源代码筛选过程中可能发生的主要错误类型包括:
i. 堆栈越界检查是检查每个函数访问操作数堆栈的范围以及堆栈高度是否合法的过程。在这种情况下,堆栈被指定为由字节码验证器创建的每个字节码的指令块(基本块)。
ii. 类型和种类检查是检查派生堆栈中变量的特定类型是否正确。例如,堆栈类不能对 Resource 类型的变量使用 CopyLoc 字节码,这直接反映了资产稀缺性。
iii. 引用检查是为了防止悬空引用;每个引用必须指向已分配的存储位置。
EVM 是链上节点为智能合约创建的一个隔离且可确定的沙箱环境,其中多个合约程序在同一进程中的不同虚拟机沙箱中运行。换句话说,以太坊上的合约间调用是同一进程中 VM 之间的调用,安全性依赖于 VM 之间的隔离。
另一方面,Move 虚拟机支持并行执行。合约之间的调用集中放置在一个沙箱中,在这种设置下,合约状态的安全性主要通过编程语言的内部安全设置来隔离,而不是依赖虚拟机进行隔离。
理想情况下,Move 应该能够通过运行字节码检查来发现合约运行时的安全漏洞。然而,这种链上验证在计算上是昂贵的;此外,它会消耗大量的网络资源,从而降低链上 TPS。因此,Move 提出了一种策略,即仅对关键安全属性执行轻量级的链上验证,并依赖链下静态验证工具来解决其他安全问题。基于此策略,Move 开发了专有的 Move Prover 形式化验证器,以防止人为编辑错误,从而提高代码的安全级别。
形式化验证是通过某些形式化规范或属性来验证程序可靠性的过程,通常基于数学模型。该过程遵循严格的逻辑推理来获得精确的结果,从而在正式部署之前证明合约没有错误。
说到 Move Prover,Move 已经建立了一套标准化的语言,即 Move 规范语言,该语言通过前置条件、后置条件、不变性等来描述如何正确运行程序。然后,Move boogie 编译器将 Move 程序规范转换为 boogie 程序。Boogie 是 Microsoft 开发的一种形式化验证中间语言,用于为其他语言构建程序验证器,因为该工具会综合验证条件并将其传递给求解器。最后,求解器给出的结果用于验证程序是否符合规范;如果不符合,将提供具体的解决方案路径。
值得一提的是,Move Prover 是一种静态验证工具,这是因为 Move 的设计机制根本不支持动态调用。动态调用是指程序以某种方式调用另一个程序时发生的合约调用,以使得被调用的目标只能在运行时确定。从机械上讲,它有点类似于服务器的远程调用。然而,动态调用在循环调用期间会引发并发问题。例如,如果合约 A 调用合约 B,而合约 B 调用合约 A,则在合约 A 的先前执行不完整时执行第二次执行。因此,后续执行无法读取先前的中间状态,最终导致安全漏洞。臭名昭著的 The DAO 事故就是由动态合约调用问题引发的。因此,在 Move 的设计中,每个函数调用都是静态的:开发者在程序运行之前就已经清楚函数被调用的顺序。这种静态系统更适合通过形式化验证进行推理,将问题的暴露提前到编译阶段,以减少运行时出现 bug 的可能性,并减轻直接在链上进行安全检查的压力。
如果将从比特币脚本到以太坊 Solidity 的扩散过程视为合约表达能力的一次革命,那么从 Solidity 到 Move 的过渡将是合约安全能力的一次进化。因此,市场对 Move 的期望也很高。
在语言机制方面,Move 对资产安全性的探索方向令人鼓舞。在语言设计、虚拟机和验证工具三个层面都看到了创新性的变化,这些变化被整合为一个有机的整体。面向资产的编程设计使 Move 语言成为部署去中心化金融应用的天然选择;线性逻辑、访问控制、静态调用和形式化验证等特性为数字资产提供了多层安全保障。
在语言接受度方面,Move 对开发者相当友好:它的目的是降低开发者的安全门槛,使合约开发者能够专注于业务逻辑。同时,Move 是从 Rust 和 Solidity 演变而来,摒弃了两者设计中不必要的“腐朽”,体现了低复杂性。因此,对于开发者来说,整体迁移成本并不高。据 Move 的从业者说,对于有 Rust 和 Solidity 编程经验的开发者来说,只需要 1-2 天就可以快速掌握 Move。对于没有智能合约编程经验的开发者来说,从头开始学习 Move 只需要 1-2 周。
从生态系统的角度来看,Move 的实际应用场景仍处于早期阶段,应用生态系统尚未广泛普及。除了已经放弃的 Libra 之外,唯一使用 Move 孵化的 L1 链项目是 Aptos、Sui 和中国的 StarCoin。Aptos 和 Sui 都处于测试网络阶段,并且都根据 Move 探索了不同的方向:Sui 引入了不可变状态,并尝试在 Move 中实现类似 UTXO 的编程模型,而 Aptos 正在探索 Layer1 上的事务并行执行和更好的性能。Starcoin 的主网络于 2021 年 5 月启动,正在探索 Layer2 甚至 Layer3 上的分层扩展模型。随着这些项目的发展,我们希望在其各自的生态系统中看到更多小众项目。由于 Move 的本质是为了金融,因此可以预见的是,第一批项目仍将属于 DEX、DeFi 和钱包等金融基础设施的范畴。随着基础设施在广泛开发的支持下得到加强,更多与金融相关的领域,如 Socialfi 和 Gamefi,将被引入生态系统。
当前新 L1 链叙事浪潮中的超级明星无疑是 Move。它能否借势而上?让我们期待 Move 的未来表现。
2. https://move-book.com/cn/index.html
3. https://move-dao.github.io/move-book-zh/modules-and-scripts.html
4. https://jolestar.com/why-move-1/
6. https://mp.weixin.qq.com/s/bSS9GAcVp6tuWjedpTysQw
7. https://starcoin.org/zh/developers/others/starcoin_ecology/
8. https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/design/virtual_machine/evm.html
9. https://doc.rust-lang.org/book/
10. https://solidity-cn.readthedocs.io/zh/develop/
火币区块链应用研究院(简称“火币研究院”)成立于2016年4月。自2018年3月起,致力于全面拓展区块链各领域的研究与探索。以区块链为研究对象,研究目标是加速区块链技术研发,促进区块链行业应用,推动区块链行业生态优化。主要研究内容包括区块链领域行业趋势、技术路径、应用创新、模式探索等。火币研究院秉承公益、严谨、创新的原则,通过多种形式与政府、企业、高校等机构开展广泛而深入的合作,构建覆盖区块链完整产业链的研究平台。行业专业人士提供坚实的理论基础和趋势判断,促进整个区块链行业的健康可持续发展。
联系我们:
网站:
电子邮件:
https://twitter.com/Huobi_Research
Telegram:
https://t.me/HuobiResearchOfficial
Medium:
https://medium.com/huobi-research
1. 本报告的作者及其所在机构与本报告中涉及的其他第三方没有影响报告客观性、独立性和公正性的任何关系。
2. 本报告中引用的信息和数据来自合规渠道。信息和数据的来源被作者认为是可靠的,并且已对其真实性、准确性和完整性进行了必要的验证,但作者对其真实性、准确性或完整性不做任何保证。
3. 本报告的内容仅供参考,报告中的事实和观点不构成商业、投资和其他相关建议。除非法律法规明确规定,作者不对因使用本报告内容而造成的损失承担任何责任。读者不应仅根据本报告做出商业和投资决策,也不应因本报告而丧失做出独立判断的能力。
4. 本报告中包含的信息、意见和推论仅反映研究人员在最终确定本报告之日的判断。未来,基于行业变化以及数据和信息更新,存在更新意见和判断的可能性。
5. 本报告的版权仅归火币区块链研究院所有。如果你需要引用本报告的内容,请注明出处。如果你需要大量参考,请提前告知(联系方式请参见“关于火币区块链研究院”),并在允许的范围内使用。在任何情况下,不得以违反其原始内容的方式引用、删除或修改本报告。
- 原文链接: medium.com/huobi-researc...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!