Electron Labs
  • Quantum: Proof Aggregation for Ethereum
    • Introduction
    • Proof Lifecycle and Architecture
    • Quantum Protocol Specifications
    • Integration
    • Developer tutorial for integrating Quantum
    • Gas Cost Analysis
    • Developer Chat
Powered by GitBook
On this page
  • Proving Schemes Supported
  • Install quantum-sdk package in your project
  • Retrieve Authorization Key
  • Initialise Connection
  • Circuit Registration
  • Proof Submission
  • Verifying Protocol Proof On-Chain
  • On-chain Contract
  1. Quantum: Proof Aggregation for Ethereum

Integration

PreviousQuantum Protocol SpecificationsNextDeveloper tutorial for integrating Quantum

Last updated 2 months ago

Proving Schemes Supported

The quantum supports the following proving schemes:

  • GnarkGroth16

  • SnarkjsGroth16 (Circom)

  • Risc0

  • Sp1

  • Plonky2

  • GnarkPlonk

  • Halo2Kzg (Poseidon)

  • Halo2KzgEvm

  • AwsNitroAttestation

Check out which demonstrates the full proof generation cycle for all schemes.

  • For Halo2Kzg and Halo2KzgEvm, Shplonk proofs are supported

  • For Sp1, are supported

  • For Risc0, are supported

Below is a step-by-step flow.

Install quantum-sdk package in your project

npm i quantum-sdk

Retrieve Authorization Key

Retrieve an authorization key for accessing quantum testnet as follows:

let requestData = { "protocol_name": "your_protocol_name" }
let resp = await axios.post(`${RPC_ENDPOINT}/auth/protocol`, requestData);
const authKey = resp.data.auth_token;

Initialise Connection

import {Quantum} from "quantum-sdk";

Before interacting with the server, a connection to the quantum layer needs to be established.

let rpcEndpoint = "xx.xxx.xx";
let authKey = "xx-xxx"; // AUTH_KEY
const quantum = new Quantum(rpcEndpoint, authKey); 

Check if the quantum instance can talk with the server. If rpcLive is True, a connection is established.

let rpcLive = await quantum.checkServerConnection();

Circuit Registration

Before submitting a proof, the user must register their circuit on the aggregation layer using some circuit data, primarily the verification key.

let vkeyPath = "path/to/vKey.bin"; 
let circuitHash = (await quantum.registerGnarkGroth16Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath = `path/to/verification_key.json`
let circuitHash = (await quantum.registerSnarkJSGroth16Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath = `path/to/method_id.json`
let circuitHash = (await quantum.registerRisc0Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath = `path/to/v_key.bin`
let circuitHash = (await quantum.registerSp1Circuit(vKeyPath)).circuitHash["hash"];
let commonDataPath = `path/to/common_data.bin`
let verifierOnlyDataPath = `path/to/verifier_only.bin`
let circuitHash = (await quantum.registerPlonky2Circuit(commonDataPath, verifierOnlyDataPath)).circuitHash["hash"];
let vKeyPath = `path/to/vKey.bin`
let circuitHash = (await quantum.registerGnarkPlonkCircuit(vKeyPath)).circuitHash["hash"];
let sg2Path = `path/to/sg2.json`
let protocolPath = `path/to/protocol.json`
let circuitHash = (await quantum.registerHalo2KZGCircuit(sg2Path, protocolPath)).circuitHash["hash"];
let sg2Path = `path/to/sg2.json`
let protocolPath = `path/to/protocol.json`
let circuitHash = (await quantum.registerHalo2KZGEvmCircuit(sg2Path, protocolPath)).circuitHash["hash"];
let pcr0Path = `path/to/pcr0.bin`
let combinedVKeyHash = (await quantum.registerNitroAttCircuit(pcr0Path)).circuitHash["hash"];

Proof Submission

Once the circuit is registered, the proof can be sent for aggregation on the quantum layer.

let proofPath = `path/to/proof.bin`
let pisPath = `path/to/pis.json`
let proofResponse = (await quantum.submitGnarkGroth16Proof(proofPath, pisPath, circuitHash));
let proofPath = `path/to/proof.json`
let pisPath = `path/to/public.json`
let proofResponse = (await quantum.submitSnarkJSGroth16Proof(proofPath, pisPath, combinedVKeyHash));
let vKeyPath = `path/to/method_id.json`
let receiptPath = `path/to/receipt.bin`
let proofResponse = (await quantum.submitRisc0Proof(receiptPath, combinedVKeyHash));
let vKeyPath = `path/to/v_key.bin`
let proofPath = `path/to/proof.bin`
let proofResponse = (await quantum.submitSp1Proof(proofPath, combinedVKeyHash));
let proofPath = `path/to/proof.bin`
let proofResponse = (await quantum.submitPlonky2Proof(proofPath, combinedVKeyHash));
let proofPath = `path/to/proof.bin`
let pisPath = `path/to/pis.json`
let proofResponse = (await quantum.submitGnarkPlonkProof(proofPath, pisPath, combinedVKeyHash));
let proofPath = `path/to/proof.bin`
let instancesPath = `path/to/instances.json`
let proofResponse = (await quantum.submitHalo2KZGProof(proofPath, instancesPath, combinedVKeyHash));
let proofPath = `path/to/proof.bin`
let instancesPath = `path/to/instances.json`
let proofResponse = (await quantum.submitHalo2KZGEvmProof(proofPath, instancesPath, combinedVKeyHash));
let attDocPath = `path/to/attestation_doc.bin`
let proofResponse = (await quantum.submitNitroAttProof(attDocPath, combinedVKeyHash));

A proofHash is returned from the quantum layer if a proof is submitted successfully.

A proof cannot be submitted if another proof associated with the same circuitHash is currently being aggregated.

Check Proof Status

let proofHash = proofResponse.proofHash

proofHash is used to track the progress or get details of the aggregation request.

let proofStatus = (await quantum.getProofData(proofHash)).proofData.status
// *** Possible Responses to this call ***
// 1 (NOT_FOUND): proof_hash was not found, 
// 2 (REGISTERED): Proof is registered but yet to be picked up for aggregation
// 3 (REDUCING): Proof is being Reduced, and prepared for aggregation
// 4 (REDUCED): Proof is reduced and ready for aggregation
// 5 (AGGREGATING): Proof is being aggregated
// 6 (AGGREGATED): Proof is aggregated, and superproof is created but yet to be verified on Ethereum
// 7 (VERIFIED): Aggregated Proof is Verified on Ethereum
// 8 (REDUCTION_FAILED): Proof Reduction Failed, Contact Admin
// 9 (AGGREGATION_FAILED): Proof Aggregation Failed, Contact Admin

proofHash is also used to query some Merkle proof data for on-chain purposes

Currently, the aggregated proof is submitted on Sepolia once every ~15 minutes, so for the STATUS to get toVERIFIEDcan take some time.

Verifying Protocol Proof On-Chain

On-chain Contract

npm i quantum-contracts

For protocols to integrate quantum, they would have to make some changes to their verification smart contract. The protocol smart contract imports CircuitVerifier from quantum-contracts which is used to verify if the pubInputs were verified as part of the aggregated proof.

The function verifyPubInputs of the CircuitVerifier lib contract is used for public input verification.

let protocolProofResponse = await quantum.getProtocolProof(proofHash);
let protocolInclusionProof = protocolProofResponse.protocolProof
pragma solidity ^0.8.24;

import {CircuitVerifier} from "quantum-contracts/lib/CircuitVerifier.sol";

contract Protocol {
    bytes32 public circuitHash;
    address public quantum;

    constructor(bytes32 circuitHash_, address quantum_) {
        circuitHash = circuitHash_;
        quantum = quantum_;
    }

    /// @dev `merkleProof` calldata must be the first parameter
    /// keeping it non-view for testing purpose
    function verifyPubInputs(
        CircuitVerifier.MerkleProof calldata merkleProof,
        uint256[] calldata pubInputs
    ) external {
        CircuitVerifier.verifyPubInputs(
            merkleProof,
            keccak256(abi.encodePacked(pubInputs)),
            circuitHash,
            quantum
        );
     
        // Protocol specific Business logic
        // ...   
    }
}

Note, merkleProof calldata must be the first parameter as assumed by CircuitVerifier

quantum-sdk lets you seamlessly interact with the quantum server for your and proof submission.

We've already established a connection in the quantum instance . Let's see how to proceed from there.

circuitHash is a unique, 32 bytes value for your circuit on the quantum layer. This will be used to and on-chain to check for . Each scheme may require a different set of circuit data. See to learn how to prepare the circuit data needed for different proving schemes.

circuitHash , which we received after will be used to submit proof for cheap verification on Ethereum. Primarily, the user sends its proof and publicInputs corresponding to the registered circuit.

Each scheme may require a different set of circuit data. See to learn how to prepare the circuit data needed for different proving schemes.

Verification requires some Merkle-proof data, which can be fetched using the as follows:

Here is an example contract initialized with the circuitHash. This example can be found in

For Risc0, refer to the example

quantum-demo
compressed proofs
succinct receipts
generate-circuit-data
example contracts
here
circuit registration
above
generate-circuit-data
submit proofs
circuit registration
proofHash