From 211d09ed3a639186f2f5fb515c92877eb9a9d9f6 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 27 May 2024 18:50:51 +0300 Subject: [PATCH 01/37] Implement tests cases for bls12_381_components_proofs against ethereum verify test cases --- beacon-light-client/plonky2/.gitignore | 1 + beacon-light-client/plonky2/crates/Cargo.lock | 1 + .../crates/circuit_executables/Cargo.toml | 8 +- .../scripts/run_bls12_381_component_proofs.sh | 61 +++ .../circuit_executables/src/bls_components.rs | 377 ++++++++++++++++++ .../crates/circuit_executables/src/lib.rs | 1 + vendor/circom-pairing | 2 +- 7 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 2ad2bdb42..5474f70c2 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -3,3 +3,4 @@ gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin gnark_plonky2_verifier/public_witness.bin +circuits_executables/ \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/Cargo.lock b/beacon-light-client/plonky2/crates/Cargo.lock index aff5b27e6..8cd53b49b 100644 --- a/beacon-light-client/plonky2/crates/Cargo.lock +++ b/beacon-light-client/plonky2/crates/Cargo.lock @@ -1210,6 +1210,7 @@ dependencies = [ "redis-work-queue", "serde", "serde_json", + "serde_yaml", "snowbridge-amcl", "starky", "starky_bls12_381", diff --git a/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml b/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml index 6a1d6bae0..9f5ce0291 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml +++ b/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml @@ -8,7 +8,12 @@ edition.workspace = true [dependencies] circuit = { path = "../circuit" } circuits = { path = "../circuits" } -redis = { version = "0.23", features = ["aio", "async-std-comp", "connection-manager", "json"] } +redis = { version = "0.23", features = [ + "aio", + "async-std-comp", + "connection-manager", + "json", +] } num = { version = "0.4.0", features = ["serde"] } plonky2 = { git = "https://github.com/metacraft-labs/plonky2" } starky = { git = "https://github.com/metacraft-labs/plonky2" } @@ -16,6 +21,7 @@ plonky2-circuit-serializer = { git = "https://github.com/metacraft-labs/plonky2- starky_bls12_381 = { git = "https://github.com/metacraft-labs/starky_bls12_381" } serde = "1.0.164" serde_json = "1.0.96" +serde_yaml = "0.9.34" anyhow = "1.0.71" hex = "0.4.3" redis-work-queue = "0.1.3" diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh new file mode 100644 index 000000000..07fb3b899 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Define variables +REPO_URL="https://github.com/ethereum/bls12-381-tests" +REPO_DIR="bls12-381-tests" +OUTPUT_DIR="eth_tests" +VERIFY_DIR="$OUTPUT_DIR/verify" + +# Clone the repository +if [ ! -d "$REPO_DIR" ]; then + git clone "$REPO_URL" +else + echo "Repository already cloned." +fi + +# Navigate to the repository directory +cd "$REPO_DIR" || exit + +# Set up a Python virtual environment +if [ ! -d "venv" ]; then + python -m venv venv +else + echo "Virtual environment already set up." +fi + +# Activate the virtual environment +# shellcheck source=/dev/null +source venv/bin/activate + +# Install dependencies +pip install -r requirements.txt + +# Create output directory if it doesn't exist +mkdir -p "$OUTPUT_DIR" + +# Run the test generator +python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml + +# Deactivate the virtual environment +deactivate + +# Navigate back to the root directory +cd .. + +# Run the verify tests +run_verify_tests() { + local test_name=$1 + local file_path=$2 + + # Run the specified Rust test with the given file path + cargo test "$test_name" --release -- --nocapture --file "$file_path" +} + +# Loop through the extracted files in the 'verify' directory +for file in "$VERIFY_DIR"/*.yaml; do + if [[ "$file" == *"wrong"* || "$file" == *"tampered"* ]]; then + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases_should_fail" "$file" + else + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$file" + fi +done \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs new file mode 100644 index 000000000..ac55832d3 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -0,0 +1,377 @@ +use anyhow::Result; +use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; +use ark_ec::Group; +use ark_ff::PrimeField; +use ark_serialize::CanonicalDeserialize; +use circuit::SerdeCircuitTarget; +use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; +use num::BigUint; +use plonky2::{ + field::{goldilocks_field::GoldilocksField, types::Field}, + iop::witness::{PartialWitness, WitnessWrite}, + plonk::{config::PoseidonGoldilocksConfig, proof::ProofWithPublicInputs}, + util::serialization::Buffer, +}; +use serde::Deserialize; +use snowbridge_amcl::bls381::{big::Big, bls381::utils::hash_to_curve_g2, ecp2::ECP2}; +use starky_bls12_381::native::{miller_loop, Fp, Fp12, Fp2}; +use std::{fs, ops::Neg, path::Path, str::FromStr}; + +use crate::{ + constants::SERIALIZED_CIRCUITS_DIR, + crud::common::{get_recursive_stark_targets, load_circuit_data_starky, read_from_file}, + provers::{ + generate_final_exponentiate, generate_fp12_mul_proof, generate_miller_loop_proof, + generate_pairing_precomp_proof, + }, +}; + +const CIRCUIT_DIR: &str = "circuits"; +const DST: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; + +const D: usize = 2; +type C = PoseidonGoldilocksConfig; +type F = GoldilocksField; + +#[derive(Clone, Debug, Deserialize)] +pub struct Input { + pub pubkey: String, + pub signature: String, + pub message: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlsComponents { + pub input: Input, + pub output: bool, +} + +impl BlsComponents { + fn remove_first_two_chars(&mut self) { + self.input.pubkey = self.input.pubkey.chars().skip(2).collect(); + self.input.signature = self.input.signature.chars().skip(2).collect(); + self.input.message = self.input.message.chars().skip(2).collect(); + } +} + +pub fn read_yaml_files_from_directory>( + dir: P, +) -> Result, Box> { + let mut components = Vec::new(); + + for entry in fs::read_dir(dir)? { + let entry = entry?; + if entry.path().extension() == Some(std::ffi::OsStr::new("yaml")) { + let config = read_yaml_file(entry.path())?; + components.push(config); + } + } + + Ok(components) +} + +fn read_yaml_file>(path: P) -> Result> { + let file_content = fs::read_to_string(path)?; + let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; + components.remove_first_two_chars(); + Ok(components) +} + +pub async fn bls12_381_components_proofs( + bls_components: BlsComponents, +) -> Result> { + let message_g2 = hash_to_curve_g2( + &hex::decode(bls_components.input.message.clone()).unwrap(), + DST.as_bytes(), + ); + let message_g2 = convert_ecp2_to_g2affine(message_g2); + + let pubkey_g1 = G1Affine::deserialize_compressed( + &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), + ) + .unwrap(); + let signature_g2 = G2Affine::deserialize_compressed( + &*hex::decode(bls_components.input.signature.clone()).unwrap(), + ) + .unwrap(); + let g1 = G1Projective::generator(); + let neg_g1 = g1.neg(); + + let miller_loop1 = miller_loop( + Fp::get_fp_from_biguint(pubkey_g1.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(pubkey_g1.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(message_g2.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(message_g2.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(message_g2.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(message_g2.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ); + + let miller_loop2 = miller_loop( + Fp::get_fp_from_biguint(neg_g1.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(neg_g1.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(signature_g2.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(signature_g2.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(signature_g2.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(signature_g2.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ); + + let fp12_mull = miller_loop1 * miller_loop2; + // PROVING HAPPENS HERE + let (pp1, pp2) = handle_pairing_precomp(&message_g2, &signature_g2).await; + + let (ml1, ml2) = + handle_miller_loop(&pubkey_g1, &message_g2, &neg_g1.into(), &signature_g2).await; + + let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; + + let final_exp_proof = handle_final_exponentiation(&fp12_mull).await; + + let circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/bls12_381")); + let target_bytes = read_from_file(&format!( + "{}/{}.plonky2_targets", + SERIALIZED_CIRCUITS_DIR, "bls12_381" + ))?; + let mut target_buffer = Buffer::new(&target_bytes); + + let targets = BlsCircuitTargets::deserialize(&mut target_buffer).unwrap(); + let mut pw = PartialWitness::::new(); + + pw.set_target_arr( + &targets.pubkey, + &hex::decode(bls_components.input.pubkey) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.sig, + &hex::decode(bls_components.input.signature) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.msg, + &hex::decode(bls_components.input.message) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + + pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); + pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); + pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); + pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); + pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); + pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); + + println!("Starting proof generation"); + + let proof = circuit_data.prove(pw).unwrap(); + + Ok(proof) +} + +async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { + let final_exp_circuit_data = + load_circuit_data_starky(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")); + + let final_exp_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")).unwrap(); + + let final_exp_proof = + generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); + + final_exp_proof +} + +async fn handle_fp12_mul( + miller_loop1: &Fp12, + miller_loop2: &Fp12, +) -> ProofWithPublicInputs { + let fp12_mul_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/fp12_mul")); + + let fp12_mul_targets = get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/fp12_mul")).unwrap(); + + let fp12_mul_proof = generate_fp12_mul_proof( + &miller_loop1, + &miller_loop2, + &fp12_mul_targets, + &fp12_mul_circuit_data, + ); + + fp12_mul_proof +} + +async fn handle_miller_loop( + pubkey_g1: &G1Affine, + message_g2: &G2Affine, + neg_g1: &G1Affine, + signature_g2: &G2Affine, +) -> ( + ProofWithPublicInputs, + ProofWithPublicInputs, +) { + let miller_loop_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/miller_loop")); + + let miller_loop_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/miller_loop")).unwrap(); + + let ml1 = generate_miller_loop_proof( + &pubkey_g1, + &message_g2, + &miller_loop_targets, + &miller_loop_circuit_data, + ); + + let ml2 = generate_miller_loop_proof( + &neg_g1, + &signature_g2, + &miller_loop_targets, + &miller_loop_circuit_data, + ); + + (ml1, ml2) +} + +async fn handle_pairing_precomp( + message_g2: &G2Affine, + signature_g2: &G2Affine, +) -> ( + ProofWithPublicInputs, + ProofWithPublicInputs, +) { + let pairing_precomp_circuit_data = + load_circuit_data_starky(&format!("{CIRCUIT_DIR}/pairing_precomp")); + + let pairing_precomp_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/pairing_precomp")).unwrap(); + + let pp1 = generate_pairing_precomp_proof( + &message_g2, + &pairing_precomp_targets, + &pairing_precomp_circuit_data, + ); + + let pp2 = generate_pairing_precomp_proof( + &signature_g2, + &pairing_precomp_targets, + &pairing_precomp_circuit_data, + ); + + (pp1, pp2) +} + +fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { + let x = Fq2::new( + convert_big_to_fq(ecp2_point.getpx().geta()), + convert_big_to_fq(ecp2_point.getpx().getb()), + ); + + let y = Fq2::new( + convert_big_to_fq(ecp2_point.getpy().geta()), + convert_big_to_fq(ecp2_point.getpy().getb()), + ); + + G2Affine::new(x, y) +} + +fn convert_big_to_fq(big: Big) -> Fq { + let bytes = &hex::decode(big.to_string()).unwrap(); + Fq::from_be_bytes_mod_order(bytes) +} + +#[cfg(test)] +pub mod tests { + use std::env; + + use plonky2::{ + field::goldilocks_field::GoldilocksField, + plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, + }; + + use super::{bls12_381_components_proofs, read_yaml_files_from_directory}; + + const D: usize = 2; + type F = GoldilocksField; + + #[tokio::test] + async fn test_bls12_381_components_proofs_with_verify_eth_cases() { + let args: Vec = env::args().collect(); + if args.len() < 2 { + panic!("Expected a file path as argument"); + } + + let bls_components_with_verify_eth_tests_cases = + read_yaml_files_from_directory(args[1].as_str()).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + for i in 0..bls_components_with_verify_eth_tests_cases.len() { + let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; + let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) + .await + .unwrap(); + + println!("Proof generated"); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + builder.assert_one(proof_t); + } + } + + #[tokio::test] + #[should_panic] + async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { + let args: Vec = env::args().collect(); + if args.len() < 2 { + panic!("Expected a file path as argument"); + } + + let bls_components_with_verify_eth_tests_cases = + read_yaml_files_from_directory(args[1].as_str()).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + for i in 0..bls_components_with_verify_eth_tests_cases.len() { + let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; + let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) + .await + .unwrap(); + + println!("Proof generated"); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + builder.assert_one(proof_t); + } + } +} diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs index 7a0240689..4e9091836 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs @@ -2,6 +2,7 @@ #![feature(async_closure)] #![feature(generic_const_exprs)] +pub mod bls_components; pub mod commitment_mapper_context; pub mod commitment_mapper_task; pub mod constants; diff --git a/vendor/circom-pairing b/vendor/circom-pairing index 52db7a215..82bac4a27 160000 --- a/vendor/circom-pairing +++ b/vendor/circom-pairing @@ -1 +1 @@ -Subproject commit 52db7a21544219e7b734e7f683d1f11328a0dc4e +Subproject commit 82bac4a27499fc11cf3ebbb64c525b526f13b552 From 88614e55bd5bd6c5a6cf17da79b370716a2c366a Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 27 May 2024 19:48:51 +0300 Subject: [PATCH 02/37] Update bls_components and shell to run the tests in it - still wip, it's not building --- .../scripts/bls12-381-tests | 1 + .../scripts/run_bls12_381_component_proofs.sh | 10 +++++++++- .../circuit_executables/src/bls_components.rs | 18 ++++-------------- 3 files changed, 14 insertions(+), 15 deletions(-) create mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests mode change 100644 => 100755 beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests new file mode 160000 index 000000000..2b6a5ba04 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests @@ -0,0 +1 @@ +Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh old mode 100644 new mode 100755 index 07fb3b899..5370cdfcd --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,6 +5,8 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/verify" +SCRIPTS_DIR="scripts" +RUST_FILES_DIR="src" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -42,13 +44,19 @@ deactivate # Navigate back to the root directory cd .. +# Navigate to the rust files directory +cd "$RUST_FILES_DIR" || exit + # Run the verify tests run_verify_tests() { local test_name=$1 local file_path=$2 + # Set the FILE_PATH environment variable + export FILE_PATH="$file_path" + # Run the specified Rust test with the given file path - cargo test "$test_name" --release -- --nocapture --file "$file_path" + RUST_MIN_STACK=16777216 cargo test "$test_name" --release -- --nocapture "$file_path" } # Loop through the extracted files in the 'verify' directory diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index ac55832d3..53d2e7641 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -302,8 +302,6 @@ fn convert_big_to_fq(big: Big) -> Fq { #[cfg(test)] pub mod tests { - use std::env; - use plonky2::{ field::goldilocks_field::GoldilocksField, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, @@ -316,13 +314,9 @@ pub mod tests { #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("Expected a file path as argument"); - } - + let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(args[1].as_str()).unwrap(); + read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); @@ -347,13 +341,9 @@ pub mod tests { #[tokio::test] #[should_panic] async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("Expected a file path as argument"); - } - + let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(args[1].as_str()).unwrap(); + read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); From 6ccdfd146c166541483a18bf35f9c150cafad2d0 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 10:06:27 +0300 Subject: [PATCH 03/37] build(bls_components) Made little changes needed for bls_components to execute its tests --- .../circuit_executables/src/bls_components.rs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 53d2e7641..4bcdeb592 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -26,7 +26,6 @@ use crate::{ }, }; -const CIRCUIT_DIR: &str = "circuits"; const DST: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; const D: usize = 2; @@ -192,11 +191,14 @@ pub async fn bls12_381_components_proofs( } async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { - let final_exp_circuit_data = - load_circuit_data_starky(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")); + let final_exp_circuit_data = load_circuit_data_starky(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )); - let final_exp_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")).unwrap(); + let final_exp_targets = get_recursive_stark_targets(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )) + .unwrap(); let final_exp_proof = generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); @@ -208,9 +210,11 @@ async fn handle_fp12_mul( miller_loop1: &Fp12, miller_loop2: &Fp12, ) -> ProofWithPublicInputs { - let fp12_mul_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/fp12_mul")); + let fp12_mul_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - let fp12_mul_targets = get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/fp12_mul")).unwrap(); + let fp12_mul_targets = + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")).unwrap(); let fp12_mul_proof = generate_fp12_mul_proof( &miller_loop1, @@ -231,10 +235,11 @@ async fn handle_miller_loop( ProofWithPublicInputs, ProofWithPublicInputs, ) { - let miller_loop_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/miller_loop")); + let miller_loop_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); let miller_loop_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/miller_loop")).unwrap(); + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")).unwrap(); let ml1 = generate_miller_loop_proof( &pubkey_g1, @@ -261,10 +266,10 @@ async fn handle_pairing_precomp( ProofWithPublicInputs, ) { let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{CIRCUIT_DIR}/pairing_precomp")); + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); let pairing_precomp_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/pairing_precomp")).unwrap(); + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")).unwrap(); let pp1 = generate_pairing_precomp_proof( &message_g2, @@ -314,7 +319,7 @@ pub mod tests { #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; + let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); @@ -341,7 +346,7 @@ pub mod tests { #[tokio::test] #[should_panic] async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; + let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); From 0f2ed35b9f3d486ad4a2ec8da350cc43077f9504 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 10:13:10 +0300 Subject: [PATCH 04/37] fix(run_bls12_381_component_proofs.sh) Fix the navigation in the root directory --- .../scripts/run_bls12_381_component_proofs.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 5370cdfcd..797f05a9b 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -41,6 +41,9 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate +# Navigate back to the scripts directory +cd .. + # Navigate back to the root directory cd .. From bb7959a66c7b5245a0493036c6b1a6e743241cd2 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 13:59:59 +0300 Subject: [PATCH 05/37] fix: Use unchecked deserialization for G1 & G2 --- .../bin/bls12_381_components_proofs.rs | 140 ++---------------- .../scripts/run_bls12_381_component_proofs.sh | 37 +++-- .../circuit_executables/src/bls_components.rs | 90 ++++++----- 3 files changed, 72 insertions(+), 195 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs index 037832750..be5b95ee5 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs @@ -1,19 +1,18 @@ use anyhow::Result; -use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; +use ark_bls12_381::{G1Affine, G1Projective, G2Affine}; use ark_ec::Group; -use ark_ff::PrimeField; use ark_serialize::CanonicalDeserialize; use circuit::SerdeCircuitTarget; use circuit_executables::{ + bls_components::{ + convert_ecp2_to_g2affine, handle_final_exponentiation, handle_fp12_mul, handle_miller_loop, + handle_pairing_precomp, + }, constants::SERIALIZED_CIRCUITS_DIR, crud::{ - common::{get_recursive_stark_targets, load_circuit_data_starky, read_from_file}, + common::{load_circuit_data_starky, read_from_file}, proof_storage::proof_storage::create_proof_storage, }, - provers::{ - generate_final_exponentiate, generate_fp12_mul_proof, generate_miller_loop_proof, - generate_pairing_precomp_proof, - }, utils::CommandLineOptionsBuilder, }; use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; @@ -22,11 +21,10 @@ use num_bigint::BigUint; use plonky2::{ field::{goldilocks_field::GoldilocksField, types::Field}, iop::witness::{PartialWitness, WitnessWrite}, - plonk::{config::PoseidonGoldilocksConfig, proof::ProofWithPublicInputs}, util::serialization::Buffer, }; -use snowbridge_amcl::bls381::{big::Big, bls381::utils::hash_to_curve_g2, ecp2::ECP2}; -use starky_bls12_381::native::{miller_loop, Fp, Fp12, Fp2}; +use snowbridge_amcl::bls381::bls381::utils::hash_to_curve_g2; +use starky_bls12_381::native::{miller_loop, Fp, Fp2}; use std::{ops::Neg, str::FromStr}; async fn async_main() -> Result<()> { @@ -41,8 +39,10 @@ async fn async_main() -> Result<()> { let message_g2 = hash_to_curve_g2(&hex::decode(msg).unwrap(), DST.as_bytes()); let message_g2 = convert_ecp2_to_g2affine(message_g2); - let pubkey_g1 = G1Affine::deserialize_compressed(&*hex::decode(pubkey).unwrap()).unwrap(); - let signature_g2 = G2Affine::deserialize_compressed(&*hex::decode(signature).unwrap()).unwrap(); + let pubkey_g1 = + G1Affine::deserialize_compressed_unchecked(&*hex::decode(pubkey).unwrap()).unwrap(); + let signature_g2 = + G2Affine::deserialize_compressed_unchecked(&*hex::decode(signature).unwrap()).unwrap(); let g1 = G1Projective::generator(); let neg_g1 = g1.neg(); @@ -153,75 +153,6 @@ async fn async_main() -> Result<()> { Ok(()) } -async fn handle_final_exponentiation( - fp12_mull: &Fp12, -) -> ProofWithPublicInputs { - let final_exp_circuit_data = load_circuit_data_starky(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )); - - let final_exp_targets = get_recursive_stark_targets(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )) - .unwrap(); - - let final_exp_proof = - generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); - - final_exp_proof -} - -async fn handle_fp12_mul( - miller_loop1: &Fp12, - miller_loop2: &Fp12, -) -> ProofWithPublicInputs { - let fp12_mul_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - - let fp12_mul_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")).unwrap(); - - let fp12_mul_proof = generate_fp12_mul_proof( - &miller_loop1, - &miller_loop2, - &fp12_mul_targets, - &fp12_mul_circuit_data, - ); - - fp12_mul_proof -} - -async fn handle_miller_loop( - pubkey_g1: &G1Affine, - message_g2: &G2Affine, - neg_g1: &G1Affine, - signature_g2: &G2Affine, -) -> ( - ProofWithPublicInputs, - ProofWithPublicInputs, -) { - let miller_loop_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - - let miller_loop_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")).unwrap(); - - let ml1 = generate_miller_loop_proof( - &pubkey_g1, - &message_g2, - &miller_loop_targets, - &miller_loop_circuit_data, - ); - - let ml2 = generate_miller_loop_proof( - &neg_g1, - &signature_g2, - &miller_loop_targets, - &miller_loop_circuit_data, - ); - - (ml1, ml2) -} fn main() { let _ = std::thread::Builder::new() .spawn(|| future::block_on(async_main())) @@ -229,50 +160,3 @@ fn main() { .join() .unwrap(); } - -async fn handle_pairing_precomp( - message_g2: &G2Affine, - signature_g2: &G2Affine, -) -> ( - ProofWithPublicInputs, - ProofWithPublicInputs, -) { - let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); - - let pairing_precomp_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")).unwrap(); - - let pp1 = generate_pairing_precomp_proof( - &message_g2, - &pairing_precomp_targets, - &pairing_precomp_circuit_data, - ); - - let pp2 = generate_pairing_precomp_proof( - &signature_g2, - &pairing_precomp_targets, - &pairing_precomp_circuit_data, - ); - - (pp1, pp2) -} - -fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { - let x = Fq2::new( - convert_big_to_fq(ecp2_point.getpx().geta()), - convert_big_to_fq(ecp2_point.getpx().getb()), - ); - - let y = Fq2::new( - convert_big_to_fq(ecp2_point.getpy().geta()), - convert_big_to_fq(ecp2_point.getpy().getb()), - ); - - G2Affine::new(x, y) -} - -fn convert_big_to_fq(big: Big) -> Fq { - let bytes = &hex::decode(big.to_string()).unwrap(); - Fq::from_be_bytes_mod_order(bytes) -} diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 797f05a9b..63316a3b8 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -3,10 +3,10 @@ # Define variables REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" -OUTPUT_DIR="eth_tests" +OUTPUT_DIR="eth_tests/bls" VERIFY_DIR="$OUTPUT_DIR/verify" SCRIPTS_DIR="scripts" -RUST_FILES_DIR="src" +SRC="src" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -41,32 +41,31 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate back to the scripts directory -cd .. +# Navigate to the verify directory +cd "$VERIFY_DIR" || exit + +# Store all files in a variable +mapfile -t all_yaml_files_in_verify < <(ls *) # Navigate back to the root directory -cd .. +cd ../../../../../ -# Navigate to the rust files directory -cd "$RUST_FILES_DIR" || exit +# Navigate to the src directory +cd "$SRC" || exit # Run the verify tests run_verify_tests() { - local test_name=$1 - local file_path=$2 + local test_name=$1 + local file_path=$2 - # Set the FILE_PATH environment variable - export FILE_PATH="$file_path" + # Set the FILE_PATH environment variable + export FILE_PATH="$file_path" - # Run the specified Rust test with the given file path - RUST_MIN_STACK=16777216 cargo test "$test_name" --release -- --nocapture "$file_path" + # Run the specified Rust test with the given file path + RUST_MIN_STACK=1116777216 cargo test "$test_name" --release -- --nocapture "$file_path" } # Loop through the extracted files in the 'verify' directory -for file in "$VERIFY_DIR"/*.yaml; do - if [[ "$file" == *"wrong"* || "$file" == *"tampered"* ]]; then - run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases_should_fail" "$file" - else - run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$file" - fi +for yaml_file in "${all_yaml_files_in_verify[@]}"; do + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" done \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 4bcdeb592..eff901653 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -69,7 +69,9 @@ pub fn read_yaml_files_from_directory>( Ok(components) } -fn read_yaml_file>(path: P) -> Result> { +pub fn read_yaml_file>( + path: P, +) -> Result> { let file_content = fs::read_to_string(path)?; let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; components.remove_first_two_chars(); @@ -190,7 +192,7 @@ pub async fn bls12_381_components_proofs( Ok(proof) } -async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { +pub async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { let final_exp_circuit_data = load_circuit_data_starky(&format!( "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" )); @@ -206,7 +208,7 @@ async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs< final_exp_proof } -async fn handle_fp12_mul( +pub async fn handle_fp12_mul( miller_loop1: &Fp12, miller_loop2: &Fp12, ) -> ProofWithPublicInputs { @@ -226,7 +228,7 @@ async fn handle_fp12_mul( fp12_mul_proof } -async fn handle_miller_loop( +pub async fn handle_miller_loop( pubkey_g1: &G1Affine, message_g2: &G2Affine, neg_g1: &G1Affine, @@ -258,7 +260,7 @@ async fn handle_miller_loop( (ml1, ml2) } -async fn handle_pairing_precomp( +pub async fn handle_pairing_precomp( message_g2: &G2Affine, signature_g2: &G2Affine, ) -> ( @@ -286,7 +288,7 @@ async fn handle_pairing_precomp( (pp1, pp2) } -fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { +pub fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { let x = Fq2::new( convert_big_to_fq(ecp2_point.getpx().geta()), convert_big_to_fq(ecp2_point.getpx().getb()), @@ -300,73 +302,65 @@ fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { G2Affine::new(x, y) } -fn convert_big_to_fq(big: Big) -> Fq { +pub fn convert_big_to_fq(big: Big) -> Fq { let bytes = &hex::decode(big.to_string()).unwrap(); Fq::from_be_bytes_mod_order(bytes) } #[cfg(test)] pub mod tests { + use std::env; + use plonky2::{ field::goldilocks_field::GoldilocksField, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, }; - use super::{bls12_381_components_proofs, read_yaml_files_from_directory}; + use super::{bls12_381_components_proofs, read_yaml_file}; + const PATH_TO_VERIFY_ETH_TEST_CASES: &str = "scripts/bls12-381-tests/eth_tests/bls/verify"; const D: usize = 2; type F = GoldilocksField; #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; - let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); - let standard_recursion_config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(standard_recursion_config); - - for i in 0..bls_components_with_verify_eth_tests_cases.len() { - let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; - let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) - .await - .unwrap(); - - println!("Proof generated"); - - println!( - "Is valid signature {}", - proof.public_inputs[proof.public_inputs.len() - 1] - ); - - let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); - builder.assert_one(proof_t); + let args: Vec = env::args().collect(); + if args.len() < 3 { + panic!("Expected a file path as argument"); } - } - #[tokio::test] - #[should_panic] - async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; - let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); + let file_path = &args[3]; + let x = format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path); + println!("file path is: {:?}", x); + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); - for i in 0..bls_components_with_verify_eth_tests_cases.len() { - let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; - let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) - .await - .unwrap(); - - println!("Proof generated"); + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(bls_components.clone()) + .await + .unwrap(); - println!( - "Is valid signature {}", - proof.public_inputs[proof.public_inputs.len() - 1] - ); + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); - let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); } } From f92897eaed8d359d14f64a9805e90ed654aa43ec Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 14:13:20 +0300 Subject: [PATCH 06/37] fix: Use unchecked deserialization for G1 & G2 in bls_components.rs --- .../plonky2/crates/circuit_executables/src/bls_components.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index eff901653..0d3fb5c62 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -87,11 +87,11 @@ pub async fn bls12_381_components_proofs( ); let message_g2 = convert_ecp2_to_g2affine(message_g2); - let pubkey_g1 = G1Affine::deserialize_compressed( + let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), ) .unwrap(); - let signature_g2 = G2Affine::deserialize_compressed( + let signature_g2 = G2Affine::deserialize_compressed_unchecked( &*hex::decode(bls_components.input.signature.clone()).unwrap(), ) .unwrap(); From 6170454a09e77b05bba636c1ca36dbc427232388 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 14:35:55 +0300 Subject: [PATCH 07/37] miller loop putted outside main bls12381 component proof function --- .../circuit_executables/src/bls_components.rs | 263 +++++++++++------- .../crates/circuit_executables/src/lib.rs | 1 + .../src/verify_bls_at_infinity.rs | 5 + .../src/verify_points_at_infinity_circuit.rs | 3 + 4 files changed, 174 insertions(+), 98 deletions(-) create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 0d3fb5c62..d44f9edb1 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -1,6 +1,6 @@ use anyhow::Result; use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; -use ark_ec::Group; +use ark_ec::{CurveGroup, Group}; use ark_ff::PrimeField; use ark_serialize::CanonicalDeserialize; use circuit::SerdeCircuitTarget; @@ -45,6 +45,15 @@ pub struct BlsComponents { pub output: bool, } +pub struct BlsProofs { + pub pairing_prec_proof1: ProofWithPublicInputs, + pub pairing_prec_proof2: ProofWithPublicInputs, + pub miller_loop_proof1: ProofWithPublicInputs, + pub miller_loop_proof2: ProofWithPublicInputs, + pub fp12_mul_proof: ProofWithPublicInputs, + pub final_exp_proof: ProofWithPublicInputs, +} + impl BlsComponents { fn remove_first_two_chars(&mut self) { self.input.pubkey = self.input.pubkey.chars().skip(2).collect(); @@ -53,22 +62,6 @@ impl BlsComponents { } } -pub fn read_yaml_files_from_directory>( - dir: P, -) -> Result, Box> { - let mut components = Vec::new(); - - for entry in fs::read_dir(dir)? { - let entry = entry?; - if entry.path().extension() == Some(std::ffi::OsStr::new("yaml")) { - let config = read_yaml_file(entry.path())?; - components.push(config); - } - } - - Ok(components) -} - pub fn read_yaml_file>( path: P, ) -> Result> { @@ -78,65 +71,75 @@ pub fn read_yaml_file>( Ok(components) } +pub fn set_bls_witness( + pw: &mut PartialWitness, + targets: &BlsCircuitTargets, + components: &BlsComponents, + proofs: &BlsProofs, +) { + pw.set_target_arr( + &targets.pubkey, + &hex::decode(&components.input.pubkey) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.sig, + &hex::decode(&components.input.signature) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.msg, + &hex::decode(&components.input.message) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + + pw.set_proof_with_pis_target(&targets.pt_pp1, &proofs.pairing_prec_proof1); + pw.set_proof_with_pis_target(&targets.pt_pp2, &proofs.pairing_prec_proof2); + pw.set_proof_with_pis_target(&targets.pt_ml1, &proofs.miller_loop_proof1); + pw.set_proof_with_pis_target(&targets.pt_ml2, &proofs.miller_loop_proof2); + pw.set_proof_with_pis_target(&targets.pt_fp12m, &proofs.fp12_mul_proof); + pw.set_proof_with_pis_target(&targets.pt_fe, &proofs.final_exp_proof); +} + pub async fn bls12_381_components_proofs( - bls_components: BlsComponents, + components: &BlsComponents, ) -> Result> { - let message_g2 = hash_to_curve_g2( - &hex::decode(bls_components.input.message.clone()).unwrap(), + let message_g2 = convert_ecp2_to_g2affine(hash_to_curve_g2( + &hex::decode(&components.input.message).unwrap(), DST.as_bytes(), - ); - let message_g2 = convert_ecp2_to_g2affine(message_g2); - - let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( - &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), + )); + let signature_g2 = G2Affine::deserialize_compressed_unchecked( + &*hex::decode(&components.input.signature).unwrap(), ) .unwrap(); - let signature_g2 = G2Affine::deserialize_compressed_unchecked( - &*hex::decode(bls_components.input.signature.clone()).unwrap(), + let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( + &*hex::decode(&components.input.pubkey).unwrap(), ) .unwrap(); - let g1 = G1Projective::generator(); - let neg_g1 = g1.neg(); + let neg_g1 = G1Projective::generator().neg(); - let miller_loop1 = miller_loop( - Fp::get_fp_from_biguint(pubkey_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(pubkey_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(message_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(message_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop1 = compute_native_miller_loop_from(pubkey_g1, message_g2); - let miller_loop2 = miller_loop( - Fp::get_fp_from_biguint(neg_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(neg_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); let fp12_mull = miller_loop1 * miller_loop2; + println!("fp12_mull is: {:?}", fp12_mull); + if fp12_mull = Fp12::one() - Fp12::one() {} + // PROVING HAPPENS HERE - let (pp1, pp2) = handle_pairing_precomp(&message_g2, &signature_g2).await; + let (pairing_prec_proof1, pairing_prec_proof2) = + handle_pairing_precomp(&message_g2, &signature_g2).await; - let (ml1, ml2) = + let (miller_loop_proof1, miller_loop_proof2) = handle_miller_loop(&pubkey_g1, &message_g2, &neg_g1.into(), &signature_g2).await; let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; @@ -151,39 +154,17 @@ pub async fn bls12_381_components_proofs( let mut target_buffer = Buffer::new(&target_bytes); let targets = BlsCircuitTargets::deserialize(&mut target_buffer).unwrap(); - let mut pw = PartialWitness::::new(); - - pw.set_target_arr( - &targets.pubkey, - &hex::decode(bls_components.input.pubkey) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.sig, - &hex::decode(bls_components.input.signature) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.msg, - &hex::decode(bls_components.input.message) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); + let proofs = BlsProofs { + pairing_prec_proof1, + pairing_prec_proof2, + miller_loop_proof1, + miller_loop_proof2, + fp12_mul_proof, + final_exp_proof, + }; - pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); - pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); - pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); - pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); - pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); - pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); + let mut pw = PartialWitness::::new(); + set_bls_witness(&mut pw, &targets, &components, &proofs); println!("Starting proof generation"); @@ -288,6 +269,28 @@ pub async fn handle_pairing_precomp( (pp1, pp2) } +pub fn compute_native_miller_loop_from( + g1_affine_point: G1Affine, + g2_affine_point: G2Affine, +) -> Fp12 { + miller_loop( + Fp::get_fp_from_biguint(g1_affine_point.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g1_affine_point.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(g2_affine_point.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g2_affine_point.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(g2_affine_point.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g2_affine_point.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ) +} + pub fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { let x = Fq2::new( convert_big_to_fq(ecp2_point.getpx().geta()), @@ -340,9 +343,73 @@ pub mod tests { println!("current pubkey: {:?}", bls_components.input.pubkey); println!("current signature: {:?}", bls_components.input.signature); println!("current message: {:?}", bls_components.input.message); - let proof = bls12_381_components_proofs(bls_components.clone()) - .await - .unwrap(); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { + builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); + } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); + } + + #[tokio::test] + async fn test_bls12_381_at_infinity_case() { + let file_path = "verify_infinity_pubkey_and_infinity_signature.yaml"; + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { + builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); + } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); + } + + #[tokio::test] + async fn test_bls12_381_one_privkey() { + let file_path = "verifycase_one_privkey_47117849458281be.yaml"; + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); println!( "Is valid signature {}", diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs index 4e9091836..ee97ec122 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs @@ -13,4 +13,5 @@ pub mod poseidon_bn128_config; pub mod poseidon_constants; pub mod provers; pub mod utils; +pub mod verify_bls_at_infinity; pub mod wrap_final_layer_in_poseidon_bn128; diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs new file mode 100644 index 000000000..9f61bf0ec --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs @@ -0,0 +1,5 @@ +// use crate::bls_components::{bls12_381_components_proofs, BlsComponents}; +// use circuit::SetWitness; +// pub async fn verify_bls_at_infinity(components: BlsComponents) { +// bls12_381_components_proofs(components) +// } diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs new file mode 100644 index 000000000..c3d641382 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs @@ -0,0 +1,3 @@ +// input: {pubkey: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', +// message: '0x1212121212121212121212121212121212121212121212121212121212121212', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} +// output: false From 53c140a86c32471baa29f94404921684c05344b6 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 14:47:58 +0300 Subject: [PATCH 08/37] Add helper comments for verify_bls_at_infinity circuit --- .../plonky2/crates/circuit_executables/src/bls_components.rs | 2 -- .../crates/circuit_executables/src/verify_bls_at_infinity.rs | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index d44f9edb1..492d00972 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -132,8 +132,6 @@ pub async fn bls12_381_components_proofs( let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); let fp12_mull = miller_loop1 * miller_loop2; - println!("fp12_mull is: {:?}", fp12_mull); - if fp12_mull = Fp12::one() - Fp12::one() {} // PROVING HAPPENS HERE let (pairing_prec_proof1, pairing_prec_proof2) = diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs index 9f61bf0ec..175ea3dca 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs @@ -3,3 +3,6 @@ // pub async fn verify_bls_at_infinity(components: BlsComponents) { // bls12_381_components_proofs(components) // } +// pk_on_curve_check +// signature_verificaton +// assert if its at infinity thus ensuring that deposit with such credentials is invalid From d315a098303931fcbfc2be358f90a23124bfaac8 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 27 May 2024 18:50:51 +0300 Subject: [PATCH 09/37] Implement tests cases for bls12_381_components_proofs against ethereum verify test cases --- beacon-light-client/plonky2/.gitignore | 1 + beacon-light-client/plonky2/crates/Cargo.lock | 1 + .../crates/circuit_executables/Cargo.toml | 8 +- .../scripts/run_bls12_381_component_proofs.sh | 61 +++ .../circuit_executables/src/bls_components.rs | 377 ++++++++++++++++++ .../crates/circuit_executables/src/lib.rs | 1 + vendor/circom-pairing | 2 +- 7 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 2ad2bdb42..5474f70c2 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -3,3 +3,4 @@ gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin gnark_plonky2_verifier/public_witness.bin +circuits_executables/ \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/Cargo.lock b/beacon-light-client/plonky2/crates/Cargo.lock index 91d9a1c68..d7b915566 100644 --- a/beacon-light-client/plonky2/crates/Cargo.lock +++ b/beacon-light-client/plonky2/crates/Cargo.lock @@ -1210,6 +1210,7 @@ dependencies = [ "redis-work-queue", "serde", "serde_json", + "serde_yaml", "snowbridge-amcl", "starky", "starky_bls12_381", diff --git a/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml b/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml index 6a1d6bae0..9f5ce0291 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml +++ b/beacon-light-client/plonky2/crates/circuit_executables/Cargo.toml @@ -8,7 +8,12 @@ edition.workspace = true [dependencies] circuit = { path = "../circuit" } circuits = { path = "../circuits" } -redis = { version = "0.23", features = ["aio", "async-std-comp", "connection-manager", "json"] } +redis = { version = "0.23", features = [ + "aio", + "async-std-comp", + "connection-manager", + "json", +] } num = { version = "0.4.0", features = ["serde"] } plonky2 = { git = "https://github.com/metacraft-labs/plonky2" } starky = { git = "https://github.com/metacraft-labs/plonky2" } @@ -16,6 +21,7 @@ plonky2-circuit-serializer = { git = "https://github.com/metacraft-labs/plonky2- starky_bls12_381 = { git = "https://github.com/metacraft-labs/starky_bls12_381" } serde = "1.0.164" serde_json = "1.0.96" +serde_yaml = "0.9.34" anyhow = "1.0.71" hex = "0.4.3" redis-work-queue = "0.1.3" diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh new file mode 100644 index 000000000..07fb3b899 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Define variables +REPO_URL="https://github.com/ethereum/bls12-381-tests" +REPO_DIR="bls12-381-tests" +OUTPUT_DIR="eth_tests" +VERIFY_DIR="$OUTPUT_DIR/verify" + +# Clone the repository +if [ ! -d "$REPO_DIR" ]; then + git clone "$REPO_URL" +else + echo "Repository already cloned." +fi + +# Navigate to the repository directory +cd "$REPO_DIR" || exit + +# Set up a Python virtual environment +if [ ! -d "venv" ]; then + python -m venv venv +else + echo "Virtual environment already set up." +fi + +# Activate the virtual environment +# shellcheck source=/dev/null +source venv/bin/activate + +# Install dependencies +pip install -r requirements.txt + +# Create output directory if it doesn't exist +mkdir -p "$OUTPUT_DIR" + +# Run the test generator +python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml + +# Deactivate the virtual environment +deactivate + +# Navigate back to the root directory +cd .. + +# Run the verify tests +run_verify_tests() { + local test_name=$1 + local file_path=$2 + + # Run the specified Rust test with the given file path + cargo test "$test_name" --release -- --nocapture --file "$file_path" +} + +# Loop through the extracted files in the 'verify' directory +for file in "$VERIFY_DIR"/*.yaml; do + if [[ "$file" == *"wrong"* || "$file" == *"tampered"* ]]; then + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases_should_fail" "$file" + else + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$file" + fi +done \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs new file mode 100644 index 000000000..ac55832d3 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -0,0 +1,377 @@ +use anyhow::Result; +use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; +use ark_ec::Group; +use ark_ff::PrimeField; +use ark_serialize::CanonicalDeserialize; +use circuit::SerdeCircuitTarget; +use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; +use num::BigUint; +use plonky2::{ + field::{goldilocks_field::GoldilocksField, types::Field}, + iop::witness::{PartialWitness, WitnessWrite}, + plonk::{config::PoseidonGoldilocksConfig, proof::ProofWithPublicInputs}, + util::serialization::Buffer, +}; +use serde::Deserialize; +use snowbridge_amcl::bls381::{big::Big, bls381::utils::hash_to_curve_g2, ecp2::ECP2}; +use starky_bls12_381::native::{miller_loop, Fp, Fp12, Fp2}; +use std::{fs, ops::Neg, path::Path, str::FromStr}; + +use crate::{ + constants::SERIALIZED_CIRCUITS_DIR, + crud::common::{get_recursive_stark_targets, load_circuit_data_starky, read_from_file}, + provers::{ + generate_final_exponentiate, generate_fp12_mul_proof, generate_miller_loop_proof, + generate_pairing_precomp_proof, + }, +}; + +const CIRCUIT_DIR: &str = "circuits"; +const DST: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; + +const D: usize = 2; +type C = PoseidonGoldilocksConfig; +type F = GoldilocksField; + +#[derive(Clone, Debug, Deserialize)] +pub struct Input { + pub pubkey: String, + pub signature: String, + pub message: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct BlsComponents { + pub input: Input, + pub output: bool, +} + +impl BlsComponents { + fn remove_first_two_chars(&mut self) { + self.input.pubkey = self.input.pubkey.chars().skip(2).collect(); + self.input.signature = self.input.signature.chars().skip(2).collect(); + self.input.message = self.input.message.chars().skip(2).collect(); + } +} + +pub fn read_yaml_files_from_directory>( + dir: P, +) -> Result, Box> { + let mut components = Vec::new(); + + for entry in fs::read_dir(dir)? { + let entry = entry?; + if entry.path().extension() == Some(std::ffi::OsStr::new("yaml")) { + let config = read_yaml_file(entry.path())?; + components.push(config); + } + } + + Ok(components) +} + +fn read_yaml_file>(path: P) -> Result> { + let file_content = fs::read_to_string(path)?; + let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; + components.remove_first_two_chars(); + Ok(components) +} + +pub async fn bls12_381_components_proofs( + bls_components: BlsComponents, +) -> Result> { + let message_g2 = hash_to_curve_g2( + &hex::decode(bls_components.input.message.clone()).unwrap(), + DST.as_bytes(), + ); + let message_g2 = convert_ecp2_to_g2affine(message_g2); + + let pubkey_g1 = G1Affine::deserialize_compressed( + &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), + ) + .unwrap(); + let signature_g2 = G2Affine::deserialize_compressed( + &*hex::decode(bls_components.input.signature.clone()).unwrap(), + ) + .unwrap(); + let g1 = G1Projective::generator(); + let neg_g1 = g1.neg(); + + let miller_loop1 = miller_loop( + Fp::get_fp_from_biguint(pubkey_g1.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(pubkey_g1.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(message_g2.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(message_g2.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(message_g2.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(message_g2.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ); + + let miller_loop2 = miller_loop( + Fp::get_fp_from_biguint(neg_g1.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(neg_g1.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(signature_g2.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(signature_g2.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(signature_g2.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(signature_g2.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ); + + let fp12_mull = miller_loop1 * miller_loop2; + // PROVING HAPPENS HERE + let (pp1, pp2) = handle_pairing_precomp(&message_g2, &signature_g2).await; + + let (ml1, ml2) = + handle_miller_loop(&pubkey_g1, &message_g2, &neg_g1.into(), &signature_g2).await; + + let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; + + let final_exp_proof = handle_final_exponentiation(&fp12_mull).await; + + let circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/bls12_381")); + let target_bytes = read_from_file(&format!( + "{}/{}.plonky2_targets", + SERIALIZED_CIRCUITS_DIR, "bls12_381" + ))?; + let mut target_buffer = Buffer::new(&target_bytes); + + let targets = BlsCircuitTargets::deserialize(&mut target_buffer).unwrap(); + let mut pw = PartialWitness::::new(); + + pw.set_target_arr( + &targets.pubkey, + &hex::decode(bls_components.input.pubkey) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.sig, + &hex::decode(bls_components.input.signature) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.msg, + &hex::decode(bls_components.input.message) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + + pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); + pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); + pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); + pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); + pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); + pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); + + println!("Starting proof generation"); + + let proof = circuit_data.prove(pw).unwrap(); + + Ok(proof) +} + +async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { + let final_exp_circuit_data = + load_circuit_data_starky(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")); + + let final_exp_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")).unwrap(); + + let final_exp_proof = + generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); + + final_exp_proof +} + +async fn handle_fp12_mul( + miller_loop1: &Fp12, + miller_loop2: &Fp12, +) -> ProofWithPublicInputs { + let fp12_mul_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/fp12_mul")); + + let fp12_mul_targets = get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/fp12_mul")).unwrap(); + + let fp12_mul_proof = generate_fp12_mul_proof( + &miller_loop1, + &miller_loop2, + &fp12_mul_targets, + &fp12_mul_circuit_data, + ); + + fp12_mul_proof +} + +async fn handle_miller_loop( + pubkey_g1: &G1Affine, + message_g2: &G2Affine, + neg_g1: &G1Affine, + signature_g2: &G2Affine, +) -> ( + ProofWithPublicInputs, + ProofWithPublicInputs, +) { + let miller_loop_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/miller_loop")); + + let miller_loop_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/miller_loop")).unwrap(); + + let ml1 = generate_miller_loop_proof( + &pubkey_g1, + &message_g2, + &miller_loop_targets, + &miller_loop_circuit_data, + ); + + let ml2 = generate_miller_loop_proof( + &neg_g1, + &signature_g2, + &miller_loop_targets, + &miller_loop_circuit_data, + ); + + (ml1, ml2) +} + +async fn handle_pairing_precomp( + message_g2: &G2Affine, + signature_g2: &G2Affine, +) -> ( + ProofWithPublicInputs, + ProofWithPublicInputs, +) { + let pairing_precomp_circuit_data = + load_circuit_data_starky(&format!("{CIRCUIT_DIR}/pairing_precomp")); + + let pairing_precomp_targets = + get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/pairing_precomp")).unwrap(); + + let pp1 = generate_pairing_precomp_proof( + &message_g2, + &pairing_precomp_targets, + &pairing_precomp_circuit_data, + ); + + let pp2 = generate_pairing_precomp_proof( + &signature_g2, + &pairing_precomp_targets, + &pairing_precomp_circuit_data, + ); + + (pp1, pp2) +} + +fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { + let x = Fq2::new( + convert_big_to_fq(ecp2_point.getpx().geta()), + convert_big_to_fq(ecp2_point.getpx().getb()), + ); + + let y = Fq2::new( + convert_big_to_fq(ecp2_point.getpy().geta()), + convert_big_to_fq(ecp2_point.getpy().getb()), + ); + + G2Affine::new(x, y) +} + +fn convert_big_to_fq(big: Big) -> Fq { + let bytes = &hex::decode(big.to_string()).unwrap(); + Fq::from_be_bytes_mod_order(bytes) +} + +#[cfg(test)] +pub mod tests { + use std::env; + + use plonky2::{ + field::goldilocks_field::GoldilocksField, + plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, + }; + + use super::{bls12_381_components_proofs, read_yaml_files_from_directory}; + + const D: usize = 2; + type F = GoldilocksField; + + #[tokio::test] + async fn test_bls12_381_components_proofs_with_verify_eth_cases() { + let args: Vec = env::args().collect(); + if args.len() < 2 { + panic!("Expected a file path as argument"); + } + + let bls_components_with_verify_eth_tests_cases = + read_yaml_files_from_directory(args[1].as_str()).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + for i in 0..bls_components_with_verify_eth_tests_cases.len() { + let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; + let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) + .await + .unwrap(); + + println!("Proof generated"); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + builder.assert_one(proof_t); + } + } + + #[tokio::test] + #[should_panic] + async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { + let args: Vec = env::args().collect(); + if args.len() < 2 { + panic!("Expected a file path as argument"); + } + + let bls_components_with_verify_eth_tests_cases = + read_yaml_files_from_directory(args[1].as_str()).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + for i in 0..bls_components_with_verify_eth_tests_cases.len() { + let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; + let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) + .await + .unwrap(); + + println!("Proof generated"); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + builder.assert_one(proof_t); + } + } +} diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs index 7a0240689..4e9091836 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs @@ -2,6 +2,7 @@ #![feature(async_closure)] #![feature(generic_const_exprs)] +pub mod bls_components; pub mod commitment_mapper_context; pub mod commitment_mapper_task; pub mod constants; diff --git a/vendor/circom-pairing b/vendor/circom-pairing index 52db7a215..82bac4a27 160000 --- a/vendor/circom-pairing +++ b/vendor/circom-pairing @@ -1 +1 @@ -Subproject commit 52db7a21544219e7b734e7f683d1f11328a0dc4e +Subproject commit 82bac4a27499fc11cf3ebbb64c525b526f13b552 From 414d68a98dbeaaa4550815722a4fbc2f8489acc4 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 27 May 2024 19:48:51 +0300 Subject: [PATCH 10/37] Update bls_components and shell to run the tests in it - still wip, it's not building --- .../scripts/bls12-381-tests | 1 + .../scripts/run_bls12_381_component_proofs.sh | 10 +++++++++- .../circuit_executables/src/bls_components.rs | 18 ++++-------------- 3 files changed, 14 insertions(+), 15 deletions(-) create mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests mode change 100644 => 100755 beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests new file mode 160000 index 000000000..2b6a5ba04 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests @@ -0,0 +1 @@ +Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh old mode 100644 new mode 100755 index 07fb3b899..5370cdfcd --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,6 +5,8 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/verify" +SCRIPTS_DIR="scripts" +RUST_FILES_DIR="src" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -42,13 +44,19 @@ deactivate # Navigate back to the root directory cd .. +# Navigate to the rust files directory +cd "$RUST_FILES_DIR" || exit + # Run the verify tests run_verify_tests() { local test_name=$1 local file_path=$2 + # Set the FILE_PATH environment variable + export FILE_PATH="$file_path" + # Run the specified Rust test with the given file path - cargo test "$test_name" --release -- --nocapture --file "$file_path" + RUST_MIN_STACK=16777216 cargo test "$test_name" --release -- --nocapture "$file_path" } # Loop through the extracted files in the 'verify' directory diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index ac55832d3..53d2e7641 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -302,8 +302,6 @@ fn convert_big_to_fq(big: Big) -> Fq { #[cfg(test)] pub mod tests { - use std::env; - use plonky2::{ field::goldilocks_field::GoldilocksField, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, @@ -316,13 +314,9 @@ pub mod tests { #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("Expected a file path as argument"); - } - + let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(args[1].as_str()).unwrap(); + read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); @@ -347,13 +341,9 @@ pub mod tests { #[tokio::test] #[should_panic] async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("Expected a file path as argument"); - } - + let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(args[1].as_str()).unwrap(); + read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); From 16bd6695504a9520f1c82bf7fc1d5ba65796c701 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 10:06:27 +0300 Subject: [PATCH 11/37] build(bls_components) Made little changes needed for bls_components to execute its tests --- .../circuit_executables/src/bls_components.rs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 53d2e7641..4bcdeb592 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -26,7 +26,6 @@ use crate::{ }, }; -const CIRCUIT_DIR: &str = "circuits"; const DST: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; const D: usize = 2; @@ -192,11 +191,14 @@ pub async fn bls12_381_components_proofs( } async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { - let final_exp_circuit_data = - load_circuit_data_starky(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")); + let final_exp_circuit_data = load_circuit_data_starky(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )); - let final_exp_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/final_exponentiate_circuit")).unwrap(); + let final_exp_targets = get_recursive_stark_targets(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )) + .unwrap(); let final_exp_proof = generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); @@ -208,9 +210,11 @@ async fn handle_fp12_mul( miller_loop1: &Fp12, miller_loop2: &Fp12, ) -> ProofWithPublicInputs { - let fp12_mul_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/fp12_mul")); + let fp12_mul_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - let fp12_mul_targets = get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/fp12_mul")).unwrap(); + let fp12_mul_targets = + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")).unwrap(); let fp12_mul_proof = generate_fp12_mul_proof( &miller_loop1, @@ -231,10 +235,11 @@ async fn handle_miller_loop( ProofWithPublicInputs, ProofWithPublicInputs, ) { - let miller_loop_circuit_data = load_circuit_data_starky(&format!("{CIRCUIT_DIR}/miller_loop")); + let miller_loop_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); let miller_loop_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/miller_loop")).unwrap(); + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")).unwrap(); let ml1 = generate_miller_loop_proof( &pubkey_g1, @@ -261,10 +266,10 @@ async fn handle_pairing_precomp( ProofWithPublicInputs, ) { let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{CIRCUIT_DIR}/pairing_precomp")); + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); let pairing_precomp_targets = - get_recursive_stark_targets(&format!("{CIRCUIT_DIR}/pairing_precomp")).unwrap(); + get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")).unwrap(); let pp1 = generate_pairing_precomp_proof( &message_g2, @@ -314,7 +319,7 @@ pub mod tests { #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; + let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); @@ -341,7 +346,7 @@ pub mod tests { #[tokio::test] #[should_panic] async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let eth_tests_directory_path = "../scripts/bls12-381-tests/eth_tests/bls/verify"; + let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; let bls_components_with_verify_eth_tests_cases = read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); From a6818ee2f138d902c70ab831fd94d1d29163a589 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 10:13:10 +0300 Subject: [PATCH 12/37] fix(run_bls12_381_component_proofs.sh) Fix the navigation in the root directory --- .../scripts/run_bls12_381_component_proofs.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 5370cdfcd..797f05a9b 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -41,6 +41,9 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate +# Navigate back to the scripts directory +cd .. + # Navigate back to the root directory cd .. From 7e3adc4e3f35ff35ed540fa13f8a483c28f85798 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 13:59:59 +0300 Subject: [PATCH 13/37] fix: Use unchecked deserialization for G1 & G2 --- .../bin/bls12_381_components_proofs.rs | 140 ++---------------- .../scripts/run_bls12_381_component_proofs.sh | 37 +++-- .../circuit_executables/src/bls_components.rs | 90 ++++++----- 3 files changed, 72 insertions(+), 195 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs index eced9ec0f..6e69d2c0f 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs @@ -1,19 +1,18 @@ use anyhow::Result; -use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; +use ark_bls12_381::{G1Affine, G1Projective, G2Affine}; use ark_ec::Group; -use ark_ff::PrimeField; use ark_serialize::CanonicalDeserialize; use circuit::SerdeCircuitTarget; use circuit_executables::{ + bls_components::{ + convert_ecp2_to_g2affine, handle_final_exponentiation, handle_fp12_mul, handle_miller_loop, + handle_pairing_precomp, + }, constants::SERIALIZED_CIRCUITS_DIR, crud::{ - common::{get_recursive_stark_targets, load_circuit_data_starky, read_from_file}, + common::{load_circuit_data_starky, read_from_file}, proof_storage::proof_storage::create_proof_storage, }, - provers::{ - generate_final_exponentiate, generate_fp12_mul_proof, generate_miller_loop_proof, - generate_pairing_precomp_proof, - }, utils::CommandLineOptionsBuilder, }; use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; @@ -22,11 +21,10 @@ use num_bigint::BigUint; use plonky2::{ field::{goldilocks_field::GoldilocksField, types::Field}, iop::witness::{PartialWitness, WitnessWrite}, - plonk::{config::PoseidonGoldilocksConfig, proof::ProofWithPublicInputs}, util::serialization::Buffer, }; -use snowbridge_amcl::bls381::{big::Big, bls381::utils::hash_to_curve_g2, ecp2::ECP2}; -use starky_bls12_381::native::{miller_loop, Fp, Fp12, Fp2}; +use snowbridge_amcl::bls381::bls381::utils::hash_to_curve_g2; +use starky_bls12_381::native::{miller_loop, Fp, Fp2}; use std::{ops::Neg, str::FromStr}; async fn async_main() -> Result<()> { @@ -41,8 +39,10 @@ async fn async_main() -> Result<()> { let message_g2 = hash_to_curve_g2(&hex::decode(msg).unwrap(), DST.as_bytes()); let message_g2 = convert_ecp2_to_g2affine(message_g2); - let pubkey_g1 = G1Affine::deserialize_compressed(&*hex::decode(pubkey).unwrap()).unwrap(); - let signature_g2 = G2Affine::deserialize_compressed(&*hex::decode(signature).unwrap()).unwrap(); + let pubkey_g1 = + G1Affine::deserialize_compressed_unchecked(&*hex::decode(pubkey).unwrap()).unwrap(); + let signature_g2 = + G2Affine::deserialize_compressed_unchecked(&*hex::decode(signature).unwrap()).unwrap(); let g1 = G1Projective::generator(); let neg_g1 = g1.neg(); @@ -153,75 +153,6 @@ async fn async_main() -> Result<()> { Ok(()) } -async fn handle_final_exponentiation( - fp12_mull: &Fp12, -) -> ProofWithPublicInputs { - let final_exp_circuit_data = load_circuit_data_starky(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )); - - let final_exp_targets = get_recursive_stark_targets(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )) - .unwrap(); - - let final_exp_proof = - generate_final_exponentiate(&fp12_mull, &final_exp_targets, &final_exp_circuit_data); - - final_exp_proof -} - -async fn handle_fp12_mul( - miller_loop1: &Fp12, - miller_loop2: &Fp12, -) -> ProofWithPublicInputs { - let fp12_mul_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - - let fp12_mul_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")).unwrap(); - - let fp12_mul_proof = generate_fp12_mul_proof( - &miller_loop1, - &miller_loop2, - &fp12_mul_targets, - &fp12_mul_circuit_data, - ); - - fp12_mul_proof -} - -async fn handle_miller_loop( - pubkey_g1: &G1Affine, - message_g2: &G2Affine, - neg_g1: &G1Affine, - signature_g2: &G2Affine, -) -> ( - ProofWithPublicInputs, - ProofWithPublicInputs, -) { - let miller_loop_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - - let miller_loop_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")).unwrap(); - - let ml1 = generate_miller_loop_proof( - &pubkey_g1, - &message_g2, - &miller_loop_targets, - &miller_loop_circuit_data, - ); - - let ml2 = generate_miller_loop_proof( - &neg_g1, - &signature_g2, - &miller_loop_targets, - &miller_loop_circuit_data, - ); - - (ml1, ml2) -} fn main() { let _ = std::thread::Builder::new() .spawn(|| future::block_on(async_main())) @@ -229,50 +160,3 @@ fn main() { .join() .unwrap(); } - -async fn handle_pairing_precomp( - message_g2: &G2Affine, - signature_g2: &G2Affine, -) -> ( - ProofWithPublicInputs, - ProofWithPublicInputs, -) { - let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); - - let pairing_precomp_targets = - get_recursive_stark_targets(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")).unwrap(); - - let pp1 = generate_pairing_precomp_proof( - &message_g2, - &pairing_precomp_targets, - &pairing_precomp_circuit_data, - ); - - let pp2 = generate_pairing_precomp_proof( - &signature_g2, - &pairing_precomp_targets, - &pairing_precomp_circuit_data, - ); - - (pp1, pp2) -} - -fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { - let x = Fq2::new( - convert_big_to_fq(ecp2_point.getpx().geta()), - convert_big_to_fq(ecp2_point.getpx().getb()), - ); - - let y = Fq2::new( - convert_big_to_fq(ecp2_point.getpy().geta()), - convert_big_to_fq(ecp2_point.getpy().getb()), - ); - - G2Affine::new(x, y) -} - -fn convert_big_to_fq(big: Big) -> Fq { - let bytes = &hex::decode(big.to_string()).unwrap(); - Fq::from_be_bytes_mod_order(bytes) -} diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 797f05a9b..63316a3b8 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -3,10 +3,10 @@ # Define variables REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" -OUTPUT_DIR="eth_tests" +OUTPUT_DIR="eth_tests/bls" VERIFY_DIR="$OUTPUT_DIR/verify" SCRIPTS_DIR="scripts" -RUST_FILES_DIR="src" +SRC="src" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -41,32 +41,31 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate back to the scripts directory -cd .. +# Navigate to the verify directory +cd "$VERIFY_DIR" || exit + +# Store all files in a variable +mapfile -t all_yaml_files_in_verify < <(ls *) # Navigate back to the root directory -cd .. +cd ../../../../../ -# Navigate to the rust files directory -cd "$RUST_FILES_DIR" || exit +# Navigate to the src directory +cd "$SRC" || exit # Run the verify tests run_verify_tests() { - local test_name=$1 - local file_path=$2 + local test_name=$1 + local file_path=$2 - # Set the FILE_PATH environment variable - export FILE_PATH="$file_path" + # Set the FILE_PATH environment variable + export FILE_PATH="$file_path" - # Run the specified Rust test with the given file path - RUST_MIN_STACK=16777216 cargo test "$test_name" --release -- --nocapture "$file_path" + # Run the specified Rust test with the given file path + RUST_MIN_STACK=1116777216 cargo test "$test_name" --release -- --nocapture "$file_path" } # Loop through the extracted files in the 'verify' directory -for file in "$VERIFY_DIR"/*.yaml; do - if [[ "$file" == *"wrong"* || "$file" == *"tampered"* ]]; then - run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases_should_fail" "$file" - else - run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$file" - fi +for yaml_file in "${all_yaml_files_in_verify[@]}"; do + run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" done \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 4bcdeb592..eff901653 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -69,7 +69,9 @@ pub fn read_yaml_files_from_directory>( Ok(components) } -fn read_yaml_file>(path: P) -> Result> { +pub fn read_yaml_file>( + path: P, +) -> Result> { let file_content = fs::read_to_string(path)?; let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; components.remove_first_two_chars(); @@ -190,7 +192,7 @@ pub async fn bls12_381_components_proofs( Ok(proof) } -async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { +pub async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs { let final_exp_circuit_data = load_circuit_data_starky(&format!( "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" )); @@ -206,7 +208,7 @@ async fn handle_final_exponentiation(fp12_mull: &Fp12) -> ProofWithPublicInputs< final_exp_proof } -async fn handle_fp12_mul( +pub async fn handle_fp12_mul( miller_loop1: &Fp12, miller_loop2: &Fp12, ) -> ProofWithPublicInputs { @@ -226,7 +228,7 @@ async fn handle_fp12_mul( fp12_mul_proof } -async fn handle_miller_loop( +pub async fn handle_miller_loop( pubkey_g1: &G1Affine, message_g2: &G2Affine, neg_g1: &G1Affine, @@ -258,7 +260,7 @@ async fn handle_miller_loop( (ml1, ml2) } -async fn handle_pairing_precomp( +pub async fn handle_pairing_precomp( message_g2: &G2Affine, signature_g2: &G2Affine, ) -> ( @@ -286,7 +288,7 @@ async fn handle_pairing_precomp( (pp1, pp2) } -fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { +pub fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { let x = Fq2::new( convert_big_to_fq(ecp2_point.getpx().geta()), convert_big_to_fq(ecp2_point.getpx().getb()), @@ -300,73 +302,65 @@ fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { G2Affine::new(x, y) } -fn convert_big_to_fq(big: Big) -> Fq { +pub fn convert_big_to_fq(big: Big) -> Fq { let bytes = &hex::decode(big.to_string()).unwrap(); Fq::from_be_bytes_mod_order(bytes) } #[cfg(test)] pub mod tests { + use std::env; + use plonky2::{ field::goldilocks_field::GoldilocksField, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, }; - use super::{bls12_381_components_proofs, read_yaml_files_from_directory}; + use super::{bls12_381_components_proofs, read_yaml_file}; + const PATH_TO_VERIFY_ETH_TEST_CASES: &str = "scripts/bls12-381-tests/eth_tests/bls/verify"; const D: usize = 2; type F = GoldilocksField; #[tokio::test] async fn test_bls12_381_components_proofs_with_verify_eth_cases() { - let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; - let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); - let standard_recursion_config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(standard_recursion_config); - - for i in 0..bls_components_with_verify_eth_tests_cases.len() { - let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; - let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) - .await - .unwrap(); - - println!("Proof generated"); - - println!( - "Is valid signature {}", - proof.public_inputs[proof.public_inputs.len() - 1] - ); - - let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); - builder.assert_one(proof_t); + let args: Vec = env::args().collect(); + if args.len() < 3 { + panic!("Expected a file path as argument"); } - } - #[tokio::test] - #[should_panic] - async fn test_bls12_381_components_proofs_with_verify_eth_cases_should_panic() { - let eth_tests_directory_path = "scripts/bls12-381-tests/eth_tests/bls/verify"; - let bls_components_with_verify_eth_tests_cases = - read_yaml_files_from_directory(eth_tests_directory_path).unwrap(); + let file_path = &args[3]; + let x = format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path); + println!("file path is: {:?}", x); + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); - for i in 0..bls_components_with_verify_eth_tests_cases.len() { - let current_eth_verify_test = &bls_components_with_verify_eth_tests_cases[i]; - let proof = bls12_381_components_proofs((*current_eth_verify_test).clone()) - .await - .unwrap(); - - println!("Proof generated"); + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(bls_components.clone()) + .await + .unwrap(); - println!( - "Is valid signature {}", - proof.public_inputs[proof.public_inputs.len() - 1] - ); + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); - let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); } } From de894914813aa8b96344cdd641c0fa9ccd822cf3 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 28 May 2024 14:13:20 +0300 Subject: [PATCH 14/37] fix: Use unchecked deserialization for G1 & G2 in bls_components.rs --- .../plonky2/crates/circuit_executables/src/bls_components.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index eff901653..0d3fb5c62 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -87,11 +87,11 @@ pub async fn bls12_381_components_proofs( ); let message_g2 = convert_ecp2_to_g2affine(message_g2); - let pubkey_g1 = G1Affine::deserialize_compressed( + let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), ) .unwrap(); - let signature_g2 = G2Affine::deserialize_compressed( + let signature_g2 = G2Affine::deserialize_compressed_unchecked( &*hex::decode(bls_components.input.signature.clone()).unwrap(), ) .unwrap(); From e4bef3cf4d4cea3ae88b0c6b9569fc569a00aa84 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 14:35:55 +0300 Subject: [PATCH 15/37] miller loop putted outside main bls12381 component proof function --- .../circuit_executables/src/bls_components.rs | 263 +++++++++++------- .../crates/circuit_executables/src/lib.rs | 1 + .../src/verify_bls_at_infinity.rs | 5 + .../src/verify_points_at_infinity_circuit.rs | 3 + 4 files changed, 174 insertions(+), 98 deletions(-) create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs create mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 0d3fb5c62..d44f9edb1 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -1,6 +1,6 @@ use anyhow::Result; use ark_bls12_381::{Fq, Fq2, G1Affine, G1Projective, G2Affine}; -use ark_ec::Group; +use ark_ec::{CurveGroup, Group}; use ark_ff::PrimeField; use ark_serialize::CanonicalDeserialize; use circuit::SerdeCircuitTarget; @@ -45,6 +45,15 @@ pub struct BlsComponents { pub output: bool, } +pub struct BlsProofs { + pub pairing_prec_proof1: ProofWithPublicInputs, + pub pairing_prec_proof2: ProofWithPublicInputs, + pub miller_loop_proof1: ProofWithPublicInputs, + pub miller_loop_proof2: ProofWithPublicInputs, + pub fp12_mul_proof: ProofWithPublicInputs, + pub final_exp_proof: ProofWithPublicInputs, +} + impl BlsComponents { fn remove_first_two_chars(&mut self) { self.input.pubkey = self.input.pubkey.chars().skip(2).collect(); @@ -53,22 +62,6 @@ impl BlsComponents { } } -pub fn read_yaml_files_from_directory>( - dir: P, -) -> Result, Box> { - let mut components = Vec::new(); - - for entry in fs::read_dir(dir)? { - let entry = entry?; - if entry.path().extension() == Some(std::ffi::OsStr::new("yaml")) { - let config = read_yaml_file(entry.path())?; - components.push(config); - } - } - - Ok(components) -} - pub fn read_yaml_file>( path: P, ) -> Result> { @@ -78,65 +71,75 @@ pub fn read_yaml_file>( Ok(components) } +pub fn set_bls_witness( + pw: &mut PartialWitness, + targets: &BlsCircuitTargets, + components: &BlsComponents, + proofs: &BlsProofs, +) { + pw.set_target_arr( + &targets.pubkey, + &hex::decode(&components.input.pubkey) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.sig, + &hex::decode(&components.input.signature) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.msg, + &hex::decode(&components.input.message) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + + pw.set_proof_with_pis_target(&targets.pt_pp1, &proofs.pairing_prec_proof1); + pw.set_proof_with_pis_target(&targets.pt_pp2, &proofs.pairing_prec_proof2); + pw.set_proof_with_pis_target(&targets.pt_ml1, &proofs.miller_loop_proof1); + pw.set_proof_with_pis_target(&targets.pt_ml2, &proofs.miller_loop_proof2); + pw.set_proof_with_pis_target(&targets.pt_fp12m, &proofs.fp12_mul_proof); + pw.set_proof_with_pis_target(&targets.pt_fe, &proofs.final_exp_proof); +} + pub async fn bls12_381_components_proofs( - bls_components: BlsComponents, + components: &BlsComponents, ) -> Result> { - let message_g2 = hash_to_curve_g2( - &hex::decode(bls_components.input.message.clone()).unwrap(), + let message_g2 = convert_ecp2_to_g2affine(hash_to_curve_g2( + &hex::decode(&components.input.message).unwrap(), DST.as_bytes(), - ); - let message_g2 = convert_ecp2_to_g2affine(message_g2); - - let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( - &*hex::decode(bls_components.input.pubkey.clone()).unwrap(), + )); + let signature_g2 = G2Affine::deserialize_compressed_unchecked( + &*hex::decode(&components.input.signature).unwrap(), ) .unwrap(); - let signature_g2 = G2Affine::deserialize_compressed_unchecked( - &*hex::decode(bls_components.input.signature.clone()).unwrap(), + let pubkey_g1 = G1Affine::deserialize_compressed_unchecked( + &*hex::decode(&components.input.pubkey).unwrap(), ) .unwrap(); - let g1 = G1Projective::generator(); - let neg_g1 = g1.neg(); + let neg_g1 = G1Projective::generator().neg(); - let miller_loop1 = miller_loop( - Fp::get_fp_from_biguint(pubkey_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(pubkey_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(message_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(message_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop1 = compute_native_miller_loop_from(pubkey_g1, message_g2); - let miller_loop2 = miller_loop( - Fp::get_fp_from_biguint(neg_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(neg_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); let fp12_mull = miller_loop1 * miller_loop2; + println!("fp12_mull is: {:?}", fp12_mull); + if fp12_mull = Fp12::one() - Fp12::one() {} + // PROVING HAPPENS HERE - let (pp1, pp2) = handle_pairing_precomp(&message_g2, &signature_g2).await; + let (pairing_prec_proof1, pairing_prec_proof2) = + handle_pairing_precomp(&message_g2, &signature_g2).await; - let (ml1, ml2) = + let (miller_loop_proof1, miller_loop_proof2) = handle_miller_loop(&pubkey_g1, &message_g2, &neg_g1.into(), &signature_g2).await; let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; @@ -151,39 +154,17 @@ pub async fn bls12_381_components_proofs( let mut target_buffer = Buffer::new(&target_bytes); let targets = BlsCircuitTargets::deserialize(&mut target_buffer).unwrap(); - let mut pw = PartialWitness::::new(); - - pw.set_target_arr( - &targets.pubkey, - &hex::decode(bls_components.input.pubkey) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.sig, - &hex::decode(bls_components.input.signature) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.msg, - &hex::decode(bls_components.input.message) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); + let proofs = BlsProofs { + pairing_prec_proof1, + pairing_prec_proof2, + miller_loop_proof1, + miller_loop_proof2, + fp12_mul_proof, + final_exp_proof, + }; - pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); - pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); - pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); - pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); - pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); - pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); + let mut pw = PartialWitness::::new(); + set_bls_witness(&mut pw, &targets, &components, &proofs); println!("Starting proof generation"); @@ -288,6 +269,28 @@ pub async fn handle_pairing_precomp( (pp1, pp2) } +pub fn compute_native_miller_loop_from( + g1_affine_point: G1Affine, + g2_affine_point: G2Affine, +) -> Fp12 { + miller_loop( + Fp::get_fp_from_biguint(g1_affine_point.x.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g1_affine_point.y.to_string().parse::().unwrap()), + Fp2([ + Fp::get_fp_from_biguint(g2_affine_point.x.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g2_affine_point.x.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(g2_affine_point.y.c0.to_string().parse::().unwrap()), + Fp::get_fp_from_biguint(g2_affine_point.y.c1.to_string().parse::().unwrap()), + ]), + Fp2([ + Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), + Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), + ]), + ) +} + pub fn convert_ecp2_to_g2affine(ecp2_point: ECP2) -> G2Affine { let x = Fq2::new( convert_big_to_fq(ecp2_point.getpx().geta()), @@ -340,9 +343,73 @@ pub mod tests { println!("current pubkey: {:?}", bls_components.input.pubkey); println!("current signature: {:?}", bls_components.input.signature); println!("current message: {:?}", bls_components.input.message); - let proof = bls12_381_components_proofs(bls_components.clone()) - .await - .unwrap(); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { + builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); + } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); + } + + #[tokio::test] + async fn test_bls12_381_at_infinity_case() { + let file_path = "verify_infinity_pubkey_and_infinity_signature.yaml"; + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); + + println!( + "Is valid signature {}", + proof.public_inputs[proof.public_inputs.len() - 1] + ); + + let proof_t = builder.constant(proof.public_inputs[proof.public_inputs.len() - 1]); + if bls_components.output { + builder.assert_one(proof_t); + } else { + builder.assert_zero(proof_t); + } + + println!( + "test case is VALID for: pubkey: {:?}, signature: {:?} and message: {:?}", + bls_components.input.pubkey, + bls_components.input.signature, + bls_components.input.message, + ); + } + + #[tokio::test] + async fn test_bls12_381_one_privkey() { + let file_path = "verifycase_one_privkey_47117849458281be.yaml"; + let bls_components = + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + println!("current pubkey: {:?}", bls_components.input.pubkey); + println!("current signature: {:?}", bls_components.input.signature); + println!("current message: {:?}", bls_components.input.message); + let proof = bls12_381_components_proofs(&bls_components).await.unwrap(); println!( "Is valid signature {}", diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs index 4e9091836..ee97ec122 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs @@ -13,4 +13,5 @@ pub mod poseidon_bn128_config; pub mod poseidon_constants; pub mod provers; pub mod utils; +pub mod verify_bls_at_infinity; pub mod wrap_final_layer_in_poseidon_bn128; diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs new file mode 100644 index 000000000..9f61bf0ec --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs @@ -0,0 +1,5 @@ +// use crate::bls_components::{bls12_381_components_proofs, BlsComponents}; +// use circuit::SetWitness; +// pub async fn verify_bls_at_infinity(components: BlsComponents) { +// bls12_381_components_proofs(components) +// } diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs new file mode 100644 index 000000000..c3d641382 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs @@ -0,0 +1,3 @@ +// input: {pubkey: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', +// message: '0x1212121212121212121212121212121212121212121212121212121212121212', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} +// output: false From a43c1517495378a1201e6de54f20310d1f53799f Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 14:47:58 +0300 Subject: [PATCH 16/37] Add helper comments for verify_bls_at_infinity circuit --- .../plonky2/crates/circuit_executables/src/bls_components.rs | 2 -- .../crates/circuit_executables/src/verify_bls_at_infinity.rs | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index d44f9edb1..492d00972 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -132,8 +132,6 @@ pub async fn bls12_381_components_proofs( let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); let fp12_mull = miller_loop1 * miller_loop2; - println!("fp12_mull is: {:?}", fp12_mull); - if fp12_mull = Fp12::one() - Fp12::one() {} // PROVING HAPPENS HERE let (pairing_prec_proof1, pairing_prec_proof2) = diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs index 9f61bf0ec..175ea3dca 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs @@ -3,3 +3,6 @@ // pub async fn verify_bls_at_infinity(components: BlsComponents) { // bls12_381_components_proofs(components) // } +// pk_on_curve_check +// signature_verificaton +// assert if its at infinity thus ensuring that deposit with such credentials is invalid From 899ef7a115de4749327e570b52950f1f7d1684e8 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 17:46:10 +0300 Subject: [PATCH 17/37] Implement point at infinity assert after g1 and g2 points are checked --- .../src/verify_bls_at_infinity.rs | 8 ----- .../src/verify_points_at_infinity_circuit.rs | 3 -- .../src/bls_verification/bls12_381_circuit.rs | 32 +++++++++++++++++-- 3 files changed, 29 insertions(+), 14 deletions(-) delete mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs delete mode 100644 beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs deleted file mode 100644 index 175ea3dca..000000000 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_bls_at_infinity.rs +++ /dev/null @@ -1,8 +0,0 @@ -// use crate::bls_components::{bls12_381_components_proofs, BlsComponents}; -// use circuit::SetWitness; -// pub async fn verify_bls_at_infinity(components: BlsComponents) { -// bls12_381_components_proofs(components) -// } -// pk_on_curve_check -// signature_verificaton -// assert if its at infinity thus ensuring that deposit with such credentials is invalid diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs deleted file mode 100644 index c3d641382..000000000 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/verify_points_at_infinity_circuit.rs +++ /dev/null @@ -1,3 +0,0 @@ -// input: {pubkey: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', -// message: '0x1212121212121212121212121212121212121212121212121212121212121212', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} -// output: false diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index cbb2842ea..87af6e0f4 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use circuit::Circuit; +use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; use num_bigint::BigUint; use plonky2::{ @@ -20,6 +20,8 @@ use plonky2_crypto::{ }; use starky_bls12_381::{ calc_pairing_precomp, final_exponentiate, fp12_mul, + fp2_plonky2::is_zero, + fp_plonky2::FpTarget, g1_plonky2::{pk_point_check, PointG1Target}, g2_plonky2::{signature_point_check, PointG2Target}, hash_to_curve::hash_to_curve, @@ -102,9 +104,11 @@ impl Circuit for BLSVerificationCircuit { let pubkey_g1 = get_g1_from_miller_loop(&pt_ml1); pk_point_check(builder, &pubkey_g1, &input.pubkey); + assert_g1_point_is_at_infinity(builder, &pubkey_g1); let signature_g2 = get_g2_point_from_pairing_precomp(builder, &pt_pp2); signature_point_check(builder, &signature_g2, &input.sig); + assert_g2_point_is_at_infinity(builder, &signature_g2); connect_pairing_precomp_with_miller_loop_g2(builder, &pt_pp2, &pt_ml2); @@ -112,7 +116,7 @@ impl Circuit for BLSVerificationCircuit { connect_miller_loop_with_g1(builder, &neg_generator, &pt_ml2); - connect_miller_loop_with_fp12_mull(builder, &pt_ml1, &pt_ml2, &pt_fp12m); + connect_miller_loop_with_fp12_mul(builder, &pt_ml1, &pt_ml2, &pt_fp12m); connect_fp12_mull_with_final_exponentiation(builder, &pt_fp12m, &pt_fe); @@ -230,7 +234,7 @@ fn get_g2_point_from_pairing_precomp, const D: usiz [[sig_point_x0, sig_point_x1], [sig_point_y0, sig_point_y1]] } -fn connect_miller_loop_with_fp12_mull, const D: usize>( +fn connect_miller_loop_with_fp12_mul, const D: usize>( builder: &mut CircuitBuilder, pt_ml1: &ProofWithPublicInputsTarget, pt_ml2: &ProofWithPublicInputsTarget, @@ -346,3 +350,25 @@ fn connect_pairing_precomp_with_g2, const D: usize> } } } + +fn assert_g1_point_is_at_infinity(builder: &mut CircuitBuilder, g1_point: &PointG1Target) { + let is_g1_x_zero = is_fp_zero(builder, &g1_point[0]); + let is_g1_y_zero = is_fp_zero(builder, &g1_point[1]); + let are_g1_x_and_y_zero = builder.and(is_g1_x_zero, is_g1_y_zero); + builder.assert_true(are_g1_x_and_y_zero) +} + +fn assert_g2_point_is_at_infinity(builder: &mut CircuitBuilder, g2_point: &PointG2Target) { + let is_g2_x_zero = is_zero(builder, &g2_point[0]); + let is_g2_y_zero = is_zero(builder, &g2_point[1]); + let are_g2_x_and_y_zero = builder.and(is_g2_x_zero, is_g2_y_zero); + builder.assert_true(are_g2_x_and_y_zero) +} + +fn is_fp_zero, const D: usize>( + builder: &mut CircuitBuilder, + input: &FpTarget, +) -> BoolTarget { + let zero = builder.zero_biguint(); + builder.cmp_biguint(input, &zero) +} From 5fa50eaf847b8101d6499da5da9c8880b661d4e5 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 17:53:32 +0300 Subject: [PATCH 18/37] Remove redundant file from lib.rs --- .../plonky2/crates/circuit_executables/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs index ee97ec122..4e9091836 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/lib.rs @@ -13,5 +13,4 @@ pub mod poseidon_bn128_config; pub mod poseidon_constants; pub mod provers; pub mod utils; -pub mod verify_bls_at_infinity; pub mod wrap_final_layer_in_poseidon_bn128; From 92587868e719ac8f47a613e454e058032e32d407 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Fri, 31 May 2024 18:14:25 +0300 Subject: [PATCH 19/37] Start test implementation against points at infinity --- .../src/bls_verification/bls12_381_circuit.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index 87af6e0f4..effd7240f 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -372,3 +372,26 @@ fn is_fp_zero, const D: usize>( let zero = builder.zero_biguint(); builder.cmp_biguint(input, &zero) } + +#[cfg(test)] +pub mod tests { + use circuit::Circuit; + use plonky2::plonk::{ + circuit_builder::CircuitBuilder, + circuit_data::CircuitConfig, + config::{GenericConfig, PoseidonGoldilocksConfig}, + }; + + use super::BLSVerificationCircuit; + + type F = >::F; + type C = PoseidonGoldilocksConfig; + const D: usize = 2; + + #[test] + fn test_bls12_381_circuit() { + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + // BLSVerificationCircuit::define(&mut builder, params); + } +} From ee225880e2865ced7355f7be2f4874a46b0b7168 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 3 Jun 2024 14:02:58 +0300 Subject: [PATCH 20/37] Add test for bls12_381 circuit --- .../src/bls_verification/bls12_381_circuit.rs | 63 +++++++++++++++++-- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index effd7240f..1eef4c8a4 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -375,23 +375,74 @@ fn is_fp_zero, const D: usize>( #[cfg(test)] pub mod tests { + use std::{fs, marker::PhantomData}; + + use anyhow::Result; use circuit::Circuit; - use plonky2::plonk::{ - circuit_builder::CircuitBuilder, - circuit_data::CircuitConfig, - config::{GenericConfig, PoseidonGoldilocksConfig}, + use plonky2::{ + iop::witness::PartialWitness, + plonk::{ + circuit_builder::CircuitBuilder, + circuit_data::{CircuitConfig, CircuitData}, + config::{GenericConfig, PoseidonGoldilocksConfig}, + }, }; + use plonky2_circuit_serializer::serializer::{CustomGateSerializer, CustomGeneratorSerializer}; use super::BLSVerificationCircuit; type F = >::F; type C = PoseidonGoldilocksConfig; const D: usize = 2; + const SERIALIZED_CIRCUITS_DIR: &str = "../circuit_executables/serialized_circuits"; + + fn read_from_file(file_path: &str) -> Result> { + let data = fs::read(file_path)?; + Ok(data) + } + + fn load_circuit_data_starky(file_name: &str) -> CircuitData { + println!("path: {:?}.plonky2_circuit", file_name); + let circuit_data_bytes = read_from_file(&format!("{file_name}.plonky2_circuit")).unwrap(); + + CircuitData::::from_bytes( + &circuit_data_bytes, + &CustomGateSerializer, + &CustomGeneratorSerializer { + _phantom: PhantomData::, + }, + ) + .unwrap() + } #[test] - fn test_bls12_381_circuit() { + fn test_bls12_381_circuit() -> std::result::Result<(), anyhow::Error> { let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); - // BLSVerificationCircuit::define(&mut builder, params); + + let pairing_precomp_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); + let miller_loop_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); + let fp12_mul_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); + let final_exponentiate_circuit_data = load_circuit_data_starky(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )); + + let params = ( + pairing_precomp_circuit_data, + miller_loop_circuit_data, + fp12_mul_circuit_data, + final_exponentiate_circuit_data, + ); + + BLSVerificationCircuit::define(&mut builder, ¶ms); + + let pw = PartialWitness::new(); + let data = builder.build::(); + let proof = data.prove(pw)?; + + data.verify(proof) } } From c3cee468bed5851b342caebd67d6a362f44d59cf Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 3 Jun 2024 15:31:44 +0300 Subject: [PATCH 21/37] Implement assert if g1 OR g2 point is at infinity --- .../src/bls_verification/bls12_381_circuit.rs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index 1eef4c8a4..5ff869241 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -104,11 +104,16 @@ impl Circuit for BLSVerificationCircuit { let pubkey_g1 = get_g1_from_miller_loop(&pt_ml1); pk_point_check(builder, &pubkey_g1, &input.pubkey); - assert_g1_point_is_at_infinity(builder, &pubkey_g1); + let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); let signature_g2 = get_g2_point_from_pairing_precomp(builder, &pt_pp2); signature_point_check(builder, &signature_g2, &input.sig); - assert_g2_point_is_at_infinity(builder, &signature_g2); + let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); + assert_g1_or_g2_point_at_infinity( + builder, + is_g1_point_is_at_infinity, + is_g2_point_is_at_infinity, + ); connect_pairing_precomp_with_miller_loop_g2(builder, &pt_pp2, &pt_ml2); @@ -351,18 +356,30 @@ fn connect_pairing_precomp_with_g2, const D: usize> } } -fn assert_g1_point_is_at_infinity(builder: &mut CircuitBuilder, g1_point: &PointG1Target) { +fn assert_g1_or_g2_point_at_infinity( + builder: &mut CircuitBuilder, + is_g1_at_infinity: BoolTarget, + is_g2_at_infinity: BoolTarget, +) -> BoolTarget { + builder.or(is_g1_at_infinity, is_g2_at_infinity) +} + +fn is_g1_point_is_at_infinity( + builder: &mut CircuitBuilder, + g1_point: &PointG1Target, +) -> BoolTarget { let is_g1_x_zero = is_fp_zero(builder, &g1_point[0]); let is_g1_y_zero = is_fp_zero(builder, &g1_point[1]); - let are_g1_x_and_y_zero = builder.and(is_g1_x_zero, is_g1_y_zero); - builder.assert_true(are_g1_x_and_y_zero) + builder.and(is_g1_x_zero, is_g1_y_zero) } -fn assert_g2_point_is_at_infinity(builder: &mut CircuitBuilder, g2_point: &PointG2Target) { +fn is_g2_point_is_at_infinity( + builder: &mut CircuitBuilder, + g2_point: &PointG2Target, +) -> BoolTarget { let is_g2_x_zero = is_zero(builder, &g2_point[0]); let is_g2_y_zero = is_zero(builder, &g2_point[1]); - let are_g2_x_and_y_zero = builder.and(is_g2_x_zero, is_g2_y_zero); - builder.assert_true(are_g2_x_and_y_zero) + builder.and(is_g2_x_zero, is_g2_y_zero) } fn is_fp_zero, const D: usize>( @@ -402,7 +419,6 @@ pub mod tests { } fn load_circuit_data_starky(file_name: &str) -> CircuitData { - println!("path: {:?}.plonky2_circuit", file_name); let circuit_data_bytes = read_from_file(&format!("{file_name}.plonky2_circuit")).unwrap(); CircuitData::::from_bytes( From 006fa5774af8ba30a924a43b5e752e884cc068e9 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 3 Jun 2024 17:08:58 +0300 Subject: [PATCH 22/37] Implement circuit asserting g1 and g2 point aren't at infinity and pk isn't the neg generator --- .../are_points_infinite_circuit.rs | 224 ++++++++++++++++++ .../src/bls_verification/bls12_381_circuit.rs | 192 +++------------ .../circuits/src/bls_verification/mod.rs | 1 + 3 files changed, 263 insertions(+), 154 deletions(-) create mode 100644 beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs new file mode 100644 index 000000000..e0d974bca --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs @@ -0,0 +1,224 @@ +use plonky2::{ + iop::target::BoolTarget, + plonk::{ + circuit_builder::CircuitBuilder, + circuit_data::{CircuitConfig, CircuitData}, + config::{GenericConfig, PoseidonGoldilocksConfig}, + }, +}; +use plonky2_crypto::biguint::CircuitBuilderBiguint; +use starky_bls12_381::{ + final_exponentiate, + fp2_plonky2::is_zero, + fp_plonky2::{is_equal, FpTarget}, + g1_plonky2::PointG1Target, + g2_plonky2::{signature_point_check, PointG2Target}, +}; + +use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; + +use crate::utils::circuit::verify_proof; + +use super::bls12_381_circuit::{ + get_g1_from_miller_loop, get_g2_point_from_pairing_precomp, get_neg_generator, + BlsCircuitTargets, +}; + +type F = >::F; +type C = PoseidonGoldilocksConfig; +const D: usize = 2; + +pub struct VerifyIsNotAtInfinityCircuit; + +impl Circuit for VerifyIsNotAtInfinityCircuit { + type F = F; + type C = C; + const D: usize = D; + + const CIRCUIT_CONFIG: CircuitConfig = CircuitConfig::standard_recursion_config(); + type Target = BlsCircuitTargets; + + type Params = ( + CircuitData, + CircuitData, + CircuitData, + CircuitData, + ); + + fn define( + builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, + ( + pairing_precomp_circuit_data, + miller_loop_circuit_data, + fp12_mul_circuit_data, + final_exponentiation_circuit_data, + ): &Self::Params, + ) -> Self::Target { + let input = Self::read_circuit_input_target(builder); + let pt_pp1 = verify_proof(builder, &pairing_precomp_circuit_data); + let pt_pp2 = verify_proof(builder, &pairing_precomp_circuit_data); + let pt_ml1 = verify_proof(builder, &miller_loop_circuit_data); + let pt_ml2 = verify_proof(builder, &miller_loop_circuit_data); + let pt_fp12m = verify_proof(builder, &fp12_mul_circuit_data); + let pt_fe = verify_proof(builder, &final_exponentiation_circuit_data); + let pubkey_g1 = get_g1_from_miller_loop(&pt_ml1); + let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); + assert_pk_ne_not_generator(builder, pubkey_g1); + + let signature_g2 = get_g2_point_from_pairing_precomp(builder, &pt_pp2); + signature_point_check(builder, &signature_g2, &input.sig); + let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); + assert_g1_or_g2_point_at_infinity( + builder, + is_g1_point_is_at_infinity, + is_g2_point_is_at_infinity, + ); + + let one = builder.one(); + let zero = builder.zero(); + + let mut is_valid_signature = builder.is_equal( + pt_fe.public_inputs[final_exponentiate::PIS_OUTPUT_OFFSET], + one, + ); + + for i in 1..24 * 3 * 2 { + let is_valid_signature_i = builder.is_equal( + pt_fe.public_inputs[final_exponentiate::PIS_OUTPUT_OFFSET + i], + zero, + ); + + is_valid_signature = builder.and(is_valid_signature, is_valid_signature_i); + } + + Self::Target { + pubkey: input.pubkey, + sig: input.sig, + msg: input.msg, + is_valid_signature, + pt_pp1, + pt_pp2, + pt_ml1, + pt_ml2, + pt_fp12m, + pt_fe, + } + } +} + +fn assert_pk_ne_not_generator(builder: &mut CircuitBuilder, public_key_point: PointG1Target) { + let get_neg_generator = get_neg_generator(builder); + + let is_pk_point_x_eq_not_generator_x = + is_equal(builder, &public_key_point[0], &get_neg_generator[0]); + let is_pk_point_y_eq_not_generator_y = + is_equal(builder, &public_key_point[1], &get_neg_generator[1]); + let pk_point_eq_not_generator = builder.and( + is_pk_point_x_eq_not_generator_x, + is_pk_point_y_eq_not_generator_y, + ); + builder.assert_false(pk_point_eq_not_generator) +} + +fn assert_g1_or_g2_point_at_infinity( + builder: &mut CircuitBuilder, + is_g1_at_infinity: BoolTarget, + is_g2_at_infinity: BoolTarget, +) -> BoolTarget { + builder.or(is_g1_at_infinity, is_g2_at_infinity) +} + +fn is_g1_point_is_at_infinity( + builder: &mut CircuitBuilder, + g1_point: &PointG1Target, +) -> BoolTarget { + let is_g1_x_zero = is_fp_zero(builder, &g1_point[0]); + let is_g1_y_zero = is_fp_zero(builder, &g1_point[1]); + builder.and(is_g1_x_zero, is_g1_y_zero) +} + +fn is_g2_point_is_at_infinity( + builder: &mut CircuitBuilder, + g2_point: &PointG2Target, +) -> BoolTarget { + let is_g2_x_zero = is_zero(builder, &g2_point[0]); + let is_g2_y_zero = is_zero(builder, &g2_point[1]); + builder.and(is_g2_x_zero, is_g2_y_zero) +} + +fn is_fp_zero(builder: &mut CircuitBuilder, input: &FpTarget) -> BoolTarget { + let zero = builder.zero_biguint(); + builder.cmp_biguint(input, &zero) +} +#[cfg(test)] +pub mod tests { + use std::{fs, marker::PhantomData}; + + use anyhow::Result; + use circuit::Circuit; + use plonky2::{ + iop::witness::PartialWitness, + plonk::{ + circuit_builder::CircuitBuilder, + circuit_data::{CircuitConfig, CircuitData}, + config::{GenericConfig, PoseidonGoldilocksConfig}, + }, + }; + use plonky2_circuit_serializer::serializer::{CustomGateSerializer, CustomGeneratorSerializer}; + + use crate::bls_verification::bls12_381_circuit::BLSVerificationCircuit; + + type F = >::F; + type C = PoseidonGoldilocksConfig; + const D: usize = 2; + const SERIALIZED_CIRCUITS_DIR: &str = "../circuit_executables/serialized_circuits"; + + fn read_from_file(file_path: &str) -> Result> { + let data = fs::read(file_path)?; + Ok(data) + } + + fn load_circuit_data_starky(file_name: &str) -> CircuitData { + let circuit_data_bytes = read_from_file(&format!("{file_name}.plonky2_circuit")).unwrap(); + + CircuitData::::from_bytes( + &circuit_data_bytes, + &CustomGateSerializer, + &CustomGeneratorSerializer { + _phantom: PhantomData::, + }, + ) + .unwrap() + } + + #[test] + fn test_bls12_381_circuit() -> std::result::Result<(), anyhow::Error> { + let standard_recursion_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(standard_recursion_config); + + let pairing_precomp_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); + let miller_loop_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); + let fp12_mul_circuit_data = + load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); + let final_exponentiate_circuit_data = load_circuit_data_starky(&format!( + "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" + )); + + let params = ( + pairing_precomp_circuit_data, + miller_loop_circuit_data, + fp12_mul_circuit_data, + final_exponentiate_circuit_data, + ); + + BLSVerificationCircuit::define(&mut builder, ¶ms); + + let pw = PartialWitness::new(); + let data = builder.build::(); + let proof = data.prove(pw)?; + + data.verify(proof) + } +} diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index 5ff869241..edcba09bc 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; +use circuit::Circuit; use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; use num_bigint::BigUint; use plonky2::{ @@ -20,8 +20,6 @@ use plonky2_crypto::{ }; use starky_bls12_381::{ calc_pairing_precomp, final_exponentiate, fp12_mul, - fp2_plonky2::is_zero, - fp_plonky2::FpTarget, g1_plonky2::{pk_point_check, PointG1Target}, g2_plonky2::{signature_point_check, PointG2Target}, hash_to_curve::hash_to_curve, @@ -104,16 +102,9 @@ impl Circuit for BLSVerificationCircuit { let pubkey_g1 = get_g1_from_miller_loop(&pt_ml1); pk_point_check(builder, &pubkey_g1, &input.pubkey); - let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); let signature_g2 = get_g2_point_from_pairing_precomp(builder, &pt_pp2); signature_point_check(builder, &signature_g2, &input.sig); - let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); - assert_g1_or_g2_point_at_infinity( - builder, - is_g1_point_is_at_infinity, - is_g2_point_is_at_infinity, - ); connect_pairing_precomp_with_miller_loop_g2(builder, &pt_pp2, &pt_ml2); @@ -157,20 +148,7 @@ impl Circuit for BLSVerificationCircuit { } } -fn connect_fp12_mull_with_final_exponentiation, const D: usize>( - builder: &mut CircuitBuilder, - pt_fp12m: &ProofWithPublicInputsTarget, - pt_fe: &ProofWithPublicInputsTarget, -) { - for i in 0..24 * 3 * 2 { - builder.connect( - pt_fp12m.public_inputs[fp12_mul::PIS_OUTPUT_OFFSET + i], - pt_fe.public_inputs[final_exponentiate::PIS_INPUT_OFFSET + i], - ); - } -} - -fn get_neg_generator, const D: usize>( +pub fn get_neg_generator, const D: usize>( builder: &mut CircuitBuilder, ) -> PointG1Target { let neg_generator_x = builder.constant_biguint(&BigUint::from_str("3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507").unwrap()); @@ -179,7 +157,7 @@ fn get_neg_generator, const D: usize>( [neg_generator_x, neg_generator_y] } -fn get_g2_point_from_pairing_precomp, const D: usize>( +pub fn get_g2_point_from_pairing_precomp, const D: usize>( builder: &mut CircuitBuilder, pt_pp2: &ProofWithPublicInputsTarget, ) -> PointG2Target { @@ -239,6 +217,41 @@ fn get_g2_point_from_pairing_precomp, const D: usiz [[sig_point_x0, sig_point_x1], [sig_point_y0, sig_point_y1]] } +pub fn get_g1_from_miller_loop(pt_ml1: &ProofWithPublicInputsTarget) -> PointG1Target { + let g1_x = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| { + U32Target(pt_ml1.public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i]) + }) + .collect(), + }; + + let g1_y = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| { + U32Target(pt_ml1.public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i]) + }) + .collect(), + }; + + [g1_x, g1_y] +} + +fn connect_fp12_mull_with_final_exponentiation, const D: usize>( + builder: &mut CircuitBuilder, + pt_fp12m: &ProofWithPublicInputsTarget, + pt_fe: &ProofWithPublicInputsTarget, +) { + for i in 0..24 * 3 * 2 { + builder.connect( + pt_fp12m.public_inputs[fp12_mul::PIS_OUTPUT_OFFSET + i], + pt_fe.public_inputs[final_exponentiate::PIS_INPUT_OFFSET + i], + ); + } +} + fn connect_miller_loop_with_fp12_mul, const D: usize>( builder: &mut CircuitBuilder, pt_ml1: &ProofWithPublicInputsTarget, @@ -278,28 +291,6 @@ fn connect_miller_loop_with_g1, const D: usize>( } } -fn get_g1_from_miller_loop(pt_ml1: &ProofWithPublicInputsTarget) -> PointG1Target { - let g1_x = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| { - U32Target(pt_ml1.public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i]) - }) - .collect(), - }; - - let g1_y = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| { - U32Target(pt_ml1.public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i]) - }) - .collect(), - }; - - [g1_x, g1_y] -} - fn connect_pairing_precomp_with_miller_loop_g2, const D: usize>( builder: &mut CircuitBuilder, pt_pp1: &plonky2::plonk::proof::ProofWithPublicInputsTarget, @@ -355,110 +346,3 @@ fn connect_pairing_precomp_with_g2, const D: usize> } } } - -fn assert_g1_or_g2_point_at_infinity( - builder: &mut CircuitBuilder, - is_g1_at_infinity: BoolTarget, - is_g2_at_infinity: BoolTarget, -) -> BoolTarget { - builder.or(is_g1_at_infinity, is_g2_at_infinity) -} - -fn is_g1_point_is_at_infinity( - builder: &mut CircuitBuilder, - g1_point: &PointG1Target, -) -> BoolTarget { - let is_g1_x_zero = is_fp_zero(builder, &g1_point[0]); - let is_g1_y_zero = is_fp_zero(builder, &g1_point[1]); - builder.and(is_g1_x_zero, is_g1_y_zero) -} - -fn is_g2_point_is_at_infinity( - builder: &mut CircuitBuilder, - g2_point: &PointG2Target, -) -> BoolTarget { - let is_g2_x_zero = is_zero(builder, &g2_point[0]); - let is_g2_y_zero = is_zero(builder, &g2_point[1]); - builder.and(is_g2_x_zero, is_g2_y_zero) -} - -fn is_fp_zero, const D: usize>( - builder: &mut CircuitBuilder, - input: &FpTarget, -) -> BoolTarget { - let zero = builder.zero_biguint(); - builder.cmp_biguint(input, &zero) -} - -#[cfg(test)] -pub mod tests { - use std::{fs, marker::PhantomData}; - - use anyhow::Result; - use circuit::Circuit; - use plonky2::{ - iop::witness::PartialWitness, - plonk::{ - circuit_builder::CircuitBuilder, - circuit_data::{CircuitConfig, CircuitData}, - config::{GenericConfig, PoseidonGoldilocksConfig}, - }, - }; - use plonky2_circuit_serializer::serializer::{CustomGateSerializer, CustomGeneratorSerializer}; - - use super::BLSVerificationCircuit; - - type F = >::F; - type C = PoseidonGoldilocksConfig; - const D: usize = 2; - const SERIALIZED_CIRCUITS_DIR: &str = "../circuit_executables/serialized_circuits"; - - fn read_from_file(file_path: &str) -> Result> { - let data = fs::read(file_path)?; - Ok(data) - } - - fn load_circuit_data_starky(file_name: &str) -> CircuitData { - let circuit_data_bytes = read_from_file(&format!("{file_name}.plonky2_circuit")).unwrap(); - - CircuitData::::from_bytes( - &circuit_data_bytes, - &CustomGateSerializer, - &CustomGeneratorSerializer { - _phantom: PhantomData::, - }, - ) - .unwrap() - } - - #[test] - fn test_bls12_381_circuit() -> std::result::Result<(), anyhow::Error> { - let standard_recursion_config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(standard_recursion_config); - - let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); - let miller_loop_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - let fp12_mul_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - let final_exponentiate_circuit_data = load_circuit_data_starky(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )); - - let params = ( - pairing_precomp_circuit_data, - miller_loop_circuit_data, - fp12_mul_circuit_data, - final_exponentiate_circuit_data, - ); - - BLSVerificationCircuit::define(&mut builder, ¶ms); - - let pw = PartialWitness::new(); - let data = builder.build::(); - let proof = data.prove(pw)?; - - data.verify(proof) - } -} diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs index 83f92cfef..b8acdd050 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs @@ -1,2 +1,3 @@ +pub mod are_points_infinite_circuit; pub mod bls12_381_circuit; pub mod build_stark_proof_verifier; From f21c2ddf0c7dfd679878eb96e82c6933ffae12b4 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 12:59:04 +0300 Subject: [PATCH 23/37] Refactor bls12_381 and bls12_381_components_proofs based on changes performed on bls_components --- .../circuit_executables/bin/bls12_381.rs | 64 +++++----- .../bin/bls12_381_components_proofs.rs | 109 ++++++------------ .../circuit_executables/src/bls_components.rs | 105 +++++++++-------- 3 files changed, 113 insertions(+), 165 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381.rs b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381.rs index ddd7b6520..aa340e1d2 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381.rs @@ -1,6 +1,7 @@ use anyhow::Result; use circuit::SerdeCircuitTarget; use circuit_executables::{ + bls_components::{set_bls_witness, BlsComponents, BlsProofs, Input}, constants::SERIALIZED_CIRCUITS_DIR, crud::{ common::{load_circuit_data_starky, load_common_circuit_data_starky, read_from_file}, @@ -12,8 +13,8 @@ use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; use futures_lite::future; use plonky2::{ - field::{goldilocks_field::GoldilocksField, types::Field}, - iop::witness::{PartialWitness, WitnessWrite}, + field::goldilocks_field::GoldilocksField, + iop::witness::PartialWitness, plonk::{config::PoseidonGoldilocksConfig, proof::ProofWithPublicInputs}, util::serialization::Buffer, }; @@ -41,44 +42,33 @@ async fn async_main() -> Result<()> { let mut proof_storage = create_proof_storage(&matches).await; - let mut pw = PartialWitness::::new(); - - pw.set_target_arr( - &targets.pubkey, - &hex::decode(pubkey) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.sig, - &hex::decode(signature) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.msg, - &hex::decode(msg) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), - ); - - let (pp1, pp2) = get_pairing_precomp_proofs(&mut proof_storage).await; - let (ml1, ml2) = get_miller_loop_proofs(&mut proof_storage).await; + let (pairing_prec_proof1, pairing_prec_proof2) = + get_pairing_precomp_proofs(&mut proof_storage).await; + let (miller_loop_proof1, miller_loop_proof2) = get_miller_loop_proofs(&mut proof_storage).await; let fp12_mul_proof = get_fp12_mul_proof(&mut proof_storage).await; let final_exp_proof = get_final_exp_proof(&mut proof_storage).await; - pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); - pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); - pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); - pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); - pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); - pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); + let mut pw = PartialWitness::::new(); + set_bls_witness( + &mut pw, + &targets, + &BlsComponents { + input: Input { + pubkey: pubkey.to_string(), + signature: signature.to_string(), + message: msg.to_string(), + }, + output: true, + }, + &BlsProofs { + pairing_prec_proof1, + pairing_prec_proof2, + miller_loop_proof2, + miller_loop_proof1, + fp12_mul_proof, + final_exp_proof, + }, + ); println!("Starting proof generation"); diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs index 6e69d2c0f..e99bf0734 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/bin/bls12_381_components_proofs.rs @@ -1,12 +1,13 @@ use anyhow::Result; use ark_bls12_381::{G1Affine, G1Projective, G2Affine}; -use ark_ec::Group; +use ark_ec::{CurveGroup, Group}; use ark_serialize::CanonicalDeserialize; use circuit::SerdeCircuitTarget; use circuit_executables::{ bls_components::{ - convert_ecp2_to_g2affine, handle_final_exponentiation, handle_fp12_mul, handle_miller_loop, - handle_pairing_precomp, + compute_native_miller_loop_from, convert_ecp2_to_g2affine, handle_final_exponentiation, + handle_fp12_mul, handle_miller_loop, handle_pairing_precomp, set_bls_witness, + BlsComponents, BlsProofs, Input, }, constants::SERIALIZED_CIRCUITS_DIR, crud::{ @@ -17,15 +18,12 @@ use circuit_executables::{ }; use circuits::bls_verification::bls12_381_circuit::BlsCircuitTargets; use futures_lite::future; -use num_bigint::BigUint; use plonky2::{ - field::{goldilocks_field::GoldilocksField, types::Field}, - iop::witness::{PartialWitness, WitnessWrite}, + field::goldilocks_field::GoldilocksField, iop::witness::PartialWitness, util::serialization::Buffer, }; use snowbridge_amcl::bls381::bls381::utils::hash_to_curve_g2; -use starky_bls12_381::native::{miller_loop, Fp, Fp2}; -use std::{ops::Neg, str::FromStr}; +use std::ops::Neg; async fn async_main() -> Result<()> { let matches = CommandLineOptionsBuilder::new("bls12_381_components_proofs") @@ -36,9 +34,10 @@ async fn async_main() -> Result<()> { let signature = "b735d0d0b03f51fcf3e5bc510b5a2cb266075322f5761a6954778714f5ab8831bc99454380d330f5c19d93436f0c4339041bfeecd2161a122c1ce8428033db8dda142768a48e582f5f9bde7d40768ac5a3b6a80492b73719f1523c5da35de275"; let msg = "5bb03392c9c8a8b92c840338f619bb060b109b254c9ab75d4dddc6d00932bce3"; - let message_g2 = hash_to_curve_g2(&hex::decode(msg).unwrap(), DST.as_bytes()); - let message_g2 = convert_ecp2_to_g2affine(message_g2); - + let message_g2 = convert_ecp2_to_g2affine(hash_to_curve_g2( + &hex::decode(&msg).unwrap(), + DST.as_bytes(), + )); let pubkey_g1 = G1Affine::deserialize_compressed_unchecked(&*hex::decode(pubkey).unwrap()).unwrap(); let signature_g2 = @@ -46,47 +45,18 @@ async fn async_main() -> Result<()> { let g1 = G1Projective::generator(); let neg_g1 = g1.neg(); - let miller_loop1 = miller_loop( - Fp::get_fp_from_biguint(pubkey_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(pubkey_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(message_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(message_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(message_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop1 = compute_native_miller_loop_from(pubkey_g1, message_g2); - let miller_loop2 = miller_loop( - Fp::get_fp_from_biguint(neg_g1.x.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(neg_g1.y.to_string().parse::().unwrap()), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.x.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.x.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(signature_g2.y.c0.to_string().parse::().unwrap()), - Fp::get_fp_from_biguint(signature_g2.y.c1.to_string().parse::().unwrap()), - ]), - Fp2([ - Fp::get_fp_from_biguint(BigUint::from_str("1").unwrap()), - Fp::get_fp_from_biguint(BigUint::from_str("0").unwrap()), - ]), - ); + let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); let fp12_mull = miller_loop1 * miller_loop2; // PROVING HAPPENS HERE let mut proof_storage = create_proof_storage(&matches).await; - let (pp1, pp2) = handle_pairing_precomp(&message_g2, &signature_g2).await; + let (pairing_prec_proof1, pairing_prec_proof2) = + handle_pairing_precomp(&message_g2, &signature_g2).await; - let (ml1, ml2) = + let (miller_loop_proof1, miller_loop_proof2) = handle_miller_loop(&pubkey_g1, &message_g2, &neg_g1.into(), &signature_g2).await; let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; @@ -103,37 +73,26 @@ async fn async_main() -> Result<()> { let targets = BlsCircuitTargets::deserialize(&mut target_buffer).unwrap(); let mut pw = PartialWitness::::new(); - pw.set_target_arr( - &targets.pubkey, - &hex::decode(pubkey) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), + set_bls_witness( + &mut pw, + &targets, + &BlsComponents { + input: Input { + pubkey: pubkey.to_string(), + signature: signature.to_string(), + message: msg.to_string(), + }, + output: true, + }, + &BlsProofs { + pairing_prec_proof1, + pairing_prec_proof2, + miller_loop_proof2, + miller_loop_proof1, + fp12_mul_proof, + final_exp_proof, + }, ); - pw.set_target_arr( - &targets.sig, - &hex::decode(signature) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.msg, - &hex::decode(msg) - .unwrap() - .iter() - .map(|x| GoldilocksField::from_canonical_usize(*x as usize)) - .collect::>(), - ); - - pw.set_proof_with_pis_target(&targets.pt_pp1, &pp1); - pw.set_proof_with_pis_target(&targets.pt_pp2, &pp2); - pw.set_proof_with_pis_target(&targets.pt_ml1, &ml1); - pw.set_proof_with_pis_target(&targets.pt_ml2, &ml2); - pw.set_proof_with_pis_target(&targets.pt_fp12m, &fp12_mul_proof); - pw.set_proof_with_pis_target(&targets.pt_fe, &final_exp_proof); println!("Starting proof generation"); diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 492d00972..99907fcfb 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -48,8 +48,8 @@ pub struct BlsComponents { pub struct BlsProofs { pub pairing_prec_proof1: ProofWithPublicInputs, pub pairing_prec_proof2: ProofWithPublicInputs, - pub miller_loop_proof1: ProofWithPublicInputs, pub miller_loop_proof2: ProofWithPublicInputs, + pub miller_loop_proof1: ProofWithPublicInputs, pub fp12_mul_proof: ProofWithPublicInputs, pub final_exp_proof: ProofWithPublicInputs, } @@ -62,54 +62,6 @@ impl BlsComponents { } } -pub fn read_yaml_file>( - path: P, -) -> Result> { - let file_content = fs::read_to_string(path)?; - let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; - components.remove_first_two_chars(); - Ok(components) -} - -pub fn set_bls_witness( - pw: &mut PartialWitness, - targets: &BlsCircuitTargets, - components: &BlsComponents, - proofs: &BlsProofs, -) { - pw.set_target_arr( - &targets.pubkey, - &hex::decode(&components.input.pubkey) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.sig, - &hex::decode(&components.input.signature) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - pw.set_target_arr( - &targets.msg, - &hex::decode(&components.input.message) - .unwrap() - .iter() - .map(|x| F::from_canonical_usize(*x as usize)) - .collect::>(), - ); - - pw.set_proof_with_pis_target(&targets.pt_pp1, &proofs.pairing_prec_proof1); - pw.set_proof_with_pis_target(&targets.pt_pp2, &proofs.pairing_prec_proof2); - pw.set_proof_with_pis_target(&targets.pt_ml1, &proofs.miller_loop_proof1); - pw.set_proof_with_pis_target(&targets.pt_ml2, &proofs.miller_loop_proof2); - pw.set_proof_with_pis_target(&targets.pt_fp12m, &proofs.fp12_mul_proof); - pw.set_proof_with_pis_target(&targets.pt_fe, &proofs.final_exp_proof); -} - pub async fn bls12_381_components_proofs( components: &BlsComponents, ) -> Result> { @@ -267,6 +219,54 @@ pub async fn handle_pairing_precomp( (pp1, pp2) } +pub fn read_yaml_file>( + path: P, +) -> Result> { + let file_content = fs::read_to_string(path)?; + let mut components: BlsComponents = serde_yaml::from_str(&file_content)?; + components.remove_first_two_chars(); + Ok(components) +} + +pub fn set_bls_witness( + pw: &mut PartialWitness, + targets: &BlsCircuitTargets, + components: &BlsComponents, + proofs: &BlsProofs, +) { + pw.set_target_arr( + &targets.pubkey, + &hex::decode(&components.input.pubkey) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.sig, + &hex::decode(&components.input.signature) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + pw.set_target_arr( + &targets.msg, + &hex::decode(&components.input.message) + .unwrap() + .iter() + .map(|x| F::from_canonical_usize(*x as usize)) + .collect::>(), + ); + + pw.set_proof_with_pis_target(&targets.pt_pp1, &proofs.pairing_prec_proof1); + pw.set_proof_with_pis_target(&targets.pt_pp2, &proofs.pairing_prec_proof2); + pw.set_proof_with_pis_target(&targets.pt_ml1, &proofs.miller_loop_proof1); + pw.set_proof_with_pis_target(&targets.pt_ml2, &proofs.miller_loop_proof2); + pw.set_proof_with_pis_target(&targets.pt_fp12m, &proofs.fp12_mul_proof); + pw.set_proof_with_pis_target(&targets.pt_fe, &proofs.final_exp_proof); +} + pub fn compute_native_miller_loop_from( g1_affine_point: G1Affine, g2_affine_point: G2Affine, @@ -330,11 +330,10 @@ pub mod tests { panic!("Expected a file path as argument"); } - let file_path = &args[3]; - let x = format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path); - println!("file path is: {:?}", x); + let current_file_path = format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, &args[3]); + println!("current file path is: {:?}", ¤t_file_path); let bls_components = - read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, file_path)).unwrap(); + read_yaml_file(format!("{}/{}", PATH_TO_VERIFY_ETH_TEST_CASES, &args[3])).unwrap(); let standard_recursion_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(standard_recursion_config); From 1c9f33b2f18d3f22c8d73173f8e5807108c16613 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 14:10:26 +0300 Subject: [PATCH 24/37] Refactor test_bls12_381_circuit in VerifyIsNotAtInfinityCircuit --- .../src/bls_verification/are_points_infinite_circuit.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs index e0d974bca..49fd870c1 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs @@ -213,12 +213,10 @@ pub mod tests { final_exponentiate_circuit_data, ); - BLSVerificationCircuit::define(&mut builder, ¶ms); - + let (targets, circuit) = BLSVerificationCircuit::build(¶ms); let pw = PartialWitness::new(); - let data = builder.build::(); - let proof = data.prove(pw)?; + let proof = circuit.prove(pw).unwrap(); - data.verify(proof) + circuit.verify(proof) } } From 467d8f43b7a235d268055849cf7bacd41e725fa8 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 14:43:21 +0300 Subject: [PATCH 25/37] Improve test_bls12_381_circuit --- .../src/bls_verification/are_points_infinite_circuit.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs index 49fd870c1..7b79ceb22 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs @@ -159,8 +159,7 @@ pub mod tests { use plonky2::{ iop::witness::PartialWitness, plonk::{ - circuit_builder::CircuitBuilder, - circuit_data::{CircuitConfig, CircuitData}, + circuit_data::CircuitData, config::{GenericConfig, PoseidonGoldilocksConfig}, }, }; @@ -193,9 +192,6 @@ pub mod tests { #[test] fn test_bls12_381_circuit() -> std::result::Result<(), anyhow::Error> { - let standard_recursion_config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(standard_recursion_config); - let pairing_precomp_circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); let miller_loop_circuit_data = @@ -213,7 +209,7 @@ pub mod tests { final_exponentiate_circuit_data, ); - let (targets, circuit) = BLSVerificationCircuit::build(¶ms); + let (_, circuit) = BLSVerificationCircuit::build(¶ms); let pw = PartialWitness::new(); let proof = circuit.prove(pw).unwrap(); From 7dde05cfd24e2fa1ef1a88295960905069474979 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 15:56:02 +0300 Subject: [PATCH 26/37] Remove verification of proofs in `VerifyIsNotAtInfinityCircuit` since we will only use the public inputs of second miller loop and first pariing precompile --- .../are_points_infinite_circuit.rs | 202 +++++++++++------- .../src/bls_verification/bls12_381_circuit.rs | 2 +- 2 files changed, 129 insertions(+), 75 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs index 7b79ceb22..c018b81c0 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs @@ -1,28 +1,27 @@ +use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; use plonky2::{ - iop::target::BoolTarget, + iop::target::{BoolTarget, Target}, plonk::{ circuit_builder::CircuitBuilder, - circuit_data::{CircuitConfig, CircuitData}, + circuit_data::CircuitConfig, config::{GenericConfig, PoseidonGoldilocksConfig}, }, }; -use plonky2_crypto::biguint::CircuitBuilderBiguint; +use plonky2_crypto::{ + biguint::{BigUintTarget, CircuitBuilderBiguint}, + u32::arithmetic_u32::U32Target, +}; use starky_bls12_381::{ - final_exponentiate, + calc_pairing_precomp, fp2_plonky2::is_zero, fp_plonky2::{is_equal, FpTarget}, g1_plonky2::PointG1Target, - g2_plonky2::{signature_point_check, PointG2Target}, + g2_plonky2::PointG2Target, }; use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; -use crate::utils::circuit::verify_proof; - -use super::bls12_381_circuit::{ - get_g1_from_miller_loop, get_g2_point_from_pairing_precomp, get_neg_generator, - BlsCircuitTargets, -}; +use super::bls12_381_circuit::{get_neg_generator, N}; type F = >::F; type C = PoseidonGoldilocksConfig; @@ -30,43 +29,42 @@ const D: usize = 2; pub struct VerifyIsNotAtInfinityCircuit; +#[derive(CircuitTarget, SerdeCircuitTarget)] +pub struct VerifyIsNotAtInfinityCircuitTargets { + // Pub inputs + #[target(in, out)] + pub pubkey: [Target; 48], + + #[target(in, out)] + pub sig: [Target; 96], + + #[target(out)] + pub is_at_infinity: BoolTarget, +} + impl Circuit for VerifyIsNotAtInfinityCircuit { type F = F; type C = C; const D: usize = D; const CIRCUIT_CONFIG: CircuitConfig = CircuitConfig::standard_recursion_config(); - type Target = BlsCircuitTargets; + type Target = VerifyIsNotAtInfinityCircuitTargets; - type Params = ( - CircuitData, - CircuitData, - CircuitData, - CircuitData, - ); + type Params = ([Target; 48], [Target; 96]); fn define( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, - ( - pairing_precomp_circuit_data, - miller_loop_circuit_data, - fp12_mul_circuit_data, - final_exponentiation_circuit_data, - ): &Self::Params, + params: &Self::Params, ) -> Self::Target { let input = Self::read_circuit_input_target(builder); - let pt_pp1 = verify_proof(builder, &pairing_precomp_circuit_data); - let pt_pp2 = verify_proof(builder, &pairing_precomp_circuit_data); - let pt_ml1 = verify_proof(builder, &miller_loop_circuit_data); - let pt_ml2 = verify_proof(builder, &miller_loop_circuit_data); - let pt_fp12m = verify_proof(builder, &fp12_mul_circuit_data); - let pt_fe = verify_proof(builder, &final_exponentiation_circuit_data); - let pubkey_g1 = get_g1_from_miller_loop(&pt_ml1); - let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); - assert_pk_ne_not_generator(builder, pubkey_g1); + let pubkey = params.0; + let signature = params.1; - let signature_g2 = get_g2_point_from_pairing_precomp(builder, &pt_pp2); - signature_point_check(builder, &signature_g2, &input.sig); + let pubkey_g1 = get_g1_point_from_public_inputs(&pubkey); + assert_pk_ne_not_generator(builder, pubkey_g1.to_owned()); + + let signature_g2 = get_g2_point_from_public_inputs(builder, &signature); + let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); assert_g1_or_g2_point_at_infinity( builder, @@ -74,34 +72,10 @@ impl Circuit for VerifyIsNotAtInfinityCircuit { is_g2_point_is_at_infinity, ); - let one = builder.one(); - let zero = builder.zero(); - - let mut is_valid_signature = builder.is_equal( - pt_fe.public_inputs[final_exponentiate::PIS_OUTPUT_OFFSET], - one, - ); - - for i in 1..24 * 3 * 2 { - let is_valid_signature_i = builder.is_equal( - pt_fe.public_inputs[final_exponentiate::PIS_OUTPUT_OFFSET + i], - zero, - ); - - is_valid_signature = builder.and(is_valid_signature, is_valid_signature_i); - } - Self::Target { pubkey: input.pubkey, sig: input.sig, - msg: input.msg, - is_valid_signature, - pt_pp1, - pt_pp2, - pt_ml1, - pt_ml2, - pt_fp12m, - pt_fe, + is_at_infinity: builder._false(), } } } @@ -150,6 +124,77 @@ fn is_fp_zero(builder: &mut CircuitBuilder, input: &FpTarget) -> BoolTarge let zero = builder.zero_biguint(); builder.cmp_biguint(input, &zero) } + +fn get_g1_point_from_public_inputs(public_inputs: &[Target; 48]) -> PointG1Target { + let g1_x = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + + let g1_y = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + + [g1_x, g1_y] +} + +fn get_g2_point_from_public_inputs( + builder: &mut CircuitBuilder, + public_inputs: &[Target; 96], +) -> PointG2Target { + let sig_point_x0 = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + let sig_point_x1 = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + let sig_point_y0 = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::Y0_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + let sig_point_y1 = BigUintTarget { + limbs: (0..N) + .into_iter() + .map(|i| U32Target(public_inputs[calc_pairing_precomp::Y1_PUBLIC_INPUTS_OFFSET + i])) + .collect(), + }; + + let zero = builder.zero(); + let one = builder.one(); + for i in 0..N { + if i == 0 { + builder.connect( + public_inputs[calc_pairing_precomp::Z0_PUBLIC_INPUTS_OFFSET + i], + one, + ); + } else { + builder.connect( + public_inputs[calc_pairing_precomp::Z0_PUBLIC_INPUTS_OFFSET + i], + zero, + ); + } + builder.connect( + public_inputs[calc_pairing_precomp::Z1_PUBLIC_INPUTS_OFFSET + i], + zero, + ); + } + + [[sig_point_x0, sig_point_x1], [sig_point_y0, sig_point_y1]] +} + #[cfg(test)] pub mod tests { use std::{fs, marker::PhantomData}; @@ -157,7 +202,7 @@ pub mod tests { use anyhow::Result; use circuit::Circuit; use plonky2::{ - iop::witness::PartialWitness, + iop::{target::Target, witness::PartialWitness}, plonk::{ circuit_data::CircuitData, config::{GenericConfig, PoseidonGoldilocksConfig}, @@ -165,7 +210,7 @@ pub mod tests { }; use plonky2_circuit_serializer::serializer::{CustomGateSerializer, CustomGeneratorSerializer}; - use crate::bls_verification::bls12_381_circuit::BLSVerificationCircuit; + use super::VerifyIsNotAtInfinityCircuit; type F = >::F; type C = PoseidonGoldilocksConfig; @@ -196,20 +241,29 @@ pub mod tests { load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); let miller_loop_circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - let fp12_mul_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/fp12_mul")); - let final_exponentiate_circuit_data = load_circuit_data_starky(&format!( - "{SERIALIZED_CIRCUITS_DIR}/final_exponentiate_circuit" - )); - let params = ( - pairing_precomp_circuit_data, - miller_loop_circuit_data, - fp12_mul_circuit_data, - final_exponentiate_circuit_data, - ); + let params = (pairing_precomp_circuit_data, miller_loop_circuit_data); + let pairing_precomp_public_inputs: [Target; 48] = params + .0 + .prover_only + .public_inputs + .into_iter() + .collect::>() + .try_into() + .unwrap(); + let miller_loop_public_inputs: [Target; 96] = params + .1 + .prover_only + .public_inputs + .into_iter() + .collect::>() + .try_into() + .unwrap(); - let (_, circuit) = BLSVerificationCircuit::build(¶ms); + let (_, circuit) = VerifyIsNotAtInfinityCircuit::build(&( + pairing_precomp_public_inputs, + miller_loop_public_inputs, + )); let pw = PartialWitness::new(); let proof = circuit.prove(pw).unwrap(); diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs index edcba09bc..28a69ebfb 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/bls12_381_circuit.rs @@ -28,7 +28,7 @@ use starky_bls12_381::{ use crate::utils::circuit::verify_proof; -const N: usize = 12; +pub const N: usize = 12; #[derive(CircuitTarget, SerdeCircuitTarget)] pub struct BlsCircuitTargets { From 7fceb12225bd5c590326a0d14ef11f1cb00bba2e Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 16:03:44 +0300 Subject: [PATCH 27/37] Fix error in test_bls12_381_circuit --- .../src/bls_verification/are_points_infinite_circuit.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs index c018b81c0..561703f67 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs @@ -242,8 +242,8 @@ pub mod tests { let miller_loop_circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - let params = (pairing_precomp_circuit_data, miller_loop_circuit_data); - let pairing_precomp_public_inputs: [Target; 48] = params + let params = (miller_loop_circuit_data, pairing_precomp_circuit_data); + let miller_loop_public_inputs: [Target; 48] = params .0 .prover_only .public_inputs @@ -251,7 +251,7 @@ pub mod tests { .collect::>() .try_into() .unwrap(); - let miller_loop_public_inputs: [Target; 96] = params + let pairing_precomp_public_inputs: [Target; 96] = params .1 .prover_only .public_inputs @@ -261,8 +261,8 @@ pub mod tests { .unwrap(); let (_, circuit) = VerifyIsNotAtInfinityCircuit::build(&( - pairing_precomp_public_inputs, miller_loop_public_inputs, + pairing_precomp_public_inputs, )); let pw = PartialWitness::new(); let proof = circuit.prove(pw).unwrap(); From a31af6415974a0594e3fe3047f1b917facd35f44 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 10 Jun 2024 19:07:45 +0300 Subject: [PATCH 28/37] Refactor VerifyIsNotAtInfinityCircuit but tests are not failling as expected --- .../circuit_executables/src/bls_components.rs | 4 +- .../circuits/src/bls_verification/mod.rs | 2 +- ...s => verify_is_not_at_infinity_circuit.rs} | 160 +++++++++--------- 3 files changed, 81 insertions(+), 85 deletions(-) rename beacon-light-client/plonky2/crates/circuits/src/bls_verification/{are_points_infinite_circuit.rs => verify_is_not_at_infinity_circuit.rs} (63%) diff --git a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs index 99907fcfb..a21302d87 100644 --- a/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs +++ b/beacon-light-client/plonky2/crates/circuit_executables/src/bls_components.rs @@ -83,7 +83,7 @@ pub async fn bls12_381_components_proofs( let miller_loop2 = compute_native_miller_loop_from(neg_g1.into_affine(), signature_g2); - let fp12_mull = miller_loop1 * miller_loop2; + let fp12_mul = miller_loop1 * miller_loop2; // PROVING HAPPENS HERE let (pairing_prec_proof1, pairing_prec_proof2) = @@ -94,7 +94,7 @@ pub async fn bls12_381_components_proofs( let fp12_mul_proof = handle_fp12_mul(&miller_loop1, &miller_loop2).await; - let final_exp_proof = handle_final_exponentiation(&fp12_mull).await; + let final_exp_proof = handle_final_exponentiation(&fp12_mul).await; let circuit_data = load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/bls12_381")); let target_bytes = read_from_file(&format!( diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs index b8acdd050..05eed362c 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/mod.rs @@ -1,3 +1,3 @@ -pub mod are_points_infinite_circuit; pub mod bls12_381_circuit; pub mod build_stark_proof_verifier; +pub mod verify_is_not_at_infinity_circuit; diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs similarity index 63% rename from beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs rename to beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs index 561703f67..12a4d0f7c 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/are_points_infinite_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs @@ -1,4 +1,7 @@ -use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; +use circuit_derive::{ + AddVirtualTarget, CircuitTarget, PublicInputsReadable, SerdeCircuitTarget, SetWitness, + TargetPrimitive, +}; use plonky2::{ iop::target::{BoolTarget, Target}, plonk::{ @@ -21,6 +24,12 @@ use starky_bls12_381::{ use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; +use crate::{ + common_targets::{PubkeyTarget, SignatureTarget}, + serializers::serde_bool_array_to_hex_string, + utils::circuit::bits_to_bytes_target, +}; + use super::bls12_381_circuit::{get_neg_generator, N}; type F = >::F; @@ -32,14 +41,24 @@ pub struct VerifyIsNotAtInfinityCircuit; #[derive(CircuitTarget, SerdeCircuitTarget)] pub struct VerifyIsNotAtInfinityCircuitTargets { // Pub inputs - #[target(in, out)] - pub pubkey: [Target; 48], - - #[target(in, out)] - pub sig: [Target; 96], + #[target(in)] + pub validator_credentials: ValidatorCredentials, +} - #[target(out)] - pub is_at_infinity: BoolTarget, +#[derive( + Clone, + Debug, + TargetPrimitive, + SetWitness, + PublicInputsReadable, + AddVirtualTarget, + SerdeCircuitTarget, +)] +pub struct ValidatorCredentials { + #[serde(with = "serde_bool_array_to_hex_string")] + pub pubkey: PubkeyTarget, + #[serde(with = "serde_bool_array_to_hex_string")] + pub signature: SignatureTarget, } impl Circuit for VerifyIsNotAtInfinityCircuit { @@ -50,32 +69,37 @@ impl Circuit for VerifyIsNotAtInfinityCircuit { const CIRCUIT_CONFIG: CircuitConfig = CircuitConfig::standard_recursion_config(); type Target = VerifyIsNotAtInfinityCircuitTargets; - type Params = ([Target; 48], [Target; 96]); - fn define( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, - params: &Self::Params, + _: &Self::Params, ) -> Self::Target { let input = Self::read_circuit_input_target(builder); - let pubkey = params.0; - let signature = params.1; + let pubkey = input.validator_credentials.pubkey; + let signature = input.validator_credentials.signature; + let pubkey = bits_to_bytes_target(builder, &pubkey); + let pubkey = pubkey.into_iter().collect::>().try_into().unwrap(); let pubkey_g1 = get_g1_point_from_public_inputs(&pubkey); assert_pk_ne_not_generator(builder, pubkey_g1.to_owned()); - + let signature = bits_to_bytes_target(builder, &signature); + let signature = signature + .into_iter() + .collect::>() + .try_into() + .unwrap(); let signature_g2 = get_g2_point_from_public_inputs(builder, &signature); let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); - assert_g1_or_g2_point_at_infinity( + assert_g1_or_g2_point_arent_at_infinity( builder, is_g1_point_is_at_infinity, is_g2_point_is_at_infinity, ); + let pubkey = input.validator_credentials.pubkey; + let signature = input.validator_credentials.signature; Self::Target { - pubkey: input.pubkey, - sig: input.sig, - is_at_infinity: builder._false(), + validator_credentials: ValidatorCredentials { pubkey, signature }, } } } @@ -94,12 +118,13 @@ fn assert_pk_ne_not_generator(builder: &mut CircuitBuilder, public_key_poi builder.assert_false(pk_point_eq_not_generator) } -fn assert_g1_or_g2_point_at_infinity( +fn assert_g1_or_g2_point_arent_at_infinity( builder: &mut CircuitBuilder, is_g1_at_infinity: BoolTarget, is_g2_at_infinity: BoolTarget, -) -> BoolTarget { - builder.or(is_g1_at_infinity, is_g2_at_infinity) +) { + let g1_or_g2_point_is_at_infinity = builder.or(is_g1_at_infinity, is_g2_at_infinity); + builder.assert_false(g1_or_g2_point_is_at_infinity); } fn is_g1_point_is_at_infinity( @@ -197,76 +222,47 @@ fn get_g2_point_from_public_inputs( #[cfg(test)] pub mod tests { - use std::{fs, marker::PhantomData}; - - use anyhow::Result; - use circuit::Circuit; - use plonky2::{ - iop::{target::Target, witness::PartialWitness}, - plonk::{ - circuit_data::CircuitData, - config::{GenericConfig, PoseidonGoldilocksConfig}, - }, - }; - use plonky2_circuit_serializer::serializer::{CustomGateSerializer, CustomGeneratorSerializer}; + use circuit::{Circuit, CircuitInput, SetWitness}; + use plonky2::iop::witness::PartialWitness; use super::VerifyIsNotAtInfinityCircuit; - type F = >::F; - type C = PoseidonGoldilocksConfig; - const D: usize = 2; - const SERIALIZED_CIRCUITS_DIR: &str = "../circuit_executables/serialized_circuits"; + #[test] + fn test_g1_or_g2_are_at_infinity() { + let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); + + let input = + serde_json::from_str::>(r#"{ + "validator_credentials": { + "pubkey": "b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", + "signature": "b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9" + } + }"#).unwrap(); - fn read_from_file(file_path: &str) -> Result> { - let data = fs::read(file_path)?; - Ok(data) - } + let mut pw = PartialWitness::new(); + targets.set_witness(&mut pw, &input); - fn load_circuit_data_starky(file_name: &str) -> CircuitData { - let circuit_data_bytes = read_from_file(&format!("{file_name}.plonky2_circuit")).unwrap(); - - CircuitData::::from_bytes( - &circuit_data_bytes, - &CustomGateSerializer, - &CustomGeneratorSerializer { - _phantom: PhantomData::, - }, - ) - .unwrap() + let proof = circuit.prove(pw).unwrap(); + let _ = circuit.verify(proof); } #[test] - fn test_bls12_381_circuit() -> std::result::Result<(), anyhow::Error> { - let pairing_precomp_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/pairing_precomp")); - let miller_loop_circuit_data = - load_circuit_data_starky(&format!("{SERIALIZED_CIRCUITS_DIR}/miller_loop")); - - let params = (miller_loop_circuit_data, pairing_precomp_circuit_data); - let miller_loop_public_inputs: [Target; 48] = params - .0 - .prover_only - .public_inputs - .into_iter() - .collect::>() - .try_into() - .unwrap(); - let pairing_precomp_public_inputs: [Target; 96] = params - .1 - .prover_only - .public_inputs - .into_iter() - .collect::>() - .try_into() - .unwrap(); + #[should_panic] + fn test_one_privkey() { + let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); - let (_, circuit) = VerifyIsNotAtInfinityCircuit::build(&( - miller_loop_public_inputs, - pairing_precomp_public_inputs, - )); - let pw = PartialWitness::new(); - let proof = circuit.prove(pw).unwrap(); + let input = + serde_json::from_str::>(r#"{ + "validator_credentials": { + "pubkey": "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", + "signature": "a42ae16f1c2a5fa69c04cb5998d2add790764ce8dd45bf25b29b4700829232052b52352dcff1cf255b3a7810ad7269601810f03b2bc8b68cf289cf295b206770605a190b6842583e47c3d1c0f73c54907bfb2a602157d46a4353a20283018763" + } + }"#).unwrap(); + + let mut pw = PartialWitness::new(); + targets.set_witness(&mut pw, &input); - circuit.verify(proof) + let proof = circuit.prove(pw).unwrap(); + let _ = circuit.verify(proof); } } From 815560026e16074c9c0866f493914980b2031785 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 11 Jun 2024 19:29:07 +0300 Subject: [PATCH 29/37] Refactor VerifyIsNotAtInfinityCircuit but test isn't successful --- beacon-light-client/plonky2/crates/Cargo.lock | 2 + .../plonky2/crates/circuits/Cargo.toml | 2 + .../verify_is_not_at_infinity_circuit.rs | 263 ++++++++---------- 3 files changed, 116 insertions(+), 151 deletions(-) diff --git a/beacon-light-client/plonky2/crates/Cargo.lock b/beacon-light-client/plonky2/crates/Cargo.lock index d7b915566..f33c44f84 100644 --- a/beacon-light-client/plonky2/crates/Cargo.lock +++ b/beacon-light-client/plonky2/crates/Cargo.lock @@ -1223,6 +1223,8 @@ version = "0.1.0" dependencies = [ "ahash 0.8.11", "anyhow", + "ark-bls12-381", + "ark-serialize", "circuit", "circuit_derive", "hex", diff --git a/beacon-light-client/plonky2/crates/circuits/Cargo.toml b/beacon-light-client/plonky2/crates/circuits/Cargo.toml index 3f238d5cc..045b9c3cf 100644 --- a/beacon-light-client/plonky2/crates/circuits/Cargo.toml +++ b/beacon-light-client/plonky2/crates/circuits/Cargo.toml @@ -27,6 +27,8 @@ starky_bls12_381 = { git = "https://github.com/metacraft-labs/starky_bls12_381" plonky2_crypto = { git = "https://github.com/metacraft-labs/plonky2-crypto" } plonky2-circuit-serializer = { git = "https://github.com/metacraft-labs/plonky2-circuit-serializer" } num-bigint = "0.4.4" +ark-bls12-381 = "0.4.0" +ark-serialize = "0.4.2" [dev-dependencies] serde_yaml = "0.9.34" diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs index 12a4d0f7c..01424a340 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs @@ -1,7 +1,4 @@ -use circuit_derive::{ - AddVirtualTarget, CircuitTarget, PublicInputsReadable, SerdeCircuitTarget, SetWitness, - TargetPrimitive, -}; +use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; use plonky2::{ iop::target::{BoolTarget, Target}, plonk::{ @@ -10,27 +7,17 @@ use plonky2::{ config::{GenericConfig, PoseidonGoldilocksConfig}, }, }; -use plonky2_crypto::{ - biguint::{BigUintTarget, CircuitBuilderBiguint}, - u32::arithmetic_u32::U32Target, -}; +use plonky2_crypto::biguint::{BigUintTarget, CircuitBuilderBiguint}; use starky_bls12_381::{ - calc_pairing_precomp, fp2_plonky2::is_zero, fp_plonky2::{is_equal, FpTarget}, - g1_plonky2::PointG1Target, - g2_plonky2::PointG2Target, + g1_plonky2::{pk_point_check, PointG1Target}, + g2_plonky2::{signature_point_check, PointG2Target}, }; use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; -use crate::{ - common_targets::{PubkeyTarget, SignatureTarget}, - serializers::serde_bool_array_to_hex_string, - utils::circuit::bits_to_bytes_target, -}; - -use super::bls12_381_circuit::{get_neg_generator, N}; +use super::bls12_381_circuit::get_neg_generator; type F = >::F; type C = PoseidonGoldilocksConfig; @@ -41,24 +28,18 @@ pub struct VerifyIsNotAtInfinityCircuit; #[derive(CircuitTarget, SerdeCircuitTarget)] pub struct VerifyIsNotAtInfinityCircuitTargets { // Pub inputs - #[target(in)] - pub validator_credentials: ValidatorCredentials, -} - -#[derive( - Clone, - Debug, - TargetPrimitive, - SetWitness, - PublicInputsReadable, - AddVirtualTarget, - SerdeCircuitTarget, -)] -pub struct ValidatorCredentials { - #[serde(with = "serde_bool_array_to_hex_string")] - pub pubkey: PubkeyTarget, - #[serde(with = "serde_bool_array_to_hex_string")] - pub signature: SignatureTarget, + #[target(in, out)] + pub pubkey_bytes: [Target; 48], + + #[target(in, out)] + pub sig_bytes: [Target; 96], + + pub pubkey_g1_x: BigUintTarget, + pub pubkey_g1_y: BigUintTarget, + pub sig_g2_x_c0: BigUintTarget, + pub sig_g2_x_c1: BigUintTarget, + pub sig_g2_y_c0: BigUintTarget, + pub sig_g2_y_c1: BigUintTarget, } impl Circuit for VerifyIsNotAtInfinityCircuit { @@ -74,37 +55,52 @@ impl Circuit for VerifyIsNotAtInfinityCircuit { _: &Self::Params, ) -> Self::Target { let input = Self::read_circuit_input_target(builder); - let pubkey = input.validator_credentials.pubkey; - let signature = input.validator_credentials.signature; - let pubkey = bits_to_bytes_target(builder, &pubkey); - let pubkey = pubkey.into_iter().collect::>().try_into().unwrap(); - let pubkey_g1 = get_g1_point_from_public_inputs(&pubkey); - assert_pk_ne_not_generator(builder, pubkey_g1.to_owned()); - let signature = bits_to_bytes_target(builder, &signature); - let signature = signature - .into_iter() - .collect::>() - .try_into() - .unwrap(); - let signature_g2 = get_g2_point_from_public_inputs(builder, &signature); + let pubkey_g1_x = builder.add_virtual_biguint_target(12); + let pubkey_g1_y = builder.add_virtual_biguint_target(12); + + let sig_g2_x_c0 = builder.add_virtual_biguint_target(12); + let sig_g2_x_c1 = builder.add_virtual_biguint_target(12); + let sig_g2_y_c0 = builder.add_virtual_biguint_target(12); + let sig_g2_y_c1 = builder.add_virtual_biguint_target(12); + let pubkey_bytes = input.pubkey_bytes; + + let pubkey_g1 = [pubkey_g1_x.to_owned(), pubkey_g1_y.to_owned()]; + pk_point_check(builder, &pubkey_g1, &pubkey_bytes); + assert_pk_ne_not_generator(builder, &pubkey_g1); let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); - let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &signature_g2); + + let sig_bytes = input.sig_bytes; + let sig_g2 = [ + [sig_g2_x_c0.to_owned(), sig_g2_x_c1.to_owned()], + [sig_g2_y_c0.to_owned(), sig_g2_y_c1.to_owned()], + ]; + signature_point_check(builder, &sig_g2, &sig_bytes); + let is_g2_point_is_at_infinity = is_g2_point_is_at_infinity(builder, &sig_g2); + assert_g1_or_g2_point_arent_at_infinity( builder, is_g1_point_is_at_infinity, is_g2_point_is_at_infinity, ); - let pubkey = input.validator_credentials.pubkey; - let signature = input.validator_credentials.signature; Self::Target { - validator_credentials: ValidatorCredentials { pubkey, signature }, + pubkey_bytes, + sig_bytes, + pubkey_g1_x, + pubkey_g1_y, + sig_g2_x_c0, + sig_g2_x_c1, + sig_g2_y_c0, + sig_g2_y_c1, } } } -fn assert_pk_ne_not_generator(builder: &mut CircuitBuilder, public_key_point: PointG1Target) { +fn assert_pk_ne_not_generator( + builder: &mut CircuitBuilder, + public_key_point: &PointG1Target, +) { let get_neg_generator = get_neg_generator(builder); let is_pk_point_x_eq_not_generator_x = @@ -150,80 +146,14 @@ fn is_fp_zero(builder: &mut CircuitBuilder, input: &FpTarget) -> BoolTarge builder.cmp_biguint(input, &zero) } -fn get_g1_point_from_public_inputs(public_inputs: &[Target; 48]) -> PointG1Target { - let g1_x = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - - let g1_y = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - - [g1_x, g1_y] -} - -fn get_g2_point_from_public_inputs( - builder: &mut CircuitBuilder, - public_inputs: &[Target; 96], -) -> PointG2Target { - let sig_point_x0 = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::X0_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - let sig_point_x1 = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::X1_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - let sig_point_y0 = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::Y0_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - let sig_point_y1 = BigUintTarget { - limbs: (0..N) - .into_iter() - .map(|i| U32Target(public_inputs[calc_pairing_precomp::Y1_PUBLIC_INPUTS_OFFSET + i])) - .collect(), - }; - - let zero = builder.zero(); - let one = builder.one(); - for i in 0..N { - if i == 0 { - builder.connect( - public_inputs[calc_pairing_precomp::Z0_PUBLIC_INPUTS_OFFSET + i], - one, - ); - } else { - builder.connect( - public_inputs[calc_pairing_precomp::Z0_PUBLIC_INPUTS_OFFSET + i], - zero, - ); - } - builder.connect( - public_inputs[calc_pairing_precomp::Z1_PUBLIC_INPUTS_OFFSET + i], - zero, - ); - } - - [[sig_point_x0, sig_point_x1], [sig_point_y0, sig_point_y1]] -} - #[cfg(test)] pub mod tests { + use ark_bls12_381::{G1Affine, G2Affine}; + use ark_serialize::CanonicalDeserialize; use circuit::{Circuit, CircuitInput, SetWitness}; + use num::BigUint; use plonky2::iop::witness::PartialWitness; + use plonky2_crypto::biguint::WitnessBigUint; use super::VerifyIsNotAtInfinityCircuit; @@ -231,36 +161,67 @@ pub mod tests { fn test_g1_or_g2_are_at_infinity() { let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); - let input = - serde_json::from_str::>(r#"{ - "validator_credentials": { - "pubkey": "b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", - "signature": "b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9" - } - }"#).unwrap(); - - let mut pw = PartialWitness::new(); - targets.set_witness(&mut pw, &input); - - let proof = circuit.prove(pw).unwrap(); - let _ = circuit.verify(proof); - } - - #[test] - #[should_panic] - fn test_one_privkey() { - let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); - - let input = - serde_json::from_str::>(r#"{ - "validator_credentials": { - "pubkey": "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", - "signature": "a42ae16f1c2a5fa69c04cb5998d2add790764ce8dd45bf25b29b4700829232052b52352dcff1cf255b3a7810ad7269601810f03b2bc8b68cf289cf295b206770605a190b6842583e47c3d1c0f73c54907bfb2a602157d46a4353a20283018763" - } - }"#).unwrap(); + let pubkey = "b781956110d24e4510a8b5500b71529f8635aa419a009d314898e8c572a4f923ba643ae94bdfdf9224509177aa8e6b73"; + println!("pubkey_as_bytes are: {:?}", pubkey.as_bytes()); + let signature = "b735d0d0b03f51fcf3e5bc510b5a2cb266075322f5761a6954778714f5ab8831bc99454380d330f5c19d93436f0c4339041bfeecd2161a122c1ce8428033db8dda142768a48e582f5f9bde7d40768ac5a3b6a80492b73719f1523c5da35de275"; + println!("signature_as_bytes are: {:?}", signature.as_bytes()); + + let input = serde_json::from_str::>( + r#"{ + "pubkey_bytes": [ + 98, 55, 56, 49, 57, 53, 54, 49, 49, 48, 100, 50, 52, 101, 52, 53, 49, 48, 97, 56, 98, + 53, 53, 48, 48, 98, 55, 49, 53, 50, 57, 102, 56, 54, 51, 53, 97, 97, 52, 49, 57, 97, + 48, 48, 57, 100, 51, 49, 52, 56, 57, 56, 101, 56, 99, 53, 55, 50, 97, 52, 102, 57, 50, + 51, 98, 97, 54, 52, 51, 97, 101, 57, 52, 98, 100, 102, 100, 102, 57, 50, 50, 52, 53, + 48, 57, 49, 55, 55, 97, 97, 56, 101, 54, 98, 55, 51 + ], + "sig_bytes": [ + 98, 55, 51, 53, 100, 48, 100, 48, 98, 48, 51, 102, 53, 49, 102, 99, 102, 51, 101, 53, + 98, 99, 53, 49, 48, 98, 53, 97, 50, 99, 98, 50, 54, 54, 48, 55, 53, 51, 50, 50, 102, + 53, 55, 54, 49, 97, 54, 57, 53, 52, 55, 55, 56, 55, 49, 52, 102, 53, 97, 98, 56, 56, + 51, 49, 98, 99, 57, 57, 52, 53, 52, 51, 56, 48, 100, 51, 51, 48, 102, 53, 99, 49, 57, + 100, 57, 51, 52, 51, 54, 102, 48, 99, 52, 51, 51, 57, 48, 52, 49, 98, 102, 101, 101, + 99, 100, 50, 49, 54, 49, 97, 49, 50, 50, 99, 49, 99, 101, 56, 52, 50, 56, 48, 51, 51, + 100, 98, 56, 100, 100, 97, 49, 52, 50, 55, 54, 56, 97, 52, 56, 101, 53, 56, 50, 102, + 53, 102, 57, 98, 100, 101, 55, 100, 52, 48, 55, 54, 56, 97, 99, 53, 97, 51, 98, 54, 97, + 56, 48, 52, 57, 50, 98, 55, 51, 55, 49, 57, 102, 49, 53, 50, 51, 99, 53, 100, 97, 51, + 53, 100, 101, 50, 55, 53 + ] + }"#, + ) + .unwrap(); + + let pubkey_g1: G1Affine = + G1Affine::deserialize_compressed_unchecked(&*hex::decode(pubkey).unwrap()).unwrap(); + let signature_g2 = + G2Affine::deserialize_compressed_unchecked(&*hex::decode(signature).unwrap()).unwrap(); let mut pw = PartialWitness::new(); targets.set_witness(&mut pw, &input); + pw.set_biguint_target( + &targets.pubkey_g1_x, + &BigUint::try_from(pubkey_g1.x).unwrap(), + ); + pw.set_biguint_target( + &targets.pubkey_g1_y, + &BigUint::try_from(pubkey_g1.y).unwrap(), + ); + pw.set_biguint_target( + &targets.sig_g2_x_c0, + &BigUint::try_from(signature_g2.x.c0).unwrap(), + ); + pw.set_biguint_target( + &targets.sig_g2_x_c1, + &BigUint::try_from(signature_g2.x.c1).unwrap(), + ); + pw.set_biguint_target( + &targets.sig_g2_y_c0, + &BigUint::try_from(signature_g2.y.c0).unwrap(), + ); + pw.set_biguint_target( + &targets.sig_g2_y_c1, + &BigUint::try_from(signature_g2.y.c1).unwrap(), + ); let proof = circuit.prove(pw).unwrap(); let _ = circuit.verify(proof); From 9dddfa18daf91ce0b2efa51f965a43ab43ec5b2c Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Wed, 12 Jun 2024 11:38:39 +0300 Subject: [PATCH 30/37] Finish VerifyIsNotAtInfinityCircuit and make tests pass successfully --- beacon-light-client/plonky2/crates/Cargo.lock | 1 + .../plonky2/crates/circuits/Cargo.toml | 1 + .../verify_is_not_at_infinity_circuit.rs | 154 ++++++++++++------ 3 files changed, 103 insertions(+), 53 deletions(-) diff --git a/beacon-light-client/plonky2/crates/Cargo.lock b/beacon-light-client/plonky2/crates/Cargo.lock index f33c44f84..3a91b8951 100644 --- a/beacon-light-client/plonky2/crates/Cargo.lock +++ b/beacon-light-client/plonky2/crates/Cargo.lock @@ -1224,6 +1224,7 @@ dependencies = [ "ahash 0.8.11", "anyhow", "ark-bls12-381", + "ark-ec", "ark-serialize", "circuit", "circuit_derive", diff --git a/beacon-light-client/plonky2/crates/circuits/Cargo.toml b/beacon-light-client/plonky2/crates/circuits/Cargo.toml index 045b9c3cf..086b0376e 100644 --- a/beacon-light-client/plonky2/crates/circuits/Cargo.toml +++ b/beacon-light-client/plonky2/crates/circuits/Cargo.toml @@ -29,6 +29,7 @@ plonky2-circuit-serializer = { git = "https://github.com/metacraft-labs/plonky2- num-bigint = "0.4.4" ark-bls12-381 = "0.4.0" ark-serialize = "0.4.2" +ark-ec = "0.4.2" [dev-dependencies] serde_yaml = "0.9.34" diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs index 01424a340..8e663ff6d 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs @@ -1,4 +1,6 @@ +use ark_bls12_381::g1::{G1_GENERATOR_X, G1_GENERATOR_Y}; use circuit_derive::{CircuitTarget, SerdeCircuitTarget}; +use num::BigUint; use plonky2::{ iop::target::{BoolTarget, Target}, plonk::{ @@ -17,11 +19,9 @@ use starky_bls12_381::{ use circuit::{circuit_builder_extensions::CircuitBuilderExtensions, Circuit}; -use super::bls12_381_circuit::get_neg_generator; - -type F = >::F; -type C = PoseidonGoldilocksConfig; -const D: usize = 2; +pub type F = >::F; +pub type C = PoseidonGoldilocksConfig; +pub const D: usize = 2; pub struct VerifyIsNotAtInfinityCircuit; @@ -67,7 +67,7 @@ impl Circuit for VerifyIsNotAtInfinityCircuit { let pubkey_g1 = [pubkey_g1_x.to_owned(), pubkey_g1_y.to_owned()]; pk_point_check(builder, &pubkey_g1, &pubkey_bytes); - assert_pk_ne_not_generator(builder, &pubkey_g1); + assert_pk_ne_g1_generator(builder, &pubkey_g1); let is_g1_point_is_at_infinity = is_g1_point_is_at_infinity(builder, &pubkey_g1); let sig_bytes = input.sig_bytes; @@ -97,19 +97,15 @@ impl Circuit for VerifyIsNotAtInfinityCircuit { } } -fn assert_pk_ne_not_generator( - builder: &mut CircuitBuilder, - public_key_point: &PointG1Target, -) { - let get_neg_generator = get_neg_generator(builder); +fn assert_pk_ne_g1_generator(builder: &mut CircuitBuilder, public_key_point: &PointG1Target) { + let g1_generator_x = builder.constant_biguint(&BigUint::from(G1_GENERATOR_X)); + let g1_generator_y = builder.constant_biguint(&BigUint::from(G1_GENERATOR_Y)); - let is_pk_point_x_eq_not_generator_x = - is_equal(builder, &public_key_point[0], &get_neg_generator[0]); - let is_pk_point_y_eq_not_generator_y = - is_equal(builder, &public_key_point[1], &get_neg_generator[1]); + let is_pk_point_x_eq_g1_generator_x = is_equal(builder, &public_key_point[0], &g1_generator_x); + let is_pk_point_y_eq_g1_generator_y = is_equal(builder, &public_key_point[1], &g1_generator_y); let pk_point_eq_not_generator = builder.and( - is_pk_point_x_eq_not_generator_x, - is_pk_point_y_eq_not_generator_y, + is_pk_point_x_eq_g1_generator_x, + is_pk_point_y_eq_g1_generator_y, ); builder.assert_false(pk_point_eq_not_generator) } @@ -152,45 +148,21 @@ pub mod tests { use ark_serialize::CanonicalDeserialize; use circuit::{Circuit, CircuitInput, SetWitness}; use num::BigUint; - use plonky2::iop::witness::PartialWitness; + use plonky2::{iop::witness::PartialWitness, plonk::circuit_data::CircuitData}; use plonky2_crypto::biguint::WitnessBigUint; - use super::VerifyIsNotAtInfinityCircuit; - - #[test] - fn test_g1_or_g2_are_at_infinity() { - let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); - - let pubkey = "b781956110d24e4510a8b5500b71529f8635aa419a009d314898e8c572a4f923ba643ae94bdfdf9224509177aa8e6b73"; - println!("pubkey_as_bytes are: {:?}", pubkey.as_bytes()); - let signature = "b735d0d0b03f51fcf3e5bc510b5a2cb266075322f5761a6954778714f5ab8831bc99454380d330f5c19d93436f0c4339041bfeecd2161a122c1ce8428033db8dda142768a48e582f5f9bde7d40768ac5a3b6a80492b73719f1523c5da35de275"; - println!("signature_as_bytes are: {:?}", signature.as_bytes()); - - let input = serde_json::from_str::>( - r#"{ - "pubkey_bytes": [ - 98, 55, 56, 49, 57, 53, 54, 49, 49, 48, 100, 50, 52, 101, 52, 53, 49, 48, 97, 56, 98, - 53, 53, 48, 48, 98, 55, 49, 53, 50, 57, 102, 56, 54, 51, 53, 97, 97, 52, 49, 57, 97, - 48, 48, 57, 100, 51, 49, 52, 56, 57, 56, 101, 56, 99, 53, 55, 50, 97, 52, 102, 57, 50, - 51, 98, 97, 54, 52, 51, 97, 101, 57, 52, 98, 100, 102, 100, 102, 57, 50, 50, 52, 53, - 48, 57, 49, 55, 55, 97, 97, 56, 101, 54, 98, 55, 51 - ], - "sig_bytes": [ - 98, 55, 51, 53, 100, 48, 100, 48, 98, 48, 51, 102, 53, 49, 102, 99, 102, 51, 101, 53, - 98, 99, 53, 49, 48, 98, 53, 97, 50, 99, 98, 50, 54, 54, 48, 55, 53, 51, 50, 50, 102, - 53, 55, 54, 49, 97, 54, 57, 53, 52, 55, 55, 56, 55, 49, 52, 102, 53, 97, 98, 56, 56, - 51, 49, 98, 99, 57, 57, 52, 53, 52, 51, 56, 48, 100, 51, 51, 48, 102, 53, 99, 49, 57, - 100, 57, 51, 52, 51, 54, 102, 48, 99, 52, 51, 51, 57, 48, 52, 49, 98, 102, 101, 101, - 99, 100, 50, 49, 54, 49, 97, 49, 50, 50, 99, 49, 99, 101, 56, 52, 50, 56, 48, 51, 51, - 100, 98, 56, 100, 100, 97, 49, 52, 50, 55, 54, 56, 97, 52, 56, 101, 53, 56, 50, 102, - 53, 102, 57, 98, 100, 101, 55, 100, 52, 48, 55, 54, 56, 97, 99, 53, 97, 51, 98, 54, 97, - 56, 48, 52, 57, 50, 98, 55, 51, 55, 49, 57, 102, 49, 53, 50, 51, 99, 53, 100, 97, 51, - 53, 100, 101, 50, 55, 53 - ] - }"#, - ) - .unwrap(); + use super::{ + VerifyIsNotAtInfinityCircuit, VerifyIsNotAtInfinityCircuitTargets, + VerifyIsNotAtInfinityCircuitTargetsWitnessInput, C, D, F, + }; + fn test_helper( + pubkey: &str, + signature: &str, + targets: VerifyIsNotAtInfinityCircuitTargets, + circuit: CircuitData, + input: VerifyIsNotAtInfinityCircuitTargetsWitnessInput, + ) { let pubkey_g1: G1Affine = G1Affine::deserialize_compressed_unchecked(&*hex::decode(pubkey).unwrap()).unwrap(); let signature_g2 = @@ -226,4 +198,80 @@ pub mod tests { let proof = circuit.prove(pw).unwrap(); let _ = circuit.verify(proof); } + + #[test] + fn test_valid_case_for_g1_and_g2_at_infinity() { + let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); + + let pubkey = "b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81"; + let signature = "b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"; + + let input = serde_json::from_str::>( + r#"{ + "pubkey_bytes": [ + 179, 1, 128, 63, 139, 90, 196, 161, 19, 53, 129, 252, 103, 109, 254, 220, 96, 216, 145, 221, 95, 169, 144, 40, 128, + 94, 94, 165, 176, 141, 52, 145, 175, 117, 208, 112, 122, 218, 179, 183, 12, 106, 106, 88, 2, 23, 191, 129 + ], + "sig_bytes": [ + 178, 60, 70, 190, 58, 0, 28, 99, 202, 113, 31, 135, 160, 5, 194, 0, 204, 85, 11, 148, 41, 213, 244, 235, 56, 215, 67, + 34, 20, 79, 27, 99, 146, 109, 163, 56, 137, 121, 229, 50, 16, 18, 251, 26, 5, 38, 188, 209, 0, 181, 239, 95, 231, 38, + 40, 206, 76, 213, 233, 4, 174, 170, 50, 121, 82, 120, 67, 250, 229, 202, 156, 166, 117, 244, 245, 30, 216, 248, 59, 191, + 113, 85, 218, 158, 204, 150, 99, 16, 10, 136, 93, 93, 198, 223, 150, 217 + ] + }"# + ) + .unwrap(); + + test_helper(pubkey, signature, targets, circuit, input); + } + + #[test] + #[should_panic] + fn test_g1_or_g2_are_at_infinity() { + let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); + + let pubkey = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + let signature = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + let input = serde_json::from_str::>( + r#"{ + "pubkey_bytes": [ + 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + "sig_bytes": [ + 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + }"# + ) + .unwrap(); + + test_helper(pubkey, signature, targets, circuit, input); + } + + #[test] + #[should_panic] + fn test_g1_is_not_the_g1_generator() { + let (targets, circuit) = VerifyIsNotAtInfinityCircuit::build(&()); + + let pubkey = "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"; + let signature = "a42ae16f1c2a5fa69c04cb5998d2add790764ce8dd45bf25b29b4700829232052b52352dcff1cf255b3a7810ad7269601810f03b2bc8b68cf289cf295b206770605a190b6842583e47c3d1c0f73c54907bfb2a602157d46a4353a20283018763"; + + let input = serde_json::from_str::>( + r#"{ + "pubkey_bytes": [ + 151, 241, 211, 167, 49, 151, 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104, 140, 79, 151, 116, 185, 5, 161, + 78, 58, 63, 23, 27, 172, 88, 108, 85, 232, 63, 249, 122, 26, 239, 251, 58, 240, 10, 219, 34, 198, 187 + ], + "sig_bytes": [ + 164, 42, 225, 111, 28, 42, 95, 166, 156, 4, 203, 89, 152, 210, 173, 215, 144, 118, 76, 232, 221, 69, 191, + 37, 178, 155, 71, 0, 130, 146, 50, 5, 43, 82, 53, 45, 207, 241, 207, 37, 91, 58, 120, 16, 173, 114, 105, + 96, 24, 16, 240, 59, 43, 200, 182, 140, 242, 137, 207, 41, 91, 32, 103, 112, 96, 90, 25, 11, 104, 66, 88, + 62, 71, 195, 209, 192, 247, 60, 84, 144, 123, 251, 42, 96, 33, 87, 212, 106, 67, 83, 162, 2, 131, 1, 135, 99 + ] + }"# + ) + .unwrap(); + + test_helper(pubkey, signature, targets, circuit, input); + } } From 38e716e6879362b895cf1bd26c013160a4472257 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Wed, 12 Jun 2024 12:28:20 +0300 Subject: [PATCH 31/37] Implement helper functions for tests for VerifyIsNotAtInfinityCircuitTargets --- .../verify_is_not_at_infinity_circuit.rs | 77 ++++++++----------- 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs index 8e663ff6d..ed28ea8e5 100644 --- a/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs +++ b/beacon-light-client/plonky2/crates/circuits/src/bls_verification/verify_is_not_at_infinity_circuit.rs @@ -156,6 +156,36 @@ pub mod tests { VerifyIsNotAtInfinityCircuitTargetsWitnessInput, C, D, F, }; + fn input_init( + pubkey: &str, + signature: &str, + ) -> VerifyIsNotAtInfinityCircuitTargetsWitnessInput { + let pubkey_bytes = hex::decode(pubkey).unwrap(); + let pubkey_bytes: [u8; 48] = pubkey_bytes + .into_iter() + .collect::>() + .try_into() + .unwrap(); + + let sig_bytes = hex::decode(signature).unwrap(); + let sig_bytes: [u8; 96] = sig_bytes + .into_iter() + .collect::>() + .try_into() + .unwrap(); + + let concatenated_str = format!( + r#"{{ + "pubkey_bytes": {:?}, + "sig_bytes": {:?} + }}"#, + pubkey_bytes, sig_bytes + ); + + serde_json::from_str::>(&concatenated_str) + .unwrap() + } + fn test_helper( pubkey: &str, signature: &str, @@ -205,22 +235,7 @@ pub mod tests { let pubkey = "b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81"; let signature = "b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"; - - let input = serde_json::from_str::>( - r#"{ - "pubkey_bytes": [ - 179, 1, 128, 63, 139, 90, 196, 161, 19, 53, 129, 252, 103, 109, 254, 220, 96, 216, 145, 221, 95, 169, 144, 40, 128, - 94, 94, 165, 176, 141, 52, 145, 175, 117, 208, 112, 122, 218, 179, 183, 12, 106, 106, 88, 2, 23, 191, 129 - ], - "sig_bytes": [ - 178, 60, 70, 190, 58, 0, 28, 99, 202, 113, 31, 135, 160, 5, 194, 0, 204, 85, 11, 148, 41, 213, 244, 235, 56, 215, 67, - 34, 20, 79, 27, 99, 146, 109, 163, 56, 137, 121, 229, 50, 16, 18, 251, 26, 5, 38, 188, 209, 0, 181, 239, 95, 231, 38, - 40, 206, 76, 213, 233, 4, 174, 170, 50, 121, 82, 120, 67, 250, 229, 202, 156, 166, 117, 244, 245, 30, 216, 248, 59, 191, - 113, 85, 218, 158, 204, 150, 99, 16, 10, 136, 93, 93, 198, 223, 150, 217 - ] - }"# - ) - .unwrap(); + let input = input_init(pubkey, signature); test_helper(pubkey, signature, targets, circuit, input); } @@ -232,18 +247,7 @@ pub mod tests { let pubkey = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; let signature = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - - let input = serde_json::from_str::>( - r#"{ - "pubkey_bytes": [ - 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ], - "sig_bytes": [ - 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }"# - ) - .unwrap(); + let input = input_init(pubkey, signature); test_helper(pubkey, signature, targets, circuit, input); } @@ -255,22 +259,7 @@ pub mod tests { let pubkey = "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"; let signature = "a42ae16f1c2a5fa69c04cb5998d2add790764ce8dd45bf25b29b4700829232052b52352dcff1cf255b3a7810ad7269601810f03b2bc8b68cf289cf295b206770605a190b6842583e47c3d1c0f73c54907bfb2a602157d46a4353a20283018763"; - - let input = serde_json::from_str::>( - r#"{ - "pubkey_bytes": [ - 151, 241, 211, 167, 49, 151, 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104, 140, 79, 151, 116, 185, 5, 161, - 78, 58, 63, 23, 27, 172, 88, 108, 85, 232, 63, 249, 122, 26, 239, 251, 58, 240, 10, 219, 34, 198, 187 - ], - "sig_bytes": [ - 164, 42, 225, 111, 28, 42, 95, 166, 156, 4, 203, 89, 152, 210, 173, 215, 144, 118, 76, 232, 221, 69, 191, - 37, 178, 155, 71, 0, 130, 146, 50, 5, 43, 82, 53, 45, 207, 241, 207, 37, 91, 58, 120, 16, 173, 114, 105, - 96, 24, 16, 240, 59, 43, 200, 182, 140, 242, 137, 207, 41, 91, 32, 103, 112, 96, 90, 25, 11, 104, 66, 88, - 62, 71, 195, 209, 192, 247, 60, 84, 144, 123, 251, 42, 96, 33, 87, 212, 106, 67, 83, 162, 2, 131, 1, 135, 99 - ] - }"# - ) - .unwrap(); + let input = input_init(pubkey, signature); test_helper(pubkey, signature, targets, circuit, input); } From b044674b51948e0c25805e86557969197f7cfaea Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Thu, 13 Jun 2024 12:09:06 +0300 Subject: [PATCH 32/37] Fix path in run_bls12_381_component_proofs script --- .../plonky2/crates/circuit_executables/bls12-381-tests | 1 + .../scripts/run_bls12_381_component_proofs.sh | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 160000 beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests new file mode 160000 index 000000000..006855c56 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests @@ -0,0 +1 @@ +Subproject commit 006855c56cb6491ee19b4aedfddb806aaeacb1db diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 63316a3b8..330d32446 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -3,8 +3,8 @@ # Define variables REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" -OUTPUT_DIR="eth_tests/bls" -VERIFY_DIR="$OUTPUT_DIR/verify" +OUTPUT_DIR="eth_tests" +VERIFY_DIR="$OUTPUT_DIR/bls/verify" SCRIPTS_DIR="scripts" SRC="src" @@ -48,7 +48,7 @@ cd "$VERIFY_DIR" || exit mapfile -t all_yaml_files_in_verify < <(ls *) # Navigate back to the root directory -cd ../../../../../ +cd ../../../../ # Navigate to the src directory cd "$SRC" || exit From 9d7f27b6ed9483e3e4c8d665b3af1f086dae4534 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 17 Jun 2024 10:39:54 +0300 Subject: [PATCH 33/37] Address PR comments --- beacon-light-client/plonky2/.gitignore | 3 +- .../scripts/bls12-381-tests | 1 - .../scripts/run_bls12_381_component_proofs.sh | 28 +++++++++++-------- .../bls12-381-tests | 0 4 files changed, 17 insertions(+), 15 deletions(-) delete mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests rename {beacon-light-client/plonky2/crates/circuit_executables => vendor}/bls12-381-tests (100%) diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 5474f70c2..8641aa27a 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -2,5 +2,4 @@ gnark_plonky2_verifier/data gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin -gnark_plonky2_verifier/public_witness.bin -circuits_executables/ \ No newline at end of file +gnark_plonky2_verifier/public_witness.bin \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests deleted file mode 160000 index 2b6a5ba04..000000000 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 330d32446..95781fa20 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,8 +5,15 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/bls/verify" -SCRIPTS_DIR="scripts" -SRC="src" +FROM_CIRCUIT_EXECUTABLES_TO="../../../.." +VENDOR="vendor" + +command pushd $GIT_ROOT/beacon-light-client/plonky2/crates/circuit_executables "$@" > /dev/null + +# Store the current directory +CIRCUIT_EXECUTABLES_DIR=$(pwd) + +cd "$FROM_CIRCUIT_EXECUTABLES_TO/$VENDOR" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -41,17 +48,12 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate to the verify directory -cd "$VERIFY_DIR" || exit +# Navigate to the circuit executables directory +cd "../.." +cd "$CIRCUIT_EXECUTABLES_DIR" # Store all files in a variable -mapfile -t all_yaml_files_in_verify < <(ls *) - -# Navigate back to the root directory -cd ../../../../ - -# Navigate to the src directory -cd "$SRC" || exit +mapfile -t all_yaml_files_in_verify < <(ls *) # Run the verify tests run_verify_tests() { @@ -68,4 +70,6 @@ run_verify_tests() { # Loop through the extracted files in the 'verify' directory for yaml_file in "${all_yaml_files_in_verify[@]}"; do run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" -done \ No newline at end of file +done + +command popd "$@" > /dev/null \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests b/vendor/bls12-381-tests similarity index 100% rename from beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests rename to vendor/bls12-381-tests From ec0c87cdd4e7a35e14b47e06a1e144eb76ce6634 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 17 Jun 2024 12:10:51 +0300 Subject: [PATCH 34/37] Revert "Address PR comments" This reverts commit 9d7f27b6ed9483e3e4c8d665b3af1f086dae4534. --- beacon-light-client/plonky2/.gitignore | 3 +- .../circuit_executables}/bls12-381-tests | 0 .../scripts/bls12-381-tests | 1 + .../scripts/run_bls12_381_component_proofs.sh | 28 ++++++++----------- 4 files changed, 15 insertions(+), 17 deletions(-) rename {vendor => beacon-light-client/plonky2/crates/circuit_executables}/bls12-381-tests (100%) create mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 8641aa27a..5474f70c2 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -2,4 +2,5 @@ gnark_plonky2_verifier/data gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin -gnark_plonky2_verifier/public_witness.bin \ No newline at end of file +gnark_plonky2_verifier/public_witness.bin +circuits_executables/ \ No newline at end of file diff --git a/vendor/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests similarity index 100% rename from vendor/bls12-381-tests rename to beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests new file mode 160000 index 000000000..2b6a5ba04 --- /dev/null +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests @@ -0,0 +1 @@ +Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 95781fa20..330d32446 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,15 +5,8 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/bls/verify" -FROM_CIRCUIT_EXECUTABLES_TO="../../../.." -VENDOR="vendor" - -command pushd $GIT_ROOT/beacon-light-client/plonky2/crates/circuit_executables "$@" > /dev/null - -# Store the current directory -CIRCUIT_EXECUTABLES_DIR=$(pwd) - -cd "$FROM_CIRCUIT_EXECUTABLES_TO/$VENDOR" +SCRIPTS_DIR="scripts" +SRC="src" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -48,12 +41,17 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate to the circuit executables directory -cd "../.." -cd "$CIRCUIT_EXECUTABLES_DIR" +# Navigate to the verify directory +cd "$VERIFY_DIR" || exit # Store all files in a variable -mapfile -t all_yaml_files_in_verify < <(ls *) +mapfile -t all_yaml_files_in_verify < <(ls *) + +# Navigate back to the root directory +cd ../../../../ + +# Navigate to the src directory +cd "$SRC" || exit # Run the verify tests run_verify_tests() { @@ -70,6 +68,4 @@ run_verify_tests() { # Loop through the extracted files in the 'verify' directory for yaml_file in "${all_yaml_files_in_verify[@]}"; do run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" -done - -command popd "$@" > /dev/null \ No newline at end of file +done \ No newline at end of file From 5a5e491171ca1e53afe24e5b99e97036f678f0fc Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 17 Jun 2024 12:18:31 +0300 Subject: [PATCH 35/37] Revert circom-pairing update --- beacon-light-client/plonky2/.gitignore | 3 +- .../scripts/bls12-381-tests | 1 - .../scripts/run_bls12_381_component_proofs.sh | 28 +++++++++++-------- .../bls12-381-tests | 0 4 files changed, 17 insertions(+), 15 deletions(-) delete mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests rename {beacon-light-client/plonky2/crates/circuit_executables => vendor}/bls12-381-tests (100%) diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 5474f70c2..8641aa27a 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -2,5 +2,4 @@ gnark_plonky2_verifier/data gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin -gnark_plonky2_verifier/public_witness.bin -circuits_executables/ \ No newline at end of file +gnark_plonky2_verifier/public_witness.bin \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests deleted file mode 160000 index 2b6a5ba04..000000000 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 330d32446..95781fa20 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,8 +5,15 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/bls/verify" -SCRIPTS_DIR="scripts" -SRC="src" +FROM_CIRCUIT_EXECUTABLES_TO="../../../.." +VENDOR="vendor" + +command pushd $GIT_ROOT/beacon-light-client/plonky2/crates/circuit_executables "$@" > /dev/null + +# Store the current directory +CIRCUIT_EXECUTABLES_DIR=$(pwd) + +cd "$FROM_CIRCUIT_EXECUTABLES_TO/$VENDOR" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -41,17 +48,12 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate to the verify directory -cd "$VERIFY_DIR" || exit +# Navigate to the circuit executables directory +cd "../.." +cd "$CIRCUIT_EXECUTABLES_DIR" # Store all files in a variable -mapfile -t all_yaml_files_in_verify < <(ls *) - -# Navigate back to the root directory -cd ../../../../ - -# Navigate to the src directory -cd "$SRC" || exit +mapfile -t all_yaml_files_in_verify < <(ls *) # Run the verify tests run_verify_tests() { @@ -68,4 +70,6 @@ run_verify_tests() { # Loop through the extracted files in the 'verify' directory for yaml_file in "${all_yaml_files_in_verify[@]}"; do run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" -done \ No newline at end of file +done + +command popd "$@" > /dev/null \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests b/vendor/bls12-381-tests similarity index 100% rename from beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests rename to vendor/bls12-381-tests From afdc20b89b93ad4ad7ca124050d178aadac64faf Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 17 Jun 2024 12:18:31 +0300 Subject: [PATCH 36/37] Revert circom-pairing update --- beacon-light-client/plonky2/.gitignore | 3 +- .../scripts/bls12-381-tests | 1 - .../scripts/run_bls12_381_component_proofs.sh | 28 +++++++++++-------- .../bls12-381-tests | 0 vendor/circom-pairing | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) delete mode 160000 beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests rename {beacon-light-client/plonky2/crates/circuit_executables => vendor}/bls12-381-tests (100%) diff --git a/beacon-light-client/plonky2/.gitignore b/beacon-light-client/plonky2/.gitignore index 5474f70c2..8641aa27a 100644 --- a/beacon-light-client/plonky2/.gitignore +++ b/beacon-light-client/plonky2/.gitignore @@ -2,5 +2,4 @@ gnark_plonky2_verifier/data gnark_plonky2_verifier/DendrETH gnark_plonky2_verifier/circuit/srs_setup gnark_plonky2_verifier/circuit/solidity_bytes.bin -gnark_plonky2_verifier/public_witness.bin -circuits_executables/ \ No newline at end of file +gnark_plonky2_verifier/public_witness.bin \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests b/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests deleted file mode 160000 index 2b6a5ba04..000000000 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/bls12-381-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b6a5ba046f2878da6e8a7b99ee3e457573a15cb diff --git a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh index 330d32446..95781fa20 100755 --- a/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh +++ b/beacon-light-client/plonky2/crates/circuit_executables/scripts/run_bls12_381_component_proofs.sh @@ -5,8 +5,15 @@ REPO_URL="https://github.com/ethereum/bls12-381-tests" REPO_DIR="bls12-381-tests" OUTPUT_DIR="eth_tests" VERIFY_DIR="$OUTPUT_DIR/bls/verify" -SCRIPTS_DIR="scripts" -SRC="src" +FROM_CIRCUIT_EXECUTABLES_TO="../../../.." +VENDOR="vendor" + +command pushd $GIT_ROOT/beacon-light-client/plonky2/crates/circuit_executables "$@" > /dev/null + +# Store the current directory +CIRCUIT_EXECUTABLES_DIR=$(pwd) + +cd "$FROM_CIRCUIT_EXECUTABLES_TO/$VENDOR" # Clone the repository if [ ! -d "$REPO_DIR" ]; then @@ -41,17 +48,12 @@ python main.py --output-dir="$OUTPUT_DIR" --encoding=yaml # Deactivate the virtual environment deactivate -# Navigate to the verify directory -cd "$VERIFY_DIR" || exit +# Navigate to the circuit executables directory +cd "../.." +cd "$CIRCUIT_EXECUTABLES_DIR" # Store all files in a variable -mapfile -t all_yaml_files_in_verify < <(ls *) - -# Navigate back to the root directory -cd ../../../../ - -# Navigate to the src directory -cd "$SRC" || exit +mapfile -t all_yaml_files_in_verify < <(ls *) # Run the verify tests run_verify_tests() { @@ -68,4 +70,6 @@ run_verify_tests() { # Loop through the extracted files in the 'verify' directory for yaml_file in "${all_yaml_files_in_verify[@]}"; do run_verify_tests "test_bls12_381_components_proofs_with_verify_eth_cases" "$yaml_file" -done \ No newline at end of file +done + +command popd "$@" > /dev/null \ No newline at end of file diff --git a/beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests b/vendor/bls12-381-tests similarity index 100% rename from beacon-light-client/plonky2/crates/circuit_executables/bls12-381-tests rename to vendor/bls12-381-tests diff --git a/vendor/circom-pairing b/vendor/circom-pairing index 82bac4a27..52db7a215 160000 --- a/vendor/circom-pairing +++ b/vendor/circom-pairing @@ -1 +1 @@ -Subproject commit 82bac4a27499fc11cf3ebbb64c525b526f13b552 +Subproject commit 52db7a21544219e7b734e7f683d1f11328a0dc4e From 14c0e16591c6ab73195ce83851ac994b0f00ec65 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 24 Jun 2024 17:04:52 +0300 Subject: [PATCH 37/37] Update gitmodules --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 8c360099e..84b52d108 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@ [submodule "vendor/snarkjs"] path = vendor/snarkjs url = git@github.com:iden3/snarkjs.git +[submodule "vendor/bls12-381-tests"] + path = vendor/bls12-381-tests + url = https://github.com/ethereum/bls12-381-tests