公链新宠Move合约如何快速入手

目录

引言

什么是 Move 合约

Move 项目工程结构

Move 的源码结构

Move 的数据存储

尝试一下 Move 的 hello-world

工具&环境准备

合约编译&测试

合约发布&调试

Move 的一些优质学习资源

欢迎关注笔者 twitter: @wallywxy沟通交流


引言

Move 语言伴随着新公链 Aptos 和 Sui 迅速崛起,其设计理念“资源是一等公民”,非常适合进行资产的数字化编程。Move 的白皮书中指出数字化资源应该不可以被复制,不能被隐式丢弃,只能在程序的存储地址之间进行移动,依据该理念 Move 为资产的稀缺性表达访问控制提供了高于 Solidity 的表达能力。本文主要探求一下 Move 的基本概念,体验基本语法,感受在 Aptos 上如何部署和调用 Move 的hello world

什么是 Move 合约

Move 是基于 Rust 演化出来的合约编程语言,基本的语法结构和 Rust 的范式类似,但是更加简单,也做了一些支持资源特征表达方面的专门设计。

Move 项目工程结构

如下所示是 Move 工程的典型结构,其中 Move.toml 和 sources 是必备的,其他部分按需安排,其中 Move.toml 是工程的配置管理文件,包括版本号、依赖、包名什么的。sources 里面就是源码,源码以 .move 作为后缀名。

a_move_package
├── Move.toml      (required)
├── sources        (required)
├── examples       (optional, test & dev mode)
├── scripts        (optional)
├── doc_templates  (optional)
└── tests          (optional, test mode)

Move 的源码结构

如下所示为一个简单的 Move 的源码实例, 在 Move 中代码组织形式包括两种,一种是 module 一种叫 script

  • 模块(module): 定义结构体以及函数,类似于 solidity 中的合约,会被发布到链上永久存储,模块进一步可以分为系统模块如 std 和 用户自定义模块,不同的区块链如 Aptos, Sui 又根据自身链的特性提供了一些链的特殊能力模块。
  • 脚本(script): 可执行的入口函数,类似传统程序中的 main 函数,一半儿也直接定义为 main, 属于执行过程中的临时代码,不存储到链上
// module example
module 0xCAFE::BasicCoin {
    struct Coin has key {
        value: u64,
    }

    public fun mint(account: signer, value: u64) {
        move_to(&account, Coin { value })
    }
}

// script example
script {
    // Import the Debug module published at the named account address std.
    use std::debug;

    const ONE: u64 = 1;

    fun main(x: u64) {
        let sum = x + ONE;
        debug::print(&sum)
    }
}

其中 module 的完整语法定义为:


module <address>::<identifier> {
    (<use> | <friend> | <type> | <function> | <constant>)*
}

module : 关键词
address: 该 module 发布到链上的用户的地址,在写合约代码时,可以用别名标识
identifier: 模块名称,一般大写驼峰结构表示

Move 的数据存储

从区块链或者智能合约虚拟机的视角而言,Move 在链上存储的数据大体上分为 module 和 state 两块,也就是合约的字节码和合约运行过程中产生数据,它们的存储示意图如下, 可以看到 Move 的数据都存储在账户地址下,这为其权限控制提供了很好的帮助。

相对而言,solidity 大部分 ERC20 合约内部用户的数据是以状态变量的形式存储的,这样一来用户的核心资产数据存储的是在合约内部,这和 move 存储在账户下面是天然的不同,这样 Solidity 中的资产除了要控制好用户的访问安全之外,也要控制好合约自身的安全性,甚至可以说用户数字资产的安全性完全取决于合约的控制逻辑。

尝试一下 Move 的 hello-world

由于 Move 的合约要上链的话其可能会涉及到具体链的 framework, 为了操作方便,这里笔者以 Aptos 的例子来进行阐述,示例代码

工具&环境准备

  1. 下载 Move 命令行工具,访问 aptos-cli 下载页面,下载对应的版本;
  2. 解压 aptos 安装包,将 aptos 的二进制放到本地的 Path 中;
  3. 如果使用 vscode 或者其他 IDE 可以在相应的市场中搜索 move 关键字安装 move 插件。

运行 aptos move 即可查看我们 aptos move 的可用功能:

aptos move 命令行工具

Aptos 区块链的交互以及 module 的存储都和个人的账户息息相关,因此这里我们得准备一下个人的账户:

  1. 运行指令 aptos init ,过程中有一些交互,可以直接默认值往下走,会得到一个.aptos文件夹 ,存储了生成的账户信息和交互的链节点的配置信息:
    profiles:
      default:
        private_key: "your private_key"
        public_key: "0x4acd9175462e7382307af2d43a50e540042ca6cdcab3329618c939a9264c0096"
        account: 49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba
        rest_url: "https://fullnode.devnet.aptoslabs.com/v1"
        faucet_url: "https://faucet.devnet.aptoslabs.com/"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
  2. 给本地生成账户接水(接受测试 Token),运行 aptos account fund-with-faucet --account default :

    {
      "Result": "Added 50000 coins to account 49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba"
    }

好了现在身份和钱(可能不一定够,如果不够多接几次水,或者用钱包去接,钱包会弄得多一点)都有了,我们进入下一个环节。

合约编译&测试

进入 示例代码moveasy/src/contract/aptos 这里保存了一些 aptos 上的示例,我们从 hello-world 开始。合约的功能很简单,核心方法就是 get_messageset_message ,联盟链的同学可能对这个比较熟悉,就是存证和取证 😃。

前文提到 move 中的 module 是存储在具体的账户之下,在本地编译调试时为了方便,可以采用 named-addresses 也就是别名来替代 0xbb 类型的真实地址,因此在编译、测试等命令运行时也要加上相应的默认 named-addresses

  • 编译合约

    aptos move compile --named-addresses hello_blockchain=default

返回值如下,这里就验证了module 存储在账户的概念了,Result 中的 49cf… 就是个人的公钥信息。

 {
  "Result": [
    "49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba::message"
  ]
}

如图 build 文件夹是编译出来的内容,我们可以看到 message.mv 这个就是本例子中的字节码,其依赖的部分除了 move 语言自身的依赖库 MoveStdlib 还包含了 AptosFramewrokAptosStdlib

  • 本地测试合约,测试代码如下

    #[test(account = @0x1)]
        public entry fun sender_can_set_message(account: signer) acquires MessageHolder {
            let addr = signer::address_of(&account);
            aptos_framework::account::create_account_for_test(addr);
            set_message(account,  string::utf8(b"Hello, Blockchain"));
    
            assert!(
                get_message(addr) == string::utf8(b"Hello, Blockchain"),
                ENO_MESSAGE
            );
        }

 运行指令:aptos move test --named-addresses hello_blockchain=default

正确执行输出:

合约发布&调试

1. 发布合约,运行指令 aptos move publish --named-addresses hello_blockchain=default

至此这个hello-world的 module 就被部署到你的个人链上账户下面了,下面针对发布合约进行调用。

  • 合约调用
    • 使用命令行提交交易

      aptos move run \
      --function-id 'default::message::set_message' \
      --args 'string:hello, blockchain'aptos move run \
      --function-id 'default::message::set_message' \
      --args 'string:hello, blockchain'
      
    • 使用 RestAPI 读取数据

      https://fullnode.devnet.aptoslabs.com/v1/accounts/49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba/resource/0x49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba::message::MessageHolder
      

      返回值:

      {
        "type": "0x49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba::message::MessageHolder",
        "data": {
          "message": "hello, blockchain", // 返回的消息体
          "message_change_events": {
            "counter": "0",
            "guid": {
              "id": {
                "addr": "0x49cf0e5ae7e483f82119eb697dd8da93af1a1703a5cd152cbb99001b3d1eb3ba",
                "creation_num": "4"
              }
            }
          }
        }
      }
      

至此,我们完整地体验了 Move 合约的完整调用流程。

Move 的一些优质学习资源

  1. Move 语言代码库
  2. Introduction - The Move Book
  3. Developer Tutorials | Aptos Docs
  4. Write Smart Contracts with Sui Move | Sui Docs
  5. asome-move 系列

欢迎关注笔者 twitter: @wallywxy沟通交流

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇
下一篇>>