狗哥区块链与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)

Hello Move | Move dApp极速入门(一)

  • 李大狗
  • 发布于 2022-07-30 09:05
  • 阅读 5304

实践:面向资源的智能合约语言

作者: 李大狗、王宁波、陈俊锋 @ NonceGeekDAO

我们从二进制到汇编到各种高级语言,一直都在发展。智能合约也一样,从比特币的Script到以太坊的Solidity,往前跨了一大步,但是,Solidity能包打天下了吗?事实上,层出不穷的安全问题一直在困扰我们,在很大程度上限制了整个行业的发展,比如前段时间炒的沸沸扬扬的Poly Network被攻击事件。「安全」在金融场景,尤其是DeFi时代,比以往任何时候都更加重要,这些问题我们不能视而不见。如果区块链行业继续发展,势必会有更好的智能合约语言出来。

在这些大前提下,新的智能合约语言Move被设计出来了。Move是面向「资源」编程的。我个人认为,「面向资源编程」是智能合约语言的一个变革,说白了,智能合约语言又往前迈了一大步。

——jolestar

——https://starcoin.org/zh/developer/blog/starcoin_move_resource

——https://mirror.xyz/jolestar.eth/sQ0nMCO3eNig6gCzqQO7xew1mn8oUi1-rKtfZKmGlNI

本系列将以 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

1 节点启动

下载最新的发行版 Starcoin 节点程序(MacOS 将其拷贝至/usr/local/bin目录即可):

https://github.com/starcoinorg/starcoin/releases

在此以Starcoin网络为基础,展现如何启动一个节点:

https://starcoinorg.github.io/starcoin-cookbook/docs/getting-started/setup/

太长不看版——关键命令合集:

# 启动一个本地 dev 节点
$ starcoin -n dev
# 启动一个本地 dev 节点的同时打开控制台,-d 参数可以确保每次打开控制台时都保有历史的数据而不是重开
$ mkdir [folder_name]
$ cd [folder_name]
$ pwd
$ starcoin -d [path_to_your_data_folder] -n dev console

starcoin 控制台命令:

# 指定账户获得测试代币
starcoin% dev get-coin 0xb7c46353c6c0e3a2559d5b12cad981e4 -v 100STC
# 账户列表
starcoin% account list
# 单一账户情况查看
starcoin% account show 0xb7c46353c6c0e3a2559d5b12cad981e4
# 创建新账户
starcoin% account create -p [pwd]

2 第一个 Move 合约 —— MyCounter

最小可实践例子:

https://github.com/starcoinorg/starcoin-cookbook/blob/main/examples/my-counter

module MyCounterAddr::MyCounter {
     use StarcoinFramework::Signer;

     struct Counter has key, store {
        value:u64,
     }
     public fun init(account: &signer){
        move_to(account, Counter{value:0});
     }
     public fun incr(account: &signer) acquires Counter {
        let counter = borrow_global_mut<Counter>(Signer::address_of(account));
        counter.value = counter.value + 1;
     }

     public(script) fun init_counter(account: signer){
        Self::init(&account)
     }

     public(script) fun incr_counter(account: signer)  acquires Counter {
        Self::incr(&account)
     }
}

MyCounter 源码分析

module 是发布在特定地址下的打包在一起的一组函数和结构体。使用script时需要与已发布的module或标准库一起运行,而标准库本身就是在 0x1 地址下发布的一组module。

module MyCounterAddr::MyCounter{ } 则在该MyCounterAddr地址下(对应Move.toml下的MyCounterAddr = "0xb7c46353c6c0e3a2559d5b12cad981e4")创建一个module。

use StarcoinFramework::Signer,是使用标准库下的Signer module,Signer 是一种原生的类似 Resource 的不可复制的类型,它包含了交易发送者的地址。引入signer类型的原因之一是要明确显示哪些函数需要发送者权限,哪些不需要。因此,函数不能欺骗用户未经授权访问其 Resource。具体可参考源码

struct Counter has key, store {
        value:u64,
     }

使用struct定义了一个叫做Counter的结构体,同时被 key,store两种限制符修饰,Move的类型系统灵活,每种类型都可以被四种限制符所修饰。这四种限制符我们称之为 abilities,它们定义了类型的值是否可以被复制、丢弃和存储。 这四种 abilities 限制符分别是: Copy, Drop, Store 和 Key.

它们的功能分别是:

  • Copy - 被修饰的值可以被复制。
  • Drop - 被修饰的值在作用域结束时可以被丢弃。
  • Key - 被修饰的值可以作为键值对全局状态进行访问。
  • Store - 被修饰的值可以被存储到全局状态。

这里用key,store修饰,则表示它不能被复制,也不能被丢弃或重新使用,但是它却可以被安全地存储和转移。

下面则是定义的方法,

public fun init(account: &signer){
    move_to(account, Counter{value:0});
}
public fun incr(account: &signer) acquires Counter {
    let counter = borrow_global_mut<Counter>(Signer::address_of(account));
    counter.value = counter.value + 1;
}

定义格式则是:

public fun 函数名(参数:参数类型){ }

move函数默认是私有函数,只能在定义它们的模块中访问。关键字 public 将更改函数的默认可见性并使其公开,即可以从外部访问。

init方法参数是一个&signer,意味着该方法必须是一个账户合法签名过后才可以调用,move_to则是move的一个原语,作用是发布、添加Counter资源到 signer 的地址下。Move的账户模型,code和data是存储在一个账户地址下的。

下面是列举的常用原语

  • move_to< T >(&signer, T):发布、添加类型为 T 的资源到 signer 的地址下。
  • move_from< T >(addr: address): T - 从地址下删除类型为 T 的资源并返回这个资源。
  • borrow_global< T >(addr: address): &T - 返回地址下类型为 T 的资源的不可变引用。
  • borrow_global_mut< T >(addr: address): &mut T - 返回地址下类型为 T 的资源的可变引用。
  • exists< T >(address): bool:判断地址下是否有类型为 T 的资源。。

incr方法参数也是一个&signer,意味着该方法必须是一个账户合法签名过后才可以调用,

关键字 acquires,放在函数返回值之后,用来显式定义此函数获取的所有 Resource。

Signer::address_of(account) 从签名者中拿到address

borrow_global_mut上面有介绍到,可变借用到address下到resource Counter,然后将Counter结构体下的value进行+1操作。

这下面的两个方法则是script方法,它与上面两个函数有什么区别呢?

  • public fun : 方法可以在任何模块中被调用。
  • public(script) fun:script function 是模块中的入口方法,表示该方法可以通过控制台发起一个交易来调用,就像本地执行脚本一样

下个版本的 Move 会用 public entry fun 替代 public(script) fun

Self则是代表自身module。

  public(script) fun init_counter(account: signer){
        Self::init(&account)
     }

     public(script) fun incr_counter(account: signer)  acquires Counter {
        Self::incr(&account)
     }

2.1 编译

下载第一个实例的源码:

$ git clone git@github.com:WeLightProject/Web3-dApp-Camp.git
$ cd Web3-dApp-Camp/move-dapp/my-counter

Move的包管理工具为Move Package Manager(mpm),它类似于Rust的Cargo或者Node的NPM。 可以通过mpm package new my-counter来创建一个新项目,典型的目录结构为:

my-counter
├── Move.toml
└── sources
    └── MyCounter.move 
  • sources用来存档Move的模块,它类似于与Java中的类文件。
  • Move.toml-用来存放配置文件:包括包的原数据、依赖和命名地址。
  • 上述文件构成一个Move包(Move Package) 更详细的Move包管理参考文档

修改move.toml中的地址为你用来部署的地址。

image-20220727123922351

编译:

$ mpm release

接下来会在release文件夹中,看到你编译好的二进制文件。

image-20220727124134402

2.2 控制台部署

在 Starcoin Console 中执行如下命令即可部署:

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

-s 即--sender,-b即--blocking,表示阻塞等待命令执行完成

如果遇到账户被锁,用 unlock命令解锁即可。

account unlock [addr] -p [pwd]

其中pwd即是在1.2中创建的密码。

部署成功后能看到:

image-20220727124625807

💡需要注意的是,在Move中代码存储在个人的地址上,而非像以太坊那样的公共地址上。因此合约部署后并不会创建新地址,当我们想要调用合约时需要采用部署合约人的地址+合约名来调用该合约。

2.3 控制台调用

https://starcoinorg.github.io/starcoin-cookbook/docs/move/interacting-with-the-contract

  1. 调用 init_counter 脚本函数来初始化资源。
starcoin% account execute-function --function {MyCounterAddr-in-Move.toml}::MyCounter::init_counter -s 0x23dc2c167fcd16e28917765848e189ce -b

其中:

  • {MyCounterAddr-in-Move.toml}::MyCounter::init_counter为完整的函数链上地址,包括合约所在地址+包名+函数名。
  • -s 即--sender,-b即--blocking,表示阻塞等待命令执行完成
  1. 查看Counter资源
starcoin% state get resource 0x23dc2c167fcd16e28917765848e189ce 0x23dc2c167fcd16e28917765848e189ce::MyCounter::Counter

在Move中合约的数据被称为资源(resource),由于读取数据不改变链上状态,因此不需要-s -b,不会执行交易,也不消耗状态。

感兴趣的同学可以试着调用incr_counter,并再次查看Counter是否+1。

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

0 条评论

请先 登录 后评论