# processing Offchain Ciphertext on Inco with hyperlane
This document outlines two approaches for the following
**Requirement** - User must be able to submit only the hash of specific ciphertext needed to be processed(in inco) on the origin EVM chain. While the actual Ciphertext is stored offchain and should be made available to the inco chain alongside the hash. The hash of ciphertext is verified against the relayed hash to verify consistency.
There are two approaches we can follow
1. Using CCIP-read ISM which baiscally tells where relayer can access the offchain ciphertext
2. Use offchain server to write ciphertext to an oracle contract and only verify consistency of hash using hyperlane
## Utilizing CCIP-read ISM and CCIP-read spec server to allow relayer to query and call mailbox.
In this approach we utilize the CCIP-read spec and CCIP-read ISM to configure the offchain URL to be queried by the Relayer. And the relayer get's this info by calling a function which reverts with an error of where the URL is what the calldata will be etc.

**step 1** : Implementing a server for ciphertext
The CCIP-read server is a spec which is configured to be able to encode return data according to the contract ABI of caller and return the result which can be easily decoded onchain.We develop such a server to return the actual ciphertext when queried with hash as a parameter and hosted on a public server.(assuming it is trusted source)
**step 2** : Implementing CCIP-read ISM which allows relayer to read server data
We configure the hyperlane CCIP-read ISM to return an `offchaiLookup` error with the URL of our server and the necessary parameters(Calldata which is nothing but our hash) as specified in hyperlane ISM spec. https://docs.hyperlane.xyz/docs/protocol/ISM/ccip-read-ISM#interface
And specify that the mailbox use this ISM using this specifier `interchainSecurityModule` to set it to the ISM address we just configured.
We now also write the logic to hash the retrieved metadata(ciphertext) and check it against submitted message(the hash from base chain) in the verify function. After which the relayer will now submit the metadata(ciphertext)+message(hash) to mailbox on inco.
**step 3** : Bringing it together
Now when the relayer tries to call the ISM with the `getOffchainVerifyInfo(bytes)` function it will revert with the revert data we specified above. I.e what URL the relayer should query to the server. And this data is accodingly processed based on module type(here CCIP-read).
This will make the relayer query the server url with the hash and The server returns the actual ciphertext for that hash.
This ciphertext is passed as metadata and hash as message.Which is verified for consistency in the ISM and then processed to recipient contract.
Now at the end the ciphertext and the Hash is available in Inco.
For a more generalized explaination refer [CCIP interface](https://docs.hyperlane.xyz/docs/protocol/ISM/ccip-read-ISM)
To understand a general server template of CCIP-read gateway refer this [repository](https://github.com/smartcontractkit/ccip-read)
## Utilizing oracle

In this approach. Instead of setting up a server which is queried by the Relayer. Whenever a Ciphertext is submitted to the server, the server writes the Ciphertext with a unique identifier(can use hash itself) to an oracle contract on inco which users can call to retrieve it.
However it's consistency is verified against the hash submitted on origin chain and relayed by hyperlane.
**Step 1** Setting up server
Setup server with basic API implementation to accept ciphertext and store it with assosiation to it's hash. We can also return this hash which is submitted to the origin chain.(which originally also needs this facility in first approach).This server writes to the oracle contract on inco the ciphertext whenever the API is called.
An oracle contract is written which accepts ciphertext,identifier and has a field to know if it is valid. To which this offhcain server writes to whenever a new ciphertext is submitted.
**Step 2** Development of oracle contract and verifier
Recipient contract retrieves ciphertext on process of hash from hyperlane and verifies if the ciphertext is consistent and is flagged as verified.
So this considers the fact that the hash has been delivered to inco via hyperlane only beacuse it has been recorded on origin chain and hence is a valid ciphertext corresponding to that origin chain.
We can use a simple hash to struct mapping for this storage type.
So now we have both offchain ciphertext and the necessary hash available on inco from other chain.
**Step 3** Bringing it together
In this approach, Now the data being relayed by hyperlane is only the hash. the ciphertext is relayed to chain by the client setup we just did.Now once the hash is relayed it automatically calls the verifier function which verifies consistency of the ciphertext.
Users can integrate to this oracle contract to retrieve their ciphertext and make sure it is consistent with the origin chain hash aswell(Meaning the verified flag is true).
## Advantages
### Approach 1
- Tightly coupled to hyperlane infrastructure
- Robust and uses relayer to query and write both ciphertext and hash to inco
- Best approach for production
- Can be paired with other ISMs
### Approach 2
- Easier to test POC with already deployed hyperlane instance
- No need to follow CCIP-read server spec
- Easy to try and add modifications and later implement same in CCIP-read format
- Best approach for POC and iteration
- Can be tested with localhost lol
## Disadvantages
### Approach 1
- Expects External server to be trusted
- Slightly more stringent wrt to protocol to be followed for proper functionality
- Cannot be setup out of the box at the moment using CLI etc
### Approach 2
- Expects External server to be trusted
- Needs extra client side oracle
- Ciphertext is always available when written by server to oracle even if yet to be verified against hash(unlike approach one where only when being relayed it is written to contract if correct.)
- Two seperate transactions are made for hash and ciphertext