本地运行Move程序
- 注意:目前只能在本地网络上运行自定义Move模块和脚本,不能在Libra测试网上运行。
本教程将指导在本地区块链上发布Move模块并执行Move交易脚本。要执行现有Move交易脚本本身不支持的操作,可以创建和发布Move模块,并编写脚本来使用这些模块。Libra CLI客户端提供dev
命令来编译、发布和执行本地的Move程序。要查看子命令列表,在CLI上输入dev
。
要创建、编译和发布Move模块到本地区块链上的帐户,请遵循以下编译和发布Move模块中的说明。要编译和执行Move交易脚本,请遵循以下编译和执行交易脚本中的说明。
编译和发布Move模块
启动一个本地验证器节点网络
首先运行一个本地验证器网络。参考启动一个本地网络文档。
创建一个账户
每个Move模块和资源类型由一个特定的帐户地址托管。例如,Libra
模块由地址为0x1
的帐户托管。要在其他模块或交易脚本中导入Libra
模块,Move代码将指定use 0x1::Libra
。
在发布Move模块之前,首先需要创建一个帐户来托管它:
libra% account create
>> Creating/retrieving next local account from wallet
Created/retrieved local account #0 address 717da70a461fef6307990847590ad7af
在上面的输出中,0是您刚刚创建的帐户的索引,十六进制字符串是该帐户的地址。索引只是在本地引用该帐户的一种方便方式,它也被称为ref_id
。有关帐号创建的更多信息,请参考我的第一次交易
。
create
命令生成一个本地密匙对。要在本地区块链上创建帐户,需要将货币注入该帐户,如下所示:
libra% account mintb 0 76 Coin1
>> Creating recipient account before minting from faucet
waiting ....
transaction executed!
no events emitted
>> Sending coins from faucet
waiting ....
transaction executed!
Finished sending coins from faucet!
要检查在本地区块链上是否成功创建了帐户,请查询帐户余额。
libra% query balance 0
Balance is: 76.000000Coin1
创建Move模块
让我们从一个名为SimpleFee
的简单模块开始。这个模块实现每个帐户的处理费用,可以添加到支付交易中。帐户可以指定链上Move资源的费用金额,应该为每种货币类型收费。帐户所有者可以设置费用金额,任何人都可以检索费用并将其添加到支付中。下面提供了这个模块的Move代码。将第一行中的地址更改为刚刚创建的帐户的地址,然后将其保存在名为SimpleFee.move
的文件中。(确保账户地址保持“0x”前缀。)
address 0x717da70a461fef6307990847590ad7af {
module SimpleFee {
// A simple fixed-price per-account processing fee that can be added
// to payment transactions. There is a different fee for each CoinType.
resource struct Fee<CoinType> {
fee: u64
}
// Set the fee amount.
public fun set_fee<CoinType>(account: &signer, fee: u64) {
move_to(account, Fee<CoinType> { fee })
}
// Get the fee for an account.
public fun get_fee<CoinType>(account: address): u64 acquires Fee {
if (exists<Fee<CoinType>>(account))
borrow_global<Fee<CoinType>>(account).fee
else
0
}
}
}
编译Move模块
为了编译SimpleFee.move
,使用dev编译命令。
libra% dev compile 0 <path to SimpleFee.move> <path to language/stdlib/modules>
- 0 - 索引/ref_id的帐户,该模块将发布在这个账户下。
- 源文件名后面列出的参数指定依赖项,由于该模块依赖于Move标准库,因此需要指定到该目录的路径。
Move代码以.Move
文件的形式输入编译器,编译器输出相应的字节码文件。当准备好将此模块发布到区块链上的帐户中时,请使用该字节码文件,而不是.move文件。
成功编译模块后,将在输出中看到以下消息,它包含编译SimpleFee.move
生成的字节码文件的路径。
Successfully compiled a program at:
/tmp/741fdedbc67720028e60cf637b835a6c/modules/0_SimpleFee.mv
发布已编译的模块
要在本地区块链上发布模块字节码,运行dev publish
命令,并使用编译后的模块字节码文件的路径,如下所示:
libra% dev publish 0 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/b8639bd9fe2403874bbfde5643486bde/modules/0_SimpleFee.mv
waiting .....
transaction executed!
no events emitted.
Successfully published module
在成功执行dev publish
命令后,SimpleFee
的字节码将在发送者的帐户下发布。要使用SimpleFee
中声明的过程和类型,其他交易脚本和模块可以通过use <sender_address>::SimpleFee
导入它。
在<sender_address>
下发布的后续模块不能被命名为SimpleFee
。每个帐户最多只能持有一个具有给定名称的模块。试图在<sender_address>
下发布第二个名为SimpleFee
的模块将导致交易失败。
编译和执行交易脚本
创建交易脚本
要使用SimpleFee
模块,首先创建一个交易脚本来设置费用金额。在下面的脚本中编辑SimpleFee
帐户地址以匹配创建的帐户,然后将其保存为set_lbr_fee.move
:
script {
use 0x1::Coin1::Coin1;
use 0x717da70a461fef6307990847590ad7af::SimpleFee;
fun set_lbr_fee(account: &signer, fee: u64) {
SimpleFee::set_fee<Coin1>(account, fee)
}
}
CLI客户端目前还没有将货币代码转换为自定义脚本的货币类型,所以这个示例脚本硬编码为使用LBR硬币。)
你还需要一个自定义脚本来发送带有附加费用的支付,所以用同样的方法,在下面的脚本中编辑帐户地址,并将其保存为pay_lbr_with_fee.move:
script {
use 0x1::LibraAccount;
use 0x1::Coin1::Coin1;
use 0x717da70a461fef6307990847590ad7af::SimpleFee;
fun pay_lbr_with_fee(payer: &signer, payee: address, amount: u64) {
let payer_withdrawal_cap = LibraAccount::extract_withdraw_capability(payer);
let total = amount + SimpleFee::get_fee<Coin1>(payee);
LibraAccount::pay_from<Coin1>(&payer_withdrawal_cap, payee, total, x"", x"");
LibraAccount::restore_withdraw_capability(payer_withdrawal_cap);
}
}
编译交易脚本
为了编译交易脚本,使用dev compile
命令。
libra% dev compile 0 <path to set_lbr_fee.move> <path to SimpleFee.move> <path to language/stdlib/modules>
set_lbr_fee.move
是Move源文件,在成功编译set_lbr_fee.move
之后。Move编译器将输出相应的字节码文件。当执行这个脚本时,将使用这个字节码文件(不是.move文件)。当脚本成功编译后,会在输出中看到字节码文件的路径:
Successfully compiled a program at:
/tmp/897541d70c8578528ed6d7ae98e044d0/scripts/set_lbr_fee.mv
对pay_lbr_with_fee.move
重复编译步骤:
libra% dev compile 0 <path to pay_lbr_with_fee.move> <path to SimpleFee.move> <path to language/stdlib/modules>
>> Compiling program
Successfully compiled a program at:
/var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/pay_lbr_with_fee.mv
执行交易脚本
要执行自定义脚本,请对上面编译交易脚本的字节码输出使用dev execute
命令。首先,使用set_lbr_fee
脚本来指定费用金额:
- 注意:传递给
dev execute
命令的确切参数集将取决于特定脚本所期望的参数。
libra% dev execute 0 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/set_lbr_fee.mv 10000
waiting .....
transaction executed!
no events emitted
Successfully finished execution
- 0 - 发件人帐户的索引/ref_id。对于本例,编译和发布模块的帐户是相同的。
-
/var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/set_lbr_fee.mv
- 已编译脚本的路径。 - 10000 - 费用金额,以微Libra为单位(0.01Libra)。
接下来,我们可以设置另一个帐户,并使用pay_lbr_with_fee
脚本发送附加费用的支付:
libra% account create
>> Creating/retrieving next local account from wallet
Created/retrieved local account #1 address aed273e4e7b36276e1442656cc16eb31
libra% account mintb 1 10 LBR
>> Creating recipient account before minting from faucet
waiting ....
transaction executed!
no events emitted
>> Sending coins from faucet
waiting ....
transaction executed!
Finished sending coins from faucet!
libra% dev execute 1 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/pay_lbr_with_fee.mv 0x717da70a461fef6307990847590ad7af 1000000
waiting ....
transaction executed!
Successfully finished execution
- 1 - 发送者帐户的Index/ref_id,这是新创建的帐户,将发送支付。
-
/var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/pay_lbr_with_fee.mv
- 已编译脚本的路径 -
0x717da70a461fef6307990847590ad7af
- 收款人帐户地址(帐户索引0)。 - 1000000 -支付金额,以微Libra为单位(0.01Libra)。
这项交易的结果可通过查询帐户余额来观察:
libra% query balance 0
Balance is: 77.010000Coin1
libra% query balance 1
Balance is: 8.990000Coin1
正如预期的那样,1.0个Coin1付款增加了0.01Coin1费用,因此1.01Coin1付款从账户1转到账户0。
故障排除
编译Move程序
如果客户端无法找到你的Move源文件,你会看到这样的错误:
libra% dev compile 0 ~/my-tscripts/set_lbr_fee.move
>> Compiling program
Error: No such file or directory '~/my-tscripts/set_lbr_fee.move'
compilation failed
这可能是因为客户端当前没有执行波浪线扩展,所以需要列出到主目录的路径。
如果看到以下错误,请参考dev compile
命令的用法,指定所有必需的参数并再次尝试编译。
Invalid number of arguments for compilation
发布已编译的模块
如果你编译一个模块使用一个帐户(例如,dev compile 0…),并试图将它发布到另一个帐户(例如,dev publish 1…),你会看到以下错误:
libra% dev publish 1 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/b8639bd9fe2403874bbfde5643486bde/modules/0_SimpleFee.mv
transaction failed to execute; status: VerificationError!
编译后的模块包含要发布模块的帐户地址,Move虚拟机(VM)只允许交易发送方在发送方自己的帐户地址下发布模块。如果不是这样,其他用户就可以在您的帐户下发布模块!若要修复此错误,请使用所需的发送方地址重新编译模块。
如果你没有提供正确的路径到你的编译模块,你会看到这个错误:
libra% dev publish 0 incorrect-path-to-compiled-module
No such file or directory (os error 2)
如果索引1的帐户不存在,尝试将模块发布到1将导致以下错误:
Unable to find account by account reference id: 1, to see all existing accounts, run: 'account list'
在相同发件人帐户地址下重新发布/更新现有模块不会对区块链产生任何影响。这是一个失败的交易,但是它从发送方帐户中扣除gas并将发送方帐户的序列号增加1。可以在不同的发送方帐户地址发布相同的模块,前提是模块是使用该帐户地址编译的。
执行交易脚本
如果发件人帐户索引无效,您将看到以下错误:
libra% dev execute 2 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/set_lbr_fee.mv 10000
Unable to find account by account reference id: 2, to see all existing accounts, run: 'account list'
下面的错误表明,交易脚本的参数要么丢失,要么一个或多个参数类型错误。
libra% dev execute 0 /var/folders/tq/8gxrrmhx16376zxd5r4h9hhn_x1zq3/T/5fa11d0acf5d53e8d257ab31534b2017/scripts/set_lbr_fee.mv
transaction failed to execute; status: VerificationError!
网友评论