Ion Stage 2: State Verification (Part 3)

Clearmatics
clearmatics
Published in
7 min readOct 16, 2018

This is part of a series of blog posts that explores the latest developments in interoperability here at Clearmatics. Follow our progress on Github and check out the rest of this blog series here.

In our first blog post, we introduced the Ion Interoperability Framework which allows for continuous execution of logic across multiple Turing-complete blockchains. Following this, we introduced the concept of the validation module and how this was implemented for Clique Proof-of-Authority. In this blog post we’ll talk about how state transitions are verified and contracts are built which depend upon transactions occuring on external chains.

In order to draw cross-dependence on some arbitrary state between chains, state must first be passed between these chains. Once passed, we can use each chain’s specific state verification mechanisms as part of a smart contract to prove any state transition to have occurred in any given block. Now that we have learnt how blocks are fetched, submitted and validated in part 2 of our blog series, we’ll now learn how we use this block information to facilitate interoperation.

Continuous execution was a concept briefly noted in the introductory blog post and is a key part of what we intend to facilitate with Ion. What exactly is it?

It is the ability to be able to execute, in series, a set of functions across different contracts across different chains in a provable sequence to create the interconnected network of blockchains.

We call this continuous execution, as we build contracts that execute dependent on proofs of state transitions that occur on external chains. This can be extended to an interconnected network of blockchains with the ability to create complex chains of logic to fulfill specific business requirements.

How does Continuous Execution Work?

We use an event consumption model. Our work is currently based on the Ethereum blockchain and as such we’ve used this as our initial playground to develop this framework. However, the design is not limited to just this environment. The event consumption model could be substituted with any other mechanism that is specific to other systems but in our case we use events as our mechanism.

Events emitted on one chain can be used and consumed on another as a proof that a certain state transition took place to trigger the execution of a function on another chain. Events can also contain extra metadata about the transition that may be useful in identifying the computation performed. This extra data is key in ensuring that we are consuming the correct event and that our subsequent function call will execute only given expected data in the event. Since we only want to perform some action if and only if some other expected action occurred on another chain, simply verifying the existence of a transaction in a block does not provide enough of a provable guarantee that any such specific action was indeed performed nor any relation to what will trigger. In other words, a transaction hash alone does not provide a provable guarantee on chain that the transaction associated with this hash is an expected state transition. As such we utilise events and the consumption of them to allow us to bind our dependence to state and its transition on another chain.

Above is a simplified illustration of how we see continuous execution across blockchains to work:

  1. Contract function is called and an event is emitted
  2. The block that that transaction is included in is then submitted to another blockchain
  3. The block is validated
  4. The event in that block is then consumed to call another contract function which also emits an event
  5. The block that includes this transaction is submitted to another chain
  6. The block is validated
  7. The event contained in the block is consumed to execute another function call

This chain of execution can continue endlessly allowing contracts to call functions through many chains, hence the term continuous execution.

Using event parameters included in an event emitted in a transaction, we can provably derive state and execute further functions upon the data included in a transaction from another chain which allows us to call functions using parameters from another chain. For example, if Alice had requested funds from Bob on chain B via a function call on chain A, the data about the amount Alice expects to be paid will be included. Bob’s use of this event to pay Alice safely encodes the amount within the event from chain A and is explicitly provable on chain B with the transaction data is not being obfuscated by compression to a transaction hash only. With this we can see that the function that consumes an event may also emit an event that is consumed elsewhere, which in turn may also emit an event etc. achieving continuous execution and dependence on state transitions across chains.

This allows us greater ability to write arbitrary use-cases for cross-chain interacting contracts across different blockchain systems. The event consumption model also means that we follow the protocol closely which allows the framework to be backwards compatible with events from both the past and future state transitions. A single smart contract will be responsible for this. This methodology can also be applied for other systems and each contract will be system-specific.

How is block information stored?

Our next core component of the Ion stack, after the validation contracts, is the block store contract. Once blocks that have been submitted to the validation contract are verified to be correct, they are passed to the Ion hub contract. This contract decodes the passed block into it’s constituents and persists this data on-chain. This contract is responsible for two different mechanisms.

  1. Persistence of State
  2. Verification of State

Persisting External Chain State

Ion has been designed to be able to interoperate with any blockchain. It achieves this by allowing the development the block store contract to be able to persist the state of any blockchain. This means that as long as the contract is able to decode and store the relevant components of a block necessary for the proving of a state transition then it can facilitate interoperation.

Thus we must support the persistence of block structures that also allow access for proofing mechanisms. The specific implementation of state persistence functions will differ depending on the chain(s) intended to be interoperated with. Currently our project has been EVM-focused and as such our blocks are decoded and the following components are stored:

  • TxTrieRoot: The root hash of the merkle patricia trie of all contained transactions in the specified block
  • ReceiptTrieRoot: The root hash of the merkle patricia trie of all contained receipts in the specified block

The above is required to perform verification of state transitions and in the context of event-consumption, receipts are used to assert data contained in events emitted in certain transactions. Blocks from differing blockchains will have different structures and verification mechanisms that may require certain specific block components be stored. This would be handled by different smart contracts. Once we are able to store block data from other chains, we can now allow querying of these blocks to assert a transaction.

Verification of State

The Ion hub contract holds all block data from other chains but must also provide an interface via which access to these blocks and their data to allow the checking of block contents for verification of state. Since verification methods are specific to block structure, the contract must also provide functions that encode a specific proofing mechanism for the block type. Once again, for our case, we are using the mechanisms as defined in the Ethereum yellow paper for merkle patricia trie proofs of transactions and receipts.

To verify a specific state transition, it consists of two steps:

  1. Check transaction exists in block
  2. Check the receipt of above transaction exists in block with expected parameters

Both steps are required in order to assert that the transaction does exist in the block and also that the transaction hash is associated with a state transition that is relevant to the consumer of the event.

When an event is consumed, a merkle patricia trie proof of the transaction and receipt with expected event parameters are passed to a function call. The proofs are then used to assert existence inside the given block and decodes the event to check against expected parameters. If all checks pass, then the transaction and receipts have been proved to exist in the block specified and the event parameters match the expected values assuring the caller that the state transition is as they expect.

Providing this verification interface means that any use-case contract can pass proofs to the Ion hub contract and it will return a boolean of the result of the check. This can then be used to perform arbitrary onchain execution if the check succeed based on events and state from another chain.

Consumption by Smart Contracts

Now with the interfaces to be able to assert any state transition in any block from another chain, how can we use this to interoperate?

Our next and final blog post in the series will detail how to develop smart contracts that utilise the Ion framework for any desired use-case.

Please stay tuned for more blog posts and articles on our Medium, and for more details on Ion Stage 2 check it out on Github and let us know your thoughts!

Friedrich Grabner, Blockchain Engineer, Clearmatics
Chris Chung, Blockchain Engineer, Clearmatics
Duarte Aragão, Senior Blockchain Engineer, Clearmatics

Tweet us @Clearmatics

--

--

Clearmatics
clearmatics

Clearmatics build distributed, autonomous economic systems that mutualise the value of network effects.