简介
Move
是一种安全、沙盒化和经过形式验证的高级编程语言。它的首要用途是为 Diem 区块链提供基础实现。Move
允许开发者编写能够灵活管理和转移资产的程序,同时提供对这些资产遭受攻击的安全性和保护。同时,Move
也考虑了在区块链环境之外的应用场景。
Move
借鉴了 Rust
的做法,通过使用具有 move
(Rust
中的关键字) 语义的资源类型来明确表示数字资产。
安装
$ cargo install --git https://github.com/move-language/move move-cli --branch main
上面的命令将在 Cargo
二进制目录中安装 move
二进制文件。在 Unix
上,这个目录通常是 ~/.cargo/bin
。在终端测试安装是否成功
$ move -V
move-cli 0.1.0
模块和脚本
Move
中有两种类型的代码
- 模块
- 脚本
模块
模块遵循下面的结构
module <address>::<identifier> {
(<use> | <friend> | <type> | <function> | <constant>)*
}
模块使用关键字 module
声明, 紧跟着的 <address>
可以是一个确定性的地址或者定义在 Move.toml
中的地址。如在文件 Move.toml
中声明了下面的地址:
[addresses]
hello = "0x2"
则模块代码可以使用 hello
来指代地址 0x2
module hello::sbt {}
在模块中可以定义 struct
类型以及操作这些类型的函数。struct
类型定义了 Move
存储结构,而函数则定义了更新存储结构的方式。
脚本
脚本遵循下面的结构
script {
<use>*
<constants>*
fun <identifier><[type parameters: constraint]*>([identifier: type]*) <function_body>
}
使用 use
声明脚本中使用的模块。接着可以定义常量和方法。脚本中只能定义一个方法,方法名任意。需要注意的是, 脚本中不能定义变量, 结构体等,其目的仅是调用模块中的函数。
命令
包命令
move new <package_name>
创建项目move build
编译 move 包move build -p <path>
编译指定目录下的 move 包move build --build-dir <path_to_save_to>
通过--build-dir
指定编译后的文件目录move prove
验证 move 包中的规范move prove -p <path>
验证指定目录下 move 包中的规范move test
运行 move 中的单元测试move test -p <path>
运行指定目录下 move 中的单元测试
沙盒命令
沙盒允许在没有验证节点、区块链或交易的情况下编写和运行 Move
代码。持久数据以模拟 Move
内存模型的目录结构存储在磁盘上。
创建项目
$ move new hello
编译并运行脚本
在项目根目录下的 sources
目录创建一个名为 debug_script.move
的文件并输入以下内容:
// sources/debug_script.move
script {
use std::debug;
fun debug_script(account: signer) {
debug::print(&account)
}
}
在运行之前,需要先导入 Move
标准库,以便访问内置的 std
模块。可以在项目根目录下的 Move.toml
文件中指定为本地目录或使用远程路径。
[addresses]
std = "0x1" # Specify and assign 0x1 to the named address "std"
[dependencies]
MoveNursery = { git = "https://github.com/move-language/move.git", subdir = "language/move-stdlib/nursery", rev = "main" }
# ^ ^ ^ ^
# Git dependency Git clone URL Subdir under git repo (optional) Git revision to use
在沙盒中运行
$ move sandbox run sources/debug_script.move --signers 0xf
[debug] signer(0xf)
传递参数
也支持通过 --args
传递参数给 move sandbox run
, 支持以下参数类型
bool
u64
address
- 十六进制字符串
- ASCII 字符串, 如
b"hi"
发布新模块
move sandbox run
命令将编译和发布该包中每个模块。例如有 Test
模块如下所示
// sources/Test.move
module 0x2::Test {
use std::signer;
struct Resource has key { i: u64 } // 资源对象
public fun publish(account: &signer) {
move_to(account, Resource { i: 10 }) // 创建资源, 并转移给 account
}
public fun write(account: &signer, i: u64) acquires Resource {
borrow_global_mut<Resource>(signer::address_of(account)).i = i;
}
}
执行编译
$ move build
在沙盒中部署模块
$ move sandbox publish -v
在项目的 storage
目录, 可以看到 Test
模块的字节码
$ ls storage/0x00000000000000000000000000000002/modules
Test.mv
通过 move view
命令查看编译的字节码
$ move sandbox view storage/0x00000000000000000000000000000002/modules/Test.mv
// Move bytecode v6
module 2.Test {
use 00000000000000000000000000000001::signer;
struct Resource has key {
i: u64
}
public publish(Arg0: &signer) {
B0:
0: MoveLoc[0](Arg0: &signer)
1: LdU64(10)
2: Pack[0](Resource)
3: MoveTo[0](Resource)
4: Ret
}
public write(Arg0: &signer, Arg1: u64) {
B0:
0: MoveLoc[1](Arg1: u64)
1: MoveLoc[0](Arg0: &signer)
2: Call signer::address_of(&signer): address
3: MutBorrowGlobal[0](Resource)
4: MutBorrowField[0](Resource.i: u64)
5: WriteRef
6: Ret
}
}
更新状态
通过脚本来调用发布的 Test
模块‘
// sources/test_script.move
script {
use 0x2::Test; // 引入 Test 模块
fun test_script(account: signer) {
Test::publish(&account)
}
}
该脚本调用了 Test
模块的 publish
方法,该函数将在签名者账户下发布一个类型为 Test::Resource
的资源。通过传递 --dry-run
可以模拟执行而不改变模块的状态。-v
表示显示资源的状态变更
$ move sandbox run sources/test_script.move --signers 0xf -v --dry-run
Changed resource(s) under 1 address(es):
Changed 1 resource(s) under address 0000000000000000000000000000000f:
Added type 0x2::Test::Resource: [10, 0, 0, 0, 0, 0, 0, 0] (wrote 40 bytes)
key 0x2::Test::Resource {
i: 10
}
Wrote 40 bytes of resource ID's and data
Discarding changes; re-run without --dry-run if you would like to keep them.
去掉 --dry-run
来实际运行
$ move sandbox run sources/test_script.move --signers 0xf -v
Changed resource(s) under 1 address(es):
Changed 1 resource(s) under address 0000000000000000000000000000000f:
Added type 0x2::Test::Resource: [10, 0, 0, 0, 0, 0, 0, 0] (wrote 40 bytes)
key 0x2::Test::Resource {
i: 10
}
Wrote 40 bytes of resource ID's and data
publish
方法会创建一个资源, 并转移给传入的地址。通过下面的命令查看发布的资源
$ move sandbox view storage/0x0000000000000000000000000000000f/resources/0x00000000000000000000000000000002::Test::Resource.bcs
key 0x2::Test::Resource {
i: 10
}
该命令的意思是查看 0xf
地址下拥有的 Test::Resource
资源数据
move sandbox clean
可清除 stroage
目录