# 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
