Facebook Libra - 第一筆交易

第一筆交易

假定

  • 運行的是Linux或者macOS系統
  • 網絡鏈接正常
  • git已安裝
  • macOS中安裝了Homebrew
  • Linux中安裝了yum或者apt-get

提交一筆交易的步驟

  1. 克隆並構建Libra Core
  2. 構建Libra命令行客戶端而且鏈接到測試網絡
  3. 建立Alice和Bob的帳戶
  4. 挖礦並添加到Alice與Bob的帳戶中
  5. 提交一筆交易

克隆並構建Libra Core

克隆Libra Core倉庫

git clone https://github.com/libra/libra.git

啓動Libra Core

切換到libra文件夾而且運行啓動腳原本安裝依賴:node

cd libra
./scripts/dev_setup.sh

這個安裝腳本里面有如下幾步git

  • 安裝rustup - rustup是一個Rust語言的安裝器,Libra Core就是用其實現的
  • 安裝rust-toolchain的正確版本
  • 安裝CMake - 管理構建過程
  • 安裝protoc - 一個protocol buffers的編譯器
  • 安裝Go - 構建protocol buffers

若是遇到問題,詳見解決問題github

構建Libra命令行客戶端而且鏈接到測試網絡

爲了鏈接到Libra測試網絡的驗證節點,按照以下方式運行客戶端bash

./scripts/cli/start_cli_testnet.sh

這條命令使用cargo(Rust的包管理器)來構建並運行客戶端,並把客戶端鏈接到測試網絡上的一個驗證節點。網絡

一旦客戶端鏈接到測試網絡上的節點,你將會看到以下輸出。退出可使用 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%

若是在構建客戶端與鏈接測試網時出現問題,詳見解決問題測試

注意:若是你想在本地運行一個驗證節點,按照這裏的操做進行:運行一個本地驗證節點fetch

建立Alice和Bob的帳戶

一旦你的客戶端鏈接到了測試網,你就能夠運行CLI命令來建立新帳戶了。咱們將會爲兩個用戶建立帳戶(就叫Alice和Bob吧)ui

第一步:檢查你的系統上是否運行着CLI客戶端

一個 libra% 的命令行前綴說明你的Libra CLI客戶端正在運行中。按照下面這樣輸入「account」能夠看到關於__account__命令的幫助信息this

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

第二步:建立Alice的帳戶

注意用CLI建立一個帳戶並不會更新到區塊鏈上,只是建立了一個本地的鑰匙對。

爲了建立Alice的帳戶,輸入下面的命令:

libra% account create

成功的話輸出就像下面這樣:

>> Creating/retrieving next account from wallet
Created/retrieved account #0 address 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8

0#是Alice帳戶的索引,這個16進制的字符串就是Alice的帳戶地址。索引只是一種指向Alice帳戶的方式。帳戶索引可讓用戶在其餘的CLI命令中便捷地指向他們所建立帳戶的一個本地CLI索引。索引對於區塊鏈來講是沒什麼意義的。只有當經過挖礦或者他人轉帳方式,有資金轉入到Alice的帳戶的時候,Alice的帳戶纔會在區塊鏈上面被建立。注意你可能使用了CLI中的16進制地址。這個帳戶索引只是對於帳戶地址的一種便利的包裝而已。

第三步:建立Bob的帳戶

爲了建立Bob的帳戶,重複下面的帳戶建立命令:

libra% account create

成功的話輸出就像下面這樣:

>> Creating/retrieving next account from wallet
Created/retrieved account #1 address 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7

#1就是Bob的帳戶索引,這個16進制字符串就是Bob的帳戶。

第四步(可選):帳戶列表

輸入下面的命令能夠列出你所建立的帳戶:

libra% account list

成功的話輸出就像下面這樣:

User account index: 0, address: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8, sequence number: 0
User account index: 1, address: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7, sequence number: 0

這個帳戶的序列號(sequence number)表明的是從這個帳戶發送的交易的數量。每當這個帳戶發送了一筆交易被執行而且存儲到了區塊鏈中,這個數字就會增長。瞭解更多詳見序列號

給Alice和Bob的帳戶中添加Libra幣

在測試網上挖礦並給帳戶添加幣是經過Faucet完成的。Faucet是一個和測試網一同運行的服務。這個服務存在的目的只是爲了促進測試網上的挖礦速度,並且主網是沒有的。它建立的Libra是沒有實際價值的。假定你已經建立了Alice和Bob的帳戶,各自的索引是0和1。那麼你能夠按照下面的步驟來添加Libra到各個帳戶中

第一步:添加110Libra到Alice的帳戶中

爲了挖取Libra並添加到Alice的帳戶中,輸入下面的命令:

libra% account mint 0 110
  • 0是Alice帳戶的索引
  • 110是添加到Alice帳戶中的Libra數量

一個成功的帳戶挖取命令同時會在區塊臉上建立Alice的帳戶。

成功的話輸出就像下面這樣:

>> Minting coins
Mint request submitted

注意當請求提交的時候,意味着它被成功地添加到了(測試網上的驗證節點的)內存池中。這並不意味着它就會被成功執行。後面,咱們將會查詢帳戶餘額來確認挖礦是否成功。

若是你的帳戶挖礦命令沒有成功提交你的請求,詳見問題

第二步:添加52Libra到Bob的帳戶中

爲了挖取Libra並添加到Bob的帳戶中,輸入下面的命令:

libra% account mint 1 51
  • 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到Bob帳戶的轉帳交易以前,咱們先去查詢每一個帳戶的序列號(sequence number)。這將幫助咱們理解交易的執行是若是改變每一個帳戶的序列號的。

查詢帳戶的序列號

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帳戶的索引。0這個序列號說明到目前爲止,Alice和Bob的帳戶都沒有發送過交易。

轉帳

爲了提交一筆從Alice到Bob的帳戶10和Libra的交易,輸入下面的命令:

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 (經過帳戶和序列號的交易)這條命令來追溯剛剛提交的交易的相關信息。第一個參數是發送者帳戶的本地索引,第二個參數是帳戶的序列號(sequence number)。

你剛剛向測試網上的驗證節點提交了一筆交易,它被包含在了驗證節點的內存池中。這並不意味着你的交易已經被執行了。理論上來講,若是系統太慢了或者負載過高,要看到結果須要一些時間,你可能須要檢查好屢次帳戶信息。爲了查詢一個索引是0的帳戶,你可使用 query account_state 0 這條命令。

關於相關的轉帳問題,能夠看看問題

阻塞轉帳命令(The Blocking Transfer command): 可使用 transferb 命令來代替 transfer 命令。 transferb 會提交交易而且只有當交易被提交到區塊鏈上的時候纔會返回到客戶端提示符上。例子以下:

libra% transferb 0 1 10

交易的生命週期描述了一筆交易從提交到執行存儲的生命週期。

轉帳後查詢序列號(sequence number)

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帳戶有100Libra同時Bob的帳戶有62Libra。

libra% query balance 0
Balance is: 100
libra% query balance 1
Balance is: 62

恭喜

你已經成功地在測試網上執行了一筆從Alice到Bob帳戶10個Libra的交易。

問題處理

啓動

  • 更新Rust:
    • 在libra文件夾中運行 rustup update
  • 更新protoc:
    • 更新protoc到3.6.0版本或者更高
  • 在libra文件夾中從新運行啓動腳本
    • ./scripts/dev_setup.sh

客戶端構建與運行

若是出現了構建錯誤,嘗試移除libra文件夾的cargo的lock文件

  • rm Cargo.lock

若是客戶端沒有鏈接到測試網:

  • 檢查網絡鏈接
  • 確保使用了最新版本的客戶端。拉取最新的Libra Core並從新運行客戶端
    • ./scripts/cli/start_cli_testnet.sh

挖礦並添加錢款到帳戶

  • 若是你鏈接的測試網驗證節點不可用,你會獲得一個"Server unavailable" (服務不可用)消息,就像下面這樣:
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

轉帳命令

若是(你的客戶端鏈接到的)測試網絡節點不可用,或者鏈接超時,你會看到這樣的錯誤:

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

爲了解決轉帳錯誤:

  • 檢查到測試網的網絡鏈接
  • 檢查發送者帳戶,肯定它是存在的。對於索引是0的帳戶,使用下面的命令:
    • query account_state 0
  • 你可使用 quit 或者 q 來嘗試退出客戶端,而後從新運行下面的命令來鏈接到測試網絡
    • libra文件夾中運行 ./scripts/cli/start_cli_testnet.sh

額外查詢命令的樣例輸出

經過帳戶和序列號查詢交易

這個例子將會使用帳戶和序列號查詢一筆單獨的交易。

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(應該是libra的一種計量單位) 展現的。

查詢結果

在下面的這個例子中,咱們將會查詢索引爲0這個帳戶的"sent"事件。你會注意到在咱們從這個帳戶發送了一筆帳戶以後會有一個事件。當前狀態的證實(proof)也被返回了,所以能夠驗證沒有丟失事件 - 當查詢沒有返回"limit"事件的時候會完成此事件。

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測試網絡),須要確保你已經運行了以前所說的構建腳本,變動到Libra Core倉庫的根路徑,而後運行 libra_swarm ,就像下面這樣:

$ cd ~/libra
$ cargo run -p libra_swarm -- -s

-p libra_swarm 是cargo開始運行 libra_swarm 包,這樣會啓動一個包含一個節點的本地區塊鏈。

-s 選項啓動一個鏈接到本地區塊鏈上的本地客戶端

爲了看到開啓節點與鏈接到Libra區塊臉上的額外選項,運行:

$ cargo run -p libra_swarm -- -h

cargo運行命令可能須要一些時間來運行。若是這條命令的執行了且沒有錯誤,那麼一個Libra CLI客戶端的實例和一個本地的驗證節點就已經運行在你的系統中了。在成功執行的基礎上,你將會看到包含着CLI客戶端菜單和 libra 提示符的輸出。

交易的生命週期

一旦你已經完成了你的第一筆交易,你能夠去看看 交易的生命週期 的文檔了,目的在於:

  • 深刻了解交易從提交到執行的過程。
  • 瞭解在交易在Libra生態系統中提交與執行過程當中,Libra驗證器的各個邏輯組件之間的交互。
相關文章
相關標籤/搜索