Skip to content

Commit

Permalink
Put the asset info in the CSV header summa-dev#183 (summa-dev#192)
Browse files Browse the repository at this point in the history
* Put the asset info in the CSV header summa-dev#183

* Fix tests

* Remove asset file description from example readme

* Eliminate ambiguity between assets/cryptos/liabilities
  • Loading branch information
alxkzmn authored Nov 27, 2023
1 parent e6cdd58 commit 2bb8bff
Show file tree
Hide file tree
Showing 24 changed files with 1,093 additions and 1,072 deletions.
4 changes: 2 additions & 2 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ futures = "0.3.28"
num-bigint = "0.4.3"
serde = { version = "1.0.166", features = ["derive"] }
snark-verifier-sdk = { git = "https://github.com/privacy-scaling-explorations/snark-verifier", version = "0.1.1" }
ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc"] }
ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc","legacy"] }
reqwest = { version = "0.11", features = ["json"] }
serde_json = "1.0.64"
tokio = { version = "1.7.1", features = ["full"] }
base64 = "0.13"
bincode = "1.3.3"

[build-dependencies]
ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc"] }
ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc", "legacy"] }
27 changes: 14 additions & 13 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ This directory contains the backend implementation for the Summa Proof of Solven

### Round

The `Round` component represents a specific period or cycle in the Summa Proof of Solvency protocol. It encapsulates the state of the system at a given time, including the snapshot of assets and liabilities, as well as the associated proofs.
The `Round` struct integrates with the `Snapshot` and `SummaSigner` to facilitate the generation and submission of proofs to the contract.
The `Round` component represents a specific period or cycle in the Summa Proof of Solvency protocol. It encapsulates the state of the system at a given time, including the snapshot of assets and liabilities, as well as the associated proofs.
The `Round` struct integrates with the `Snapshot` and `SummaSigner` to facilitate the generation and submission of proofs to the contract.

Key Features:

- Initialization of a new round with specific parameters.
- Building a snapshot of the current state.
- Submitting commitment to the contract.
Expand All @@ -20,6 +21,7 @@ Key Features:
The `AddressOwnership` component is responsible for managing and verifying the ownership of addresses. It ensures that addresses used in the protocol owned by the respective participants. This component interacts with the `SummaSigner` to submit proofs of address ownership to on-chain.

Key Features:

- Initialization with specific signer details.
- Dispatching proofs of address ownership to the contract.

Expand Down Expand Up @@ -49,8 +51,8 @@ cargo test --release -- --nocapture
### Generating and updating verifier contract for Backend

The verifier contract in the backend were generated using a predefined set of parameters: `N_ASSETS = 2` and `N_BYTES=14`, as indicated [here](https://github.com/summa-dev/summa-solvency/blob/master/zk_prover/examples/gen_inclusion_verifier.rs#L21-L22).
If you intend to work with different parameters, you'll need to adjust these hard-coded values and then generate new verifier contract.
If you intend to work with different parameters, you'll need to adjust these hard-coded values and then generate new verifier contract.

The process described below assists in both generating the verifier and updating the Summa contract, which integrates the new verifier as constructors.

#### Using the Bash Script
Expand Down Expand Up @@ -91,7 +93,6 @@ If executed successfully, you'll see:
1. Ownership proofs are submitted successfully!
```


### 2. Submit Commitment

The CEX must submit a commitment to the Summa contract for each round. This commitment consists of a `timestamp`, the root hash of the Merkle Sum Tree (`mst_root`), and `balances`.
Expand All @@ -101,11 +102,10 @@ Without publishing the commitment, users cannot verify their inclusion proof on
In here, we'll introduce you through the process of submitting a commitment using the `Round` to the Summa contract.
The Round serves as the core of the backend in Summa, and we have briefly described it in the Components section.

To initialize the `Round` instance, you'll need paths to specific CSV files (`assets.csv` and `entry_16.csv`) and the `ptau/hermez-raw-11` file. Here's what each file does:
To initialize the `Round` instance, you'll need paths to the liabilities CSV file (`entry_16.csv`) and the `ptau/hermez-raw-11` file. The files serve the following purpose:

- `assets.csv`: Calculates the total balance of assets for the solvency proof. Only the CEX can generate this file.
- `entry_16.csv`: Used to build the Merkle sum tree, with each leaf element derived from sixteen entries in the CSV.
- `ptau/hermez-raw-11`: Contains parameters for constructing the zk circuits.
- `entry_16.csv`: contains the username and liabilities entries for each CEX user (necessary to build the commitment). Liabilities column names have the following format: `balance_<CRYPTOCURRENCY>_<CHAIN>`, where <CRYPTOCURRENCY> and <CHAIN> are the names of the cryptocurrencies and their corresponding blockchains. <CHAIN> values are the same as in the Address Ownership Proof step;
- `ptau/hermez-raw-11`: contains parameters for constructing the zk circuits.

Using the `Round` instance, the solvency proof is dispatched to the Summa contract with the `dispatch_solvency_proof` method.

Expand Down Expand Up @@ -136,12 +136,13 @@ Users receive the proof for a specific round and use methods available on the de
In this step, the user has to:

- Ensure the `leaf_hash` (public input of the proof) aligns with the Poseidon hash of the `username` and `balances` provided by the CEX.
- Submit the proof to the `verify_inclusion_proof` method on the Summa contract Which will:
- Retrieve the `mstRoot` from the Summa contract and match it with the `root_hash` in the proof.
- Retrieve the `rootBalances` from the Summa contract and match it with the `root_balances` in the proof
- Verify the zk Proof
- Submit the proof to the `verify_inclusion_proof` method on the Summa contract Which will:
- Retrieve the `mstRoot` from the Summa contract and match it with the `root_hash` in the proof.
- Retrieve the `rootBalances` from the Summa contract and match it with the `root_balances` in the proof
- Verify the zk Proof

The result will display as:

```
4. Verifying the proof on contract verifier for User #0: true
```
Expand Down
10 changes: 1 addition & 9 deletions backend/examples/summa_solvency_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
//
// Initialize the `Round` instance to submit the liability commitment.
let params_path = "ptau/hermez-raw-11";
let assets_csv_path = "src/apis/csv/assets.csv";
let entry_csv = "../zk_prover/src/merkle_sum_tree/csv/entry_16.csv";
let mst = MerkleSumTree::new(entry_csv).unwrap();

// Using the `round` instance, the commitment is dispatched to the Summa contract with the `dispatch_commitment` method.
let timestamp = 1u64;
let mut round = Round::<4, 2, 14>::new(
&signer,
Box::new(mst),
assets_csv_path,
params_path,
timestamp,
)
.unwrap();
let mut round = Round::<4, 2, 14>::new(&signer, Box::new(mst), params_path, timestamp).unwrap();

// Sends the commitment, which should ideally complete without errors.
round.dispatch_commitment().await?;
Expand Down
3 changes: 0 additions & 3 deletions backend/src/apis/csv/assets.csv

This file was deleted.

56 changes: 1 addition & 55 deletions backend/src/apis/csv_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{error::Error, fs::File, path::Path};
use ethers::{abi::AbiEncode, types::Bytes};
use serde::{Deserialize, Serialize};

use crate::contracts::generated::summa_contract::{AddressOwnershipProof, Asset};
use crate::contracts::generated::summa_contract::AddressOwnershipProof;

#[derive(Debug, Deserialize, Serialize)]
pub struct SignatureRecord {
Expand Down Expand Up @@ -46,39 +46,6 @@ pub fn parse_signature_csv<P: AsRef<Path>>(
Ok(address_ownership_proofs)
}

#[derive(Debug, Deserialize)]
struct AssetRecord {
chain: String,
asset_name: String,
}

pub fn parse_asset_csv<P: AsRef<Path>, const N_ASSETS: usize>(
path: P,
) -> Result<[Asset; N_ASSETS], Box<dyn Error>> {
let file = File::open(path)?;
let mut rdr = csv::ReaderBuilder::new().delimiter(b';').from_reader(file);

let mut assets_vec = Vec::with_capacity(N_ASSETS);

for result in rdr.deserialize() {
let record: AssetRecord = result?;

assets_vec.push(Asset {
asset_name: record.asset_name,
chain: record.chain,
});
}

let assets_array: [Asset; N_ASSETS] = assets_vec.try_into().map_err(|v: Vec<Asset>| {
format!(
"The number of assets in CSV file does not match the expected count {:?}",
v
)
})?;

Ok(assets_array)
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -98,25 +65,4 @@ mod tests {

assert_eq!(address_ownership[0], first_address_ownership);
}

#[test]
fn test_parse_csv_to_assets() {
let path = "src/apis/csv/assets.csv";
let assets = parse_asset_csv::<&str, 2>(path).unwrap();

assert_eq!(
assets[0],
Asset {
chain: "ETH".to_string(),
asset_name: "ETH".to_string(),
}
);
assert_eq!(
assets[1],
Asset {
chain: "ETH".to_string(),
asset_name: "USDT".to_string(),
}
);
}
}
27 changes: 15 additions & 12 deletions backend/src/apis/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use halo2_proofs::{
use serde::{Deserialize, Serialize};
use std::error::Error;

use super::csv_parser::parse_asset_csv;
use crate::contracts::{generated::summa_contract::summa::Asset, signer::SummaSigner};
use crate::contracts::{generated::summa_contract::summa::Cryptocurrency, signer::SummaSigner};
use summa_solvency::{
circuits::{
merkle_sum_tree::MstInclusionCircuit,
Expand Down Expand Up @@ -40,8 +39,7 @@ impl MstInclusionProof {
}

pub struct Snapshot<const LEVELS: usize, const N_ASSETS: usize, const N_BYTES: usize> {
mst: Box<dyn Tree<N_ASSETS, N_BYTES>>,
assets_state: [Asset; N_ASSETS],
pub mst: Box<dyn Tree<N_ASSETS, N_BYTES>>,
trusted_setup: SetupArtifacts,
}

Expand All @@ -60,14 +58,12 @@ where
pub fn new<'a>(
signer: &'a SummaSigner,
mst: Box<dyn Tree<N_ASSETS, N_BYTES>>,
asset_csv_path: &str,
params_path: &str,
timestamp: u64,
) -> Result<Round<'a, LEVELS, N_ASSETS, N_BYTES>, Box<dyn Error>> {
Ok(Round {
timestamp,
snapshot: Snapshot::<LEVELS, N_ASSETS, N_BYTES>::new(mst, asset_csv_path, params_path)
.unwrap(),
snapshot: Snapshot::<LEVELS, N_ASSETS, N_BYTES>::new(mst, params_path).unwrap(),
signer: &signer,
})
}
Expand All @@ -91,7 +87,18 @@ where
.submit_commitment(
mst_root,
root_sums,
self.snapshot.assets_state.to_vec(),
self.snapshot
.mst
.cryptocurrencies()
.iter()
.map(|cryptocurrency| Cryptocurrency {
name: cryptocurrency.name.clone(),
chain: cryptocurrency.chain.clone(),
})
.collect::<Vec<Cryptocurrency>>()
.as_slice()
.try_into()
.unwrap(),
U256::from(self.get_timestamp()),
)
.await?;
Expand All @@ -118,11 +125,8 @@ where
{
pub fn new(
mst: Box<dyn Tree<N_ASSETS, N_BYTES>>,
asset_csv_path: &str,
params_path: &str,
) -> Result<Snapshot<LEVELS, N_ASSETS, N_BYTES>, Box<dyn std::error::Error>> {
let assets_state = parse_asset_csv::<&str, N_ASSETS>(asset_csv_path).unwrap();

let mst_inclusion_circuit = MstInclusionCircuit::<LEVELS, N_ASSETS, N_BYTES>::init_empty();

// get k from ptau file name
Expand All @@ -135,7 +139,6 @@ where

Ok(Snapshot {
mst,
assets_state,
trusted_setup: mst_inclusion_setup_artifacts,
})
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/contracts/abi/Summa.json

Large diffs are not rendered by default.

Loading

0 comments on commit 2bb8bff

Please sign in to comment.