A view of Plasma Cash for Ethereum

1. Introduction

At FiNC we are examining blockchain technology, and scalability solutions for the Ethereum Blockchain are one of the topics which we are particularly interested in. As the title suggests, this article discusses Plasma Cash, a new scalability solution for the Ethereum Network. It is currently being discussed widely by the Ethereum community [1].

For those who want to know why scalability solutions for Ethereum Blockchain matter, I would suggest you check out Johannes Hagemann’s article.

2. Motivation

When I first read the Plasma Cash specification many questions arose in my mind. Some were easy to find convincing answers on the Internet, but for many I struggled to find answers that satisfied my curiosity. Therefore, I tried to analyze several open source Plasma Cash implementations to understand it more deeply. After collating those implementations, I found the strongest candidate is Loom Network’s implementation which has been released recently [2]. I decided to systematize what I had learnt about Plasma Cash from an engineer perspective to share it with my colleague and external engineers who are also interested in Blockchain.

3. Plasma Cash for ERC721 Tokens

3.1. Overview

Generally, a scalable Ethereum Blockchain model consists of the following components:

A scalable Ethereum Blockchain paradigm

(1) Client application

A mobile or web app that uses a web3 library (A library for interacting with Ethereum nodes) to communicate with both Root Chain and Plasma Chain.

(2) Root Chain

Root Chain

Root Chain hosts an ERC721 Token Contract and a Plasma Contract, where ERC721 Token Contract supplies and manages Non-Fungible Tokens (NTFs). For example, the Axiom Zen company has deployed the CryptoKittiesCore smart contract on Ethereum Blockchain which is an ERC721 Token Contract. This smart contract supplies and manages Non-Fungible CryptoKitties tokens like my lovely kitty:

A Non-Fungible Token

He has a unique DNA string producing his unique appearance that is distinct from all kitties over the CryptoKitties world :)

Plasma Contract is deployed on the Root Chain (Ethereum) and has main functions:

  • Handle Deposit events: In order to transact ERC721 tokens on the Plasma Chain, the users first need to deposit their tokens to the Plasma Contract and get Non-Fungible Plasma Coins in return.
  • Handle Exit events: When the users want to exit their tokens from the Plasma Chain, they submit exit requests directly to the Plasma Contract on the Root Chain.

(3) Plasma Chain

Plasma Chain is also a Blockchain and currently being run by one operator (authority) who may be any company providing ERC721 tokens. Plasma Chain has the following characteristics:

  • It consists of blocks, each block can contain a single transaction or multiple transactions depending on its type. Each block also maintains one Sparse Merkle Tree.
  • Users are free to transact and use their Plasma Coins on the Plasma Chain in any way, including transferring it to other users on the Plasma Chain [2].
  • It periodically submits the Merkle root of the current block to the Plasma Contract, showing any changes in ownership of the Plasma Coins.

3.2. Deep dive into Plasma Cash implemented by Loom Network

I guess that if you read this post up to here, maybe some questions arose in your mind, such as: How does Deposit work? How does Plasma Chain organize blocks? How does Transaction get executed? How does Exit work? In this section, I will try to answer those questions in a practical manner by dissecting Loom Network’s Plasma Cash source code.

Firstly, let’s git clone the Plasma Cash source code from Loom Network’s repository here [3]. Alright, let’s start the journey.

3.2.1. Deposit ERC721 Tokens

Before the users can perform transactions related to their ERC721 tokens on the Plasma Chain, the users need to deposits their ERC721 tokens to the Plasma Chain. Depositing process proceeds sequentially through steps:

Deposit ERC721 Tokens flow diagram
  • Step (1): Client calls the depositToPlasma(uint tokenId) function on the ERC721 Token Contract (ERC721 Token Contract must implement this function) using certain web3 library. The tokenId is ID of an ERC721 token.
  • Step (2): depositToPlasma() transfers the specified tokenId to the Plasma Contract. If the transferring succeeds, then depositToPlasma() will calls the onERC721Received() function on the Plasma Contract.

The Plasma Contract is implemented in the file:

plasma-cash/server/contracts/Core/RootChain.sol

with the contract name RootChain. The RootChain contract provides a mapping coins for storing Plasma Coins which are represented by struct Coin instances. The RootChain contract also keeps track of currentBlock which is current block number of the Plasma Chain. In addition, it provides a mapping childChain for storing Merkle roots of the Plasma Chain blocks.

  • Step (3): Now that the control is passed to the onERC721Received() function on the Plasma Contract. It proceeds to call deposit() function. The deposit() function increments currentBlock by 1, then it generates an unique slot (a uint64 number) and creates a coin (a Plasma Coin) based on the input parameters. The coin stores crucial information such as the tokenId, the ERC721 Token Contract’s address, owner’s address (the address of who owns that tokenId), etc. And, the coin is stored into the mapping coins at the slot position. Finally, the deposit() function emits a Deposit event including the unique slot number and the currentBlock number. Because the Plasma Chain is watching Deposit events, when it receives the Deposit event, it passes the event data and the control to a callback function.

The Plasma Chain is implemented at the business tier of a Flask REST API server in the directory:

plasma-cash/plasma_cash/child_chain/

Blocks are organized as follows:

Blocks on Plasma Chain

There are 2 types of blocks on the Plasma Chain, Deposit Block and Plasma Block. A Deposit Block includes only 1 transaction which is called Deposit Transaction, while a Plasma Block may includes many transactions. The initial block is always a Deposit Block and Deposit Blocks are placed between Plasma Blocks (orange blocks in the above figure). Two consecutive Plasma Blocks have blockNumbers difference is N (in the above figure, N = 1000). The type of a block can be identified programmatically using a trick like this: A block that blockNumber % N != 0is a Deposit Block, while A block that blockNumber % N == 0 is a Plasma Block.

  • Step (4): The callback function creates a Deposit Transaction based on the received Deposit event data. The Deposit Transaction stores the slot number into its uid field and the depositor’s address into its new_owner field. This transaction is a true Unspent Transaction Output (UTXO). The callback function also creates a Deposit Block to include only the Deposit Transaction. The Deposit Block gets added to the blocks dictionary with the key is the blockNumber which is extracted from the Deposit event data. The Deposit process finishes here.

Summarily, the Deposit process turns a ERC721 token into a Plasma Coin on the Root Chain and a corresponding UTXO on the Plasma Chain. Because one Plasma Coin maps with one UTXO, we can think of UTXOs as Plasma Coins. Now, the owner can spend the Plasma Coin on the Plasma Chain at will.

Depositing an ERC721 token

3.2.2. Spending Plasma Coins on the Plasma Chain

Suppose that Alice uses a client application to register to an ERC721 Token Contract and receive 5 tokens with tokenIds: 1, 2, 3, 4, 5. Alice deposits 3 tokens 1, 2 and 3 to Root Chain and receives pairs of deposit slot number and deposit blockNumber by catching Deposit events:

(deposit_slot1, deposit_block_number1) --> coin1
(deposit_slot2, deposit_block_number2) --> coin2
(deposit_slot3, deposit_block_number3) --> coin3

Now Alice wants to send coin3 to Bob, what Alice is going to do is: Alice creates a Transaction object from input parameters:

uid = deposit_slot3
prev_block = deposit_block_number3
new_owner = Bob’s address

Alice signs the transaction with her private key and then she encodes the transaction object using RLP encoding scheme. Next, Alice calls the Plasma Chain’s API send_transaction through the HTTP endpoint /send_tx. Upon receiving the request from Alice, the Plasma Chain decodes the serialized transaction object and validates it. If the transaction object is valid, it gets added to the current block on the Plasma Chain.

Following coin3, Alice also needs to send the history of coin3 to Bob by some way (currently, this is not standardized yet). But what is the history of coin3?

Alice’s UTXOs

The history of coin3 consists of 2 collections of proofs:

  • Inclusion proofs: An inclusion proof consists of a blockNumber and a Merkle Proof for the said coin in a block with the blockNumber is greater than or equal the Deposit Block’s blockNumber. And, that block must includes a least one transaction related to the said coin. In this example, there is only one block with blockNumber = 3003 that includes one transaction related to coin3. Therefore, there is only one inclusion proof.
  • Exclusion proofs: An exclusion proof consists of a blockNumber and a Merkle Proof for the said coin in a block with the blockNumber is greater than the Deposit Block’s blockNumber. And, that block must not include any transaction related to the said coin. By this definition, Exclusion proofs may have quite big size when the number of blocks grows really bigger.

Getting back to Bob, before Bob can spend coin3, Bob needs to verify the history of coin3 to ensure that coin3 is valid.

3.2.3. Creating Plasma Blocks

Like Bitcoin Blockchain and Ethereum Blockchain, Plasma Chain also has a consensus algorithm which is so-called Proof of Authority (PoA). An authority /operator/validator may be a certain company running several nodes allowing them to submit the current block’s Merkle root to the Root Chain and create a new block for the Plasma Chain. For example, Loom Network is an operator of the Loom DAppChain which is a Plasma Chain.

Periodically, the Plasma Chain operator submits the current Plasma Block’s root to the blockchain. The frequency of block submissions can be either some time constant, or can be depending on a metric such as Merkle Tree sparseness. [4]

3.2.4. Exiting Plasma Coins

Exiting is a mechanism allowing the users to quit transacting on the Plasma Chain fairly and safely. The users then can get back ERC721 tokens by transferring their exited Plasma Coins back to the ERC721 Token Contract.

Plasma Cash requires the users to watch their Plasma Coins (by listening to StartedExit events emitting from the Root Chain) to protect them from fraudulences. This watching task may be automated by client application or delegated to the third party. If the users detect an fraudulent exit, they should challenge against that fraudulent exit.

To exit a Plasma Coin, the user need to make a transaction directly to the Root Chain. That transaction calls the startExit() function on the Plasma Contract with required parameters: slot number, blockNumber and Merkle proof for the Plasma Coin in the previous block, blockNumber and Merkle proof for the Plasma Coin in the exiting block, and a bond amount (a small ETH amount).

There are 3 major Exit — Challenge cases needing to be considered seriously [5]:

3.2.4.1. Exit Spent Coin Challenge

Exit Spent Coin Challenge

A malicious user tries to exit a coin at the exiting block with blockNumber = 2000 and the coin owner notices that the exit is fraudulent. The coin owner fetches exit information from the Root Chain and the coin history from the Plasma Chain. If there exists a block in the coin history that its blockNumber is greater than the exiting block’s blockNumber, the coin owner will trigger a CHALLENGE AFTER by sending the challenging block’s blockNumber and the Merkle proof for the exiting coin at that challenging block to the Root Chain. The Root Chain will terminate the exit immediately and the malicious user’s bond will be slashed and transferred to the coin owner.

3.2.4.2. Exit Double Spend Challenge

Exit Double Spend Challenge

If there exists a challenging block in the coin history that is between the previous block and the exiting block, and the previous transaction (at the previous block) is the parent transaction of the challenging transaction (at the challenging block), this means that the coin was spent double at the previous block, the exit will be undergone a CHALLENGE BETWEEN and terminated immediately. The exiter’s bond will also be slashed and transferred to the coin owner.

3.2.4.3. Exit With Invalid History Challenge

Suppose that for some reason, the coin history becomes invalid and the exiter submits 2 seemingly valid transactions at blocks 2000 and 3000 to the Root Chain. The coin owner suspects that the exit is fraudulent, and decides to attest that he/she can exit the coin at block 1000 by submitting 2 valid transactions at blocks 1 and 1000 and making a CHALLENGE BEFORE against the exiter. The exiter has to respond the coin owner’s challenge with a valid child transaction of the challenging transaction. But that child transaction doesn’t exist, and so the exit will be eventually canceled.

In summary, the 3 Exit — Challenge cases above are modeled as follows [6]:

Coin State — Exits — Challenges [6]

When a Plasma Coin is created through the deposit process, the coin is assigned a DEPOSITED state. When a exiter starts exiting the coin, its state is transitioned to EXITING. If the exit is valid, the coin’s state is eventually transitioned to EXITED. Otherwise, either the exit is terminated and the coin’s state is transitioned back to DEPOSITED or the exit is challenged by CHALLENGE BEFORE and the coin’s state is transitioned to CHALLENGED. If the exiter can respond the CHALLENGE BEFORE, the coin’s state is transitioned back to EXITING, and after a maturity period, its state is eventually transitioned to EXITED. Conversely, the coin’s state is transitioned back to the initial state DEPOSITED.

4. Conclusion

I started this blog post with a WHY: Why do scalability solutions for Ethereum Blockchain matter? and diverted the answer to another blog. Next, I tried to draw your attention into a walkthrough of Plasma Cash which is a new scalability solution for the Ethereum Network. I hope that I helped you see some aspects of it rather clearly. However, I think if you read this blog post up to here, definitely, your mind is spinning with many other WHYs: Why X? Why Y? Why Z, etc and maybe many HOWs as well. If you are really interested in demystifying them, please drop a comment. Then, we can start a brainstorming together. Besides, I also have an intention of considering demerits of Plasma Cash and how Plasma XT (next generation of Plasma Cash) can fix them in the near future. Stay tuned.

5. References

[1] https://ethresear.ch/t/plasma-cash-plasma-with-much-less-per-user-data-checking/1298

[2] https://medium.com/loom-network/plasma-cash-initial-release-plasma-backed-nfts-now-available-on-loom-network-sidechains-37976d0cfccd

[3] https://github.com/loomnetwork/plasma-cash

[4] https://github.com/loomnetwork/plasma-cash/blob/master/FullSpec.md

[5] https://karl.tech/plasma-cash-simple-spec/

[6] https://ethresear.ch/t/loom-network-plasma-cash-for-erc721-tokens/2385