实验环境:
- Ubuntu20.04
- Europa https://github.com/patractlabs/europa
- ink!https://github.com/paritytech/ink
- polkadot explorer https://polkadot.js.org/apps/#/explorer
- rust 开发环境。因为开发过程中会遇到rust的环境,可以根据这块的引导实现配置 https://docs.substrate.io/v3/getting-started/installation/
这篇博文主要是介绍部署ink!合约的一些流程,以及入坑的一些前提准备。
ink! 合约简介
简介
ink! 是构建在Substrate框架上的区块链智能合约。ink! 合约会被编译为 WebAssembly。它有着和传统 solidity 类似的逻辑,你也可以简单的把它理解为 Rust 版本的 Solidity。
WASM简介
ink!合约最大的特点就是它会编译为WebAssembly。至于为什么要选用WASM虚拟机来代替传统的EVM虚拟机并不在这篇文章的讨论范围内,感兴趣的可以移步这里。 WebAssembly 就是运行在 Web 平台上的 Assembly。 Assembly 是指汇编代码,是直接操作 CPU 的指令代码,比如 x86 指令集上的汇编代码有指令集、寄存器、栈等等设计,CPU 根据汇编代码的指导进行运算。汇编代码相当于 CPU 执行的机器码能够转换成的人类适合读的一种语言。一个典型的编译执行链路是 Cpp、Rust 等编译型语言编译成汇编指令,再转换成二进制机器码由 CPU 读取。
通过 Europa 启动一个合约编译沙盒环境
用于运行和调试智能合约的 沙箱,以及用于 Substrate runtime 的沙箱框架。
我们可以通过 Europa 部署一个专门用来 部署和调试合约的沙盒环境。在关于合约调试方面的内容,Europa 会提供十分详细的log信息给我们,便于我们定位到合约代码的问题所在。 我们可以把启动 Europa 的过程理解为 以太坊开发solidity的时候在本地通过 geth 启动了一个本地的测试链,并且这个本地测试链还会提供有 Alice Bob 账户,以及详细的log信息。 下载 Europa
> git clone https://github.com/patractlabs/europa.git
> cd europa/vendor
> git submodule update --init --recursive
编译 Europa
> cargo build --release
> ln -s target/release/europa /bin/europa
运行 Europa
> europa --dev --tmp --ws-external --rpc-methods=unsafe
自此我们的Europa链搭建并运行成功了,之后我们的合约就会部署在Europa这条链上。
部署合约
把合约部署在链上之后,我们才能对链上的合约方法进行调用。 那合约调用前需要经历哪些步骤呢? —— 编译合约 和 部署合约 其实ink!合约调用的流程和以太坊调用合约的流程类似 编译合约会生成在部署合约需要的 xxx.contract 、xxx.wasm 、metadata.json 部署合约可以根据 xxx.contract 或者 xxx.wasm 和 metadata.json 实现部署。 部署完之后就可以找一个调用合约的工具进行调用。
这里的metadata.json 可以理解为 以太坊里的 abi 文件,xxx.wasm 可以理解为 以太坊里的 bin 文件,至于xxx.contract 可以理解为 abi 文件+bin 文件的结合。
编译
我们可以通过ink!的cli工具(cargo-contract )实现编译合约的目的,并获得 xxx.contract 、xxx.wasm 、metadata.json 文件。 环境配置
> rustup component add rust-src --toolchain nightly
> rustup target add wasm32-unknown-unknown --toolchain nightly
> sudo apt install binaryen
安装 cargo-contract
> cargo install cargo-contract --vers ^0.15 --force --locked
通过 cargo-contract 获取 example例子
> cargo contract new flipper
> cd flipper/
只要是官方库内的example都可以通过 cargo contract new xxx 获取。这里我们以flipper合约为例。
flipper 合约内容 flipper合约是一个仅包含单个bool值的简单合约。它提供了方法 flip() 翻转它的值从 true 到 false(反之亦然)和 get() 返回当前bool值的状态。
#![cfg_attr(not(feature = "std"), no_std)]
use ink_lang as ink;
#[ink::contract]
mod flipper {
#[ink(storage)]
pub struct Flipper {
value: bool,
}
impl Flipper {
#[ink(constructor)]
pub fn new(init_value: bool) -> Self {
Self { value: init_value }
}
#[ink(constructor)]
pub fn default() -> Self {
Self::new(Default::default())
}
#[ink(message)]
pub fn flip(&mut self) {
self.value = !self.value;
}
#[ink(message)]
pub fn get(&self) -> bool {
self.value
}
}
}
编译flipper合约 回到刚才flipper文件夹处。 开始编译合约
> cargo +nightly contract build --keep-debug-symbols --optimization-passes=0
编译完成之后,我们可以在 ./target/ink 下找到 flipper.contract 、flipper.wasm 、metadata.json 自此编译工作就完成了,下面我们要利用这几个文件将合约部署在之前运行的 Europa 测试链上。
—— ink!-example https://github.com/paritytech/ink/tree/master/examples
部署
接下来我们可以直接通过 polkadot explorer https://polkadot.js.org/apps/#/explorer 实现合约的部署了。 切换网络到 Eruopa 链 在Contract模块下实现合约的部署 在这里需要注意一点,我们可以通过两种组合实现部署。 一种是通过 flipper.contract 实现部署
另外一种是通过 flipper.wasm 和 metadata.json 实现部署。 上传完之后就可以设置初始内容了。设置完之后就可以通过deploy实现部署
自此我们的合约部署成功了。
调用
通过Alice调用get方法,得知 bool值 是 true。 通过调用flip() 方法实现bool值的取反。 成功!下篇我会介绍如何通过go sdk来调用链上的合约,并介绍一下ink!范式下的合约调用三要素。
参考链接
https://www.bilibili.com/video/BV1HL411u772?spm_id_from=333.999.0.0 https://www.bilibili.com/video/BV1RX4y1V7W9?spm_id_from=333.999.0.0 https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/#/0/setup https://docs.patract.io/en/europa/intro/europa-cli https://mp.weixin.qq.com/s/lMj1MxYPJCaw7DFORctPLw https://mp.weixin.qq.com/s?__biz=MzI3MzYxNzQ0Ng==&mid=2247485373&idx=1&sn=7953d3665e1170d1bfd7ce29853f8bed&chksm=eb21c0f4dc5649e29945941821150e608a3a50269f509d8c34da3cce8725e62b0a1b88b3ca33&scene=21#wechat_redirect
关于作者
作者的联系方式:
微信:thf056 qq:1290017556 邮箱:1290017556@qq.com
你也可以通过 github | csdn | @新浪微博 关注我的动态
|