From f038c9540b0b17bf1bdda1e24c867336ae30d0ca Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 25 May 2024 17:00:21 +0200 Subject: [PATCH] add rust-native hashing to compare final state --- Cargo.toml | 4 +-- compile-circuit.sh | 2 +- src/lib.rs | 69 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5e3fbdd..d915d60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,11 +24,11 @@ ark-crypto-primitives = { version = "^0.4.0", default-features = false, features ark-std = "0.4.0" color-eyre = "0.6.2" num-bigint = "0.4.3" -# folding-schemes = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "folding-schemes"} -folding-schemes = { path = "../folding/sonobe_FIX-CIRCOM/folding-schemes", package = "folding-schemes"} +folding-schemes = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "folding-schemes", branch="fix/circom-frontend", features=["light-test"]} solidity-verifiers = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "solidity-verifiers"} serde = "1.0.198" serde_json = "1.0.116" +tiny-keccak = { version = "2.0", features = ["keccak"] } rand = "0.8.5" diff --git a/compile-circuit.sh b/compile-circuit.sh index 35534de..18dc362 100755 --- a/compile-circuit.sh +++ b/compile-circuit.sh @@ -9,4 +9,4 @@ cd circuit npm install cd .. -circom ./circuit/keccak-chain.circom --O0 --r1cs --sym --wasm --prime bn128 --output ./circuit/ +circom ./circuit/keccak-chain.circom --r1cs --sym --wasm --prime bn128 --output ./circuit/ diff --git a/src/lib.rs b/src/lib.rs index da12996..390a6b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ mod tests { use ark_groth16::{Groth16, ProvingKey, VerifyingKey as G16VerifierKey}; use ark_poly_commit::kzg10::VerifierKey as KZGVerifierKey; + use ark_ff::{BigInteger, BigInteger256, PrimeField}; use ark_std::Zero; use std::path::PathBuf; @@ -118,6 +119,34 @@ mod tests { (fs_prover_params, kzg_vk, g16_pk, g16_vk) } + fn f_vec_to_bits(v: Vec) -> Vec { + v.iter() + .map(|v_i| { + if v_i.is_one() { + return true; + } + return false; + }) + .collect() + } + // returns the bytes representation of the given vector of finite field elements that represent + // bits + fn f_vec_to_bytes(v: Vec) -> Vec { + let b = f_vec_to_bits(v); + BigInteger256::from_bits_le(&b).to_bytes_le() + } + + // function to compute the next state of the folding via rust-native code (not Circom). Used to + // check the Circom values. + use tiny_keccak::{Hasher, Keccak}; + fn rust_native_step(z_i: [u8; 32]) -> [u8; 32] { + let mut h = Keccak::v256(); + h.update(&z_i); + let mut z_i1 = [0u8; 32]; + h.finalize(&mut z_i1); + z_i1 + } + #[test] fn full_flow() { // set the initial state @@ -149,14 +178,46 @@ mod tests { >; // initialize the folding scheme engine, in our case we use Nova - let mut nova = NOVA::init(&fs_prover_params, f_circuit.clone(), z_0).unwrap(); + let mut nova = NOVA::init(&fs_prover_params, f_circuit.clone(), z_0.clone()).unwrap(); // run n steps of the folding iteration - for i in 0..10 { + for _ in 0..3 { let start = Instant::now(); nova.prove_step(vec![]).unwrap(); - println!("Nova::prove_step {}: {:?}", i, start.elapsed()); + println!("Nova::prove_step {}: {:?}", nova.i, start.elapsed()); } + // perform the hash chain natively in rust + let z_0_bytes: [u8; 32] = [0u8; 32]; + let z_1_bytes = rust_native_step(z_0_bytes); + let z_2_bytes = rust_native_step(z_1_bytes); + let z_3_bytes = rust_native_step(z_2_bytes); + + // check that the value of the last folding state (nova.z_i) computed through folding, is equal to the natively + // computed hash using the rust_native_step method + let nova_z_i = f_vec_to_bytes(nova.z_i.clone()); + assert_eq!(nova_z_i, z_3_bytes); + + /* + // The following lines contain a sanity check that checks the IVC proof (before going into + // the zkSNARK proof) + let verifier_params = VerifierParams:: { + poseidon_config: nova.poseidon_config.clone(), + r1cs: nova.clone().r1cs, + cf_r1cs: nova.clone().cf_r1cs, + }; + let (running_instance, incoming_instance, cyclefold_instance) = nova.instances(); + NOVA::verify( + verifier_params, + z_0, + nova.z_i.clone(), + nova.i, + running_instance, + incoming_instance, + cyclefold_instance, + ) + .unwrap(); + */ + let rng = rand::rngs::OsRng; let start = Instant::now(); let proof = DECIDERETH_FCircuit::prove( @@ -180,7 +241,7 @@ mod tests { assert!(verified); println!("Decider proof verification: {}", verified); - // Now, let's generate the Solidity code that verifies this Decider final proof + // generate the Solidity code that verifies this Decider final proof let function_selector = get_function_selector_for_nova_cyclefold_verifier(nova.z_0.len() * 2 + 1);