原文链接:https://developers.libra.org/docs/my-first-transaction
译者:humyna
日期:2019.07.24
更新日期:2020.02.22
版权及转载声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
文档将指导您在 Libra 区块链上执行您的第一笔交易。 在您按照文档的步骤执行第一笔交易之前,我们建议您阅读以下文档,以熟悉 Libra 生态系统和 Libra 协议的关键概念:
我们提供了一个命令行界面(CLI)客户端来与区块链进行交互。
本文档中的所有命令均假设为:
- 您使用的是 Linux(Red Hat或基于Debian)或 macOS系统。
- 您可以稳定地连接到互联网。
- 您的系统上安装了
git
。 - macOS 系统上已安装了 Homebrew。
- Linux系统上安装了
yum
或者apt-get
。
在这个例子中,我们将下载必要的 Libra 组件并在两个用户(Alice和Bob)之间执行一笔交易。
执行以下步骤将提交一笔交易到 Libra 测试网络testnet上的验证节点:
git clone https://github.com/libra/libra.git
安装 Libra Core,需要切换到 libra
目录并运行安装脚本来安装相关的依赖,如下所示:
cd libra
./scripts/dev_setup.sh
安装脚本执行以下操作:
- 安装rustup — rustup 是 Rust 编程语言的安装程序,Libra Core是基于Rust实现的。
- 安装相应版本的 Rust 工具链。
- 安装CMake — 用于管理编译过程。
- 安装protoc — protocol buffers编译器。
- 安装Go — 用于构建protocol buffers。
如果您的安装失败,详见故障排除说明
为了连接到 Libra 测试网络testnet的验证器节点,运行如下所示的客户端:
./scripts/cli/start_cli_testnet.sh
这个命令构建和运行客户端使用cargo(Rust的包管理器),并连接到测试网络testnet上的验证器节点。
客户端连接到测试网络testnet上的节点后,您将看到下面的输出。 可以使用quit
命令,随时退出客户端。
usage: <command> <args>
Use the following commands:
account | a
Account operations
query | q
Query operations
transfer | transferb | t | tb
<sender_account_address>|<sender_account_ref_id> <receiver_account_address>|<receiver_account_ref_id> <number_of_coins> [gas_unit_price (default=0)] [max_gas_amount (default 10000)] Suffix 'b' is for blocking.
Transfer coins from account to another.
help | h
Prints this help
quit | q!
Exit this client
Please, input commands:
libra%
如果您在构建客户端和连接到测试网络testnet时遇到问题,请参阅故障排除说明.
注意: 如果您要在您的系统上本地运行验证器节点,请按照运行一个本地验证器中的说明操作。 创建帐户,铸币和执行一笔交易就像在测试网络testnet上的节点一样。
将客户端连接到测试网络testnet后,可以运行CLI命令来创建新帐户。我们将引导你为两个用户(Alice和Bob)创建帐户。
出现一个 libra% 命令行提示符表名您的 Libra CLI客户端正在运行。 要查看account
命令的帮助信息,请输入“account”,如下所示:
libra% account
usage: account <arg>
Use the following args for this command:
create | c
Create an account. Returns reference ID to use in other operations
list | la
Print all accounts that were created or loaded
recover | r <file path>
Recover Libra wallet from the file path
write | w <file name>
Save Libra wallet mnemonic recovery seed to disk
mint | mintb | m | mb <receiver account> <number of coins>
Mint coins to the account. Suffix 'b' is for blocking
请注意,使用CLI创建帐户不会更新区块链,只是创建一个本地密钥对。
要创建Alice的帐户,请输入以下命令:libra% account create
成功示例输出:
>> Creating/retrieving next account from wallet
Created/retrieved account #0 address 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8
#0是Alice帐户的索引,十六进制字符串是Alice帐户的地址。 索引只是引用Alice帐户的一种方式。 帐户索引是本地CLI索引,可以在其他CLI命令中使用,以便用户方便地引用他们创建的帐户。 该索引对区块链毫无意义。 只有当通过挖矿将任何一笔钱添加到Alice的账户时,才会在区块链上创建Alice的账户,或者通过来自另一个用户的转账将钱转移到Alice的账户。 请注意,您也可以在CLI命令中使用十六进制地址。 帐户索引只是帐户地址的方便显示。
要创建Bob的帐户,请重复之前帐户创建命令:libra% account create
成功示例输出:
>> Creating/retrieving next account from wallet
Created/retrieved account #1 address 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7
#1 是Bob帐户的索引,十六进制字符串是Bob帐户的地址。 有关索引的更多详细信息,请参阅创建Alice的账户
要列出您创建的帐户,输入命令:libra% account list
成功示例输出:
User account index: 0, address: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8, sequence number: 0
User account index: 1, address: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7, sequence number: 0
帐户中的序列号表示从该帐户发送的交易数。 每次从该帐户发送一笔交易被执行并存储在区块链中,它会加+1。 要了解更多,请参阅 序列号。
在测试网络testnet上挖矿和添加币是通过Faucet完成的。 Faucet是与testnet一起运行的服务。 此服务仅用于为testnet创建币,并在主网上并不存在. 它创建的Libra 币并没有真实的价值,假设你已经创建了Alice和Bob的账户, 分别是索引0和索引1,您可以按照以下步骤将Libra 币添加到两个帐户。
铸造Libra币,并添加到Alice的帐户,输入命令:libra% account mint 0 110
- 0 是Alice账户的索引号。
- 110 是要添加到Alice账户的Libra币的数量。
账户成功运行铸币命令,也会在Libra区块链上创建Alice的账户。
成功示例输出:
>> Minting coins
Mint request submitted
请注意,当请求被提交意味着它已被成功添加到内存池(测试网络testnet上的验证节点)。 但并不一定意味着它将成功完成。 稍后,我们将查询帐户余额以确认铸币是否成功。
如果您的帐户铸币命令不能成功提交您的请求,请参阅故障排除说明
铸造Libra币并添加到Bob的帐户,输入命令:libra% account mint 1 52
- 1 是Bob账户的索引号。
- 52 是要添加到Bob账户的Libra币数量。
- **一个成功的账户铸币命令将在区块链上创建Bob的账户。**在区块链上创建Bob帐户的另一种方法是将钱从Alice的帐户交易到Bob的帐户。
成功后输出如下:
>> Minting coins
Mint request submitted
如果您的帐户铸币命令不能成功提交您的请求,请参阅故障排除说明
检查Alice账户的余额,运行命令:libra% query balance 0
成功示例输出:Balance is: 110
检查Bob账户的余额,运行命令:libra% query balance 1
成功示例输出:Balance is: 52
在我们将Libra币从Alice的账户转移到Bob的账户的交易被提交之前,我们将查询每个账户的序列号。 这将帮助我们理解执行一笔交易是怎样改变每个帐户的序列号的。
libra% query sequence 0
>> Getting current sequence number
Sequence number is: 0
libra% query sequence 1
>> Getting current sequence number
Sequence number is: 0
在 query sequence 0
, 0是Alice的帐户的索引。 Alice和Bob的帐户的序列号都为0,表示到目前为止Alice或Bob的帐户仍未执行任何交易。
提交一笔从Alice账户转账10个Libra币到Bob账户的交易,输入命令:libra% transfer 0 1 10
- 0是Alice的帐户索引。
- 1是Bob的帐户索引。
- 10是从Alice的账户转到Bob账户的Libra币的数量。
成功示例输出:
>> Transferring
Transaction submitted to validator
To query for transaction status, run: query txn_acc_seq 0 0 <fetch_events=true|false>
您可以使用命令 query txn_acc_seq 0 0 true
(按帐户和序列号进行交易)来查看有关您刚提交的交易的信息。 第一个参数是发送方帐户的本地索引,第二个参数是帐户的序列号。要查看此命令的示例输出,请参阅 示例输出。
您刚刚将交易提交到测试网络testnet上的验证节点,它被添加进验证器的内存池 。这并不意味着您的交易已被执行。 理论上,如果系统运行缓慢或过载,则需要一些时间才能看到结果,您需要通过多次查询账户。 要查询索引为0的帐户,可以使用命令 query account_state 0.
预期输出显示在示例输出。
要解决转账命令问题,请参阅 故障排除说明.
区块转账命令: 您可以使用 transferb
命令 (如下所示)代替 transfer
命令。 transferb
命令将提交交易并仅在交易被提交到区块链后在客户端提示返回结果。一个例子如下所示:libra% transferb 0 1 10
参考交易的生命周期 了解一笔交易从提交到执行和存储的整个生命周期。
libra% query sequence 0
>> Getting current sequence number
Sequence number is: 1
libra% query sequence 1
>> Getting current sequence number
Sequence number is: 0
Alice的帐号(索引0)的序号为1表示到目前为止已经从Alice的帐户发送了一个交易。 Bob的帐户(索引1)的序列号为0表示到目前为止尚未从Bob的帐户发送任何交易。 每次从帐户发送一笔交易,序列号都会增加1。
要检查两个帐户中的最终余额,请按照 这个步骤 再次查询每个账户余额. 如果您的交易(转账)成功执行,您应该在Alice的账户中看到100个Libra币,在Bob的账户中看到62个Libra币。
libra% query balance 0
Balance is: 100
libra% query balance 1
Balance is: 62
您已成功在 Libra 测试网络testnet上执行了您的交易,并将10个Libra币从Alice的账户转移到了Bob的账户!
- 更新 Rust:
- 在libra目录运行
rustup update
- 在libra目录运行
- 更新 protoc:
- 更新的版本
protoc
至3.6.0或以上。
- 更新的版本
- 从你的libra目录重新运行安装脚本:
./scripts/dev_setup.sh
如果您遇到构建失败,请尝试从libra目录中删除cargo的lock文件:
rm Cargo.lock
如果您的客户端没有连接到测试网络testnet:
- 检查您的网络连接。
- 确保您使用的是最新版本的客户端。 拉取最新的Libra Core并重新运行客户端:
./scripts/cli/start_cli_testnet.sh
- 如果您在测试网络testnet上连接的验证节点不可用,您将收到一个如下所示的“服务器不可用”的消息:
libra% account mint 0 110
>> Minting coins
[ERROR] Error minting coins: Server unavailable, please retry and/or check **if** host passed to the client is running
-
如果您在提交一笔交易后余额没有更新,请稍等片刻再次查询余额。 如果区块链上有大量交易在处理,那么可能会有延迟。 如果您的余额仍没有被更新,请尝试再次铸币。
-
要检查帐户是否存在,请查询帐户状态。 对于索引为0的帐户,请输入命令:
libra% query account_state 0
如果您的客户端连接的测试网络testnet上的验证节点不可用或与测试网络testnet的连接超时,您将看到错误:
libra% transfer 0 1 10
>> Transferring
[ERROR] Failed to perform transaction: Server unavailable, please retry and/or check if host passed to the client is running
为了解决转账错误:
- 检查测试网络testnet的连接。
- 查询发件人帐户以确保它存在。 对索引为0的帐户使用下面的命令:
query account_state 0
- 您可以使用
quit
或q!
退出客户端, 然后重新运行以下命令连接到测试网络testnet:- 从libre目录运行
./scripts/cli/start_cli_testnet.sh
- 从libre目录运行
这个例子将使用帐户和序列号查询单个交易的详细信息。
libra% query txn_acc_seq 0 0 true
>> Getting committed transaction by account and sequence number
Committed transaction: SignedTransaction {
{ raw_txn: RawTransaction {
sender: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8,
sequence_number: 0,
payload: {,
transaction: peer_to_peer_transaction,
args: [
{ADDRESS: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7},
{U64: 10000000},
]
},
max_gas_amount: 10000,
gas_unit_price: 0,
expiration_time: 1560466424s,
},
public_key: 55af3fe3f28550a2f1e5ebf073ef193feda44344d94c463b48be202aa0b3255d,
signature: Signature( R: CompressedEdwardsY: [210, 23, 214, 62, 228, 179, 64, 147, 81, 159, 180, 138, 100, 211, 111, 139, 178, 148, 81, 1, 240, 135, 148, 145, 104, 234, 227, 239, 198, 153, 13, 199], s: Scalar{
bytes: [203, 76, 105, 49, 64, 130, 162, 81, 22, 237, 159, 26, 80, 181, 111, 94, 84, 6, 152, 126, 181, 192, 62, 103, 130, 94, 246, 174, 139, 214, 3, 15],
} ),
}
}
Events:
ContractEvent { access_path: AccessPath { address: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8, type: Resource, hash: "217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97", suffix: "/sent_events_count/" } , index: 0, event_data: AccountEvent { account: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7, amount: 10000000 } }
ContractEvent { access_path: AccessPath { address: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7, type: Resource, hash: "217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97", suffix: "/received_events_count/" } , index: 0, event_data: AccountEvent { account: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8, amount: 10000000 } }
请注意,交易金额以 microlibra 单位显示.
在下面的例子中,我们将从索引为0的帐户查询“发送”事件。您会注意到我们从这个帐户发送了一个交易后发生了一个事件。当前状态的凭证也被返回以便可以执行不会丢失任何事件的验证 ——这在查询不返回“限制”事件时完成。
libra% query event 0 sent 0 true 10
>> Getting events by account and event type.
EventWithProof {
transaction_version: 3,
event_index: 0,
event: ContractEvent { access_path: AccessPath { address: e7460e02058b36d28e8eef03f0834c605d3d6c57455b8ec9c3f0a3c8b89f248b, type: Resource, hash: "217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97", suffix: "/sent_events_count/" } , index: 0, event_data: AccountEvent { account: 46efbad798a739c088e0e98dd9d592c27c7eb45ba1f8ccbdfc00bd4d7f2947f3, amount: 10000000 } },
proof: EventProof { ledger_info_to_transaction_info_proof: AccumulatorProof { siblings: [HashValue(62570ae9a994bcb20c03c055667a4966fa50d0f17867dd5819465072fd2c58ba), HashValue(cce2cf325714511e7d04fa5b48babacd5af943198e6c1ac3bdd39c53c87cb84c)] }, transaction_info: TransactionInfo { signed_transaction_hash: HashValue(69bed01473e0a64140d96e46f594bc4b463e88e244b694e962b7e19fde17f30d), state_root_hash: HashValue(5809605d5eed94c73e57f615190c165b11c5e26873012285cc6b131e0817c430), event_root_hash: HashValue(645df3dee8f53a0d018449392b8e9da814d258da7346cf64cd96824f914e68f9), gas_used: 0 }, transaction_info_to_event_proof: AccumulatorProof { siblings: [HashValue(5d0e2ebf0952f0989cb5b38b2a9b52a09e8d804e893cb99bf9fa2c74ab304bb1)] } }
}
Last event state: Some(
AccountStateWithProof {
version: 3,
blob: Some(
AccountStateBlob {
Raw: 0x010000002100000001217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc974400000020000000e7460e02058b36d28e8eef03f0834c605d3d6c57455b8ec9c3f0a3c8b89f248b00e1f50500000000000000000000000001000000000000000100000000000000
Decoded: Ok(
AccountResource {
balance: 100000000,
sequence_number: 1,
authentication_key: 0xe7460e02058b36d28e8eef03f0834c605d3d6c57455b8ec9c3f0a3c8b89f248b,
sent_events_count: 1,
received_events_count: 0,
},
)
},
),
proof: AccountStateProof {
ledger_info_to_transaction_info_proof: AccumulatorProof {
siblings: [
HashValue(62570ae9a994bcb20c03c055667a4966fa50d0f17867dd5819465072fd2c58ba),
HashValue(cce2cf325714511e7d04fa5b48babacd5af943198e6c1ac3bdd39c53c87cb84c),
],
},
transaction_info: TransactionInfo {
signed_transaction_hash: HashValue(69bed01473e0a64140d96e46f594bc4b463e88e244b694e962b7e19fde17f30d),
state_root_hash: HashValue(5809605d5eed94c73e57f615190c165b11c5e26873012285cc6b131e0817c430),
event_root_hash: HashValue(645df3dee8f53a0d018449392b8e9da814d258da7346cf64cd96824f914e68f9),
gas_used: 0,
},
transaction_info_to_account_proof: SparseMerkleProof {
leaf: Some(
(
HashValue(c0fbd63b0ae4abfe57c8f24f912f164ba0537741e948a65f00d3fae0f9373981),
HashValue(fc45057fd64606c7ca40256b48fbe486660930bfef1a9e941cafcae380c25871),
),
),
siblings: [
HashValue(4136803b3ba779bb2c1daae7360f3f839e6fef16ae742590a6698b350a5fc376),
HashValue(5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000),
HashValue(a9a6bda22dd6ee78ddd3a42da152b9bd39797b7da738e9d6023f407741810378),
],
},
},
},
)
在这个例子中,我们将查询单个帐户的状态。
libra% query account_state 0
>> Getting latest account state
Latest account state is:
Account: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8
State: Some(
AccountStateBlob {
Raw: 0x010000002100000001217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc9744000000200000003ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a800e1f50500000000000000000000000001000000000000000100000000000000
Decoded: Ok(
AccountResource {
balance: 100000000,
sequence_number: 1,
authentication_key: 0x3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8,
sent_events_count: 1,
received_events_count: 0,
},
)
},
)
Blockchain Version: 3
要在本地计算机上启动验证节点,并创建你自己的本地区块链网络(未连接到Libra测试网络testnet),请确保您已经运行 安装Libra Core 中描述的构建脚本, 然后切换到Libra Core库的根目录,运行如下所示的 libra-swarm
命令:
$ cd ~/libra
$ cargo run -p libr-swarm -- -s
-p libra-swarm
- 使用cargo运行libra-swarm包,启动由一个节点组成的本地区块链。
-s
启动一个本地客户端以连接到本地区块链。
要查看启动一个节点和连接到Libra区块链的其他选项,请运行:
$ cargo run -p libra-swarm -- -h
Cargo命令可能需要一些时间才能执行完成。 如果这个命令执行完成且没有错误,则您的系统上将运行一个Libra CLI客户端实例和一个Libra验证节点。 成功执行后,您应该看到包含CLI客户端菜单和libra%
提示符的输出。
执行完您的第一笔交易后,您可以参阅文档 交易的生命周期 以便:
- 深入“底层”理解一笔交易从提交到执行的生命周期
- 理解在Libra生态系统中提交和执行一笔交易时Libra验证器的各个逻辑组件之间的交互。
- 欢迎页
- Libra 协议关键概念 — 介绍 Libra 协议的核心概念。
- 开始使用Move — 介绍新区块链编程语言Move。
- 交易的生命周期 — 介绍交易被提交和执行的底层实现
- Libra Core 概述 — Libra Core 组件的概念和实现细节。
- CLI 指南 — 列出了Libra CLI客户端的命令及其用法。
- Libra 词汇表 — 提供了一份Libra技术的快速参考。