LibraBridge: Connect Libra with Ethereum

Hi, My name is TSAN-HSIANG HSU and I’m from AMIS technology in Taiwan. In this video, I will present a fun project called LibraBridge. It basically is an exchange between Libra and Ethereum by leveraging SPV validation to implement a cross-chain transfer SPV proof is a way for light client to verify if interested transaction happened on the blockchain. With the help of smart contract, Libra SPV proof can be implemented on Ethereum. Okay, we will introduce the Libra transaction verification first. It contains the merkle tree, transaction information transaction accumulator, and a real gRPC example. Next, we will introduce the concept of LibraBridge. And we will also have a demo. Merkle tree is a data structure used to store data. We called the root of the tree as merkle root. Like, this one. Each leaf node represents for the hash of the data. And every non-leaf node is the hash of its children nodes. For example, h4 is the hash of the concatenation of h0 and h1. If we want to verify whether s2 is in the merkle tree, we should have h3 and h4. First, we calculate h5 by hash of the concatenation of h2 and h3. And we should check if the root is equal to the hash of h4 and h5. In this case, we can say the merkle proof of h2 is h3 and h4. A transaction infomation is the basic object that Libra adds to the transaction merkle tree. It consists of the transaction information like the raw transaction and the public key and the signature. Also, it contains the execution result of the transaction like the state and the event. Since Libra doesn’t have the concept of block explicitly, every transaction will be processed immediately when it passes validation and is sent to the network. Whenever a new transaction is added to the blockchain, the transaction will be put to the rightmost leaf in the merkle tree. Therefore, the value of the merkle root will change every time a new transaction is committed and the merkle tree will grow up with time. Given an ever growing tree, the transaction merkle tree is also named transaction accumulator. Okay, let’s look on a real transaction from Libra testnet. This is a transaction from Libra testnet. You can see the response has a version. So the version represents a unique ID for a transaction and it’s useful to identify the location of one transaction in the transaction accumulator. For example, in this case, a transaction’s version is 4 and its binary representation is 100. 0 means the direction is left and 1 means the direction is right. Therefore, we can simply find this transaction by going right once and going left twice from the root. Let’s move on. There is a bitmap and some non default siblings. So, the bitmap indicates which siblings are default. 1 means non-default and 0 means default. Since the transaction accumulator is growing larger, very often the tree is not a full binary tree. Therefore, a placeholder is needed to maintain the merkle root calculation. For example, in this case, the right one, here, is a placeholder. The binary representation of the bitmap will be 101 or 5 in integer representation. Let’s take a look on transaction info. The transaction information encompasses the detail of this transaction. major_status is 4001 indicating it’s EXECUTED by the node. And the gas_used is not shown because its value is zero. events events is the contract events. A normal peer-to-peer transaction will create exactly two events One is for sent event and one is for received event. Okay. Let’s move on to LibraBridge. Let’s assume we have two roles, a custodian and a participant. Participant is the one who has LIB tokens and he wants to trade his LIB tokens for custodian’s ETH. Custodian, by contrast, is like an Ether merchant, for example, MAX, a crypto exchange in Taiwan. In order to perform the swap, the easiest way is that participant transfers Libra token to the custodian and hopes custodian also transfers Ether back to the participant. If custodian misbehaves by not sending Ether back or there are some unexpected interrupted during the transmission, participant will suffer losses. In this scenario, can we achieve it without trusting custodian? The idea is to leverage the smart contract in Ethereum. The contract requires two methods deposit and challenge to make custodian trustworthy. Custodian needs to put the deposit in the contract, and the contract acts as an escrow to complete the trade. Once custodian misbehaves without transferring Ether to the participant, the participant can use challenge function to prove the Libra transaction existence. Here, it will need to validate the Libra transaction merkle proof inside the smart contract. Last, if the challenge is successful, the contract will slash the deposit and give it to the participant. Okay. Let’s take a look at a normal case. MAX, as an exchange, and is also a custodian here, will put some digital assets into the smart contract as security deposit for the first step. And the deposit is locked within a period of time to ensure that MAX cannot move the fund itself. If there is a user wants to trade Libra for Ether, the user can query whether the smart contract has enough security deposit. If the response is true, the user can transfer its Libra token to MAX’s Libra address. Once the transaction is done and MAX receives the notification, MAX will transfer Ether to user’s ETH address to complete the trade. The final step. Great! Everything seems perfect. However, similar to the normal case, MAX has to put security deposit in the contract to earn user’s trust so the user is willing to trade on the platform. If the user doesn’t receive Ether after sending the Libra transaction at Step 4, we consider it as a breach of contract. Then, the user can launch a challenge process. Since the contract includes Libra merkle proof verification, the user can submit the transaction proof to the smart contract. If the smart contract verifies the proof successfully, it will transfer Ether to the user. In addition, it will also slash a portion of deposit as the penalty to compensate the user to finish the trade. Okay, let’s have a demo. I have already deployed the smart contract to ganache and I also created a local Libra swarm. Before we started the demo, let’s simplify some roles. Here, we call participant, the one who has Libra token, A and custodian, the one who has Ether, B. And the scenario is A wants to trade its LIB token for B’s Ether. First, B will deposit 2 ether and specifies A to be beneficiary. After this action you could see that the Ether balance of B reduced about 2 ether. Next, participant A could check the deposit. You could see the deposit information like depositor, beneficiary, and total amount by query_deposit. Then, after confirming the deposit is correct, A could transfers 1 Libra token to B. You could see the result. The Libra balance of A becomes 99 and the Libra balance of B becomes 1. Finally, after receiving the payment, B should transfer 1 Ether to A by calling transfer_1_eth. However, in this demo, I want to demonstrate the challenge. Let’s assume B never transferred Ether to A. Then B could challenge the situation. As a result, you could see the Libra balance of A becomes about 102 Ether which is more than expected because the whole deposit is slashed for the punishment to B. That’s all. Hope this video useful and helpful. If you are interested in the technical detail, I will put the article and the GitHub page below. Also, feel free to ask me anything if you have any problem. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *