狗哥区块链与AI精品内容集@NonceGeek

2025年03月28日更新 75 人订阅
原价: ¥ 20 限时优惠
专栏简介 「造」最关键的是什么?| Hackathon 漫游指南(贰) Why Hackathon?| Hackathon 漫游指南(壹) 设计「众人维护」的 BuidlerBoard | BeWater.xyz Movement 白皮书中文版 Rebuidl RSS 生产因素与反生产因素 | 独立黑客创业手册(陆) 组织 | 独立黑客创业手册(伍) 生产 | 独立黑客创业手册(肆) 销售 | 独立黑客创业手册(叄) 最优先的能力 | 独立黑客创业手册(贰) 为什么从独立黑客开始 | 独立黑客创业手册(壹) Aptos Token Object V2 | Move dApp 极速入门(贰拾肆) 可編程交易塊 | Move dApp 極速入門(貳拾叁) Aptos 密鑰輪換 | Move dApp 極速入門(貳拾貳) Aptos 对象模型 | Move dApp 极速入门(贰拾壹) Aptos Moveflow SDK使用指南 | Move dApp 极速入门(贰拾) Sui 上简单 Swap 的实现 | Move dApp 极速入门(拾玖) 用 Elixir 交互 Aptos | Move dApp 极速入门(拾捌) Sui 链上数据查询 | Move dApp 极速入门(拾柒) SUI 合约测试攻略 | Move dApp 极速入门(拾陆) Sui 数据类型详解 | Move dApp 极速入门(拾伍) Airdropper Contract in Aptos | Move dApp 极速入门(拾肆) Sandwich合约源码解析 | Move dApp 极速入门(拾叁) Sui 极速上手 | Move dApp 极速入门(拾贰) scaffold-aptos 脚手架 | Move dApp 极速入门(拾壹) 对 DID Document 的思考 | Move dApp 极速入门(九) DID中地址聚合器的实现 | Move dApp 极速入门(八) 值的存取应用3.0 | Web3.0 dApp 开发(五) 合约数据类型综述 | Move dApp 极速入门(四) 操作资源 | Move dApp 极速入门(三) 第一个 Move dApp | Move dApp 极速入门(二) Hello Move | Move dApp极速入门(一) Staker | Web3.0 dApp 开发(九) Token 自动售卖机 | Web3.0 dApp 开发(七) SVG NFT 全面实践 | Web3.0 dApp 开发(六) 值的存取应用2.0 | Web3.0 dApp 开发(四) 值的存取应用1.0 | Web3.0 dApp开发(三) Scaffold-eth 快速上手 | Web3.0 dApp 开发(二) eth.build 快速上手 | Web3.0 dApp 开发(一) 1 小时理解比特币系统 【NonceGeek Workshop 0x01总结】基于链上数据生成游戏地图 Remix 完全本地化部署 NFT:实体与虚拟载体的主与辅 | 狗哥的元宇宙思辨(一) Web3Camp 内容大全@NonceGeek 用 Python 创建一条 Pow 区块链(上) 区块链与共识机制演变史 基于 Etherscan 实现 Blockchain Syncer 【论文分享】去中心化社会:寻找 Web3 的灵魂(上) 【论文分享】去中心化社会:寻找 Web3 的灵魂(下) Ted Yin | 2021 年的区块链基础设施将是什么? 0. 公链、联盟链与分布式未来(全文) 基于 Infura 与 Web3py 部署调用 Hello 合约全过程 | 以太坊开发极速入门 太上中的基因设计与Binary | 函数式与区块链(一) 理解以太坊合约数据读取过程 | 函数式与区块链(二) Hello, Ink! | 用 Rust 写智能合约(一) Mapping 数据结构 | 用 Rust 写智能合约(二) 用 Rust 程序和 Webase 交互 | Rust 学习笔记(四) 用 Sqlite 存储 WeId | Rust 学习笔记(五) 链上注册WeId与错误处理 | Rust 学习笔记(六) WeId 链上创建与本地存储的完整闭环 | Rust 学习笔记(七) 以太坊上的核心开发者 Austin | 以太坊上的最佳开发实践 1. FISCO BCOS 开发环境节点搭建全攻略 伪代码简述 ECDSA 签名过程 | 联盟链开发 WeIdentity 源码分析 | 狗哥解码 WeIdentity 源码分析 | 狗哥解码 FISCO BCOS 介绍 | 联盟链开发 给Remix升个级 | 联盟链开发 2. 控制台的安装与使用 3. 【实验】补全一个区块链应用 4. 控制台的Web化 5. Web化控制台2.0:打造团队共用区块链学习平台 6. 使用脚手架快速搭建 Java DApp 【视频+文字】分布式思维 Rebuidl RSS (EN)

操作资源 | Move dApp 极速入门(三)

  • 李大狗
  • 发布于 2022-09-17 12:06
  • 阅读 3584

MOVE 中的重要概念 —— 资源

本系列将以 Starcoin 为例,讲解 Move 语言以及 Move dApp 的开发,及其背后的计算机原理。

本系列的全文更新中,见:

https://github.com/WeLightProject/Web3-dApp-Camp/tree/main/move-dapp

同步的打卡任务:

https://github.com/WeLightProject/Web3-dApp-Camp/discussions/categories/projects-others

「资源」是 Move 语言中最关键的概念。本篇将以 Library 图书馆 Demo 为例,讲解在 Rust 下是如何操作资源的。

0x01 源码下载

本文的 Demo 源码包含 smart contractreact dAppscript.sh三部分,资源链接如下:

https://github.com/WeLightProject/Web3-dApp-Camp/tree/main/move-dapp/my-library

0x02 Types with Abilities

https://move-book.com/advanced-topics/types-with-abilities.html#types-with-abilities

https://move-book.com/cn/advanced-topics/types-with-abilities.html

Move 的类型系统非常灵活,每种类型都可以定义四种能力(abilities)。它们决定了类型的值是否可以被「使用、丢弃和存储」。

这四种 abilities 能力分别是: Copy, Drop, Store 和 Key。

它们的功能分别是:

  • Copy - 值可以被复制
  • Drop - 在作用域(Scope)结束时值可以被丢弃
  • Key - 值可以作为键值(Key)被「全局存储操作( global storage operations)」进行访问
  • Store - 值可以被 存储 到全局状态。

在上一篇中,我们已经初步接触到了 Abilities。在本实例中,我们将进一步的通过 Play with Abilities 掌握其原理。

0x03 Abilities 的语法

基本类型和内建类型的 abilities 是预先定义好的并且不可改变: integers, vector, addresses 和 boolean 类型的值先天具有 copy、drop 和 store ability。

然而,结构体的 ability 可以按照下面的语法进行添加:

struct NAME has ABILITY [, ABILITY] { [FIELDS] }

一个图书馆的Struct例子:

module Library {

    // each ability has matching keyword
    // multiple abilities are listed with comma
    struct Book has store, copy, drop {
        year: u64
    }

    // single ability is also possible
    struct Storage has key {
        books: vector<Book>
    }

    // this one has no abilities 
    struct Empty {}
}

0x04 Library 合约实践

合约源码见:

https://github.com/WeLightProject/Web3-dApp-Camp/blob/main/move-dapp/my-library/sources/MyLibrary.move

对应的脚本合集如下(脚本中的路径、地址等信息需自行调整):

# deploy
dev deploy [path to blob] -s [addr] -b
dev deploy /Users/cjf/Documents/bc/Web3-dApp-Camp/move-dapp/my-library/release/my_library.v0.0.3.blob -s 0x07ffe973c72356c25e623e2470172a69 -b
# call function init library
account execute-function --function 0x07Ffe973C72356C25e623E2470172A69::MyLibrary::init_library -s 0x07Ffe973C72356C25e623E2470172A69 -b
# get library
state get resource 0x07Ffe973C72356C25e623E2470172A69 0x07Ffe973C72356C25e623E2470172A69::MyLibrary::Library
# add book
account execute-function --function 0x07Ffe973C72356C25e623E2470172A69::MyLibrary::s_add_book --arg b"web3" --arg b"github.com" -s 0x07Ffe973C72356C25e623E2470172A69 -b
# update book at index
account execute-function --function 0x07Ffe973C72356C25e623E2470172A69::MyLibrary::s_update_book_at_id --arg 0 --arg b"atest" --arg b"noncegeek.com" -s 0x07Ffe973C72356C25e623E2470172A69 -b
# delete book at index
account execute-function --function 0x07Ffe973C72356C25e623E2470172A69::MyLibrary::s_add_book --arg b"web3" --arg b"github.com" -s 0x07Ffe973C72356C25e623E2470172A69 -b

通过如下命令在starcoin console中进行合约部署:

starcoin% dev deploy [path to blob] -s [deployer addr] -b

初始化 Library:

starcoin% account execute-function --function [deployer addr]::MyLibrary::init_library -s [deployer addr] -b

查看 Library:

starcoin% state get resource [caller addr] [deployer addr]::MyLibrary::Library

此时因为还没有藏书,所以图书馆是空的:

image-20220801210648788

插入一本 Book:

starcoin% account execute-function --function [deployer addr]::MyLibrary::s_add_book --arg b"web3" --arg b"github.com" -s [caller addr] -b

此时再执行get resource,会发现多了一个 item:

image-20220801211027796

更新(Update)和删除(Delete)的操作同理,你自己来动手试试吧:)!

0x05 Library 合约源码分析

Move 合约包含Structfuncscript三个部分。

其中,Struct定义数据结构、func是一般函数、script是暴露被外部调用的脚本。

module MyAddr::MyLibrary {
   use StarcoinFramework::Signer;
   use StarcoinFramework::Vector;
   // each ability has matching keyword
   // multiple abilities are listed with comma
   struct Book has store, copy, drop {
      id: u64,
      name: vector<u8>,
      link: vector<u8>
   }

   // single ability is also possible
   struct Library has key {
      books: vector<Book>
   }

   public fun create_library(account: &signer){
      move_to<Library>(account, Library{books: Vector::empty<Book>()});
   }
   //because the script function cannot have return value,
   //query only can be done by: state get resource Addr Addr::MyLibraryV4::Library
   public fun addBook(account: &signer,name:vector<u8>, link: vector<u8>) acquires  Library {
      let lib = borrow_global_mut<Library>(Signer::address_of(account));
      let id = Vector::length(&lib.books);
      Vector::push_back(&mut lib.books, Book{id:id,name:name,link:link});
   }

   public fun updateBookAtId(account: &signer,id:u64,name:vector<u8>, link: vector<u8>) acquires  Library {
      let lib = borrow_global_mut<Library>(Signer::address_of(account));
      let book = Vector::borrow_mut<Book>(&mut lib.books,id);
      book.name = name;
      book.link = link;
   }

   public fun deleteBookAtId(account: &signer,id:u64) acquires  Library {
      let lib = borrow_global_mut<Library>(Signer::address_of(account));
      Vector::remove(&mut lib.books, id);
   }

   public(script) fun init_library(account: signer){
      Self::create_library(&account)
   }

   public(script) fun s_add_book(account: signer, name:vector<u8>, link: vector<u8>) acquires  Library {
      Self::addBook(&account,name, link)
   }

   public(script) fun s_update_book_at_id(account: signer, id:u64,name:vector<u8>, link: vector<u8>) acquires  Library {
      Self::updateBookAtId(&account,id,name,link)
   }

   public(script) fun s_delete_book_at_id(account: signer, id:u64) acquires  Library {
      Self::deleteBookAtId(&account,id)
   }
}

5.1 move_to 函数

还记得 signer 吗? 现在你可以看看它是如何运作的! 要将资源移动到帐户,您有内置函数 move_to,它将signer作为第一个参数,Collection作为第二个参数。 move_to 函数的签名可以表示为:

native fun move_to<T: key>(account: &signer, value: T);

这导致两个结论:

  • 您只能将资源放在您的帐户下。 您无法访问另一个帐户的 signer value,因此无法将资源放在那里。
  • 一个地址下只能存储一种单一类型的资源。 两次执行相同的操作会导致丢弃现有资源——这种情况绝不能发生(想象您存储了您的硬币,并且由于不准确的操作,您通过推空余额丢弃了所有储蓄!)。 第二次尝试创建现有资源将失败并出现错误。

—— https://move-book.com/resources/resource-by-example/storing-new-resource.html

在本 demo 中,我们通过 move_to 函数创建了Library资源:

public fun create_library(account: &signer){
    move_to<Library>(account, Library{books: Vector::empty<Book>()});
}

5.2 borrow_global & borrow_global_mut

见:

https://move-book.com/cn/resources/resource-by-example/access-resource-with-borrow.html#%E8%AF%BB%E5%8F%96%E5%92%8C%E4%BF%AE%E6%94%B9-resource

5.3 Vector

Vector 是 Rust 中的一种数据类型,其允许我们在一个单独的数据结构中储存多于一个的值,它在内存中彼此相邻地排列所有的值。Vector 只能储存相同类型的值。它们在拥有一系列项的场景下非常实用,例如文件中的文本行或是购物车中商品的价格。

在本 Demo 中,我们使用vector&lt;u8>来统一处理字符串,相当于 Python 中的 b"something",或 Elixir 中的 <<1,2,3>>。

此外,Library 中存放了很多书籍,我们能用vector&lt;Book>表示,相当于其他语言中的List类型:

struct Library has key {
    books: vector&lt;Book>
}

要了解更多关于 Vector 的内容,可以见starcoin-framework

https://github.com/starcoinorg/starcoin-framework/blob/3e24ac46c2ada60956bce1d104e7d7de3a42d849/sources/Vector.move

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论