# Deep Dive

## Architecture Overview

The Proof Aggregation Service consists of three main components that work together to aggregate user proofs and submit them on-chain.

```
┌──────┐    ┌───────────────────────────────┐    ┌─────────────┐
│      │ 1  │ AggregationModePaymentService │ 2  │   Payments  │
│      │--->│           (Contract)          │--->│    Poller   │
│      │    └───────────────────────────────┘    └─────┬───────┘
│      │                                               │
│      │                                             3 │
│      │                                               v
│      │    ┌───────────────┐  5                ┌──────────────┐    ┌───────────────────────────────┐
│ User │ 4  │    Gateway    │------------------>│  PostgreSQL  │    │ AlignedProofAggregationService│
│      │--->│               │                   │      DB      │    │           (Contract)          │
│      │    └───────────────┘                   └──────────────┘    └───────────────────────────────┘
│      │                                               ^                          ^
│      │                                             6 │                          │
│      │                                               │                        7 │
│      │                                        ┌─────────────┐                   │
│      │                                        │    Proof    │-------------------┘
│      │                                        │  Aggregator │
└──────┘                                        └─────────────┘
```

1. User deposits ETH into `AggregationModePaymentService` contract to get quota.
2. `Payments Poller` monitors the contract for deposit events.
3. `Payments Poller` updates user quotas in the database.
4. User submits proofs to the `Gateway`.
5. `Gateway` validates and stores proofs in the database.
6. `Proof Aggregator` fetches pending proofs from the database.
7. `Proof Aggregator` aggregates proofs in the zkVM and submits to `AlignedProofAggregationService` contract.

## Supported Proof Types

The aggregation service currently supports:

* **SP1**: Aggregates proofs of type `Compressed`

## Proof Commitment

The **proof commitment** is a hash that uniquely identifies a proof. It is defined as the keccak of the proof public inputs + program ID:

* **For SP1**: The commitment is computed as: `keccak(proof_public_inputs_bytes || vk_hash_bytes)`

## Multilayer Aggregation

To scale aggregation without exhausting zkVM memory, aggregation is split into two programs:

```
                        User Proofs (n per chunk)
                                  │
          ┌───────────────────────┼───────────────────────┐
          │                       │                       │
          ▼                       ▼                       ▼
   ┌─────────────┐         ┌─────────────┐         ┌─────────────┐
   │   Chunk 1   │         │   Chunk 2   │         │   Chunk N   │
   │  Aggregator │         │  Aggregator │         │  Aggregator │
   └──────┬──────┘         └──────┬──────┘         └──────┬──────┘
          │                       │                       │
          │    Aggregated Proofs + Merkle Roots           │
          │                       │                       │
          └───────────────────────┼───────────────────────┘
                                  │
                                  ▼
                        ┌─────────────────┐
                        │     Chunk       │
                        │   Aggregator    │
                        └────────┬────────┘
                                 │
                                 ▼
                        ┌─────────────────┐
                        │  Final Proof +  │
                        │   Merkle Root   │
                        └─────────────────┘
```

1. **User Proof Aggregator** Processes chunks of `n` user proofs. Each run creates an aggregated proof that commits to a Merkle root of the user proofs inputs. This step is repeated for as many chunks as needed. Usually each chunk contains `256` proofs but it can be lowered based on the machine specs.
2. **Chunk Aggregator** Aggregates all chunk-level proofs into a single final proof. It receives:

   * The chunked proofs
   * The original [proofs commitments](#proof-commitment) included in each chunk received

   During verification, it checks that each chunk's committed Merkle root matches the reconstructed root to ensure input correctness. The final Merkle root, representing all user [proofs commitments](#proof-commitment), is then committed as a public input.

## Verification

Once aggregated, the proof is sent to Ethereum and verified via the `AlignedProofAggregationService` contract. The contract invokes `verifySP1` which receives:

* The public inputs
* The proof binary

The program ID is hardcoded in the contract to ensure only trusted aggregation programs (`chunk_aggregator`) are accepted.

If verification succeeds, the new proof is added to the `aggregatedProofs` map in contract storage.

### Proof Inclusion Verification

To verify a user's proof on-chain, the following must be provided:

* The proof bytes
* The proof public inputs
* The program ID (vk hash)
* A Merkle proof

The Merkle root is computed and checked for existence in the contract using the `verifyProofInclusion` function of the `AlignedProofAggregationService` contract, which:

1. Computes the merkle root
2. Returns `true` or `false` depending on whether there exists an `aggregatedProof` with the computed root.

## Data Availability

When submitting the aggregated proof to Ethereum, we include a **blob** that contains the [commitments](#proof-commitment) of all the individual proofs that were aggregated. This blob serves two main purposes:

* It makes the [proof commitments](#proof-commitment) publicly available for **18 days**.
* It allows users to:
  * Inspect which proofs were aggregated
  * Get a Merkle proof to verify that their proof is included in the aggregated proof


---

# 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.alignedlayer.com/architecture/2_aggregation_mode/1_deep_dive.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.
