> For the complete documentation index, see [llms.txt](https://summa.gitbook.io/summa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://summa.gitbook.io/summa/v3/backend/summa-solvency.md).

# summa-solvency

This section describes how to use `summa-solvency` backend to perform a full [Protocol Flow](/summa/v3/introduction/protocol-flow.md).

## Setup

### 1. Generic Parameters

First of all, it is essential to determine two key parameters:&#x20;

* The number of currencies that will be handled simultaneously in a single Proof of Solvency - `N_CURRENCIES`
* The number of users included in a proof of solvency - `N_USERS`

Take, for example, a scenario where a Custodian opts to include ten currencies and 64 users in one proof. This setup enables the commitment to cover 64 users. Furthermore, it allows users to simultaneously verify their inclusion proof for all ten currencies in one go, rather than having to verify ten separate proofs.

Therefore, before starting, Custodians need to thoughtfully determine the `N_CURRENCIES` and `N_USERS` values.

### 2. Powers Of Tau&#x20;

[Zero-knowledge-proof](/summa/v3/cryptographic-primitives/zero-knowledge-proof.md) systems require a Trusted Setup. Summa uses the [Plonkish](https://github.com/summa-dev/plonkish/tree/summa) backend with the multilinear KZG polynomial commitment. The `Summa` circuit requires a one-time, universal trusted setup, commonly known as a powers-of-tau ceremony.\
However, there is no existing SRS file, which is a result of trusted setup, that has undergone a trusted setup ceremony for the Plonkish backend, especially for the HyperPlonk used in the backend of V3.

{% hint style="warning" %}
We provide SRS files that were generated for testing purposes only. These files were created temporarily and were not produced through a formal ceremony process.
{% endhint %}

To download the appropriate SRS file, the custodian needs to know the size of the SRS file, which is related to the K parameter. Identifying the correct `K` value is essential for Summa's circuit. The minimum circuit size can be accurately determined based on the number of users by applying the following formula:

$$
K = MAX(\log\_2({N\_USERS} + 2), 17)
$$

This formula ensures that the chosen `K` value satisfies both the prerequisite condition `N_USERS < 2^K - 2` and the minimum rows required for the range check circuit.

Pre-existing trusted setup files can be found at [here - Prerequisites of Backend](https://github.com/summa-dev/summa-solvency/tree/v3a-fix-backend/backend#prerequisites). To download a specific SRS file, use the following command:

```
wget https://summa-solvency.s3.eu-central-1.amazonaws.com/trusted-setup-hyperplonk2kzg/hyperplonk-srs-17
```

This action downloads an SRS file for a circuit size of `k=17`.

## Interact with the Backend

Once the setup is completed, the custodian can utilize summa-solvency [backend](https://github.com/summa-dev/summa-solvency/tree/v3a/backend) to perform a [full Proof of Solvency flow](/summa/v3/introduction/protocol-flow.md).

The  [Summa Solvency Flow Example](https://github.com/summa-dev/summa-solvency/blob/v3a/backend/examples/summa_solvency_flow.rs) illustrates the process for performing the necessary steps, as outlined below.

#### 1. Liabilities Commitment

To generate the liabilities commitment and user inclusion proofs, the custodian has to prepare a CSV file, referred to as "entry.csv", which contains all usernames and their `N_CURRENCIES` balances. The csv file format looks like this:

```
username,balance_ETH_ETH,balance_DAI_ETH
dxGaEAii,11888,41163
```

The first column header must be the username, and the rest of the columns should follow the pattern *balance\_\[Currency]\_\[Chain]*. Assuming the CSV file is named as `entry.csv`, initialize Summa circuit as follows:

```rust
let entry_csv = "entry.csv";
let mut entries: Vec<Entry<N_CURRENCIES>> = vec![Entry::init_empty(); N_USERS];
let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES];
parse_csv_to_entries::<&str, N_CURRENCIES>(entry_csv, &mut entries, &mut cryptos).unwrap();

let circuit = SummaHyperplonk::<N_USERS, N_CURRENCIES>::init(entries.to_vec());
```

Initializing a round requires multiple parameters: `zk_snark_proof`, `advice_polys`, `prover_arams`, `verifier_params`, and `timestamp`:

```rust
let mut round = Round::<N_CURRENCIES, N_USERS>::new(
    zk_snark_proof,
    advice_polys,
    prover_params,
    verifier_params,
    timestamp,
);
```

* `zk_snark_proof`: The proof generated from the `Summa` circuit.
* `advice_polys`: The advice polynomials that were used as witness data to create the zk\_snark\_proof.
* `prover_params`: An instance of `HyperPlonkProverParam` from the plonkish backend. It is used in generating the commitment proof, which corresponds to `zk_snark_proof`.
* `verifier_params`: The verifying parameters for the `zk_snark_proof` and inclusion proofs.
* `timestamp`: A UNIX timestamp marking the moment the liabilities snapshot (reflected in the "entry\_16.csv" file) was taken.

Now, the custodian can retrieve the commitment and verifier params as files using the `gen_commitment_and_vp` method:

```rust
 let (zk_snark_proof, verifier_params) = round.gen_commitment_and_vp().unwrap();
```

At the end of this step, the custodian should ready to publish the commitment and the verifier params to user in public way.&#x20;

#### 2. Generate Inclusion Proofs

Now, the custodian can generate inclusion proofs for their users using the `round`, Initialized from the previous step.

The `get_proof_of_inclusion` method requires a `user_index`, which corresponds to the index of the user's data within the Entry CSV file ("entry.csv"), as established in the prior section.

```rust
let inclusion_proof = round.get_proof_of_inclusion(user_index).unwrap();
```

The custodian can then provide these inclusion proofs to their users.

{% hint style="info" %}
Generating proofs for all the users at once can present some [scaling issues](/summa/v3/open-issues.md#timing-of-proofs-of-inclusion-generation). Alternatively, the custodian can generate such proof only if the user queries it. Please refer to the [benchmarks](/summa/v3/benchmarks.md).
{% endhint %}

#### 3. Verify Inclusion Proof

In V3 of Summa, users who have received an inclusion proof and commitment for a specific round can verify their proofs using a locally executable verifier provided by the custodian. This process differs from other Summa versions, as V3 does not utilize an on-chain verifier contract.

The executable verifier may include the verifying parameter necessary for verifying the inclusion proof. However, in the interest of transparency, we assume that the verifying parameter will be served separately, like a file. This means that the custodian must provide both the executable verifier and the verifying parameter either before or immediately after sending inclusion proofs to users.

The executable verifier would consist of three parts:

* Reading Proofs and Verifying Parameters from files:

  ```rust
  let commitment: KZGProof = load_from_file(commitment_proof_filename).unwrap();
  let verifier_params: HyperPlonkVerifierParam<Fp, MultilinearKzg<Bn256>> =
      load_from_file(vp_filename).unwrap();

  let inclusion_proof: KZGProof = load_from_file("user_inclusion_proof.json").unwrap();
  ```
* Getting evaluation from the inclusion proof:

  ```rust
  let mut kzg_transcript = Keccak256Transcript::from_proof((), inclusion_proof.get_proof().as_slice());
  let mut multivariate_challenge: Vec<Fp> = Vec::new();
  for _ in 0..num_vars {
      multivariate_challenge.push(kzg_transcript.read_field_element().unwrap());
  }

  let input_values = inclusion_proof.get_input_values();
  let evals: Vec<Evaluation<Fp>> = (0..N_CURRENCIES + 1)
      .map(|i| Evaluation::new(i, 0, input_values[i]))
      .collect();
  ```
* Verifying the inclusion proof with the commitment and verifying parameters:

  ```rust
  let mut transcript = Keccak256Transcript::from_proof((), commitment.get_proof().as_slice());
  let user_entry_commitments = MultilinearKzg::<Bn256>::read_commitments(
      &verifier_params.pcs,
      N_CURRENCIES + 1,
      &mut transcript,
  )
  .unwrap();

  MultilinearKzg::<Bn256>::batch_verify(
      &verifier_params.pcs,
      &user_entry_commitments,
      &[multivariate_challenge.clone()],
      &evals,
      &mut kzg_transcript,
  ).unwrap();
  ```

If the verifying process in the verifier completes without error, it will return a successful message.

For more detailed information on the verifying process, refer to the Summa Solvency Flow Example -[3. Verifying Inclusion Proof](https://github.com/summa-dev/summa-solvency/blob/2d878e4ab102baa135e8acd1edc7dbf23339cf40/backend/examples/summa_solvency_flow.rs#L118-L155)&#x20;

Now, users who receive an inclusion proof can verify their proof with this kind of executable verifier on their local machine.
