Our Initial Tests of Facebook’s Libra — What’s There Today

Unless you’ve been living under a rock, you’ve probably heard the big announcement about Facebook’s new Libra cryptocurrency.

With partners like Visa, Mastercard, Paypal, Uber, Coinbase, etc, we are looking at a big disruptive force coming for the banking industry (and note, there are no banks signed on). Make no mistake, this is massive news. And no matter what your thoughts are on Facebook as a company, it cannot be ignored that they have one of the largest distribution networks on earth of more than 1 billion people. This will be a huge step forward for cryptocurrency onboarding and adoption. Eric Voorhees ends his Libra tweet storm with this comment:

Anything that causes normal people to consider new forms of money (apart from their default position of “my nation, my currency”) is a good thing. Libra will crack open further global discussion about what money is, and that sunshine will hurt fiat, and help all sound monies.

I decided to give Libra a hands-on test to get my feet wet and see what it is you can actually do with Libra today.

Installing Libra Testnet

Whoa, this part was much easier than I expected. It took less than five minutes to get up and running on the Libra testnet.

Linux and macOS are supported today (I’m using a Macbook). I have all of the dev environment tools already installed, so it would take longer if you had to install git and homebrew. I’ve included the steps below, but you should read the official developer documentation here.

  1. Clone the git repo

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

2. Setup Libra core

cd libra./scripts/dev_setup.sh

3. Build and connect to Libra testnet

./scripts/cli/start_cli_testnet.sh

The last command will run the client that connects to a validator node on the testnet.

Everything You Can Do With Libra Today

With my client running, I can see all of the CLI commands available. This gives me a picture of what I can do with Libra today. Here are the three top-level CLI commands available (other than help and quit):

  1. account — Account operations

  2. query — Query operations

  3. transfer — Transfer coins from account to another

Let’s dive into each of these.

Account Operations

Here are the account level operations that can be performed:

  1. create — Creates an account. This just creates an account locally. The account isn’t actually written to the blockchain until either money is added to the account via the mint command or money is transferred to the account from another account via the transfer command.

  2. list — Print all accounts that were created or loaded.

  3. recover — Recover Libra wallet from the file path. This assumes the writecommand was already executed.

  4. write — Save Libra wallet mnemonic recovery seed to disk.

  5. mint — Mint coins to the account.

Query Operations

Here are the query level operations that can be performed:

  1. balance — Get the current balance of an account.

  2. sequence — Get the current sequence number for an account, and reset current sequence number in CLI.

  3. account_state — Get the latest state for an account.

  4. txn_acc_seq — Get the committed transaction by account and sequence number. Optionally also fetch events emitted by this transaction.

  5. txn_range — Get the committed transactions by version range. Optionally also fetch events emitted by these transactions.

  6. event — Get events by account and event type (sent|received).

Transfer Operations

There is only one command in this category:

transfer — Transfer coins from account to another.

This is a simple command with a simple format of transfer <from> <to> <amount>.

transferb — You can also add a Suffix ‘b’ to the command for blocking. This is a nice feature so that you will only get the CLI prompt back after the command is committed to the blockchain. Otherwise, you need to keep manually checking on the transaction status to see that the transaction was successfully added to the blockchain by a validator node.

Testing a Transfer

The first thing I needed to do to test a transfer (following the steps in the developer docs) is to create two accounts:

libra% account create>> Creating/retrieving next account from walletCreated/retrieved account #0 address 8a5188bebb6c16a4376ad00c7b21dfce838a981909993b2591264f28ddfc3284
libra% account create>> Creating/retrieving next account from walletCreated/retrieved account #1 address 2f33a551c51a6e519578960d5830bcf5f8ef4fc5f393159d510e29e882fafe82

As noted previously, these two accounts aren’t actually created on the blockchain yet until the accounts actually have money (via minting or transfer of money from another account).

Next, I had to mint some Libra:

libra% account mint 0 110>> Minting coinsMint request submitted

The ‘0’ is the index of the first account I created, and the ‘110’ is the amount of Libra to mint to this account. The “Mint request submitted” does not mean that the minting was successfully completed. It simply means the minting request was added to the mempool (of a validator node on testnet) successfully.

Next, I attempted to mint Libra to the second account (index 1):

libra% account mint 1 52>> Minting coins[ERROR] Error minting coins: Failed to query remote faucet server[status=429 Too Many Requests]: "<html><body><h1>429 Too Many Requests</h1>\nYou have sent too many requests in a given amount of time.\n</body></html>\n"

However, I was blocked from performing this action so soon after the request for account 0 minting. The testnet faucet is currently throttling/limiting the amount of times one client can mint Libra successively. After waiting another minute, I tried again successfully.

After waiting just a little bit longer, I could query the account balances to verify the Libra had been written to the accounts:

libra% query balance 0Balance is: 110
libra% query balance 1Balance is: 52

Next, it was time to test a transfer:

libra% transfer 0 1 10>> TransferringTransaction submitted to validatorTo query for transaction status, run: query txn_acc_seq 0 0 <fetch_events=true|false>

The syntax is <sender index> <receiver index> <amount>. Just like in the minting case, the transfer request was simply added to the mempool (of a validator node on testnet) successfully.

Querying the transaction status as suggested above yields the following output:

libra% query txn_acc_seq 0 0 true>> Getting committed transaction by account and sequence numberCommitted transaction: SignedTransaction {raw_txn: RawTransaction {
sender: 8a5188bebb6c16a4376ad00c7b21dfce838a981909993b2591264f28ddfc3284,
sequence_number: 0,
payload: {,
transaction: peer_to_peer_transaction,
args: [
{ADDRESS: 2f33a551c51a6e519578960d5830bcf5f8ef4fc5f393159d510e29e882fafe82},
{U64: 10000000},
]
},
max_gas_amount: 10000,
gas_unit_price: 0,
expiration_time: 1560938597s,
},
public_key: 78dba684b80e52c4cda11aea58b14adf57acaef039903ecd6c5af14c2da263ec,
signature: Signature( R: CompressedEdwardsY: [0, 67, 215, 248, 136, 219, 43, 209, 135, 145, 128, 66, 239, 185, 56, 169, 165, 211, 206, 165, 44, 99, 157, 247, 134, 189, 203, 197, 236, 96, 238, 200], s: Scalar{
bytes: [44, 133, 8, 174, 158, 254, 153, 4, 52, 218, 60, 255, 203, 47, 121, 213, 222, 108, 105, 16, 124, 219, 99, 53, 35, 44, 139, 235, 34, 222, 148, 3],
} ),
}
Events:
ContractEvent { access_path: AccessPath { address: 8a5188bebb6c16a4376ad00c7b21dfce838a981909993b2591264f28ddfc3284, type: Resource, hash: "217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97", suffix: "/sent_events_count/" } , index: 0, event_data: AccountEvent { account: 2f33a551c51a6e519578960d5830bcf5f8ef4fc5f393159d510e29e882fafe82, amount: 10000000 } }
ContractEvent { access_path: AccessPath { address: 2f33a551c51a6e519578960d5830bcf5f8ef4fc5f393159d510e29e882fafe82, type: Resource, hash: "217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97", suffix: "/received_events_count/" } , index: 0, event_data: AccountEvent { account: 8a5188bebb6c16a4376ad00c7b21dfce838a981909993b2591264f28ddfc3284, amount: 10000000 } }
Once the transaction is successful, a query of balances shows:
libra% query balance 0Balance is: 100
libra% query balance 1Balance is: 62

After this, I submitted 3 more transactions in succession from account 0 to account 1:

libra% transfer 0 1 15>> TransferringTransaction submitted to validatorTo query for transaction status, run: query txn_acc_seq 0 1 <fetch_events=true|false>
libra% transfer 0 1 20>> TransferringTransaction submitted to validatorTo query for transaction status, run: query txn_acc_seq 0 2 <fetch_events=true|false>
libra% transfer 0 1 25>> TransferringTransaction submitted to validatorTo query for transaction status, run: query txn_acc_seq 0 3 <fetch_events=true|false>
libra% query balance 0Balance is: 40

Now I queried the sequence number for Account 0:

libra% query sequence 0>> Getting current sequence numberSequence number is: 4

The sequence number for this account indicates the total number of transactions send from this account.

For Account 1, the sequence number is still 0, because no transactions were actually sent from this account (it only received money):

libra% query sequence 1>> Getting current sequence numberSequence number is: 0
libra% query balance 1Balance is: 122

Conclusion

So today, this is what clients can do with Libra: create user accounts, transfer money (Libra) between these accounts, and query the status of those accounts and transfers. That’s it for now, but there is definitely much more feature functionality to be added in the future. It will be exciting to see the development and rollout of this project over the upcoming year.

Further reading:

Our work at GigLabs: www.giglabs.io

Libra developer documentation: https://developers.libra.org/docs/welcome-to-libra

Libra blockchain whitepaper: https://developers.libra.org/docs/assets/papers/the-libra-blockchain.pdf

Brian Burns