Skip to content

Commit

Permalink
refactor: Refine code
Browse files Browse the repository at this point in the history
  • Loading branch information
VanhGer committed Jul 22, 2024
1 parent 2a5cad6 commit 492c750
Show file tree
Hide file tree
Showing 14 changed files with 576 additions and 409 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["plonk", "kzg", "fri"]
members = ["plonk", "kzg", "fri", "nova"]
resolver = "2"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
40 changes: 39 additions & 1 deletion kzg/src/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use ark_ec::pairing::Pairing;
use ark_ec::short_weierstrass::Affine;
use ark_ec::{AffineRepr, CurveGroup};
use ark_ff::{One, Zero};
use ark_poly::univariate::DensePolynomial;
use ark_poly::{DenseUVPolynomial, Polynomial};
use rand::{Rng, RngCore};

use crate::commitment::KzgCommitment;
use crate::opening::KzgOpening;
use crate::srs::Srs;
use crate::types::{G1Point, Poly};
use crate::types::{G1Point, Poly, ScalarField};

/// Implements the KZG polynomial commitment scheme.
///
Expand Down Expand Up @@ -50,6 +51,21 @@ impl KzgScheme {
KzgCommitment(commitment)
}

/// Commits to a coefficient vector using the KZG scheme.
///
/// # Parameters
///
/// - `coeffs`: The coefficient vector to be committed to.
///
/// # Returns
///
/// The commitment to the polynomial.
pub fn commit_vector(&self, coeffs: &[ScalarField]) -> KzgCommitment {
let new_poly = DensePolynomial::from_coefficients_vec(coeffs.clone().into());

Check warning on line 64 in kzg/src/scheme.rs

View workflow job for this annotation

GitHub Actions / Cargo check

call to `.clone()` on a reference in this situation does nothing

Check warning

Code scanning / clippy

call to .clone() on a reference in this situation does nothing Warning

call to .clone() on a reference in this situation does nothing
let commitment = self.evaluate_in_s(&new_poly);
KzgCommitment(commitment)
}

/// Commits to a parameter using the KZG scheme.
///
/// # Parameters
Expand Down Expand Up @@ -103,6 +119,28 @@ impl KzgScheme {
KzgOpening(opening, evaluation_at_z)
}

/// Opens a commitment at a specified point.
///
/// # Parameters
///
/// - `coeffs`: The coefficient vector to be opened.
/// - `z`: The point at which the polynomial is opened.
///
/// # Returns
///
/// The opening at the specified point.
pub fn open_vector(&self, coeffs: &[ScalarField], z: impl Into<Fr>) -> KzgOpening {
let z = z.into();
let mut polynomial = DensePolynomial::from_coefficients_vec(coeffs.clone().into());

Check warning on line 134 in kzg/src/scheme.rs

View workflow job for this annotation

GitHub Actions / Cargo check

call to `.clone()` on a reference in this situation does nothing

Check warning

Code scanning / clippy

call to .clone() on a reference in this situation does nothing Warning

call to .clone() on a reference in this situation does nothing
let evaluation_at_z = polynomial.evaluate(&z);
let first = polynomial.coeffs.first_mut().expect("at least 1");
*first -= evaluation_at_z;
let root = Poly::from_coefficients_slice(&[-z, 1.into()]);
let quotient_poly = &polynomial / &root;
let opening = self.evaluate_in_s(&quotient_poly);
KzgOpening(opening, evaluation_at_z)
}

/// Verifies the correctness of an opening.
///
/// # Parameters
Expand Down
107 changes: 68 additions & 39 deletions nova/examples/examples.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
use ark_ff::{BigInteger, One, PrimeField, Zero};
use sha2::Sha256;
use kzg::scheme::KzgScheme;
use kzg::srs::Srs;
use kzg::types::{BaseField, ScalarField};
use nova::circuit::{AugmentedCircuit, FCircuit, State};
use nova::ivc::{IVC, IVCProof, ZkIVCProof};
use nova::ivc::{IVCProof, ZkIVCProof, IVC};
use nova::r1cs::{create_trivial_pair, FInstance, FWitness, R1CS};
use nova::transcript::Transcript;
use nova::utils::{to_f_matrix, to_f_vec};
use sha2::Sha256;

struct TestCircuit {}
impl FCircuit for TestCircuit {
fn run(&self, z_i: &State, w_i: &FWitness) -> State {
let x = w_i.w[0].clone();
let x = w_i.w[0];
let res = x * x * x + x + ScalarField::from(5);
let base_res = BaseField::from_le_bytes_mod_order(&res.into_bigint().to_bytes_le());

State {
state: z_i.state + base_res
state: z_i.state + base_res,
}
}
}
Expand All @@ -27,7 +27,11 @@ fn main() {

// generate R1CS, witnesses and public input, output.
let (r1cs, witnesses, x) = gen_test_values::<ScalarField>(vec![3, 4, 1, 2]);
let (matrix_a, _, _) = (r1cs.matrix_a.clone(), r1cs.matrix_b.clone(), r1cs.matrix_c.clone());
let (matrix_a, _, _) = (
r1cs.matrix_a.clone(),
r1cs.matrix_b.clone(),
r1cs.matrix_c.clone(),
);

// Trusted setup
let domain_size = witnesses[0].len() + x[0].len() + 1;
Expand All @@ -36,38 +40,48 @@ fn main() {
let x_len = x[0].len();

// Generate witnesses and instances
let w: Vec<FWitness> = witnesses.iter().map(|witness| FWitness::new(witness, matrix_a.len())).collect();
let mut u: Vec<FInstance> = w.iter().zip(x).map(|(w, x)| w.commit(&scheme, &x)).collect();
let w: Vec<FWitness> = witnesses
.iter()
.map(|witness| FWitness::new(witness, matrix_a.len()))
.collect();
let mut u: Vec<FInstance> = w
.iter()
.zip(x)
.map(|(w, x)| w.commit(&scheme, &x))
.collect();

// step i
let mut i = BaseField::zero();

// generate trivial instance-witness pair
let (trivial_witness, trivial_instance) = create_trivial_pair(x_len, witnesses[0].len(), &scheme);
let (trivial_witness, trivial_instance) =
create_trivial_pair(x_len, witnesses[0].len(), &scheme);

// generate f_circuit instance
let f_circuit = TestCircuit{};
let f_circuit = TestCircuit {};

// generate states
let mut z = vec![State{state: BaseField::from(0)}; 5];
let mut z = vec![
State {
state: BaseField::from(0)
};
5
];
for index in 1..5 {
z[index] = f_circuit.run(&z[index - 1], &w[index-1]);
z[index] = f_circuit.run(&z[index - 1], &w[index - 1]);
}

let mut prover_transcript;
let mut verifier_transcript = Transcript::<Sha256>::default();

// create F'
let augmented_circuit = AugmentedCircuit::<Sha256, TestCircuit>::new(
f_circuit,
&trivial_instance,
&z[0]
);
let augmented_circuit =
AugmentedCircuit::<Sha256, TestCircuit>::new(f_circuit, &trivial_instance, &z[0]);

// generate IVC
let mut ivc = IVC::<Sha256, TestCircuit> {
scheme,
augmented_circuit
augmented_circuit,
};

// initialize IVC proof, zkIVCProof, folded witness and folded instance
Expand All @@ -80,18 +94,13 @@ fn main() {
for step in 0..4 {
println!("Step: {:?}", step);
if step == 0 {
res = ivc.augmented_circuit.run(
&u[step],
None,
&w[step],
None,
);
res = ivc.augmented_circuit.run(&u[step], None, &w[step], None);
} else {
res = ivc.augmented_circuit.run(
&ivc_proof.u_i,
Some(&ivc_proof.big_u_i.clone()),
&ivc_proof.w_i,
Some(&zk_ivc_proof.com_t.clone().unwrap())
Some(&zk_ivc_proof.com_t.clone().unwrap()),
);
}

Expand All @@ -109,20 +118,34 @@ fn main() {

// update for next step

if step != 3 { // do not update if we have done with IVC
if step != 3 {
// do not update if we have done with IVC
ivc.augmented_circuit.next_step();
i = i + BaseField::one();
i += BaseField::one();
assert_eq!(ivc.augmented_circuit.z_i.state, z[step + 1].state);
prover_transcript = Transcript::<Sha256>::default();
verifier_transcript = Transcript::<Sha256>::default();

let hash_x = AugmentedCircuit::<Sha256, TestCircuit>::hash_io(i, &z[0], &z[step + 1], &folded_instance);
let hash_x = AugmentedCircuit::<Sha256, TestCircuit>::hash_io(
i,
&z[0],
&z[step + 1],
&folded_instance,
);
// convert u_1_x from BaseField into ScalarField
u[step + 1].x = vec![ScalarField::from_le_bytes_mod_order(&hash_x.into_bigint().to_bytes_le())];
u[step + 1].x = vec![ScalarField::from_le_bytes_mod_order(
&hash_x.into_bigint().to_bytes_le(),
)];

// generate ivc_proof and zkSNARK proof.
ivc_proof = IVCProof::new(&u[step + 1], &w[step + 1], &folded_instance, &folded_witness);
(folded_witness, folded_instance, zk_ivc_proof) = ivc.prove(&r1cs, &ivc_proof, &mut prover_transcript);
ivc_proof = IVCProof::new(
&u[step + 1],
&w[step + 1],
&folded_instance,
&folded_witness,
);
(folded_witness, folded_instance, zk_ivc_proof) =
ivc.prove(&r1cs, &ivc_proof, &mut prover_transcript);
}
}
}
Expand All @@ -131,19 +154,19 @@ fn gen_test_values<F: PrimeField>(inputs: Vec<usize>) -> (R1CS<F>, Vec<Vec<F>>,
// R1CS for: x^3 + x + 5 = y (example from article
// https://vitalik.eth.limo/general/2016/12/10/qap.html )

let a = to_f_matrix::<F>(vec![
let a = to_f_matrix::<F>(&vec![
vec![1, 0, 0, 0, 0, 0],
vec![0, 1, 0, 0, 0, 0],
vec![1, 0, 1, 0, 0, 0],
vec![0, 0, 0, 1, 0, 5],
]);
let b = to_f_matrix::<F>(vec![
let b = to_f_matrix::<F>(&vec![
vec![1, 0, 0, 0, 0, 0],
vec![1, 0, 0, 0, 0, 0],
vec![0, 0, 0, 0, 0, 1],
vec![0, 0, 0, 0, 0, 1],
]);
let c = to_f_matrix::<F>(vec![
let c = to_f_matrix::<F>(&vec![
vec![0, 1, 0, 0, 0, 0],
vec![0, 0, 1, 0, 0, 0],
vec![0, 0, 0, 1, 0, 0],
Expand All @@ -156,15 +179,21 @@ fn gen_test_values<F: PrimeField>(inputs: Vec<usize>) -> (R1CS<F>, Vec<Vec<F>>,
for input in inputs {
let w_i = to_f_vec::<F>(vec![
input,
input * input, // x^2
input * input * input, // x^2 * x
input * input * input + input, // x^3 + x
input * input, // x^2
input * input * input, // x^2 * x
input * input * input + input, // x^3 + x
]);
w.push(w_i.clone());
let x_i = to_f_vec::<F>(vec![input * input * input + input + 5]); // output: x^3 + x + 5
let x_i = to_f_vec::<F>(vec![input * input * input + input + 5]); // output: x^3 + x + 5
x.push(x_i.clone());
}

let r1cs = R1CS::<F> { matrix_a: a, matrix_b: b, matrix_c: c, num_io: 1, num_vars: 4 };
let r1cs = R1CS::<F> {
matrix_a: a,
matrix_b: b,
matrix_c: c,
num_io: 1,
num_vars: 4,
};
(r1cs, w, x)
}
}
Loading

0 comments on commit 492c750

Please sign in to comment.