智能合约有几种类型的合约 (智能合约是指什么)

 网络   2022-10-12 21:44   55

原文题目:《Smart Contract Development—Move vs.Rust》

作家:Krešimir Klas,Move 语言开创人

编译:郭倩雯,链捕手

1. 先容

迩来,对于 Aptos 以及 Sui 的议论如火如荼,二者是新兴的高机能 L1 公链,Move 智能合约编程语言是这些新链必弗成缺的组成全体。一些开垦人员在努力转向Move,传颂它是智能合约繁华的他日。其他人尤其束缚,以为 Move 与现有编程语言比拟,没有能供给更多太新的货色。

加密投资者也正在猎奇这些 L1 公链的特殊之处,若何能与 Solana 抗拒,后者是今朝高机能 L1 的主要玩家,以利用 Rust 算作智能合约编程而知名。

但今朝咱们看到的议论并没有到达特定深度,恐怕真正参透这些新科技对于咱们的作用。这正在议论的两极都合用——Move 的置疑者将 Move 降低得一无是处,没法观赏到它更轻微(但十分主要)的部分,但 Move 的支柱者,适度提议 Move,也没有能识破毕竟是甚么使其渺小。这就带来辽阔的中间地域与迷糊没有清,以致外界看客、加密开垦人员、投资人员,存眷此话题,但又没法对于自身的概念置信。

正在这篇文章中,我将对于 Move、其现代的编程模子、Sui 区块链以及它若何运用 Move 的功能,和它与 Solana 及其编程模子的较为施行深切的本领开采。为了优异 Move 的特征,我将把 Solana/Rust 与 Sui/Move 施行较为。由于当你把一个货色与另一个你已纯熟的货色施行较为时,领会就会更轻易。

Move 还有其他变种,如 Aptos Move,它们正在某些方面略有分歧。本文的中心没有是议论 Move 分歧变体之间的轻微差异,而是揭示 Move 的集体劣势,和它与 Solana 编程模子的较为。所以为了简捷起见,我正在本文中只利用一个变体(Sui Move)。所以,我正在本文中先容的某些Move概念(即工具以及相干功能)只合用于 Move 的 Sui 变体,而没有合用于其他变体。虽然 Move 的其他变体没有特定有这些概念,但它们利用分歧的体制(比如全部保存)恐怕完结异样功能。但即便如许,本文所议论的一切Move的主要优点都合用于一切Move集成(原生设定上支柱Move字节码 Move bytecode),席卷Aptos。我挑选Sui,仅仅由于我对于它更纯熟,且我感慨它更直不雅一些,更轻易以文章的大局消失。

2. Solana编程模子

正在Solana上,法式(智能合约)是无状态的,它们自身没有能拜候(读或写)一切正在整体买卖中延续生存的状态。为了拜候或维持状态,法式须要利用账户。每个账户都有一个仅有的地方(Ed25519密钥对于的公钥),也许保存随便的数据。

咱们也许把Solana的账户空间看作是一个寰球键值保存,个中键是账户地方(pubkey),值是账户数据。法式经过读取以及改动其值正在该键值保存上施行操作。

账户有一个一切权的概念。每个账户由一个(且只要一个)法式拥有。当一个账户被一个法式拥有时,该法式被禁止改动其数据。法式没有能改动所没有拥有的账户(但禁止读取这些账户)。运行时期,较为法式施行前后的账户状态,就恐怕施行这种动静反省,若有作歹改正,则买卖退步。

每个账户也有一个与之相干的私钥(相映的公钥是它的地方),恐怕拜候这个私钥的用户也许用它来订立买卖。运用这种体制,咱们正在Solana智能合约中完结了权力以及一切权的功能--比如,为了猎取某些资金,智能合约也许要求用户供给须要的出面。

正在其他做法式挪用时,客户须要指定这个法式正在挪用时将拜候哪些账户。这样一来,买卖处置运行时光就也许设计没有重迭的买卖并行施行,同时保险数据统一性。这是Solana的妄图特征之一,使其拥有高吞吐量。

法式也许经过CPI挪用来挪用其他法式。这些挪用的处事原理与来自客户真个挪用根底不异——挪用者法式须要指定被挪用者法式将拜候的账户,被挪用者法式将施行输入反省,就以及从客户端挪用是一律的(由于它没有信赖挪用者法式)。

PDA账户是一种寻常账户,使法式能正在没有拥有或储藏私钥的状况下供给账户出面。PDA保险只要为其天生PDA的法式也许为其建立一个出面(而其他用户以及法式不能)。当一个法式须要经过CPI挪用与另一个法式施行交互并供给授权时,这是很实用的(比如,实行一个金库)。PDA保险除了法式之外没有人也许直接拜候法式资源。PDA也可用于正在决定地方建立账户。

这些是Solana上安全智能合约编程的根底构件。正在某种水准上,你也许把Solana法式看作是操作系统中的法式,而账户则是文件,一切人均可以自在施行一切法式,以至摆设自身的法式。当法式(智能合约)运行时,它们将读取以及写入文件(账户)。一切文件均可被一切法式读取,但只要对于文件有一切权权力的法式才也许对于其施行改写。法式也也许施行其他法式,但它们互相之间没有一切信赖——不管谁施行法式,它都须要假定输入是潜伏好心的。因为该操作系统是一切人正在寰球范围内都拜候的,因而正在法式中参加了原生出面验证支柱,以便为用户完结权力以及一切权功能......这没有是一个完善的比喻,但依然挺乐趣的。

3. Move的编程模子

正在Move中,智能合约是以模块大局揭晓的。模块由函数以及自定义类别(组织/struct)组成。组织由字段组成,也许是原始类别(u8,u64,bool...)或其他组织。函数也许挪用其他函数——也许是统一模块,也也许是其他秘密的模块。

正在Solana中,这就异常于一切智能合约都算作模块揭晓正在一个法式中。这意味着一切的智能合约(模块)都蕴含正在统一类系统中,也许直接彼此挪用,而没有须要经过中间的API或接口。这一点很是主要,其作用将正在本文中彻底议论。

3.1. 工具

要留神的是,上面的工具概念针对付Move的Sui变体。而正在Move的其他集成中(比如Aptos或Diem/core Move),状况大概略有分歧。没有过,正在其他Move变体中也有一致的束缚规划,也许完结异样的办事(状态的长久性),这些束缚规划并没有太大区分。

这边先容Sui变体的主要缘由是,文章后面的代码样本都基于Move的Sui变体,同时其工具例如core Move中的全部保存体制更直不雅易懂一点。主要的是,本文所议论的Move的一切主要优点都合用于一切Move集成(原生支柱Move字节码),席卷Aptos。

工具是由运行时保存的组织实例(struct instance),并正在事情中延续维持状态。

有三种分歧类别的工具(正在Sui中):

- 自有工具(owned objects)

- 共享工具(shared objects)

- 弗成变工具(immutable objects)

自有工具是属于用户的工具。只要拥有该工具的用户才华正在买卖中利用它。一切权元数据是全面透明的,由运行处置。它利用公钥加密本领完结——每个自有工具都与一个公钥有关(运行时保存正在工具元数据中),一切时分你想正在买卖中利用工具,你都须要供给相映出面(而今支柱Ed25519,行将支柱ECDSA以及K-of-N多出面)。

共享工具一致于自有工具,但它们没有一个与之相干的一切者。所以,你没有须要拥有一切私钥就也许正在买卖中利用它们(一切人均可以利用它们)。一切自有工具均可以被共享(由其一切者),一旦一个工具被共享,它将永久维持共享——永久没有能被转化或再次成为自有工具。

弗成变工具是没有能被改正的工具。一旦一个工具被符号为弗成变,它的字段就没有能再被改动。与共享工具一致,这些工具没有一切者,也许被一切人利用。

Move编程模子很是直不雅以及简捷。每个智能合约是一个模块,由函数以及组织定义组成。组织正在函数中被实例化,并也许经过函数挪用传播到其他模块。为了使一个组织恐怕正在跨买卖中维持长久,咱们把它变为一个也许被拥有、共享或弗成改革的工具(仅限于Sui,正在其他Move变体中略有分歧)。

4. Move的安全性

咱们一经看到,正在Move:

- 你也许将你拥有(或共享)的一切工具传播给一切模块中的一切函数

- 一切人均可以揭晓一个(潜伏的敌视)模块

- 没有生存模块拥有组织的概念,这将使一切者模块拥有改革组织的仅有权益,就像Solana账户的状况一律——组织也许流入其他模块,也也许嵌入其他组织中。

课题是,这种做法为甚么是安全的?是甚么制止了人们揭晓好心模块,猎取共享工具(如AMM池),并将其发送到好心模块中,然后连续耗尽其资金?

正在Solana中,有一个账户一切权的概念,也便是说只要拥有账户的法式才被禁止对于其施行改正。不过正在Move中,没有模块拥有工具的概念,你也许将工具发送就任意的模块中——没有仅也许引用工具、整体工具,也也许引用其自己价值。而且,运行时也没有全部反省,以确保这个工具正在经过没有受信模块时没有被作歹改动。那么,是甚么正在损坏这个工具的安全?若何保险这个工具没有被弗成信的代码滥用?

这便是Move的现代之处......让咱们来谈谈资源。

4.1. 组织

定义一个组织(struct)类别以及你所渴望的差没有多:

到今朝为止还没有错——这也是你正在Rust中定义一个组织的办法。但正在Move中,组织有其特殊之处与传统编程语言比拟,Move模块正在若何利用类别上拥有更多空间。正在下面的代码片段中定义的组织将受以上限制:

- 它只可正在定义该组织的模块中被实例化(“打包”)以及袪除(“解包”)——也便是说,你没有能从一切其他模块的一切函数中实例化或袪除一个组织实例。

- 组织实例的字段只可正在其模块中被拜候(所以也也许被改正)。

- 没有能正在其模块之外克隆或复制组织实例

- 没有能将一个组织实例保存正在其他组织实例的字段中

这意味着,假设正在其他模块的函数中处置这个组织的实例,咱们将没法改正其字段、克隆它、将其保存正在其他组织的字段中,或将其丢弃(必需经过函数挪用将其传播到其他地点)。状况是这样的:该组织的模块实行了能从咱们模块中挪用的函数,来告竣这些办事。但除此之外,咱们没法直接为外部类别做这些办事。这使模块也许全面掌握若何利用以及没有利用其类别。

因为这些限制,咱们犹如落空良多精巧性。这也是真相——正在传统编程中,处置这样的组织会很是障碍,但真相上,这正是咱们正在智能合约中想要的。智能合约开垦到底是对于数字物业(资源)的编程。假设你看一下下面形容的组织,这正是它的本体——它是一种资源。它没有能草草被捏造发觉,没有能被复制,也没有能被不料地袪除。所以,咱们确切正在这边落空了一些精巧性,但咱们落空的精巧性正是咱们所指望的,由于这使对于资源的操作变得直不雅而安全。

其余,Move禁止咱们经过向组织推广才略(capability)来放宽个中一些限制。有四种才略:键、保存、复制以及节略。你也许将这些才略的一切配合推广到一个组织中。

上面是它们的影响:

- 键 - 禁止一个组织成为一个工具(专属Sui,core Move状况略有分歧)。如前所述,工具是长久化的,假设是自有工具,须要用户出面才华正在智能合约挪用中利用。当利用键才略时,组织的第一个字段必需是拥有UID类别的工具ID。这将给它一个寰球仅有的ID,恐怕用它施行引用。

- 保存 - 禁止将该组织算作一个字段嵌入另一个组织中

- 复制 - 禁止从一切地点随便复制/克隆该组织

- 节略 - 禁止从一切地点随便袪除该组织

从本体上讲,Move中的每个组织都是默认的资源。才略给了咱们权益,也许精巧地放宽这些限制,使其展现得更像传统组织。

4.2. 币(Coin)

币正在Sui中完结了一致ERC20/SPL代币的功能,是Sui Move Library的一全体。它的定义是这样的:

你也许正在Sui代码库中找到齐全的模块完结(链接)。

币类别拥有键以及保存的功能。键意味着它也许算作一个工具利用。这禁止用户直接拥有币(算作一个顶层工具)。当你拥有一个币时,除你之外,其他人以至没有能正在买卖中引用它(更没有用说利用它)。保存意味着,币也许算作一个字段嵌入到另一个组织中,这对付可配合性很实用。

因为没有丢弃功能,币没有能正在函数中被不料丢弃(袪除)。这是一个很是好的个性——它意味着你没有领会外洋丢掉一个币。假设你在完结以领受硬币为参数的函数,正在函数停止时,你须要清爽地对于它做一些办事——把它转化给用户,把它嵌入另一个工具,大概经过挪用把它送入另一个函数(异样须要对于它做一些办事)。固然,经过挪用币模块中的coin::burn函数来袪除一个币是大概的,但你须要有想法地这样做(你没有会这样不料操作的)。

没有克隆才略意味着没有人也许复制币,进而捏造发觉新的供应。发觉新的供应也许经过coin::mint函数来告竣,而且只可由该币的国库才略工具(treasury capability)的一切者挪用。

其它,因为泛型(generics)的生存,每个分歧的硬币都是特殊类别。因为两个币只可经过coin::join函数加正在一统(而没有是直接拜候它们的字段),这意味着弗成能把分歧类别的币值加正在一统(币A+币B)——由于没有这种出面的函数。类别系统恐怕损坏咱们免受坏账作用。

正在Move中,资源的安全性由其类别定义。思虑到Move有全部类别系统,这使编程模子更当然以及更安全,资源也许直接传入以及传出没有受信赖的代码。

4.3. 字节码验证

如前所述,迁徙智能合约是算作模块揭晓的。一切人都被禁止建立并上传一切随便模块到区块链上,由一切人施行。咱们也一经看到,Move对于组织体的利用办法有特定法则。

那么,是甚么保险了这些法则被随便模块所按照?是甚么制止了人们上传拥有寻常创造字节码的模块,比如领受一个币工具,然后直接改革其内部字段来绕过这些法则?经过这样做,也许作歹地推广一切币的数目。光是字节码的语法就一定禁止这样做。

字节码验证可有避让这品种型的滥用。Move验证器是一个静态分解器械,它分解Move字节码并决定它是否按照所需的类别、内存以及资源安全法则。一切上传到链上的代码都须要经过验证器。当你试图上传一个Move模块到链上时,节点以及验证器将开始经过验证器运行,然后才禁止提交。假设一切模块试图绕过Move的安全法则,它将被验证器推辞,并且没有会被揭晓。

Move字节码以及验证器是Move的当中改革之处。它完结了一个以资源为焦点的直不雅编程模子,正在其他处是没法完结的。最枢纽的是,它禁止组织化类别越过信赖界限而没有落空其齐全性。

正在Solana上,智能合约是法式,而正在Move中,它们是模块。这犹如仅仅一个语义上的分裂,但真相并非如许,拥有远大意思。区分正在于,正在Solana上,跨法式界限是没有类别安全的——每个法式经过手动从原始账户数据解码来加载实例,这须要手动施行枢纽的安全反省,也没有要地资源安全。相反,资源安全必需由每个智能合约零丁完结。这确切恐怕完结渊博的可编程性,但与Move的模式比拟,它正在很大水准上妨碍了可配合性以及人机工程学,由于Move的模式对于资源有原生支柱,它们也许安全地流入以及流出没有信的代码。

正在Move中,类别确切生存于各个模块中——类别系统是全部的。这意味着没有须要CPI挪用,账户编码/解码,账户一切权反省等——你只需直接挪用另一个模块中的函数与参数。整体智能合约的类别以及资源安全由编译/揭晓时的字节码验证来保险,没有须要像Solana那样正在智能合约层面上完结,然后正在运行时反省。

5. Solana与Move

而今咱们一经看到了Move编程若何处事,根基安全的缘由。那么让咱们从可配合性、人机工程学以及安全性的角度深切领会一下这对于智能合约编程有甚么样的作用。正在这边,我将把Move/Sui的开垦与EVM以及Rust/Solana/Anchor施行较为,以帮忙领会Move的编程模子所带来的优点。

5.1. 闪电贷

闪电贷是DeFi中的一种贷款类别,贷款金额必需正在借入的统一买卖中了偿。这样做的主要优点是,因为买卖是原子性的,贷款也许全面没有抵押。这也许用来正在物业之间施行套利,而没有须要有本金。

完结这一目的的主要容易是——你若何从闪电贷智能合约中,保险贷款金额将正在统一买卖中失去了偿?为了使贷款无需抵押,买卖须要是原子性的——也便是说,假设贷款金额没有正在统一买卖中被了偿,整体买卖须要退步。

EVM有动静调剂,因而也许利用重入性(reentrancy)来完结这一点,以下所示:

- 闪电贷用户建立并上传自定义智能合约,当挪用该合约时,将经过挪用将掌握权传播给闪电贷智能合约

- 然后,闪电贷智能合约将向自定义智能合约发送恳求的贷款金额,并挪用自定义智能合约中的executeOperation()回调函数。

- 然后,自定义智能合约将利用收到的贷款金额来施行它所须要的操作(如套利)。

- 正在自定义智能合约告竣其操作后,它须要将借出的金额前往给闪电贷智能合约。

- 这样,自定义智能合约的executionOperation()就告竣了,掌握权将前往给闪电贷智能合约,它将反省贷款金额是否一经正确前往。

- 假设自定义智能合约没有正确前往贷款金额,整体买卖将退步。

这很好地完结了所需的功能,但课题是,它依附于可重入性,咱们很是指望它没有要呈现到处智能合约编程中。由于可重入性本体上很是安全,是许多马脚的根基缘由,席卷恶名昭著的DAO黑客报复。

Solana正在这方面做得更好,由于它没有禁止重入。不过,假设没有可重入性,假设闪电贷款智能合约没法回调到自定义智能合约,如该安在Solana上完结闪电贷款?多亏了指令自省( instruction introspection)。正在Solana上,每个买卖由多个指令(智能合约挪用)组成,从一切指令中你均可以反省统一买卖中生存的其他指令(它们的法式ID、指令数据以及账户)。这使得完结闪存贷款成为大概,全部以下:

闪电贷款智能合约完结借钱(borrow)以及还款(repay)指令

用户经过正在统一买卖中把借钱以及还款指令的挪用堆迭正在一统,建立一个闪电贷买卖。借钱指令正在施行时,将利用指令自省察查了偿指令是否设计正在统一买卖的前期。假设了偿指令的挪用没有生存或有效,买卖将正在这个阶段退步。

正在借钱以及还款的挪用之间,借来的资金也许被一切其他处于二者之间的指令随便利用。

正在买卖停止时,还款指令挪用将把资金返还给闪电放款人智能合约 (该指令的生存将正在借钱指令的沉思中施行反省)

这个束缚规划渊博好,但仍没有巴望。指令自省正在某种水准上是一个惯例,正在Solana中并没有常用,它的利用要求开垦者掌握大度概念,本来现自己也有很大本领要求,由于有一些轻微差异须要妥善思虑。还有一个本领上的限——-了偿指令须要静态地生存于买卖中,所以弗成能正在买卖施行时期经过CPI挪用动静地挪用了偿。这并没有是甚么大课题,但正在与其他智能合约整当令,它正在特定水准下限制了代码的精巧性,也将更多繁复性推向客户端。

Move也允许动静调剂以及重入,但与Solana分歧的是,它有一个很是简捷以及当然的闪电贷束缚规划。Move的线性类别系统禁止建立组织,保险正在买卖施行历程中适值被消费一次。这便是所谓的 “烫手山芋”(Hot Potato)模式——一个没有键、保存、节略或克隆功能的组织。完结这种模式的模块常常会有一个实例化组织的函数以及一个袪除组织的函数。因为”烫手山芋”组织没有丢弃、键或保存功能,所以也许保险它的袪除(destroy)函数能被挪用,以此来消费它。即使咱们也许将其传播给一切模块中的一切其他函数,但最终它依然须要正在袪除函数停止。由于没有其他方式来处置它,而且验证器要求正在买卖停止时对于它施行处置(它没有能被随便丢弃,由于没有丢弃功能)。

让咱们看看若何运用这一点来完结闪电贷。

- 闪电贷智能合约完结了一个“烫手山芋”的收条(Receipt)组织

- 当经过挪用贷款函数施行贷款时,它将向挪用者发送两个工具——恳求的资金(一个币)以及一个收条,是须要了偿贷款金额的纪录。

- 然后,借钱人也许将收到的资金用于其须要的操作(如套利)。

- 正在借钱人告竣其预期的操作后,它须要挪用还款函数,该函数将收到借钱资金以及收条算作参数。这个函数被保险正在统一个买卖中被挪用,由于挪用者没有其他方法脱节收条实例(它没有禁止被丢弃或嵌入到另一个工具中,这是验证器所要求的)。

- 还款函数经过读取嵌入正在收条中的贷款信息来反省是否已前往正确的金额。

Move的资源安全个性使Move中的闪电贷成为大概,而无需利用重入或自省。它们保险了收条没有能被没有受信赖的代码所改动,并且它须要正在买卖停止时被前往给还款函数。这样,咱们也许保险正在统一个买卖中前往正确的资金数额。

该功能全面利用根底的语言原语完结,Move的完结没有会像Solana的完结那样受到集成课题的作用,由于后者须要买卖是留心树立的。没有一切繁复性被推到客户端。

闪电贷很好揭示Move的线性类别系统以及资源安全保险若何使咱们以其他编程语言没法完结的办法去表达功能。

5.2. 铸币权力锁(Mint Authority Lock)

“铸币权力锁”智能合约扩充了代币铸造的功能,禁止多个白名片面(authority)铸造代币。该智能合约的所需功能以下(同时合用于Solana以及Sui的完结):

- 原始的代币铸币权力方建立一个“铸币锁”,这将使咱们的智能合约恐怕监管铸币。挪用者成为该铸币锁的办理员。

- 办理员也许为该锁建立极度的铸币授权,也许授权给其他各方,并禁止他随时利用该锁来铸造代币。

- 每个铸币授权都有 每日也许铸造的代币数目限制。

- 办理员也许正在一切时分允许(息争除)一切铸币权力方。

- 办理员的才略也许让渡给另一方。

这个智能合约可用于,比如将代币的铸币才略交给其他用户或智能合约,而原本的铸币权力方(办理员)仍然保全对于铸币的掌握权。没有然,咱们将没有得没有把铸币的全数掌握权交给另一方,这并没有巴望,由于咱们只好置信它没有会滥用该权益。而且给多方供给答应也是弗成能的。

这些智能合约的齐全完结也许正在这边(Solana)以及这边(Sui)找到。

留神:请没有要正在损耗中利用这段代码! 这是示例代码,仅用于教训想法。虽然我一经测试了它的功能,但我还没有做彻底的审计或安全测试。

而今让咱们来看看这些代码,看看完结办法有甚么分歧。上面是这个智能合约的齐全Solana以及Sui完结的并排代码截图。

也许留神到的是,对付不异的功能,Solana的完结的领域是Sui的两倍多(230 LOC vs 104)。这是一个大课题,由于更少代码常常意味着更少正确以及更短开垦时光。

那么,Solana的这些极度行数是怎样来的呢?假设咱们提防看Solana的代码,咱们也许把它分为两个全体——指令完结(智能合约逻辑)以及账户反省。指令完结与咱们正在Sui上的状况较为凑近-——Solana136行,Sui上104行。极度的行数源于两个CPI挪用的引用(每个约莫10个LOC)。最主要的分裂是正在账户反省(正在下面的截图中标为白色的全体),这正在Solana上是必需的(真相上是枢纽的),但正在Move中没有是。帐户反省占这个智能合约的约莫40%(91 LOC)。

Move没有须要账户反省。LOC的削减恐怕带来利处,但同时去除做账户反省也十分须要。由于真相证实,正确切施这些反省利害常辣手的,假设你正在犯了哪怕一个正确,每每会导致远大马脚以及用户资金的亏空。真相上,一些最大的(就用户资金亏空而言)Solana智能合约马脚便是由没有当的账户反省引起的账户更换打击。

- Wormhole(3.36亿美元) - https://rekt.news/wormhole-rekt/

- Cashio (4800万美元) - https://rekt.news/cashio-rekt/

- Crema Finance (880万美元) - https://rekt.news/crema-finance-rekt/

那么,Move是若何做到没有这些反省又异样安全的呢?让咱们提防看看这些反省的理论影响。这边是mint_to指令所需的账户反省(权力持有人经过挪用这个指令来铸造代币):

有6个反省(用白色标出):

1. 反省所供给的锁账户是否为该智能合约所拥有,并且是MintLock类别的。须要传入锁,由于要用于CPI挪用,到代币法式施行铸币(它保存了权力)。

2.反省所供给的铸币权力账户是否属于所供给的锁。铸币权力账户持有权力状态(它的公钥,它是否被允许,等等)。

3.反省指令挪用者是否拥有该权力的所需密钥(所需权威订立了该买卖)。

4.须要传入代币目的账户,由于代币法式将正在CPI挪用中退换它(推广余额)。铸币反省正在此处并没有是矜重须要的,由于假设传入了正确账户,CPI挪用就会退步,但这个反省依然很好的做法。

5.与4一致。

6.反省代币法式账户是否被正确传入。

咱们也许看到,账户反省(正在这个例子中)分为这五类:

- 帐户一切权反省(1,2,4,5)

- 帐户类别反省(1、2、4、5)

- 帐户实例反省 (某一账户类别的正确切例是否被传入)(2,5)

- 账户出面反省 (3)

- 法式账户地方反省 (6)

但正在Move中,没有账户反省或一致的货色,只要功能出面:

mint_balance函数只须要四个参数。正在这四个参数中,只要lock以及cap代表工具(有点一致于账户)。

正在Solana中,咱们须要证实6个账户,并手动完结对于它们的各类反省,而正在Move中,咱们只须要传入2个工具,而且没有须要清爽的反省,这是若何完结的?

正在Move中,这些反省有些是由运行透明地告竣的,有些是由验证器正在编译时静态地告竣的,而有些则是正在组织上根基没有须要的。

账户一切权反省——Move有类别系统,所以这种妄图没有须要。一个Move组织只可经过其模块中定义的函数施行改正,而没有能直接改正。字节码验证保险结束构实例也许自在地流入没有受信赖的代码(其他模块)而没有被作歹改正。

账户类别反省——没有须要,由于Move类别生存于整体智能合约中。类别定义被嵌入到模块二进制文件中(正在区块链上揭晓并由假造机施行)。验证器将反省,编译/揭晓时期,咱们的函数被挪用时,正确的类别是否被传播。

账户实例反省——正在Move中(有时正在Solana上也是如许),你会正在函数主体中做这件事。正在这个惯例中,这是没有须要的,由于锁以及cap参数类别的通用类别参数T逼迫要求对于cap(铸币才略/权力)工具的传入要正确匹配其锁(每个币类别T只可有一个锁)。

帐户出面反省——咱们正在Sui中没有直接处置出面。工具也许由用户拥有。造币权力由造币权力才略工具的一切权授与(由办理员建立)。正在mint_balance函数中传播对于该工具的引用将禁止咱们施行铸币。自有工具只可由其一切者正在买卖中利用。换句话说,工具的出面反省是由运行透明地告竣的。

从本体上讲,Move运用字节码验证,以使数字物业的编程模子尤其当然。Solana的模子缭绕账户一切权、出面、CPI挪用、PDA等。但咱们退一步想一想,就会发明,咱们并没有想处置这些课题。它们与数字物业自己没有一切联系——相反,咱们没有得没有利用它们,由于这使咱们恐怕正在Solana的编程模子中完结所需功能。

正在Solana上,没有字节码验证来保险更细化的类别或资源安全,你没有能禁止一切法式改正一切账户,因而引入账户一切权的概念是须要的。因为一致缘由(没有跨法式挪用的类别/资源安全),也没有也许进出法式的用户一切工具的概念,相反,咱们用账户出面来证实权力。因为有时法式也须要恐怕供给账户出面,因而咱们有PDA......

虽然你也许正在Solana上拥有与Move不异的跨法式类别以及资源安全,但你必需利用庸俗其余构建模块(账户出面、PDA...)手动完结它。归根结底,咱们在用庸俗其余基元来构建可编程的资源(线性类别)。而这便是账户反省的影响——它们是完结类别安全以及手动建模资源需施行的支付。

Move对于资源施行原生的抽象,禁止咱们直接处置资源,而没有须要引入一切庸俗的构建块,如PDA。越过智能合约界限的类别以及资源安全保险是由验证者确保的,没有须要手动完结。

5.3 Solana可配合性的限度性

我想再举一个例子,夸大Solana上智能合约可分解性的一些痛点。

咱们正在铸币权力锁的例子中看到,与Sui比拟,咱们须要正在Solana上证实更多的输入(Solana上的6个账户 vs. Sui上的2个工具的mint_to挪用)。昭彰,处置6个账户比处置2个工具更障碍,稀奇是假设思虑到还须要为账户完结账户反省。外貌上来讲这全体是可控的,但当咱们结束正在简单的挪用中把多个分歧智能合约配合正在一统时会产生甚么?

假定咱们想建立一个智能合约,恐怕做以下办事:

它从铸币权力锁法式中拥有某个代币的铸币权,也许施行铸币

当它被挪用时,它将利用其权力来铸造用户指定数目的代币,利用AMM将其调换为分歧的代币,并正在统一指令中将其发送给用户

这个例子的中心是为阐明铸币权力锁智能合约以及AMM智能合约将若何被配合正在一统。指令挪用的账户反省大概看起来像这样:

17个账户。每个CPI挪用(铸币以及调换)5-6法式,加上法式账户。

正在Sui上,一个异常的函数的出面是这样的:

只要3个工具。

为甚么咱们正在Sui上传播的工具与Solana上的账户比拟要少很多(3比17)?从根基上说,是由于正在Move中咱们恐怕嵌入(包裹)它们。类别系统的安全保险使咱们恐怕做到这一点。

上面是一个Solana账户以及Sui工具之间的较为,它们持有一个AMM池的状态。

咱们也许看到,正在Solana上咱们保存了其他账户的地方(Pubkeys),它们就像指针一律,并没有保存理论的数据。为了拜候这些账户,它们须要被零丁传入,咱们还需手动反省正确的账户是否被传入。正在Move中,咱们恐怕将组织彼此嵌入并直接拜候其值。咱们也许混杂以及匹配来自一切模块的类别,同时它们保全其资源以及类别的安全保险,这都受益于Move的全部类别系统以及资源安全,它们都由字节码验证所启动。

不过,正在组成多个智能合约时,没有得没有传播(并所以反省)许多账户,这形成了异常大的实行繁复性,并拥有安全作用。这些账户之间的联系大概异常错综繁复,正在某种水准上,难以跟踪一切须要的账户反省及其是否正确切施。

本来,这便是我以为正在Cashio马脚中产生的状况(4800万美元)。上面是该(没有充分)账户反省的分化,也由此导致了该马脚。如你所见,这些账户反省变得有些繁复。开垦者充溢好的计划施行正确反省,但正在某某水准上,精神压力变得太大,就会很是轻易堕落。账户越多,越轻易呈现正确。

Move的全部类别系统以及更当然的编程模子,意味着咱们也许正在到达情绪蒙受压力的限度以前,以更大的安全性驱策智能合约的变成。

附带阐明一下,Move的TCB(可托算计根底)要比Rust/Anchor小很多。较小的TCB意味着须要投入智能合约编译施行、被信赖的的组件较少。这就削减了大概作用智能合约的马脚皮相积——TCB之外的马脚没有会作用智能合约的安全。

Move的妄图思虑到了削减TCB——为尽大概削减TCB,Move做了许多确定。字节码验证器将许多由Move编译器施行的反省从TCB中移除,而正在Rust/Anchor中,有更多的组件须要被信赖,所以致命安全正确的皮相积要更大。

6. Solana上的Move

咱们可否正在Solana上拥有Move,和若何拥有?

6.1. 有全部类别安全的Anchor?

正在咱们结束争论以前,让咱们简捷看看Anchor,并做个小的思维测验。只怕咱们也许以某种办法进级Anchor,来供给咱们从Move中失去的一些优点?只怕咱们也许取得对于跨法式挪用的类别安全的要地支柱?到底,Anchor指令一经一致于Move的出口函数:

只怕咱们也许蔓延Anchor,使账户能直接被传入指令参数。

咱们也许避免账户反省?

正在这种状况下,咱们指望类别反省由运行而没有是法式来告竣——运行将读取Anchor账户判别器(或其等价物),并恐怕反省账户传入是否契合所需的判别器(Anchor账户的前8个字节)。

Solana错误统一法式的分歧指令挪用施行识别,这是由法式手动完结的(正在这种状况下,深厚的处事由Anchor告竣)。所以,为了做到这一点,运行必需以某种办法领会分歧指令、它们的出面、类别信息。

Solana法式编译为SBF(Solana Bytecode Format,eBPF的一种变体),并以这种办法上传到链上(以及施行)。SBF自己并没有嵌入一切也许帮忙咱们的类别或函数信息。但只怕咱们也许改动SBF,以禁止指令以及类别信息被嵌入二进制文件中?这样所需的指令以及出面信息就也许由运行从二进制文件中读取。

咱们确切也许这样做。这将要求异常大的工程量,稀奇是思虑到咱们须要维持与旧法式的向后兼容,但这是咱们能取得的优点:

-账户一切权以及类别反省由运行而没有是法式告竣

-对付正在编译时已知地方的账户(比如法式账户),咱们也许避免从客户端传入它们,而今也许由运行传入。

-假设咱们设法将账户制约嵌入到二进制文件中,咱们也许进一步削减必需由客户端传入的账户数目,用运行对于其施行动静递归正在加载(基于嵌入的制约信息)。

咱们仍然没有失去:

-嵌入的账户。咱们仍然必需利用Pubkeys来引用其他账户,而没有恐怕直接嵌入它们。这意味着咱们没有脱节第5.3节中形容的账户肥胖的课题。

-当施行跨法式挪用时,账户类别反省仍然须要正在运行时动静施行,而没有是像Move中那样正在编译时静态施行。

留神:这仅仅一个思维测验。并没有阐明其也许安全告竣,也没有是代表本来现容易,更没有标榜这些优点值得支出工程量般的尽力。

这些优点确切没有错,但从智能合约开垦的角度来看,它们并没有从根基上改革甚么。正在运行时而没有是法式中做类别反省大概能带来一些机能上的优点,而且没有必正在编译时从客户端手动传播地方账户,正在特定水准上选拔功效(这也也许经过器械化来减缓)。但咱们最终仍然正在处置Solana的编程模子,它自己正在处置数字物业上供给更多帮忙——咱们仍然没有原生的资源安全,咱们没有能嵌入账户,因而仍然有账户伸展课题,咱们仍然正在处置账户出面以及PDA......

巴望状况下,咱们指望一切的智能合约都糊口正在一个简单的类别系统中,并且恐怕像Move那样自在地将工具传入传出。但因为其他智能合约没有能被信赖,咱们没有能直接这样做。为了绕过这一点,Solana设有法式结合以及账户一切权——每个法式办理自身的账户,它们经过CPI挪用施行互动。这很安全,并禁止渊博的可编程性,但由此孕育的编程模子并没有巴望——没有全部类别系统,也就没有有本性意思的资源安全。

咱们指望有一个当然的编程模子,但与此同时,咱们也正在处置没有受信赖的代码。虽然正在Solana上咱们也许安全地处置没有受信代码,但正在编程模子上上做出和解。字节码验证使咱们有大概同时拥有二者。没有它,咱们犹如真的没法改善编程模子。

6.2 Solana字节码花样

如前所述,SBF(Solana字节码花样),即Solana智能合约的编译以及链上保存花样,是基于eBPF的。正在Solana上利用eBPF而没有是一切其他字节码花样(如WASM),主假如由于Solana对于安全以及高机能智能合约施行的要求,与eBPF妄图的内核沙盒法式施行要求统一(它也须要安全以及高机能)

从皮相上看,eBPF确切是一个切实的挑选。高机能、缭绕安全妄图,法式的巨细以及指令的数目是有限的,有一个字节码验证器......看起来很有没有错。

但让咱们看看这正在尝试满意味着甚么。只怕咱们也许以某种办法运用eBPF验证器来进步咱们智能合约的安全性?以下是eBPF验证器所做的一些办事:

-没有禁止无限轮回

-反省法式是否是一个DAG(有向无环图)

-没有禁止越界跳转(out-of-bounds jump)

-正在施行各类协助(helper)函数挪用时反省参数类别(协助函数正在内核中施行定义,比如用于改动收集数据包)。

好吧,允许越界跳转犹如很实用,但其他影响有限。真相上,逼迫要求法式必需是一个DAG并且没有无限轮回是有课题的,由于它大大限制了法式的可操作性(咱们没有图灵齐备性)。正在eBPF法式中须要这样做的缘由是,验证器须要决定法式正在特定数目的指令内停止(这样法式就没有会使内核停止;这便是有名的停机课题),而气鼓鼓体计量(gas metering)没有是一个选项,由于它将太甚作用机能。

虽然这种选择对于完结高机能的防火墙来讲是很好的,但对付智能合约的开垦来讲就没有那么好了。eBPF验证器的绝大全体都没有能被重用正在Solana法式上。真相上,Solana根基就没有利用原始的eBPF验证器,它利用的是一个(更根底的)自定义验证器,主假如反省指令是否正确以及是否有越界跳转。

同时,eBPF正在妄图上至多禁止5个参数被传播给一个函数施行挪用。这意味着Rust规范库没有能直接编译到eBPF。或栈的巨细被限制正在512字节,这削减了咱们也许传播给一个函数的参数的巨细而没有须要堆分配(heap allocation)。

所以,即使Rust编译到LLVM,有LLVM的eBPF后端,以至支柱Rust编译器针对于eBPF利用,你仍然没法使Solana智能合约以其原本的式样编译到eBPF上。这便是为甚么Solana团队没有得错误Rust代码库以及eBPF LLVM后端(比如,经过栈传播参数)施行屡次改动。

因为个中一些改动自己是支柱上游(不管是Rust依然LLVM),因而Solana团队今朝正在维护Rust以及LLVM的分叉时都做了这些改动。当你施行cargo build-bpf(构建Solana智能合约的规范敕令)时,Cargo会拉出这个Solana一定版本的rustc(Rust编程语言的编译器)来施行智能合约的编译(原本的rustc没有起影响)。

这便是SBF的出生历程——Solana须要的一些要求与eBPF没有兼容。Solana团队今朝在尽力将SBF算作一个独立的LLVM后端下流,并将其算作一个Rust目的参加,以避免维护零丁分叉。

所以,虽然eBPF也许算作智能合约的一种花样,但它并没有像表上看起来那么巴望。它须要施行一些改动,而且原本的验证器也没有很大的好处。

正在对于Move以及Solana/SBF的议论中,一个曲解便是,一些人以为Move的主要思维应该合用于SBF,由于它是基于eBPF的,只怕也许运用其验证器做静态的账户改正反省,而没有是正在运行时做动静反省。

正在我可见,这是一个令人猜疑的说法。即使有大概证实,法式没有会正在eBPF中改正他们没有拥有的账户,这也确切是Move正在做的办事,但这一定没有是Move的主要设法。

Move的主要思维是发觉一个以资源为焦点的编程模子,恐怕当然地与弗成信代码互动。

正在尝试中,这意味着:

- 全部类别安全

- 资源安全(键、克隆、保存、丢弃)

- 可嵌入的资源

- 资源安全地流入以及流出没有受信赖的代码

...

将主要的Move思维引入eBPF/SBF很是难。假设错误eBPF施行远大改动,逼迫施行一些个性例如“这个没有受信赖的代码没有能丢弃一个T”是弗成能的。这须要大度改动,及至于你最终会失去一个新的字节码,它看起来更像Move而没有是eBPF。

真相上,一致的思路是导致Move出生的主要缘由。Move团队(其时正在Diem)最初思虑从其他花样归来,如WASM、JVM或CLR,但过后推广这个简直是太难了——线性/才略利害通例的。因而Move是重新结束妄图的,其设法是经过轻量级的验证器通道来无效施行这些反省。

假设你提防想想,这本来并没有令人惊奇。到底最终,智能合约编程没有是系统编程,后端编程,或一切一种其他传统编程,它是一种全面分歧的编程类别。因而现有字节码以及指令花样的功能没有能被运用也就没有足为奇了,由于它们正在妄图时思虑的是全面分歧的利用状况。

我没有是正在挑剔Solana利用eBPF。真相上,我以为这是一个很是切实的挑选,也是团队思虑到背景的优秀判别。过后来看,团队大概会挑选WASM而没有是eBPF,这样就也许避免前方提到的将智能合约编译成eBPF的课题,由于WASM正在Rust中有一流的支柱(没有过WASM大概会有其他课题),但也许看到,思虑到对于机能的夸大,团队大概感慨eBPF是一个更安全的挑选。其它,正在做出这些妄图挑选的时分,Move以至还没有施行发布,对付一个首创公司来讲,重新结束建立一种新语言一定没有是一个正当的挑选。最终,Solana设法供给了一个乐成的高机能L1,这才是最主要的。

有三种方式也许正在Solana上取得Move:

- 将Move假造机算作一个要地加载器推广(与SBF假造机一统)

- 将Move假造机算作一个法式运行(如Neon)

- 将Move编译为SBF(像Solang)

让咱们先来议论(3)。这边的设法是为Move建立一个LLVM前端,以便将其编译为SBF。编译成SBF的Move智能合约被透明地施行,就像用Rust(或其他一切也许编译成SBF的语言)构建的智能合约一律,而且运行时没有须要对于Move有一切识别或领会。从运行角度来看,这将是一个很是温存的束缚规划,由于它没有须要改革它或它的安全假定。

智能合约有几种类型的合约 (智能合约是指什么)

但我以为以这种办法开垦智能合聚会比直接利用Anchor更糟。你经过(3)失去的是Solana编程模子中的Move语法。这意味着第五章中议论的Move的一切主要劣势(全部类别安全、全部资源安全、可嵌入工具......)将没有复生存。相反,咱们仍将没有得没有处置账户反省、CPI挪用、PDA等课题,就像正在Rust中一律。而且,因为Move没有支柱宏(macro),所以利用eDSL完结一个像Anchor这样的框架,来简化个中的一些处事是弗成能的,因而代码将与原始Rust如同(但大概更糟了)。Rust规范库以及生态系统也是弗成用的,因而像账户序列化以及反序列化这样的办事必需正在Move中从新完结。

Move没有是很顺应与其他编程模子一统利用。这是由于它被稀奇妄图为恐怕编译成Move字节码,并经过验证器。思虑到缭绕才略以及假贷反省器的自定义法则,这是须要的。其字节码验证十分寻常全部,及至于其他语言多少乎没有机缘编译成Move字节码并经过验证器。由于Move缭绕这种很是寻常的字节码验证而设,因而它没有像Rust等语言那样精巧。

剥离字节码就摒弃了Move的一切主要劣势。虽然Move的类别、资源以及内存安全个性会正在法式级别上被保全,但它们没有会被全部保全。而法式级的安全并没有带来几许新的了局——经过Rust咱们一经完结了这些了局。

Move的智能合约生态系统也没有能正在Solana上利用——编程模子分歧,及至于智能合约的主要全体必需被誊写。思虑到一切这些,我瞻望用(3)完结Move的做法没有会被采用。

至于(1),这边的设法是(与SBF加载器一统)正在运行时推广对于Move加载器的支柱。Move智能合约将被保存为链上的Move字节码,并由Move VM施行(就像正在Sui中一律)。这意味着咱们将有一个SBF智能合约的生态系统以及一个Move智能合约的生态系统,前者将正在现在的Solana编程模子上运行,嗣后者则正在一个(也许说是更高等的)Move模子上运行。

有了这种方式,就有大概维持Move智能合约之间彼此影响的一切优点,但这边的一个寻衅是让Move智能合约恐怕与SBF智能合约施行互动,反之亦然——你须要一个对于Move以及Solana有粗浅领会的人,验证器也必需施行保养。

还有一个误差是须要正在运行时维护两个分歧的加载器。这会对于安全有作用,由于它意味着打击面会翻倍——一切一个加载器的正确均可能意味着整体链被运用。理论上早正在2019年,Solana就参加了对于MoveVM的早期支柱(#5150),但以后因为安全课题而被移除(#11184)。

至于(2),设法是将整体Move VM算作一个Solana法式(智能合约)运行。Move VM是用Rust完结的,因而大概会把它编译成SBF(除非它利用线程或其他没有支柱的API)。虽然这听起来很猖狂,但Neon一经完结了一致的方式,将EVM算作一个Solana法式来运行。这种方式的优点是,没有须要对于运上进行改动,而且也许维持不异的安全假定。

我没有纯熟Move VM的本领细节,因而我没有能对于这种做法的可行性和它的限度性做太多指摘。我的第一个反应是,验证器也必需算作一个法式运行,这意味着正在算计估算内。这种方式也会像(1)一律,受到SBF以及Move智能合约之间互操作性课题的作用。

没有直接的方式也许将Move的主要功能带到Solana。虽然有大概建立一个LLVM前端,并将Move编译为SBF,但这没有会起太多影响,由于编程模子将维持没有变。正如第6.1节中的思维测验所阐明的那样,假设没有某种字节码验证,就没法改善编程模子。改革eBPF/SBF以支柱字节码验证将利害常容易的。犹如仅有正当的挑选便是以某种办法让MoveVM运行。但这意味着将有两个生态系统正在分歧的编程模子上运行,而让它们正确地互操作是极具寻衅性。

6.4. Move的机能

Move的字节码没有是一种通用的字节码语言。它有一个很是有“主张”的类别系统,为禁止一切须要验证,它是异常高等的。这意味着与其他字节码花样(如eBPF/SBF)比拟,其机能较低,由于后者更凑近于要地代码,人们大概会以为这对付其正在高机能L1中的利用是一个课题。

不过,到今朝为止,智能合约的施行正在Solana(正在写这篇文章的时分,平衡有3k TPS)以及Sui(基于团队所做的最初e2e基准)上都还未成为瓶颈。进步买卖处置机能的主要办法便是并行施行。Solana以及Sui都完结了这一点,它们要求事先证实依附联系,并对于依附分歧工具/账户集的事情施行施行并行调剂。

其余,一旦TX施行呈现正在枢纽途径上,没有一切货色也许制止Move被AOT编译或JIT化以进步机能。这便是为Move构建一个LLVM前真个优点住址。其它,因为Move自己对于静态分解的符合性,Move也大概博得特有的进一步优化。

思虑到一切这些,我指望Move的机能正在可猜测的他日没有会成为一个主要的闭塞。

7. Move其他功能

7.1. 验证器

Move有一个用于智能合约的大局化验证器械,叫做Move Prover。经过这个器械,你恐怕判别分歧的没有变量对于你的智能合约是否创制。正在幕后,验证条件被翻译成SMT公式,然后利用SMT求解器施行反省。这与迷糊测试有很大分歧,比如,迷糊测试是经过走查输入空间来试错。比如,假设迷糊测试以及单元/集成测试未能测试出一定的输入或输入配合,再现法式有误,那么它们仍然也许供给一个假阴性。另一方面,验证器本体上供给了大局上的证实,即指定的没有变量对于所供给的法式创制。这就像针对于一切大概的输入反省法式一律,但没有须要这样做。

迁徙验证器的速率很是快,使它也许像类别反省器或linter那样被整合到通例开垦处事过程中。

上面是一个验证器的例子(摘自《用Move Prover对于智能合约施行加紧切实的大局验证白皮书》)。

7.2. 钱包安全

因为Sui要求一切买卖将拜候的工具都正在函数参数中传播(没有从全部状态中动静加载),并且迁徙函数出面连同类别信息都保存正在字节码自己中,咱们也许让钱包正在用户出面以前向用户供给更成心义的信息,阐明买卖的实质。

比如,假设咱们有一个拥有以下出面的函数:

咱们也许从函数的出面中看出,这个买卖将拜候用户的3个物业(物业类别)。没有仅如许,根据&以及&mut枢纽字(或没相关键字),咱们还也许分解物业1也许被读取,物业2也许被改正(但没有能转化或袪除),而物业3有大概被改正、转化或袪除。

钱包也许向用户再现这些信息,然后用户也许尤其领会买卖大概对于物业做出甚么动作。假设有甚么同样,比如,来自Web3利用法式的买卖挪用在战斗一些没有招待触的物业或币,用户也许查看到这一点,确定没有连续施行买卖。

本文地址:http://yz.ziyouea.com/p/31039.html
版权声明:本站文章来自网络,如有违规侵权请联系我们下架。