前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Sui Move合约开发入门(1)

Sui Move合约开发入门(1)

作者头像
Tiny熊
发布2023-01-09 17:44:06
1.6K0
发布2023-01-09 17:44:06
举报

本文作者:晴天咩咩[1]

Sui 简单介绍

Sui 是由 Mysten Labs 团队开发的高性能公链,目标是建设安全、高效、大规模使用的智能合约平台,完善的 web 3 基础设施,Sui 主要相比于其他区块链有以下特点:

  • 区分了简单交易和复杂交易,采用不同的共识机制,实行大规模并行计算。
  • 采用“面向资源”的 Sui Move 语言,提供更具备安全性和可组合性的区块链编程语言。

Aptos 和 Sui 都采用了 Move 这一语言,不过,具体使用的模型略有不同。Aptos 使用 Diem 团队创建的 Core Move 语言,而 Sui 正在利用他们自己的替代版本,称为“Sui Move”,对象是 Sui Move 中最基础的概念,像组织数据,某款 NFT 、某个代币的余额、某项智能合约,这些都是不同的对象,

这意味着 Sui 链上的交易可以根据对象的不同可以来分组处理。使得大规模并行计算成为可能。下图是一个简单的例子,描述了可分为 3 组的 5 笔不同交易。这 3 组交易完全可以实现并行处理。

环境搭建

本节可以了解到如何安装和配置 Sui,在安装 Sui 之前,您需要安装一些必备工具并配置您的开发环境。

工具安装

Sui 需要在所有支持的操作系统上使用 Rust 和 Cargo。一些操作系统需要 cURL 来下载 Rust 和 Cargo,因此如有必要,请检查相关先决条件部分以先安装 cURL,接下来的安装我们以 Linux 系统为例。

使用以下命令在 macOS 或 Linux 上安装 Rust 和 Cargo:

代码语言:javascript
复制
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

随后安装

代码语言:javascript
复制
sudo apt-get install curl git-all libssl-dev libclang-dev

安装 Sui

安装 Cargo 后,使用以下命令安装 Sui 二进制文件:

代码语言:javascript
复制
cargo install --locked --git https://github.com/MystenLabs/sui.git --branch devnet sui

输入以下命令查看安装是否成功

代码语言:javascript
复制
sui --version

命令行

安装完 Sui 二进制文件后,我们可以便可以与 Sui Devnet 交互。

要将 Sui 客户端连接到 Sui Devnet,请运行以下命令:

代码语言:javascript
复制
sui client

当客户端第一次启动时,Sui CLI 会打印以下行:

代码语言:javascript
复制
Config file ["/Users/dir/.sui/sui_config/client.yaml"] doesn't exist, do you want to connect to a Sui RPC server [y/n]?

键入y然后按Enter。您应该看到以下输出:

代码语言:javascript
复制
Sui RPC server Url (Default to Sui Devnet if not specified) :

Sui 客户端会提示您输入 RPC 服务器 URL。按 Enter 以使用 Devnet 的默认值。您还可以输入自定义 URL 以连接到自定义 RPC 端点。

代码语言:javascript
复制
Select key scheme to generate keypair (0 for ed25519, 1 for secp256k1):

键入01选择密钥方案,并创建了账户地址为0x15bfbffe3425ad6e8e61fcc93bfb5c3ee4145d29

如果想重置客户端配置,可以删除用户下的 sui 文件夹即可

代码语言:javascript
复制
rm ~/.sui/sui_config/*

获取测试代币

通过以上步骤,我们获得了一个可以使用的账户和对应的助记词信息

输入 Sui console 进入 Sui 控制台,随后输入active-address查看当前默认地址

代码语言:javascript
复制
sui client active-address

要获得测试代币可以在 sui wallet 中导入之前的助记词信息,随后点击 request 按钮即可。

第二种方式是加入Discord[2],在faucet 频道[3]输入你的地址,从而获取代币。例如(注意前面的感叹号):

代码语言:javascript
复制
!faucet 0x1083871113de333758c3d46136030d573f09ae18

输入地址

随后查看 gas,请求一次会获得 5 个 Sui 代币

合约目录结构

Move 中的代码组织(和分发)的主要单位是。包由一组模块组成,这些模块定义在.move扩展名的单独文件中。这些文件包括 Move 函数和类型定义。一个 Move 包必须包含Move.toml描述包配置的清单文件,例如包元数据或包依赖项。在我们先不要担心模块的其余内容,稍后您可以在 Move 书中阅读更多关于模块的内容[4]

首先,我们创建一个空的 Move 包:

代码语言:javascript
复制
sui move new hello_world

这将创建一个名叫 hello_world 的 Move 包,包含toml文件和sources文件夹,这一个最简单的包目录结构如下所示:

代码语言:javascript
复制
.
├── Move.toml
└── sources

查看 Move.toml 文件

代码语言:javascript
复制
[package]
name = "hello_world"
version = "0.0.1"

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet" }

[addresses]
hello_world =  "0x0"
sui =  "0000000000000000000000000000000000000002"

其中内容有:

  • 名称和版本([package]部分)
  • 此包依赖的其他包([dependencies]部分)。该包只依赖 Sui Framework,其他第三方依赖需要在这里添加。
  • 命名地址列表([addresses]部分)。这些名称可以用作源代码中给定地址的方便别名。

第一个 Move 合约

编写

让我们从在包中创建一个源文件开始我们的合约:

代码语言:javascript
复制
touch hello_world/sources/my_module.move

在文件中填入以下内容:

代码语言:javascript
复制
module hello_world::counter {
    // Part 1: imports
    use sui::transfer;
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};

    // Part 2: struct definition
    struct Counter has key {
        id: UID,
        value: u64,
    }

    // Part 3: transfer the counter object to the sender
    entry public fun getCounter(ctx: &mut TxContext) {
        // sender address
        let sender = tx_context::sender(ctx);
        let counter_obj = Counter {
            id: object::new(ctx),
            value: 0
        };
        transfer::transfer(counter_obj, sender);
    }

    // part 4: public/ entry functions
    public entry fun incr(counter: &mut Counter) {
        counter.value = counter.value + 1;
    }
}

此合约的功能是一个简单的计数器合约:

  • 用户可以调用getCounter获得一个Counter计数器对象
  • 用户可以调用incr并且能够让他的value值+1

让我们分解这段代码为四个不同部分:

  1. Part1 导入:这些允许我们的模块使用在其他模块中声明的类型和函数。在此模块中,我们从三个不同的模块中引入导入,分别是transferobjecttx_context,其作用我们在下文解释。
  2. Part2 结构声明:这里定义了可以由该模块创建/销毁的类型。这里的key 表明这些结构是作为全局索引资源。store能力允许它存储在其他结构的字段中并可以自由转移。
  3. Part3getCounter函数:向调用者转入一个Counter对象
  4. Part4incr函数:传入一个对象的可变引用,并对其 value 字段+1

合约一开始引入了transfer库,transfer函数有两个参数一个是被对象,二是接受者地址,能够转让一个对象的所有权给另一个地址,同时这个对象必须有一个全局独一无二的ID也就是Counter中的id字段,这个ID就是由object中的new函数生成,new函数接受当前交易的上下文作为参数,从而生成一个独一无二的ID

编写完成之后,我们需要位于项目的根目录,然后使用sui move build来编译它。

代码语言:javascript
复制
sui move build

成功的构建会返回类似于以下内容的响应:

如果构建失败,可以通过日志输出中的错误信息来排除和解决问题。

部署

现在我们已经能够编译合约,那么这一节让我们发布我们的合约。

首先确保我们的账户已经有一定的测试代币

发布合约和调用合约,我们都可以使用 Sui CLI 客户端来完成。

Sui 中的发布命令publish要求我们指定用户定义包所在的目录。同时需要设置 gas 消耗一个上限,我们使用 1000 作为我们的 gas 预算,所以通过如下命令来发布我们的合约。更多的命令请参阅 Sui CLI 客户端文档。[5]

代码语言:javascript
复制
sui client publish --path . --gas-budget 1000

发布时,Sui 还会再次编译,随后会返回交易哈希,发布结果,交易结果等等。这些信息可以通过交易哈希在区块浏览器[6]上找到。

可以发现,运行此命令会创建一个Immutable类型的对象(0x31f33e53a2c7a2620fc1bbf8140ffc7bde3984fa),在 sui 中的对象包含三种类型:

  • owned:这是 Move 对象最常见的对象。在 Sui 中每一个对象都属于一个地址,并且这个拥有权可以在 Move 代码中转移[7]到另一个地址。
  • immutable:这意味着一个对象是不可变的,不能被任何人改变。因此,这样的对象没有拥有者。任何人都可以在他们的 Move 通话中使用它。并且所有 Move 包都是不可变对象:一旦发布,就无法更改。在 Move 代码中可以通过freeze_object[8]库 API 将对象变成不可变对象。不可变对象只能作为只读引用 ( &T) 在 Move 调用中传递。
  • shared:对象可以共享,这意味着任何人都可以读取或写入该对象。与可变拥有的对象(单写者)相比,共享对象需要共识[9]来排序读取和写入。有关创建和访问共享对象的示例,请参阅https://examples.sui.io 上的共享对象[10]

在交易最后,我们看到用于支付发布费用的 gas 对象(0x2c45ed66ecff9e49ff14938cc557016065307fea)由于支付了 gas 费从而也被修改了。

调用

为了获得一个Counter计数器对象并且,使得Counter计数器对象中的值增加,我们需要调用合约中的函数。

在函数getCounter中,存在publicentry修饰符,这保证了我们拥有调用权限,并且可以通过命令行调用。transfer函数的参数为对象接收者地址,在代码中,我们通过tx_context::sender(ctx)来获取发送者地址,ctx是当前交易的上下文,包含此交易的相关信息。

所以我们首先需要调用getCounter函数,在命令行输入如下命令。

代码语言:javascript
复制
sui client call \
    --function getCounter \
    --module counter \
    --package 0x31f33e53a2c7a2620fc1bbf8140ffc7bde3984fa \
    --gas-budget 1000

这是一个相当复杂的命令,所以让我们一一解释它的所有参数:

  • --function:要调用的函数的名称
  • --module:包含函数的模块的名称
  • --package:包含函数的模块所在的包对象的 ID
  • --gas-budge:是一个十进制数,表示我们交易的 gas 上限,以避免 gas pay 中所有 gas 的意外耗尽)

可以发现交易结果中返回了一个新创建的对象ID,很明显这就是我们获得的Counter对象

同时在浏览器上[11]可以直接通过对象ID看到countervalue字段的具体值

最后我们试图调用incr来使得value的值+1

代码语言:javascript
复制
sui client call \
    --function incr \
    --module counter \
    --package 0x31f33e53a2c7a2620fc1bbf8140ffc7bde3984fa \
    --args 0x846e1db8383dd68373cd83c6ce5242951d7beb77 \
    --gas-budget 1000

其中--args用来传递我们的参数,参数格式参考 Sui-JSON[12]值的函数参数列表。

再次通过浏览器可以发现 version(可以理解为修改的次数)被+1,同时value的字段值也成功+1

以上是 Sui Move 合约开发入门的第一节,此处[13]可以查看本文提到的代码。在 Sui 入门的第二节会来带 Sui 中的Event,初始化Init函数和 Sui 合约测试的相关内容。

参考资料

[1]

晴天咩咩: https://learnblockchain.cn/people/6415

[2]

Discord: https://discord.gg/sui

[3]

faucet频道: https://discord.com/channels/916379725201563759/971488439931392130

[4]

模块的内容: https://movebook.chrisyy.top/modules-and-scripts.html

[5]

Sui CLI 客户端文档。: https://docs.sui.io/build/cli-client

[6]

区块浏览器: https://explorer.sui.io/transactions/M7SLyxPpt2kXi0idQ4ANNAYg3pw3BfulZhEf9z3L%2F0w%3D

[7]

转移: https://docs.sui.io/build/move/sui-move-library

[8]

freeze_object: https://docs.sui.io/build/move/sui-move-library

[9]

共识: https://docs.sui.io/learn/architecture/consensus

[10]

共享对象: https://examples.sui.io/basics/shared-object.html#shared-object

[11]

同时在浏览器上: https://explorer.sui.io/object/0x846e1db8383dd68373cd83c6ce5242951d7beb77

[12]

Sui-JSON: https://docs.sui.io/build/sui-json

[13]

此处: https://github.com/chrisyy2003/sui-by-example/tree/main/hello_world

Twitter : https://twitter.com/NUpchain Discord : https://discord.gg/pZxy3CU8mh

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Sui 简单介绍
  • 环境搭建
    • 工具安装
      • 安装 Sui
        • 命令行
          • 获取测试代币
          • 合约目录结构
          • 第一个 Move 合约
            • 编写
              • 部署
                • 调用
                  • 参考资料
                  相关产品与服务
                  区块链
                  云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档