# Integration

## Proving Schemes Supported

The quantum supports the following proving schemes:

* GnarkGroth16
* SnarkjsGroth16 (Circom)
* Risc0
* Sp1
* Plonky2
* GnarkPlonk
* Halo2Kzg (Poseidon)
* Halo2KzgEvm
* AwsNitroAttestation

Check out [quantum-demo](https://github.com/Electron-Labs/quantum-demo) which demonstrates the full proof generation cycle for all schemes.

{% hint style="info" %}

* For Halo2Kzg and Halo2KzgEvm, Shplonk proofs are supported
* For Sp1, [compressed proofs](https://docs.succinct.xyz/generating-proofs/proof-types.html#compressed) are supported
* For Risc0, [succinct receipts](https://dev.risczero.com/proof-system/#types-of-receipts) are supported
  {% endhint %}

Below is a step-by-step flow.

## Install quantum-sdk package in your project

```sh
npm i quantum-sdk
```

`quantum-sdk` lets you seamlessly interact with the quantum server for your [circuit registration](#circuit-registration) and proof submission.

## Retrieve Authorization Key

Retrieve an authorization key for accessing quantum testnet as follows:

```typescript
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**

```javascript
import {Quantum} from "quantum-sdk";
```

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

```javascript
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.

```javascript
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.

We've already established a connection in the `quantum` instance [above](#initialise-connection). Let's see how to proceed from there.

{% tabs %}
{% tab title="GnarkGroth16" %}

```javascript
let vkeyPath = "path/to/vKey.bin"; 
let circuitHash = (await quantum.registerGnarkGroth16Circuit(vKeyPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="SnarkjsGroth16" %}

```javascript
let vKeyPath = `path/to/verification_key.json`
let circuitHash = (await quantum.registerSnarkJSGroth16Circuit(vKeyPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="Risc0" %}

```javascript
let vKeyPath = `path/to/method_id.json`
let circuitHash = (await quantum.registerRisc0Circuit(vKeyPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="Sp1" %}

```javascript
let vKeyPath = `path/to/v_key.bin`
let circuitHash = (await quantum.registerSp1Circuit(vKeyPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="Plonky2" %}

```javascript
let commonDataPath = `path/to/common_data.bin`
let verifierOnlyDataPath = `path/to/verifier_only.bin`
let circuitHash = (await quantum.registerPlonky2Circuit(commonDataPath, verifierOnlyDataPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="GnarkPlonk" %}

```javascript
let vKeyPath = `path/to/vKey.bin`
let circuitHash = (await quantum.registerGnarkPlonkCircuit(vKeyPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="Halo2Kzg" %}

```javascript
let sg2Path = `path/to/sg2.json`
let protocolPath = `path/to/protocol.json`
let circuitHash = (await quantum.registerHalo2KZGCircuit(sg2Path, protocolPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="Halo2KzgEvm" %}

```javascript
let sg2Path = `path/to/sg2.json`
let protocolPath = `path/to/protocol.json`
let circuitHash = (await quantum.registerHalo2KZGEvmCircuit(sg2Path, protocolPath)).circuitHash["hash"];
```

{% endtab %}

{% tab title="AwsNitroAttestation" %}

```javascript
let pcr0Path = `path/to/pcr0.bin`
let combinedVKeyHash = (await quantum.registerNitroAttCircuit(pcr0Path)).circuitHash["hash"];
```

{% endtab %}
{% endtabs %}

`circuitHash` is a unique, 32 bytes value for your circuit on the quantum layer. This will be used to [submit proofs](#proof-submission) and on-chain to check for [proof-inclusion purposes](#user-content-fn-1)[^1].\
Each scheme may require a different set of circuit data. See [generate-circuit-data](https://github.com/Electron-Labs/quantum-demo?tab=readme-ov-file#generate-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.

`circuitHash` , which we received after [circuit registration](#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.&#x20;

{% tabs %}
{% tab title="GnarkGroth16" %}

```javascript
let proofPath = `path/to/proof.bin`
let pisPath = `path/to/pis.json`
let proofResponse = (await quantum.submitGnarkGroth16Proof(proofPath, pisPath, circuitHash));
```

{% endtab %}

{% tab title="SnarkjsGroth16" %}

```javascript
let proofPath = `path/to/proof.json`
let pisPath = `path/to/public.json`
let proofResponse = (await quantum.submitSnarkJSGroth16Proof(proofPath, pisPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="Risc0" %}

```javascript
let vKeyPath = `path/to/method_id.json`
let receiptPath = `path/to/receipt.bin`
let proofResponse = (await quantum.submitRisc0Proof(receiptPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="Sp1" %}

```javascript
let vKeyPath = `path/to/v_key.bin`
let proofPath = `path/to/proof.bin`
let proofResponse = (await quantum.submitSp1Proof(proofPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="Plonky2" %}

```javascript
let proofPath = `path/to/proof.bin`
let proofResponse = (await quantum.submitPlonky2Proof(proofPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="GnarkPlonk" %}

```javascript
let proofPath = `path/to/proof.bin`
let pisPath = `path/to/pis.json`
let proofResponse = (await quantum.submitGnarkPlonkProof(proofPath, pisPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="Halo2Kzg" %}

```javascript
let proofPath = `path/to/proof.bin`
let instancesPath = `path/to/instances.json`
let proofResponse = (await quantum.submitHalo2KZGProof(proofPath, instancesPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="Halo2KzgEvm" %}

```javascript
let proofPath = `path/to/proof.bin`
let instancesPath = `path/to/instances.json`
let proofResponse = (await quantum.submitHalo2KZGEvmProof(proofPath, instancesPath, combinedVKeyHash));
```

{% endtab %}

{% tab title="AwsNitroAttestation" %}

```javascript
let attDocPath = `path/to/attestation_doc.bin`
let proofResponse = (await quantum.submitNitroAttProof(attDocPath, combinedVKeyHash));
```

{% endtab %}
{% endtabs %}

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

{% hint style="info" %}
A proof cannot be submitted if another proof associated with the same `circuitHash` is currently being aggregated.
{% endhint %}

#### Check Proof Status

```javascript
let proofHash = proofResponse.proofHash
```

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

```javascript
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

{% hint style="info" %}
Currently, the aggregated proof is submitted on Sepolia once every \~15 minutes, so for the STATUS to get to`VERIFIED`can take some time.
{% endhint %}

Each scheme may require a different set of circuit data. See [generate-circuit-data](https://github.com/Electron-Labs/quantum-demo?tab=readme-ov-file#generate-circuit-data) to learn how to prepare the circuit data needed for different proving schemes.

## Verifying Protocol Proof On-Chain

### On-chain Contract

```bash
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.

Verification requires some Merkle-proof data, which can be fetched using the [proofHash](#check-proof-status) as follows:

```javascript
let protocolProofResponse = await quantum.getProtocolProof(proofHash);
let protocolInclusionProof = protocolProofResponse.protocolProof
```

Here is an example contract initialized with the `circuitHash.` This example can be found in [example contracts](https://github.com/Electron-Labs/quantum-verifier-contracts/tree/master/contracts/example_protocol)

```solidity
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
        // ...   
    }
}
```

{% hint style="info" %}
For Risc0, refer to the example [here](https://github.com/Electron-Labs/quantum-verifier-contracts/blob/master/contracts/example_protocol/Protocol2.sol)
{% endhint %}

{% hint style="info" %}
Note, `merkleProof` calldata must be the first parameter as assumed by `CircuitVerifier`
{% endhint %}

[^1]: verify that the proof is aggregated in quantum superproof


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.electron.dev/quantum-proof-aggregation-for-ethereum/integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
