Skip to main content

Guide: Setting up cross-chain replication for ZK Passport

info

Native state transfer to Ethereum L1 is currently under construction.

This guide walks you through the process of setting up cross-chain replication for ZK Passport Registry state. By the end of this tutorial, you will have:

  1. Deployed the RegistrationSMTReplicator contract on the target chain.
  2. Set up your relayer or front-end submission flow.

Step 1: Deploy the RegistrationSMTReplicator

The RegistrationSMTReplicator handles the replication of state from the ZK Registry onto your chain. This ensures your chain is kept up to date with changes to passport registrations.

  1. Install the Rarimo Passport Contracts package:

    npm install @rarimo/passport-contracts
  2. Generate a key pair for the relayer that will submit state updates to the RegistrationSMTReplicator contract.

    You can use the ethers library to generate a new key pair:

    import { ethers } from 'ethers';

    const wallet = ethers.Wallet.createRandom();
    console.log('Address:', wallet.address);
    console.log('Private Key:', wallet.privateKey);

    Make sure to securely store the private key, as it will be used by the relayer to sign state updates.

  3. Deploy the RegistrationSMTReplicator to your chain and initialize it:

    import { RegistrationSMTReplicator } from '@rarimo/passport-contracts';

    const replicator = await RegistrationSMTReplicator.deploy({
    // Specify the chain and network parameters here
    });

    const oracle = '0x...'; // Replace with your relayer address from the previous step
    const sourceSMT = '0x479F84502Db545FA8d2275372E0582425204A879'; // This is the address of the original ZK Passport Registry on Rarimo L2.

    await replicator.__RegistrationSMTReplicator_init(
    [oracle], // list of oracle public keys that can submit roots directly
    sourceSMT // contract address of the original registry on Rarimo L2
    );

Step 2: Set up the relayer with front-end submission to replicate the states

To keep the state of the ZK Registry in sync with your chain, you need to set up a relayer with front-end submission. This will ensure that any changes in the ZK Registry are reflected in the RegistrationSMTReplicator contract.

You have to set up backend service and make your front-end app update the root:

  1. Relayer: Run a relayer service that listens for events from the ZK Registry.

    • Follow the instructions in proof-verification-relayer README.
    • Make sure you set the right replicator contract address and private key of corresponding allowedUpdaterAddress in the config.
    • Make sure endpoint is available for your frontend app.
    • Make sure that the relayer's corresponding key is set as an oracle in the replicator contract. You can check this using the isOracle(address) method on the RegistrationSMTReplicator contract.
  2. Front-end: Send the state update transactions on-demand from your front-end:

    • After obtaining the proof from verificator-svc you know the required root (it is a 11th pub signal).
    • Now you can get signed state by root
    async function getSignedRootState(root: string) {
    const API_BASE_URL = 'https://api.example.com'

    const requestUrl = new URL(`${API_BASE_URL}/integrations/proof-verification-relayer/v2/state`)
    requestUrl.searchParams.set('filter[root]', root)

    const res = await fetch(requestUrl.toString())
    const { data } = await res.json()

    return {
    // Signature of root state signed by relayer private key.
    signature: data.attributes.signature,
    // Time when the event was caught, a.k.a state transition timestamp
    timestamp: data.attributes.timestamp,
    }
    }