Today you will see a bridge between two Ethereum-like
chains, with a mechanism for general state synchronization. Presently, bridges have been built due to
a need for scaling Ethereum and avoiding big gas fees. Most bridges have required a trusted authority
and separate development effort for each use case (for example, each ERC standard for tokens). Our bridge can handle general states and you
will see an example of syncing state mutated on one chain to a second chain. We are in the Factotum IDE and I have set
up an environment with two EVM-based test chains.
We will be using the same account address
on each chain. This is important, because we are effectively
replaying the transaction sent from Chain A, on Chain B. We have deployed two Counter contracts, one
on each chain. They have the same address. Then, we have a Light Client contract on chain
B, which keeps track of chain A blocks and stores block hashes. And a Prover contract on chain B, to which
we will send the transaction data that needs to be replayed on chain B. Now, the counter on chain A is 14 and on chain
B, 14 .
They are in sync. We will make a transaction to increase the
counter with 2, on chainA. So, now, when we query the chains, we have
16 on chain A and 14 on chain B. Not in sync anymore. During this time, the Light client watcher
has picked up the new block from chain A, in which the incrementCounter transactions
has been added and has sent it to the Light Client. So, we can proceed and build our proofs for
the Prover contract. The forwardAndVerify function takes in a transaction,
receipt and sender account proof for the transaction that we want replayed, along with the block
header where the transaction has been included. Block header, with number from the transaction
receipt received. The header contains the receipt tree root,
which, along with this receipt proof, allows the Prover contract to verify that the status
of the original transaction is the same as the status for the replayed transaction.
It also contains the transaction root, which,
along with the transaction proof enables the Prover to verify that the replayed transaction
(included already in the proof) is part of the transaction tree sealed by the block. The Prover contract also checks that the RLP-serialized
block header is hashed to a valid block hash, that has been registered with the Light Client. Last, we send the account proof
to make sure we know a valid account nonce, which is used as a monotonically increasing
value for tracking the state changes in order thus dissallowing the reuse of the same transaction
for replay. The Prover contract keeps a mapping of nonces
per transaction sender account and (at least in the current version) does not allow nonces
to be skipped.
Now, we can send the forwardAndVerify transaction. And check the counter values again. Chain A remains the same. Chain B, the counter has been synced with
Chain A. You have seen a short demo of bridging two
Ethereum chains and keeping state in sync by proving blocks, transactions, receipts
and account information. All, inside Factotum IDE..