Parity 官方博客:什么是 ink! 智能合约语言?
加入 PolkaWorld 社区,共建 Web 3.0!
ink! 是一种智能合约的编程语言,也是使用 Substrate 框架构建区块链的时候可以选择的几种编程语言之一。这是我们在 Parity 通过扩展主流编程语言 Rust 时,所构建的一种自用的语言,这个语言具有与智能合约兼容所需的功能。
感谢大家帮助 ink! 超过 1,000 个 GitHub 星星!
ink! 库(http://github.com/paritytech/ink)最近在 GitHub 上超过了 1000 颗星。它现在是 GitHub 上排名第三的 Parity 存储库,仅次于 Substrate 和 Polkadot。我们想说一声 “谢谢 !” 感谢所有为实现这一目标做出贡献的人!在过去的几年里,我们看到了各种形式的贡献,才使 ink! 达到了今天的成绩。感谢大家使用 ink! 编写合约,为我们提供了良好和建设性的反馈,也感谢大家回答 Substrate StackExchange 上的有关问题,为 ink! 创建第三方工具,还发布了很多有关 ink! 的文章,并举办研讨会!
在过去的几年里,ink! 发生了很多事情。ink! 的第一次提交是在 2018 年 12 月,我们当前的版本是 v3.3.1。我们正在努力尽快推出 v4.0 的下一个主要迭代。经常出现的一个建议是,我们从未写过一篇文章从头到尾解释什么 ink! 以及它如何与 Substrate 和 Polkadot 联系在一起。因此,这次是一个很好的机会来向大家解释什么是 ink!。
ink! 与 Substrate 有什么关系?
在我们谈论 ink! 之前,我们首先需要明确 Substrate 和它的合约模块(pallet-contracts)是什么。Substrate 是一个构建区块链的框架,它可以构建独立的区块链,也可以是连接到 Kusama 或 Polkadot 的区块链,即所谓的平行链。Substrate 包含许多模块,在 Substrate 术语中称为 pallets。Substrate 本身自带一组模块,可满足现代区块链通常具有的许多功能 —— 质押、可替代 tokens、不可替代 tokens、治理等。
Substrate 还附带了一个名为 Contracts pallet 的智能合约模块。如果使用 Substrate 开发平行链,它可以通过添加此模块轻松添加智能合约功能。
那 ink! 怎么在这里发挥作用?ink! 是一种编程语言,具体来说,它是主流 Rust 编程语言的嵌入式的特定领域语言 (eDSL)。这意味着你可以使用所有正常的 Rust 语法以及我们添加的一些细节,以使该语言适用于智能合约世界。合约模块需要这些 ink! 合约并以安全的方式执行。简而言之:
“使用 ink!,你可以为包含合约模块的 Substrate 链用 Rust 编写智能合约。
智能合约 vs 平行链
当有人了解 Substrate、Polkadot 或 Kusama 时,我们通常会遇到的第一个问题是何时开发平行链与何时开发智能合约。
这里的区别在于,在 Polkadot 和 Kusama 的背景下,平行链租用一个插槽几个月,最长可达两年。插槽租赁是平行链获得一个固定的插槽来执行其业务逻辑(通常称为状态转换功能),并且可以将其修改后的状态保存在一个块中。在 Substrate 术语中,此状态转换函数称为链的运行时(runtime)。
这里与其他生态系统的区别在于,在 Polkadot 的背景下,平行链和智能合约存在于堆栈的不同层:智能合约位于平行链之上。平行链通常被描述为 Layer1 区块链 —— 除了它们不必建立自己的安全性,并且是可升级和可互操作的。
值得注意的是,平行链的状态转换功能没有得到进一步验证 —— 这取决于平行链如何利用其插槽时间。一旦平行链通过绑定代币(或通过 crowdloan 从社区收集)来赢得一个插槽,该插槽基本上是预付费的,执行链的业务逻辑不需要额外费用。这意味着平行链可以建立自己的(区块链)世界!例如,它可以决定如何收取交易费用,甚至是否收取交易费用。在构建新的或更用户友好的业务模型时,这些选项至关重要。
我们在真实环境中观察到的平行链之间的其他区别因素是链的治理或加密经济学如何运作的差异。但是,平行链如何构建其世界存在一些限制。就像现实世界中的物理学一样,它必须遵守某些基本规则。对于 Polkadot 和 Kusama,例如中继链与平行链通信的共识算法。从这些基本规则中可以看出 Polkadot 和 Kusama 的优势。诸如上述共享安全性、跨链通信或保证执行的 slot 时间等优点。
另一方面,对于智能合约,现有的平行链必须包含合约模块来供用户部署智能合约。部署的智能合约始终是不受信任的代码。拥有链上代币的任何人(或任何程序)都可以在不需要许可的情况下上传智能合约。智能合约允许在区块链上无权部署不受信任的程序。合约模块必须假设这些程序是对抗性的,它必须放置一些安全支柱以确保合约不能使链停滞或导致其他合约的状态出现问题。对于合约模块,这些安全支柱包括诸如 gas 计量或用于在链上存储数据的存款等机制。
“重申这一重要区别:开发平行链 runtime 不同于开发智能合约 —— 智能合约部署在平行链之上。可以权衡的是平行链可以(几乎)自由决定构成平行链的所有规则。有了智能合约,就会受到链所允许的内容和必须到位的安全支柱的限制。
另一方面,智能合约在开发和部署方面的摩擦较小。开发人员不必考虑治理、加密经济学等。一个人只需要几个代币,就可以愉快的部署智能合约。就这么简单。
合约模块如何运行?
我们特意设计了合约模块(Contracts pallet),使其与用于编写智能合约的语言分离。这个 pallet 只是执行环境,它以 WebAssembly 文件作为输入。这个 pallet 的智能合约必须编译为 WebAssembly (Wasm) 目标架构。
对于合约开发者来说,这意味着他们可以使用 ink! 编写智能合约,但也可以使用其他语言。目前存在三种可供选择的语言:
用于 Rust 的 ink! 用于 AssemblyScript 的 ask! 用于 Solidity 的 Solang 编译器 添加新语言并不难。只需要一个用于 WebAssembly 的语言的编译器,然后就可以实现 Contracts 模块 API。目前,该 API 包含大约 15-20 个功能,可用于智能合约可能需要的任何功能:存储访问、加密功能、环境信息(如区块号)、访问获取随机数或自行终止合约的功能等。不是所有这些都必须用语言来实现 —— ink! 的 “ Hello, World! ” 只需要六个 API 函数。以下架构描述了这种关系:
我们认为这种设计比其他竞争生态系统中的一些架构更具前瞻性。语言和执行环境之间没有紧密耦合。WebAssembly 是一种行业标准,现在可以将多种编程语言编译为 WebAssembly。如果在十年后,研究人员提出了一种用于编写智能合约(或现有语言的子集)的创新语言,那么只要有一个 WebAssembly 编译器,就很容易使这种语言与合约模块兼容。
为什么要在平行链上添加合约模块?
在平行链上添加智能合约功能有几个用例。我们分享三个大的用例:
用例 1:智能合约作为“一等公民”
最明显的用例是将智能合约作为“一等公民”的平行链,这意味着智能合约是该链的核心价值主张。
这些链通常采用现成的合约模块,并在其上创造一些额外的创新。这方面的例子有:
Astar:在合约模块上构建了一个 layer,以便合约开发者在使用合约时可以赚取被动收入。
Phala:在受信任的执行环境中使用合约模块,实现隐私的智能合约执行和互操作性。
Aleph Zero:在零知识语境中使用合约模块。
t3rn:使用合约模块作为构建块,为智能合约启用多链执行。
用例 2:智能合约作为“二等公民”
合约模块还有另一个不那么明显的用例:将智能合约作为现有链上的“二等公民”。意思是,链的核心价值主张与智能合约无关,但仍然将它们作为附加组件包含在内。
我们提供了一个 API(称为链扩展),平行链可以通过它向智能合约开发人员公开其业务逻辑的某些部分。通过这个,智能合约开发人员可以利用链的业务逻辑原语在其之上构建新的应用程序。以去中心化交易区块链为例。这条链最简单的形式将有一个订单簿来进行投标和询价 —— 不需要从外部获取不受信任的、图灵完备的程序。不过,平行链可以决定将订单簿公开到智能合约中,让外部开发人员可以选择构建使用订单簿的新应用程序。例如,将交易算法作为智能合约上传到链上。
这里的智能合约是一个帮助提高用户参与度的机会。使用已经内置在模块中的计费 —— 用户必须为执行他们的智能合约支付 gas 费用。
用例 3:将智能合约作为进入 Polkadot 或 Kusama 的第一步
合约模块的第三个大用例是在租用 Polkadot 或 Kusama 上的专用平行链插槽之前,将一个想法原型化为概念验证智能合约。
开发和部署智能合约的时间比平行链要短。可以先部署一个概念验证智能合约,看看它是否能获得关注,这个想法是否适用于现实世界。随后,一旦需要,例如更便宜的交易费用、更高效的执行或社区的治理机制的时候,智能合约可以迁移到具有自己插槽的专用平行链 runtime 上。ink! 合约和 Substrate runtime 都是用 Rust 编写的,并且共享相似的原语,这为项目从智能合约升级到自己的 runtime 提供了一条清晰的路径。开发人员可以重复使用大部分代码、测试以及前端和客户端代码。
一个简单的 ink! 智能合约
ink! 其实就是 Rust,这是我们的首要目标。我们的目标是影响最小化,让开发者能够使用 “正常” Rust 所用的东西 —— IDE、 cargo fmt
、 cargo clipy
、 代码片段、crates.io 生态等。
在下图中,你可以看到一个简单的 ink! 合约。这里的合约在其存储中保存了一个布尔值。创建合约后,它将布尔值设置为 true
。该合约公开了两个函数,一个读取布尔值的当前值 (fn get()
) ,另一个将值切换到相反的布尔值 (fn flip()
)。
彩色的几行是代码中的 ink! 专用注释,其余的是普通的 Rust 语法。这些注释抽象出为了让程序兼容以在链上执行所需要的后台操作。对于我们当前的 3.3.1 版本,单元和集成测试也可以像在 “普通” Rust 中一样编写:
#[ink::test]
fn default_works() {
let flipper = Flipper::default();
assert_eq!(flipper.get(), false);
}
此处的 #[ink::test]
注释具有在模拟区块链环境中执行此测试的效果。这让开发者能够模拟例如传输到合约的值、执行合约的调用者、区块编号等。例如,你可以使用 #\[ink::test\]
中的 ink_env::test::set_value_transferred
来模拟发送到一个合约的值(即 token)。你可以再我们的 crate 文档中查看 ink_env
函数的完整列表:https://docs.rs/ink_env/3.3.1/ink_env/。
cargo-contract —— ink! 合约的瑞士军刀
构建 ink! 智能合约,你可以直接使用构建 Rust 程序所用的正常 cargo build
工作流程。不过,你必须为命令添加一些参数才能使其在链上工作。我们创建了一个已经为你选择最佳标志集的工具:cargo-contract
。这是一个映射了 cargo
的命令行工具,你可以把它想象成一把 ink! 智能合约的瑞士军刀,它除了建立合约之外还可以做更多事情,我们稍后再讨论。
构建合约时,你可以使用 cargo contract build
。请注意,典型的 Rust cargo build
操作中,如果你想要尽可能小的二进制文件大小,你需要提供 --release
,与 cargo contract build --release
相同。如果你运行这个命令,你会看到 cargo-contract
在你的合约上执行 “正常的” cargo build
,但它也做了一些更多的步骤。三个最重要的附加步骤是:
它会为 ink! 合约运行一个 linter。这个 linter 的工作方式类似于 Rust 的
clippy
,它会检查你的合约的 ink! 语法使用情况。我们正在不断改进这个监测工具,未来将增加对常见安全缺陷的监测。它对合约的二进制文件进行后期处理和压缩。这样做是为了降低用户部署合约的成本,以及用户与合约交互的费用。合约大小还与链可以实现的吞吐量相关,并有助于链足迹。
它为合约生成元数据(metadata)。元数据一词是指与合约二进制文件交互所需的任何信息。二进制文件本身将只是一个 WebAssembly blob——合约的字节码,没有更多信息就无法与之交互。例如,为了知道合约公开了哪些函数以及这些函数需要哪些参数,需要拥有元数据。你可能还从其他区块链的术语 ABI 中了解这个概念。在我们这里,元数据包含的不仅仅是 ABI,它还包含一些信息,例如合约如何存储其数据,这有助于链下工具(例如区块浏览器)或关于合约功能的人类可读文档。执行
cargo contract build
后,会创建三个文件:my_contract.contract
: 一个 JSON 文件,其中包含以十六进制编码的合约的 WebAssembly blob 以及合约的元数据。metadata.json
: 一个仅包含合约元数据的 JSON 文件,不含 WebAssembly blob。my_contract.wasm
: 合约的 WebAssembly blob。每个文件有不同的使用场景:
WebAssembly 是唯一实际存储在链上的文件。应该仅对严格需要上链的数据进行链上数据存储。任何在链上不必要的东西仍然会给用户带来成本并增加链上的足迹。元数据不必存在链上,dapp 或前端可以包含硬编码的元数据,以确定如何与合约交互。
仅当你正在开发智能合约时才需要 *.contract
包,然后你可以将此文件与开发者 UI 一起使用。开发者 UI 让你能够部署合约、与它们交互以及调试它们。
开发环境
许多平行链已经开发了定制工具,在他们使用 Contract pallet 和 ink! 的上下文时提供了更加符合上下文的角度。我们在本文开头提到了其中一些团队。有关更多信息,请参阅我们的 awesome-ink
存储库。
我们作为开发 ink! 和 Contracts pallet 的团队,也提供了一些方便的工具:
substrate-contracts-node
这个存储库包含了 Substrate 的node-template
配置为包含pallet-contracts
。该节点跟踪 Substrate 的master
分支,并且已经过修改以使其非常适合开发和测试。例如,它没有任何固定的出块时间,一切都立即处理。这是以让节点不适合生产使用为代价的,但非常适合脚本、测试或持续集成(CI)环境。如果你在找生产环境模板,请查看 Substrate 的node
或者 Substrate 文档中关于如何增加pallets-contracts
的指南:https://docs.substrate.io/reference/how-to-guides/pallet-design/add-contracts-pallet/。我们在 Rococo 上维护了一个名为 Contracts
的测试网。Rococo 是 Polkadot 和 Kusama 的测试网。许多平行链通过自己的测试网连接到 Rococo。你可以在我们的文档中阅读关于如何在我们的测试网上部署的更多信息:https://ink.substrate.io/testnet。还有一些社区测试网,你可以在我们的awesome-ink
存储库中找到。
开发者 UI 目前有三种选择:
Contracts UI: 适合初学者,会提供有用的提示并协助开发者。 polkadot.js: 高级界面,牺牲了一些用户友好度,为开发者提供了灵活性。 ink! playground: 一个在浏览器中尝试 ink! 或者共享指向代码片段的永久连接的 Playground。如果你在 Substrate StackExchange 上提问的话,一个非常方便的用途是:你可以分享代码,例如描述你面临的问题并附上代码。 cargo-contract
: 如果你希望从命令行部署合约、调用它们、解码它们的输出等,那么此工具提供了一个方便的选项,可以从命令行界面完成所有这些操作。该工具也非常适合脚本或 CI 集成。
为什么在 Substrate Ethereum 兼容层上选择这条路线?
除了合约模块,Substrate 中另外两个流行的智能合约选项是pallet-``evm
和 Frontier(https://paritytech.github.io/frontier/)。两者都是 Substrate 的以太坊兼容层。
选择 ink! 和 EVM 上的合约模块有很多好处。总结一下本文中详细介绍的一些内容:
ink! 就是 Rust:你可以使用所有普通的 Rust 工具 ‒ clippy、crates.io、IDE 等。 Rust 是一种融合了多年语言研究的语言,它安全且快速。最重要的是,我们从较旧的智能合约语言(如 Solidity)中学到了重要知识,并将它们融入到了 ink! 语言设计中。我们选择了更明智的默认行为,例如默认禁用重入或默认将函数设为私有。 Rust 是一种令人惊叹的语言,它在 StackOverflow 上连续七年被评为最受欢迎的编程语言(来源:https://survey.stackoverflow.co/2022/)。 如果你是一家公司并希望聘请智能合约开发人员,你可以从 Rust 生态系统中招聘,该生态系统比小众市场,比如 Solidity 开发人员,要大得多。 ink! 是 Substrate 原生的,我们使用类似的原语,就像相同类型的系统。 从合约到平行链有一条明确的迁移路径。因为 ink! 和 Substrate 都是 Rust,开发人员可以重复使用大部分代码、测试以及前端和客户端代码。 WebAssembly 是一个行业标准,它不仅仅用于区块链世界。谷歌、苹果、微软、Mozilla 和 Facebook 等大公司不断改进它。未来,我们将受益于该标准及其实施的所有改进。这是一件大事。WebAssembly 主要用于 Web,其要求与区块链相似 —— 安全且快速。 WebAssembly 扩展了智能合约开发人员可用的语言系列,包括 Rust、C/C++、C#、Typescript、Haxe、Kotlin 等。这意味着你可以使用你熟悉的任何语言编写智能合约。我们认为这种设计比紧密耦合的语言和执行架构更具前瞻性。我们支持与旧版 Solidity 代码库的互操作性:HyperLedger 项目的 Solang 为合约模块编译了 Solidity。
了解更多
我们的文档可以在 ink.substrate.io 上找到,它包含了关于 ink! 的最全面的信息! 因为 ink! 只是 Rust,你也可以查看 crate 文档。我们在这里的自述文件中链接了相关的 crate 文档,例如数据结构的 crate 文档。https://github.com/paritytech/ink#developer-documentation 我们的存储库中有许多合约示例。这些涵盖了广泛的典型用例:ERC-20、可升级合约等。https://github.com/paritytech/ink/tree/master/examples 如果你正在寻找快速入门,ink! 的初学者指导教程是一个很好的开始。https://docs.substrate.io/tutorials/smart-contracts/ 如果你对 ink! 的内部工作原理感兴趣,我们会在 ARCHITECTURE.md 文件中解释这些内容。 对于合约模块,可以查看 README.md 文档。
接下来
我们写这篇文章的目的是想整体介绍什么是 ink!。ink! 的下一个重要步骤是 v4.0.0 —— 我们已经发布了 alpha 版本的下一个主要迭代。此版本将对合约规模、开发人员体验和原生端到端测试进行重大改进。除此之外,许多平行链团队即将在 Kusama 或 Polkadot 上推出合约模块和 ink!。这些事会很有趣,我们非常期待下一个 1000 颗星星。
如果你有任何问题,请随时与我们联系。最好的方法是在 Substrate StackExchange(https://substrate.stackexchange.com/questions/tagged/ink?tab=Votes)上或通过 https://info.polkadot.network/contact 联系我们。如果你已经在构建,请在相关存储库中打开一个 issue。
想在 Polkadot 上进行创建吗?在这里联系我们。https://info.polkadot.network/contact
原文链接:https://www.parity.io/blog/what-is-paritys-ink
翻译:PolkaWorld 社区
活动预告
9 月 28 日 19:00,PolkaWorld 将在线上举办 9 月份的 Polkadot 社区聚会。这次我们将邀请 7 位生态创建者和平行链,来分享关于 Polkadot 和他们各自的生态的最新进展。感兴趣的朋友赶紧关注起来啦!
关注「波卡世界」视频号,或点击下方 “预约” 按钮,你将在开播的时候收到提醒!
PolkaWorld Telegram 群:
t.me/polkaworld
PolkaWorld Youtube 频道:
https://www.youtube.com/c/PolkaWorld
PolkaWorld Twitter:
@polkaworld_org
更多内容
正在竞拍波卡平行链的项目:OAK、Crust 和 OmniBTC
波卡周报丨Tether 在 Polkadot 上推出!Astar 与 Moonbeam 的跨链转账已全面启用!
波卡 9 月社区聚会报名中!了解 6 大生态项目最新进展及应用场景!
关注 PolkaWorld
发现 Web 3.0 时代新机遇
点个 “在看” 再走吧