Architecture Overview

How does it work?

In a nutshell, Wisp is a combination of an on-chain light client and a verification mechanism for data inclusion inside a rollup. The on-chain light client makes sure that the destination rollup can trust and reason about a specific execution state root at a specific height of the Ethereum L1. Based on this root, smart contracts can reason about the inclusion (or not) of a certain piece of information inside any rollup anchoring with Ethereum L1. The way that the data inclusion reasoning happens is specific to each source rollup.

The proposed system involves relayers that transfer data from a source rollup into a destination rollup and are paid for that service. The data transfer is two-fold:

  1. ZK proof proving the Ethereum L1 execution state root within the on-chain Light Client contract. The L1 state is enough to give the protocol the ability to prove the state of the source rollup and the CRC messages sent. In the alpha version and the demo, the state that is brought into the destination network is proven via SNARK similar to Proof of Consensus.

  2. 2x Merkle Inclusion Proofs. The first MIP is proving the state of the source rollup posted on L1 using the already proven L1 execution root (step 1). The second MIP is proving the state of the outbox contract within the Source rollup, containing the raw data that must be transported to the destination rollup given the already proven state of the source rollup (1st MIP).

Technical Architecture

Keep in mind that the “Anchor Rollup State” process is performed by Rollups independently of the Wisp Protocol.

The proposed solution incorporates a new permissionless role - Relayer. The relayer is an actor that generates ZKPs of the state of L1 and posts it inside a rollup. Additionally, the relayer can optionally finalise Wisp CRC transfers as a service to the user.

The flow of operations of the Wisp Protocol has four stages: Initiation, State Relay, Delivery and Relay Payment.

As an example of the protocol and how the different architectural pieces fit together, we will use the application of a decentralised cross-rollup token bridge. The token bridge receives and locks some tokens in the source rollup, and mints and releases a wrapped version of the token in the destination rollup.

Initiation Phase

The initiation phase is the phase where the user triggers message transfer through the Wisp protocol. Normally this is done with the intent to perform some business logic operation across rollups.

In order to initiate CRC, the user sends a CRCInitCRC_{Init} message to COutboxC_{Outbox} inside RSourceR_{Source}. The message includes information on the destination rollup, target address, payload and details about the payment for the relay service.

Importantly, anyone can initiate CRCmsgCRC_{msg} by sending an initiation message to the Outbox smart contract (both EOAs and smart contracts).

In our bridge example, the user sends a “deposit” transaction to a “bridge” application smart contract (AppSourceRollupApp_{Source Rollup}) which crafts and sends a CRCmsgCRC_{msg} to CInboxC_{Inbox} on RSourceR_{Source}.

This concludes this phase from the perspective of the user. However, from the perspective of the rollup, the transaction needs to be sequenced in CSourceRollupStateC_{Source Rollup State}. The process of sequencing and verification of the rollup state is outside of the scope of this document and is specific to each rollup. It is an important consideration later when executing Merkle Inclusion Proofs for the CRCmsgCRC_{msg}.

State Relay Phase

Once the user transaction (containing CRCmsgCRC_{msg}) is (at least) sequenced in CSourceRollupStateC_{Source Rollup State}, the second phase kicks in. In this phase, relayers monitor CSourceRollupStateC_{Source Rollup State} for CRCmsgCRC_{msg}. Once such message is detected, a relayer can decide to create an L1 Light Client State SNARK (referred to as SNARKL1StateSNARK_{L1 State}) and provide it to CL1LightClientC_{L1 Light Client} on RDestination R_{Destination} via CRCStateRelayCRC_{State Relay} transaction. Sending SNARKL1StateSNARK_{L1 State} to CL1LightClientC_{L1 Light Client} allows the contract to be convinced of the state of L1 and by proxy the state of RSourceR_{Source} (the state of RSourceR_{Source} is rolled up and verified in CSourceRollupStateC_{Source RollupState} which is part of the verified state of L1).

The method of producing SNARKL1StateSNARK_{L1 State} and posting it to CL1LightClientC_{L1 Light Client} is completely permissionless and trustless.

If and when a relayer will decide to create the SNARKL1StateSNARK_{L1 State} and execute CRCStateRelayCRC_{State Relay} depends on their own consideration. These considerations are influenced by:

  • The number of fees that the user(s) sending the CRCmsgCRC_{msg} has offered to pay compared to the resources spent on monitoring and producing and posting SNARKL1StateSNARK_{L1 State}.

  • The type of CRCmsgCRC_{msg}. It is possible that some dApps may run their own Relayers or sponsor certain types of CRCmsgCRC_{msg} (relay them for free). Such transactions can be “system” transactions for a dApp (f.e balancing assets between networks, passing voting data etc.) but they may be user transactions as well (if they want to incentivise user participation).

At the end of this phase, RDestination R_{Destination} has a verified state of L1 and by proxy the state of RSourceR_{Source}.

Delivery Phase

With the state of L1 and RSourceR_{Source} available in RDestination R_{Destination} the end user, or a relayer on their behalf, can trigger CRCDeliveryCRC_{Delivery} transaction inside RDestination R_{Destination}. The delivery transaction is a transaction sent to the CInboxC_{Inbox} on RDestination R_{Destination} and must include proof that the corresponding CRCmsgCRC_{msg} is in the state of RSourceR_{Source}. The proof is going to be based on merkle tree inclusion and is trivial to validate by CInboxC_{Inbox} based on the currently available and verified L1 state (in CL1LightClientC_{L1 Light Client}) and RSourceR_{Source} state.

Once the proof is verified, the data transfer is completed. This results in triggering the corresponding AppDestRollupApp_{Dest Rollup} contract on RDestination R_{Destination} (specified inside the CRCmsgCRC_{msg}).

In our bridge example, the user (or a relayer in exchange for an additional fee on top of the relaying fee) will trigger the CRCDeliveryCRC_{Delivery} transaction providing proof that the corresponding CRCInitCRC_{Init} transaction has been executed when the user deposited the tokens inside RSourceR_{Source}. The CInboxC_{Inbox} will verify the proof validity and subsequently trigger AppDestRollupApp_{Dest Rollup} mint transaction, thus releasing the wrapped tokens to the user.

This concludes the Delivery phase and the CRC process from the perspective of the User.

State Relay Acknowledge Phase

The final state of the CRCmsgCRC_{msg} transfer involves acknowledging the state relay and paying the relayer for the work done. In order for the relayer to “unlock” the fees deposited by the User in the initiation phase, the Relayer needs to be able to showcase that they did the state relay work.

Any Relayer that has enough incentive can relay the L1 state inside RSourceR_{Source} thus, by proxy, relaying the state of RDestination R_{Destination} too (remember that RDestination R_{Destination} state will be rolled up in L1). With the L1 state updated inside RSourceR_{Source}, the relayer that did the original state relay work can submit CRCStateRelayAckCRC_{State Relay Ack} transaction with proof (merkle tree inclusion) that they did update the state in RDestination R_{Destination} and are entitled to the corresponding fees that the user locked up. At this point the COutboxC_{Outbox} on RSourceR_{Source} can safely release the fees owed to the Relayer, thus concluding the CRC process.

Similarly, any Relayer that has delivered a CRCDeliveryCRC_{Delivery} and is owed a fee for the service can submit CRCDeliveryAckCRC_{Delivery Ack} transaction with proof that they did the work, and are entitled to the corresponding delivery fee.

Inbox & Outbox Contracts

Inbox (CInboxC_{Inbox}) and Outbox (COutboxC_{Outbox}) Contracts are the smart contracts used for the ingress and egress of CRCmsgCRC_{msg}.

The Outbox contracts are used for sending messages. When a user or a contract on their behalf sends a message to the Outbox, the outbox creates a message hash of it and saves it in its state inside RSourceR_{Source}. This exact state is proven later in RDestination R_{Destination}. In order for the proving to be easier, the list of outgoing messages is an array. This allows the storage slot key derivation for every message m to be as simple as keccak(array_position + index) where array_position is the position of the variable within the contract (0 for the alpha version) plus the index of the CRCmsgCRC_{msg}. The Outbox contract is generic for each RSourceR_{Source}.

The Inbox contracts are used for the verification of CRCmsgCRC_{msg} inclusion inside RSourceR_{Source} and the RSourceR_{Source} root inside L1. As each rollup has a different mechanism for maintaining its storage and anchoring its state inside Ethereum the Inbox contract implementations will vary.

The alpha version of Wisp Protocol and the demo have Inboxes supporting Optimism Bedrock rollups - Optimism and Base.

Relayers

Importantly, both of the relayers' described below ensure the liveness of the system and not the security of the system. The protocol security is derived from cryptography and verified through smart contracts. As long as there is at least one relayer willing to perform the job, the system will continue to be secure under the standard technological risks (circuits and smart contract bugs).

There are two types of relayers in the system - state relayer and message relayer.

The state relayer job is to produce the computation integrity proofs (SNARK) - SNARKL1StateSNARK_{L1 State} - that update the L1 state in CL1LightClientC_{L1 Light Client} on RDestination R_{Destination}. The newly updated L1 state can be used later for message delivery.

The message relayer job is to trigger the CRCDeliveryCRC_{Delivery} transaction once the L1 state is updated in CL1LightClientC_{L1 Light Client}. These transactions prove the inclusion of the CRCmsgCRC_{msg} inside RSourceR_{Source}.

Both roles are permissionless and can be played by any actor. Any willing actor can assume one or both roles.

Trust Assumptions

Due to the design of Wisp no new trust assumptions are introduced apart from the ones already in place for the rollups. The communication is secured by a combination of Computational Integrity proofs and Merkle Inclusion proofs.

Possible Improvements Exploration

Aggregating Public State Relay

While the initial version of the protocol highlights state relayers as actors running the software for generating $SNARK_{L1State}$ and submitting it towards $C_{L1LightClient}$, this also introduces a software risk - a bug inside this software can cause complete failure of the whole system.

Furthermore, this positions Wisp as a competitor inside the “Onchain Light Client” space, rather than the aligning initiative it strives to be.

As a means, to address this risk, Wisp can move into “State Relay Aggregation”. Public State Relayers can be delivering their L1 state proofs to the destination rollups and the protocol can start using these and utilizing these. Due to the deterministic nature of the Sync Protocol, the aggregation of multiple Light client sources will further enhance the security, lower the trust assumptions and lower the risk for the system.

In addition, the State Relay fees will now be flowing back to the community and to the actors doing the state relay work. This creates a new revenue stream for these actors and aligns the whole system together.

Utilizing Available Anchors

The proposed protocol specifies the Light client-based, state relay phase as a necessary phase for the communication to occur. While this is generally correct, there are cases like Optimism Bedrock and Taiko, where the L1 state is immediately available.

In these cases, it makes sense for the protocol to use them as a source of the L1 state rather than forcing the existence (and the costs) of running onchain L1 Light Client.

Optimising Delivery Message

The biggest cost factor for most rollups is the size of the calldata they need to anchor inside L1. With this in mind, the Delivery Message transaction is quite a bulky one and almost all of it eventually goes to L1. This makes the message delivery a costly process and risks the scalability of the system.

A possible improvement is the creation of Computational Integrity Proof to minimize the calldata footprint inside the L2s and respectively the L1s. Moving into ZK proving system (f.e. Groth16) that produces a minimally sized proof will enable the overhead of Wisp to be as little as possible.

Last updated