For the beta version of the protocol, access to Quantum is permissioned. Every permissioned protocol is given an AUTH_KEY and RPC Endpoint to communicate with the quantum layer RPC endpoint. To get whitelisted and get your key reach out to @garvit_electron or @utsavjnn on Telegram.
Proving Schemes Supported
The quantum supports the following proving schemes:
GnarkGroth16
SnarkjsGroth16 (Circom)
Risc0
Sp1
Plonky2
GnarkPlonk
Halo2Kzg (Poseidon)
Halo2KzgEvm
Check out quantum-demo which demonstrates the full proof generation cycle for all schemes.
For Halo2Kzg and Halo2KzgEvm, Shplonk proofs are supported
quantum-sdk lets you seamlessly interact with the quantum server for your circuit registration and proof submission.
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 accessKey ="xx-xxx"; // AUTH_KEYconstquantum=newQuantum(rpcEndpoint, accessKey);
Check if the quantum instance can talk with the server. If rpcLive is True, a connection is established.
let rpcLive =awaitquantum.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.
We've already established a connection in the quantum instance above. Let's see how to proceed from there.
let vkeyPath ="path/to/vKey.bin"; let combinedVKeyHash = (awaitquantum.registerGnarkGroth16Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath =`path/to/verification_key.json`let combinedVKeyHash = (awaitquantum.registerSnarkJSGroth16Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath =`path/to/method_id.json`let combinedVKeyHash = (awaitquantum.registerRisc0Circuit(vKeyPath)).circuitHash["hash"];
let vKeyPath =`path/to/v_key.bin`let combinedVKeyHash = (awaitquantum.registerSp1Circuit(vKeyPath)).circuitHash["hash"];
let commonDataPath =`path/to/common_data.bin`let verifierOnlyDataPath =`path/to/verifier_only.bin`let combinedVKeyHash = (await quantum.registerPlonky2Circuit(commonDataPath, verifierOnlyDataPath)).circuitHash["hash"];
let vKeyPath =`path/to/vKey.bin`let combinedVKeyHash = (awaitquantum.registerGnarkPlonkCircuit(vKeyPath)).circuitHash["hash"];
let sg2Path =`path/to/sg2.json`let protocolPath =`path/to/protocol.json`let combinedVKeyHash = (awaitquantum.registerHalo2KZGCircuit(sg2Path, protocolPath)).circuitHash["hash"];
let sg2Path =`path/to/sg2.json`let protocolPath =`path/to/protocol.json`let combinedVKeyHash = (awaitquantum.registerHalo2KZGEvmCircuit(sg2Path, protocolPath)).circuitHash["hash"];
combinedVKeyHash is a unique, 32 bytes value for your circuit on the quantum layer. This will be used to submit proofs and on-chain to check for .Each scheme may require a different set of circuit data. Seegenerate-circuit-data to learn how to prepare the circuit data needed for different proving schemes.
Proof Submission
Once the circuit is registered, the proof can be sent for aggregation on the quantum layer.
combinedVKeyHash , which we received after circuit registration will be used to submit proof for cheap verification on Ethereum. Primarily, the user sends its proof and publicInputs corresponding to the registered circuit.
let proofPath =`path/to/proof.bin`let pisPath =`path/to/pis.json`let proofResponse = (awaitquantum.submitGnarkGroth16Proof(proofPath, pisPath, combinedVKeyHash));
let proofPath =`path/to/proof.json`let pisPath =`path/to/public.json`let proofResponse = (awaitquantum.submitSnarkJSGroth16Proof(proofPath, pisPath, combinedVKeyHash));
let vKeyPath =`path/to/method_id.json`let receiptPath =`path/to/receipt.bin`let proofResponse = (awaitquantum.submitRisc0Proof(receiptPath, combinedVKeyHash));
let vKeyPath =`path/to/v_key.bin`let proofPath =`path/to/proof.bin`let proofResponse = (awaitquantum.submitSp1Proof(proofPath, combinedVKeyHash));
let proofPath =`path/to/proof.bin`let proofResponse = (awaitquantum.submitPlonky2Proof(proofPath, combinedVKeyHash));
let proofPath =`path/to/proof.bin`let pisPath =`path/to/pis.json`let proofResponse = (awaitquantum.submitGnarkPlonkProof(proofPath, pisPath, combinedVKeyHash));
let proofPath =`path/to/proof.bin`let instancesPath =`path/to/instances.json`let proofResponse = (awaitquantum.submitHalo2KZGProof(proofPath, instancesPath, combinedVKeyHash));
let proofPath =`path/to/proof.bin`let instancesPath =`path/to/instances.json`let proofResponse = (awaitquantum.submitHalo2KZGEvmProof(proofPath, instancesPath, combinedVKeyHash));
If a proof is submitted successfully, a proofHash is returned from the quantum layer.
let proofPath =`path/to/proof.bin`let pisPath =`path/to/pis.json`let proofResponse = (awaitquantum.submitGnarkGroth16Proof(proofPath, pisPath, combinedVKeyHash));
Check Proof Status
let proofHash =proofResponse.proofHash
proofHash is used to track the progress or get details of the aggregation request.
let proofStatus = (awaitquantum.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.
Each scheme may require a different set of circuit data. Seegenerate-circuit-data to learn how to prepare the circuit data needed for different proving schemes.
Verifying Protocol Proof On-Chain
On-chain Contract
For protocols to integrate quantum, they would have to make some changes to their verification smart contract. The protocol smart contract imports ProtocolVerifier corresponding to their number of public inputs which is used to verify if the pubInputs were verified as part of the aggregated proof.
The function verifyPubInputs of the ProtocolVerifier lib contract is used for public input verification.
Verification requires some Merkle-proof data, which can be fetched using the proofHash as follows:
let protocolProofResponse =awaitquantum.getProtocolProof(proofHash);let protocolInclusionProof =protocolProofResponse.protocolProof
The pubInputs, together with the , are submitted on-chain for verification.
An example contract initialized with the combinedVKeyHash
pragmasolidity ^0.8.24;// Import ProtocolVerifier_{n} corresponding to your n number of public inputs// We support ProtocolVerifier_{1} to ProtocolVerifier_{15}; import accordinglyimport {ProtocolVerifier_5} from"quantum-sdk/contracts/lib/ProtocolVerifier.sol";contract Protocol {bytes32 combinedVKeyHash;addressconstant QUANTUM =0x6afbB1c4296D2b4d333E24f2462b15f2D97449Cb;constructor(bytes32 combinedVKeyHash_) { combinedVKeyHash = combinedVKeyHash_; }functionverifyPubInputs_5(uint256[5] calldata pubInputs,uint256 merkleProofPosition,bytes32[] calldata merkleProof ) external { ProtocolVerifier_5.verifyPubInputs( pubInputs, merkleProofPosition, merkleProof, combinedVKeyHash, QUANTUM ); }// Protocol specific Business logic// ... }}