Skip to content

Commit

Permalink
Improve code documentation as per PR review
Browse files Browse the repository at this point in the history
  • Loading branch information
alxkzmn committed Dec 12, 2023
1 parent e134e5f commit f4c1417
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 26 deletions.
92 changes: 81 additions & 11 deletions kzg_prover/src/circuits/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,28 @@ mod test {
valid_prover.assert_satisfied();

// 1. Proving phase
// The Custodian generates the ZK proof
// The Custodian generates the ZK-SNARK Halo2 proof that commits to the user entry values in advice polynomials
// and also range-checks the user balance values
let (zk_snark_proof, advice_polys, omega) =
full_prover(&params, &pk, circuit.clone(), vec![vec![]]);

// Both the Custodian and the Verifier know what column range are the balance columns
// (The first column is the user IDs)
let balance_column_range = 1..N_CURRENCIES + 1;

// The Custodian makes multi-openings at x = 0 for the Verifier
let grand_sums_multi_proof = open_grand_sums::<N_CURRENCIES>(
// The Custodian makes a batch opening proof of all user balance polynomials at x = 0 for the Verifier
let grand_sums_batch_proof = open_grand_sums::<N_CURRENCIES>(
&advice_polys.advice_polys,
&advice_polys.advice_blinds,
&params,
balance_column_range,
);

// The Custodian creates a KZG multi-proof of the 4th user ID & balances inclusion
// The Custodian creates a KZG batch proof of the 4th user ID & balances inclusion
let user_index = 3_u16;

let column_range = 0..N_CURRENCIES + 1;
let openings_multi_proof = open_user_points::<N_CURRENCIES>(
let openings_batch_proof = open_user_points::<N_CURRENCIES>(
&advice_polys.advice_polys,
&advice_polys.advice_blinds,
&params,
Expand All @@ -122,12 +123,12 @@ mod test {
// Both the Custodian and the Verifier know what column range are the balance columns
let balance_column_range = 1..N_CURRENCIES + 1;

// The Custodian communicates the KZG multi-opening transcript to the Verifier
// The Verifier verifies the KZG multi-opening and calculates the grand sums
// The Custodian communicates the KZG batch opening transcript to the Verifier
// The Verifier verifies the KZG batch opening and calculates the grand sums
let (verified, grand_sum) = verify_grand_sum_openings::<N_CURRENCIES>(
&params,
&zk_snark_proof,
grand_sums_multi_proof,
grand_sums_batch_proof,
poly_degree,
balance_column_range,
);
Expand All @@ -143,7 +144,7 @@ mod test {
let (inclusion_verified, id_and_balance_values) = verify_user_inclusion::<N_POINTS>(
&params,
&zk_snark_proof,
&openings_multi_proof,
&openings_batch_proof,
column_range,
omega,
user_index,
Expand All @@ -164,7 +165,74 @@ mod test {
);
}
}
}

#[test]
fn test_invalid_univariate_grand_sum_proof() {
const N_USERS: usize = 16;

// Initialize an empty circuit
let circuit = UnivariateGrandSum::<N_BYTES, N_USERS, N_CURRENCIES>::init_empty();

// Generate a universal trusted setup for testing purposes.
//
// The verification key (vk) and the proving key (pk) are then generated.
// An empty circuit is used here to emphasize that the circuit inputs are not relevant when generating the keys.
// Important: The dimensions of the circuit used to generate the keys must match those of the circuit used to generate the proof.
// In this case, the dimensions are represented by the number fo users.
let (params, pk, vk) = generate_setup_artifacts(K, None, circuit).unwrap();

// Only now we can instantiate the circuit with the actual inputs
let path = "src/csv/entry_16.csv";

let mut entries: Vec<Entry<N_CURRENCIES>> = vec![Entry::init_empty(); N_USERS];
let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES];

let _ =
parse_csv_to_entries::<&str, N_CURRENCIES, N_BYTES>(path, &mut entries, &mut cryptos)
.unwrap();

// Calculate total for all entry columns
let mut csv_total: Vec<BigUint> = vec![BigUint::from(0u32); N_CURRENCIES];

for entry in &entries {
for (i, balance) in entry.balances().iter().enumerate() {
csv_total[i] += balance;
}
}

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

let valid_prover = MockProver::run(K, &circuit, vec![vec![]]).unwrap();

valid_prover.assert_satisfied();

// 1. Proving phase
// The Custodian generates the ZK proof
let (zk_snark_proof, advice_polys, omega) =
full_prover(&params, &pk, circuit.clone(), vec![vec![]]);

// The Custodian creates a KZG batch proof of the 4th user ID & balances inclusion
let user_index = 3_u16;

let column_range = 0..N_CURRENCIES + 1;
let openings_batch_proof = open_user_points::<N_CURRENCIES>(
&advice_polys.advice_polys,
&advice_polys.advice_blinds,
&params,
column_range,
omega,
user_index,
);

// 2. Verification phase
// The Verifier verifies the ZK proof
assert!(full_verifier(&params, &vk, &zk_snark_proof, vec![vec![]]));

// The Verifier is able to independently extract the omega from the verification key
let omega = pk.get_vk().get_domain().get_omega();

// Both the Custodian and the Verifier know what column range are the balance columns
let balance_column_range = 1..N_CURRENCIES + 1;

// Test failure case with the wrong group generator
Expand All @@ -173,18 +241,20 @@ mod test {
let (balances_verified, _) = verify_user_inclusion::<N_CURRENCIES>(
&params,
&zk_snark_proof,
&openings_multi_proof,
&openings_batch_proof,
balance_column_range,
bad_omega,
user_index,
);
//The verification should fail
assert!(!balances_verified);

// TODO add more negative tests
}

#[cfg(feature = "dev-graph")]
#[test]
fn print_solvency_v2_circuit() {
fn print_univariate_grand_sum_circuit() {
use plotters::prelude::*;

let path = "src/csv/entry_16.csv";
Expand Down
116 changes: 101 additions & 15 deletions kzg_prover/src/circuits/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,20 @@ pub fn full_prover<C: Circuit<Fp>>(
(proof, advice_polys, omega)
}

/// Creates the univariate polynomial grand sum openings
/// The challenge is set to zero to obtain the constant term of the polynomials
/// Creates the univariate polynomial grand sum openings.
/// The polynomials are evaluated at X = 0 to obtain their constant term.
///
/// # Arguments
///
/// * `advice_polys` - the advice polynomials
/// * `advice_blinds` - the advice polynomials blinds
/// * `params` - the KZG parameters
/// * `balance_column_range` - the range of the balance columns used to calculate the grand sums
///
/// # Returns
///
/// * `Vec<u8>` - the KZG batch proof containing the quotient polynomial commitments
/// and the evaluations of the polynomials at X = 0
pub fn open_grand_sums<const N_CURRENCIES: usize>(
advice_polys: &[Polynomial<Fp, Coeff>],
advice_blinds: &[Blind<Fp>],
Expand All @@ -141,6 +153,22 @@ pub fn open_grand_sums<const N_CURRENCIES: usize>(
.to_vec()
}

/// Creates a KZG batch proof for the `advice_polys` polynomial openings
/// at a point corresponding to the `user_index`
///
/// # Arguments
///
/// * `advice_polys` - the advice polynomials
/// * `advice_blinds` - the advice polynomials blinds
/// * `params` - the KZG parameters
/// * `column_range` - the advice column range to be used for the proof
/// * `omega` - $\omega$, the generator of the $2^k$ order multiplicative subgroup used to interpolate the polynomials.
/// * `user_index` - the index of the user whose entry is being proven
///
/// # Returns
///
/// * `Vec<u8>` - the KZG batch proof containing the quotient polynomial commitments
/// and the evaluations of the polynomials at the point corresponding to the `user_index`
pub fn open_user_points<const N_CURRENCIES: usize>(
advice_polys: &[Polynomial<Fp, Coeff>],
advice_blinds: &[Blind<Fp>],
Expand All @@ -165,10 +193,24 @@ pub fn open_user_points<const N_CURRENCIES: usize>(
}

/// Verifies the univariate polynomial grand sum openings
/// and calculates the grand sums
///
/// # Arguments
///
/// * `params` - the KZG parameters
/// * `zk_snark_proof` - the ZK-SNARK proof of the circuit whose advice columns contain the user balance polynomials
/// * `grand_sum_opening_batch_proof` - the KZG batch proof of the grand sum polynomials
/// * `polynomial_degree` - the degree of the polynomials
/// * `balance_column_range` - the range of the advice columns that represent user balances
///
/// # Returns
///
/// * `bool` - whether the grand sum openings are verified correctly
/// * `Vec<BigUint>` - the grand sums
pub fn verify_grand_sum_openings<const N_CURRENCIES: usize>(
params: &ParamsKZG<Bn256>,
zk_snark_proof: &[u8],
challenge_opening_multi_proof: Vec<u8>,
grand_sum_opening_batch_proof: Vec<u8>,
polynomial_degree: u64,
balance_column_range: Range<usize>,
) -> (bool, Vec<BigUint>) {
Expand All @@ -194,7 +236,7 @@ pub fn verify_grand_sum_openings<const N_CURRENCIES: usize>(
N_CURRENCIES,
>(
params,
&challenge_opening_multi_proof,
&grand_sum_opening_batch_proof,
Fp::zero(),
&advice_commitments,
);
Expand All @@ -208,11 +250,26 @@ pub fn verify_grand_sum_openings<const N_CURRENCIES: usize>(
)
}

pub fn verify_user_inclusion<const N_CURRENCIES: usize>(
/// Verifies the KZG batch proof of the polynomial openings being the evaluations
/// of the advice polynomials at the point corresponding to the user index
///
/// # Arguments
/// * `params` - the KZG parameters
/// * `zk_snark_proof` - the ZK-SNARK proof of the circuit whose advice columns contain the user entry polynomials
/// * `balance_opening_batch_proof` - the KZG batch proof of the user entry polynomials
/// * `column_range` - the range of the advice columns that represent user entry
/// * `omega` - $\omega$, the generator of the $2^k$ order multiplicative subgroup used to interpolate the polynomials.
/// * `user_index` - the index of the user whose entry is being proven
/// * `N_POINTS` - the size of the user entry being verified (e.g., 1 ID value + 4 balance values = 5)
///
/// # Returns
/// * `bool` - whether the user entry openings are verified correctly
/// * `Vec<BigUint>` - the evaluations of the advice polynomials at the point corresponding to the user index
pub fn verify_user_inclusion<const N_POINTS: usize>(
params: &ParamsKZG<Bn256>,
zk_snark_proof: &[u8],
balance_opening_multi_proof: &[u8],
balance_column_range: Range<usize>,
balance_opening_batch_proof: &[u8],
column_range: Range<usize>,
omega: Fp,
user_index: u16,
) -> (bool, Vec<BigUint>) {
Expand All @@ -221,10 +278,13 @@ pub fn verify_user_inclusion<const N_CURRENCIES: usize>(

//Read the commitment points for all the advice polynomials from the proof transcript and put them into a vector
let mut advice_commitments = Vec::new();
(0..N_CURRENCIES + balance_column_range.start).for_each(|_| {
for i in 0..column_range.end {
let point = transcript.read_point().unwrap();
advice_commitments.push(point);
});
//Skip advice polynomial commitments before the desired range
if i >= column_range.start {
advice_commitments.push(point);
}
}

let mut verification_results = Vec::<bool>::new();

Expand All @@ -234,10 +294,10 @@ pub fn verify_user_inclusion<const N_CURRENCIES: usize>(
Challenge255<G1Affine>,
Blake2bRead<_, _, Challenge255<_>>,
AccumulatorStrategy<_>,
N_CURRENCIES,
N_POINTS,
>(
params,
balance_opening_multi_proof,
balance_opening_batch_proof,
omega.pow_vartime([user_index as u64]),
&advice_commitments,
);
Expand All @@ -252,7 +312,19 @@ pub fn verify_user_inclusion<const N_CURRENCIES: usize>(
)
}

/// Creates a KZG multi-opening proof for the polynomial evaluations at a challenge
/// Creates a KZG batch proof for the polynomial evaluations at a challenge
///
/// # Arguments
///
/// * `params` - the KZG parameters
/// * `polynomials` - the polynomials to be opened
/// * `blinds` - the polynomials blinds
/// * `challenge` - the challenge at which the polynomials are evaluated
///
/// # Returns
///
/// * `Vec<u8>` containing the quotient polynomial commitments
/// and the evaluations of the polynomials at the challenge
fn create_opening_proof_at_challenge<
'params,
Scheme: CommitmentScheme<Curve = halo2_proofs::halo2curves::bn256::G1Affine, Scalar = Fp>,
Expand Down Expand Up @@ -298,8 +370,22 @@ where
transcript.finalize()
}

/// Verifies a KZG proof for a polynomial evaluation at a challenge
pub fn verify_opening<
/// Verifies a KZG batch proof for a polynomial evaluation at a challenge
/// and returns the evaluations of the polynomials at the challenge
/// as well as the verification result
///
/// # Arguments
///
/// * `params` - the KZG parameters
/// * `proof` - the KZG batch proof
/// * `challenge` - the challenge at which the polynomials are evaluated
/// * `commitment_points` - the commitment points of the polynomials
///
/// # Returns
///
/// * `bool` - whether the proof is verified correctly
/// * `Vec<Fp>` - the evaluations of the polynomials at the challenge
fn verify_opening<
'a,
'params,
Scheme: CommitmentScheme<Curve = halo2_proofs::halo2curves::bn256::G1Affine, Scalar = Fp>,
Expand Down

0 comments on commit f4c1417

Please sign in to comment.