From f0c8706c2dcc3e45003aa0adcda9235429b6fcaf Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 29 Jul 2025 17:18:13 -0400 Subject: [PATCH 1/4] removing hyrax/orion/bikzg pcs --- Cargo.lock | 15 - Cargo.toml | 4 - bin/src/exec.rs | 15 - bin/src/main.rs | 27 +- bin/src/main_mpi.rs | 27 +- config_macros/src/lib.rs | 11 +- config_macros/tests/macro_expansion.rs | 19 +- gkr/src/gkr_configs.rs | 42 +- gkr/src/tests/gkr_correctness.rs | 31 +- gkr_engine/src/poly_commit/definition.rs | 8 +- poly_commit/Cargo.toml | 2 +- poly_commit/src/hyrax.rs | 10 - poly_commit/src/hyrax/expander_api.rs | 202 ------ poly_commit/src/hyrax/hyrax_impl.rs | 429 ------------ poly_commit/src/hyrax/pcs_trait_impl.rs | 159 ----- poly_commit/src/hyrax/pedersen.rs | 143 ---- poly_commit/src/kzg.rs | 3 - poly_commit/src/kzg/bi_kzg.rs | 19 - poly_commit/src/kzg/bi_kzg/bivariate.rs | 197 ------ poly_commit/src/kzg/bi_kzg/expander_api.rs | 170 ----- poly_commit/src/kzg/bi_kzg/hyper_bikzg.rs | 650 ------------------ .../src/kzg/bi_kzg/hyper_bikzg_tests.rs | 603 ---------------- poly_commit/src/kzg/bi_kzg/pcs_trait_impl.rs | 119 ---- poly_commit/src/kzg/bi_kzg/structs_bi_kzg.rs | 96 --- .../src/kzg/bi_kzg/structs_hyper_bi_kzg.rs | 56 -- .../src/kzg/uni_kzg/structs_hyper_kzg.rs | 117 ---- poly_commit/src/lib.rs | 6 - poly_commit/src/orion.rs | 28 - poly_commit/src/orion/expander_api.rs | 204 ------ poly_commit/src/orion/linear_code.rs | 291 -------- poly_commit/src/orion/linear_code_tests.rs | 84 --- poly_commit/src/orion/mpi_utils.rs | 257 ------- poly_commit/src/orion/pcs_trait_impl.rs | 233 ------- poly_commit/src/orion/simd_field_impl.rs | 120 ---- poly_commit/src/orion/simd_field_mpi_impl.rs | 132 ---- poly_commit/src/orion/utils.rs | 579 ---------------- poly_commit/src/orion/verify.rs | 132 ---- poly_commit/src/traits.rs | 29 +- poly_commit/tests/test_bi_kzg.rs | 89 --- poly_commit/tests/test_hyrax.rs | 93 --- poly_commit/tests/test_orion.rs | 141 ---- tree/Cargo.toml | 22 - tree/benches/tree.rs | 112 --- tree/src/leaf.rs | 51 -- tree/src/lib.rs | 17 - tree/src/node.rs | 55 -- tree/src/path.rs | 172 ----- tree/src/tests.rs | 64 -- tree/src/tree.rs | 310 --------- 49 files changed, 14 insertions(+), 6381 deletions(-) delete mode 100644 poly_commit/src/hyrax.rs delete mode 100644 poly_commit/src/hyrax/expander_api.rs delete mode 100644 poly_commit/src/hyrax/hyrax_impl.rs delete mode 100644 poly_commit/src/hyrax/pcs_trait_impl.rs delete mode 100644 poly_commit/src/hyrax/pedersen.rs delete mode 100644 poly_commit/src/kzg/bi_kzg.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/bivariate.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/expander_api.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/hyper_bikzg.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/hyper_bikzg_tests.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/pcs_trait_impl.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/structs_bi_kzg.rs delete mode 100644 poly_commit/src/kzg/bi_kzg/structs_hyper_bi_kzg.rs delete mode 100644 poly_commit/src/orion.rs delete mode 100644 poly_commit/src/orion/expander_api.rs delete mode 100644 poly_commit/src/orion/linear_code.rs delete mode 100644 poly_commit/src/orion/linear_code_tests.rs delete mode 100644 poly_commit/src/orion/mpi_utils.rs delete mode 100644 poly_commit/src/orion/pcs_trait_impl.rs delete mode 100644 poly_commit/src/orion/simd_field_impl.rs delete mode 100644 poly_commit/src/orion/simd_field_mpi_impl.rs delete mode 100644 poly_commit/src/orion/utils.rs delete mode 100644 poly_commit/src/orion/verify.rs delete mode 100644 poly_commit/tests/test_bi_kzg.rs delete mode 100644 poly_commit/tests/test_hyrax.rs delete mode 100644 poly_commit/tests/test_orion.rs delete mode 100644 tree/Cargo.toml delete mode 100644 tree/benches/tree.rs delete mode 100644 tree/src/leaf.rs delete mode 100644 tree/src/lib.rs delete mode 100644 tree/src/node.rs delete mode 100644 tree/src/path.rs delete mode 100644 tree/src/tests.rs delete mode 100644 tree/src/tree.rs diff --git a/Cargo.lock b/Cargo.lock index 56e8bf727..0d6296269 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1761,7 +1761,6 @@ dependencies = [ "thiserror", "transcript", "transpose", - "tree", "tynm", "utils", ] @@ -2369,20 +2368,6 @@ dependencies = [ "strength_reduce", ] -[[package]] -name = "tree" -version = "0.1.0" -dependencies = [ - "arith", - "ark-std", - "criterion", - "gf2", - "gf2_128", - "serdes", - "tiny-keccak", - "tynm", -] - [[package]] name = "try-lock" version = "0.2.5" diff --git a/Cargo.toml b/Cargo.toml index 829df8fd9..1154a72ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,24 +2,20 @@ members = [ "arith", # definitions of Field, Extensions, SIMDS "arith/babybear", - "arith/gf2", "arith/gf2_128", "arith/goldilocks", "arith/mersenne31", "arith/polynomials", "bin", # binary executables "circuit", - "config_macros", # proc macros used to declare a new config, this has to a separate crate due to rust compilation issues "gkr", "gkr_engine", # definitions of GKR engine and associated types "hasher", # definitions of FiatShamirFieldHasher, FiatShamirBytesHash, and associated types "poly_commit", "serdes", # serialization and deserialization of various data structures - "serdes_derive", "sumcheck", "crosslayer_prototype", "transcript", # instantiations of transcripts - "tree", "utils", ] resolver = "2" diff --git a/bin/src/exec.rs b/bin/src/exec.rs index 9bed10d5e..cbcdc98cc 100644 --- a/bin/src/exec.rs +++ b/bin/src/exec.rs @@ -36,9 +36,6 @@ async fn main() { root_println!(&mpi_config, "field type: {:?}", field_type); match (fs_hash_type.clone(), pcs_type.clone(), field_type.clone()) { - (FiatShamirHashType::SHA256, PolynomialCommitmentType::Orion, FieldType::M31x16) => { - run_command::(&expander_exec_args, &mpi_config).await; - } (FiatShamirHashType::Poseidon, PolynomialCommitmentType::Raw, FieldType::M31x16) => { run_command::(&expander_exec_args, &mpi_config).await; } @@ -48,24 +45,12 @@ async fn main() { (FiatShamirHashType::SHA256, PolynomialCommitmentType::Raw, FieldType::BN254) => { run_command::(&expander_exec_args, &mpi_config).await; } - (FiatShamirHashType::SHA256, PolynomialCommitmentType::Hyrax, FieldType::BN254) => { - run_command::(&expander_exec_args, &mpi_config).await; - } (FiatShamirHashType::MIMC5, PolynomialCommitmentType::KZG, FieldType::BN254) => { run_command::(&expander_exec_args, &mpi_config).await; } - (FiatShamirHashType::SHA256, PolynomialCommitmentType::Orion, FieldType::GF2Ext128) => { - run_command::(&expander_exec_args, &mpi_config).await; - } (FiatShamirHashType::SHA256, PolynomialCommitmentType::Raw, FieldType::GF2Ext128) => { run_command::(&expander_exec_args, &mpi_config).await; } - (FiatShamirHashType::SHA256, PolynomialCommitmentType::Orion, FieldType::Goldilocksx8) => { - run_command::(&expander_exec_args, &mpi_config).await; - } - (FiatShamirHashType::SHA256, PolynomialCommitmentType::Orion, FieldType::BabyBearx16) => { - run_command::(&expander_exec_args, &mpi_config).await; - } _ => panic!( "FS: {fs_hash_type:?}, PCS: {pcs_type:?}, Field: {field_type:?} setting is not yet integrated in expander-exec" ), diff --git a/bin/src/main.rs b/bin/src/main.rs index 2d94bd1a1..c1ee4954f 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -7,10 +7,8 @@ use std::{ use circuit::Circuit; use clap::Parser; use gkr::{ - BN254ConfigMIMC5KZG, BN254ConfigSha2Hyrax, BN254ConfigSha2Raw, GF2ExtConfigSha2Orion, - GF2ExtConfigSha2Raw, Goldilocksx8ConfigSha2Orion, Goldilocksx8ConfigSha2Raw, - M31x1ConfigSha2RawVanilla, M31x16ConfigSha2OrionSquare, M31x16ConfigSha2OrionVanilla, - M31x16ConfigSha2RawSquare, M31x16ConfigSha2RawVanilla, Prover, + BN254ConfigMIMC5KZG, BN254ConfigSha2Raw, GF2ExtConfigSha2Raw, Goldilocksx8ConfigSha2Raw, + M31x1ConfigSha2RawVanilla, M31x16ConfigSha2RawSquare, M31x16ConfigSha2RawVanilla, Prover, utils::{ KECCAK_BABYBEAR_CIRCUIT, KECCAK_BABYBEAR_WITNESS, KECCAK_BN254_CIRCUIT, KECCAK_BN254_WITNESS, KECCAK_GF2_CIRCUIT, KECCAK_GF2_WITNESS, KECCAK_GOLDILOCKS_CIRCUIT, @@ -73,15 +71,6 @@ fn main() { "poseidon" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => { - run_benchmark::(&args, mpi_config.clone()) - } - "poseidon" => { - run_benchmark::(&args, mpi_config.clone()) - } - _ => unreachable!(""), - }, _ => unreachable!("Unsupported PCS type for M31"), }, "fr" => match pcs_type { @@ -89,10 +78,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Hyrax => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, PolynomialCommitmentType::KZG => match args.circuit.as_str() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), @@ -104,10 +89,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, _ => unreachable!("Unsupported PCS type for GF2"), }, "goldilocks" => match pcs_type { @@ -115,10 +96,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, _ => unreachable!("Unsupported PCS type for Goldilocks"), }, _ => unreachable!(), diff --git a/bin/src/main_mpi.rs b/bin/src/main_mpi.rs index 8bc935ec2..1612287d7 100644 --- a/bin/src/main_mpi.rs +++ b/bin/src/main_mpi.rs @@ -3,10 +3,8 @@ use std::str::FromStr; use circuit::Circuit; use clap::Parser; use gkr::{ - BN254ConfigMIMC5KZG, BN254ConfigSha2Hyrax, BN254ConfigSha2Raw, GF2ExtConfigSha2Orion, - GF2ExtConfigSha2Raw, Goldilocksx8ConfigSha2Orion, Goldilocksx8ConfigSha2Raw, - M31x16ConfigSha2OrionSquare, M31x16ConfigSha2OrionVanilla, M31x16ConfigSha2RawSquare, - M31x16ConfigSha2RawVanilla, Prover, + BN254ConfigMIMC5KZG, BN254ConfigSha2Raw, GF2ExtConfigSha2Raw, Goldilocksx8ConfigSha2Raw, + M31x16ConfigSha2RawSquare, M31x16ConfigSha2RawVanilla, Prover, utils::{ KECCAK_BABYBEAR_CIRCUIT, KECCAK_BABYBEAR_WITNESS, KECCAK_BN254_CIRCUIT, KECCAK_BN254_WITNESS, KECCAK_GF2_CIRCUIT, KECCAK_GF2_WITNESS, KECCAK_GOLDILOCKS_CIRCUIT, @@ -67,15 +65,6 @@ fn main() { "poseidon" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => { - run_benchmark::(&args, mpi_config.clone()) - } - "poseidon" => { - run_benchmark::(&args, mpi_config.clone()) - } - _ => unreachable!(""), - }, _ => unreachable!("Unsupported PCS type for M31"), }, "fr" => match pcs_type { @@ -83,10 +72,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Hyrax => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, PolynomialCommitmentType::KZG => match args.circuit.as_str() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), @@ -98,10 +83,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, _ => unreachable!("Unsupported PCS type for GF2"), }, "goldilocks" => match pcs_type { @@ -109,10 +90,6 @@ fn main() { "keccak" => run_benchmark::(&args, mpi_config.clone()), _ => unreachable!(), }, - PolynomialCommitmentType::Orion => match args.circuit.as_str() { - "keccak" => run_benchmark::(&args, mpi_config.clone()), - _ => unreachable!(), - }, _ => unreachable!("Unsupported PCS type for Goldilocks"), }, _ => unreachable!(), diff --git a/config_macros/src/lib.rs b/config_macros/src/lib.rs index a7011a4ef..caf4b0dcb 100644 --- a/config_macros/src/lib.rs +++ b/config_macros/src/lib.rs @@ -110,20 +110,11 @@ fn parse_polynomial_commitment_type( "Raw".to_owned(), format!("RawExpanderGKR::<{field_config}>").to_owned(), ), - ("Hyrax", "BN254") => ("Hyrax".to_string(), "HyraxPCS::".to_string()), - ("KZG", "BN254") => ("KZG".to_owned(), "HyperBiKZGPCS::".to_string()), + ("KZG", "BN254") => ("KZG".to_owned(), "HyperUniKZGPCS::".to_string()), ("Orion", "GF2Ext128") => ( "Orion".to_owned(), format!("OrionPCSForGKR::<{field_config}, GF2x128>").to_owned(), ), - ("Orion", "M31x16") => ( - "Orion".to_owned(), - format!("OrionPCSForGKR::<{field_config}, M31x16>").to_owned(), - ), - ("Orion", "Goldilocksx8") => ( - "Orion".to_owned(), - format!("OrionPCSForGKR::<{field_config}, Goldilocksx8>").to_owned(), - ), _ => panic!( "Unknown polynomial commitment type in config macro expansion. PCS: '{pcs_type_str}', Field: '{field_type}'" ), diff --git a/config_macros/tests/macro_expansion.rs b/config_macros/tests/macro_expansion.rs index 26714091d..4920ccb33 100644 --- a/config_macros/tests/macro_expansion.rs +++ b/config_macros/tests/macro_expansion.rs @@ -1,7 +1,6 @@ use std::any::type_name; use config_macros::declare_gkr_config; -use gf2::GF2x128; use gkr_engine::{ BN254Config, BabyBearx16Config, FieldEngine, GF2ExtConfig, GKREngine, GKRScheme, Goldilocksx8Config, M31x16Config, MPIConfig, @@ -9,7 +8,7 @@ use gkr_engine::{ use gkr_hashers::{Keccak256hasher, MiMC5FiatShamirHasher, PoseidonFiatShamirHasher, SHA256hasher}; use halo2curves::bn256::Bn256; use mersenne31::M31x16; -use poly_commit::{HyperBiKZGPCS, OrionPCSForGKR, RawExpanderGKR}; +use poly_commit::{HyperUniKZGPCS, RawExpanderGKR}; use transcript::BytesHashTranscript; fn print_type_name() { @@ -32,13 +31,6 @@ fn main() { PolynomialCommitmentType::Raw, GKRScheme::Vanilla, ); - declare_gkr_config!( - M31ExtPoseidonOrionConfig, - FieldType::M31x16, - FiatShamirHashType::Poseidon, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, - ); declare_gkr_config!( BN254MIMCConfig, FieldType::BN254, @@ -60,13 +52,6 @@ fn main() { PolynomialCommitmentType::Raw, GKRScheme::Vanilla, ); - declare_gkr_config!( - GF2ExtKeccak256OrionConfig, - FieldType::GF2Ext128, - FiatShamirHashType::Keccak256, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, - ); declare_gkr_config!( GoldilocksExtSHA256Config, FieldType::Goldilocksx8, @@ -84,11 +69,9 @@ fn main() { print_type_name::(); print_type_name::(); - print_type_name::(); print_type_name::(); print_type_name::(); print_type_name::(); - print_type_name::(); print_type_name::(); print_type_name::(); } diff --git a/gkr/src/gkr_configs.rs b/gkr/src/gkr_configs.rs index 761118871..52eb7930a 100644 --- a/gkr/src/gkr_configs.rs +++ b/gkr/src/gkr_configs.rs @@ -1,14 +1,12 @@ use config_macros::declare_gkr_config; -use gf2::GF2x128; use gkr_engine::{ BN254Config, BabyBearx16Config, FieldEngine, GF2ExtConfig, GKREngine, GKRScheme, Goldilocksx1Config, Goldilocksx8Config, M31x16Config, M31x1Config, MPIConfig, }; use gkr_hashers::{MiMC5FiatShamirHasher, PoseidonFiatShamirHasher, SHA256hasher}; -use goldilocks::Goldilocksx8; -use halo2curves::bn256::{Bn256, G1Affine}; +use halo2curves::bn256::Bn256; use mersenne31::M31x16; -use poly_commit::{raw::RawExpanderGKR, HyperBiKZGPCS, HyraxPCS, OrionPCSForGKR}; +use poly_commit::{raw::RawExpanderGKR, HyperUniKZGPCS}; use transcript::BytesHashTranscript; // ============== M31 ============== @@ -34,20 +32,6 @@ declare_gkr_config!( PolynomialCommitmentType::Raw, GKRScheme::GkrSquare, ); -declare_gkr_config!( - pub M31x16ConfigSha2OrionVanilla, - FieldType::M31x16, - FiatShamirHashType::SHA256, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, -); -declare_gkr_config!( - pub M31x16ConfigSha2OrionSquare, - FieldType::M31x16, - FiatShamirHashType::SHA256, - PolynomialCommitmentType::Orion, - GKRScheme::GkrSquare, -); declare_gkr_config!( pub M31x16ConfigSha2RawVanilla, FieldType::M31x16, @@ -78,13 +62,6 @@ declare_gkr_config!( PolynomialCommitmentType::Raw, GKRScheme::Vanilla, ); -declare_gkr_config!( - pub BN254ConfigSha2Hyrax, - FieldType::BN254, - FiatShamirHashType::SHA256, - PolynomialCommitmentType::Hyrax, - GKRScheme::Vanilla, -); declare_gkr_config!( pub BN254ConfigSha2KZG, FieldType::BN254, @@ -101,13 +78,6 @@ declare_gkr_config!( ); // ============== GF2 ============== -declare_gkr_config!( - pub GF2ExtConfigSha2Orion, - FieldType::GF2Ext128, - FiatShamirHashType::SHA256, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, -); declare_gkr_config!( pub GF2ExtConfigSha2Raw, FieldType::GF2Ext128, @@ -134,14 +104,6 @@ declare_gkr_config!( GKRScheme::Vanilla, ); -declare_gkr_config!( - pub Goldilocksx8ConfigSha2Orion, - FieldType::Goldilocksx8, - FiatShamirHashType::SHA256, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, -); - // ============== Babybear ============== declare_gkr_config!( pub BabyBearx16ConfigSha2Raw, diff --git a/gkr/src/tests/gkr_correctness.rs b/gkr/src/tests/gkr_correctness.rs index 73b8e7e25..39ec55500 100644 --- a/gkr/src/tests/gkr_correctness.rs +++ b/gkr/src/tests/gkr_correctness.rs @@ -6,18 +6,15 @@ use std::{fs, panic}; use arith::Field; use circuit::Circuit; use config_macros::declare_gkr_config; -use gf2::GF2x128; use gkr_engine::{ root_println, BN254Config, BabyBearx16Config, FieldEngine, FieldType, GF2ExtConfig, GKREngine, GKRScheme, Goldilocksx1Config, Goldilocksx8Config, M31x16Config, M31x1Config, MPIConfig, MPIEngine, MPISharedMemory, }; use gkr_hashers::{Keccak256hasher, MiMC5FiatShamirHasher, PoseidonFiatShamirHasher, SHA256hasher}; -use halo2curves::bn256::{Bn256, G1Affine}; +use halo2curves::bn256::Bn256; use mersenne31::M31x16; -use poly_commit::{ - expander_pcs_init_testing_only, HyperBiKZGPCS, HyraxPCS, OrionPCSForGKR, RawExpanderGKR, -}; +use poly_commit::{expander_pcs_init_testing_only, HyperUniKZGPCS, RawExpanderGKR}; use rand::Rng; use serdes::ExpSerde; use sha2::Digest; @@ -82,13 +79,6 @@ fn test_gkr_correctness() { PolynomialCommitmentType::Raw, GKRScheme::Vanilla, ); - declare_gkr_config!( - C7, - FieldType::GF2Ext128, - FiatShamirHashType::Keccak256, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, - ); declare_gkr_config!( C8, FieldType::M31x16, @@ -96,20 +86,6 @@ fn test_gkr_correctness() { PolynomialCommitmentType::Raw, GKRScheme::Vanilla, ); - declare_gkr_config!( - C9, - FieldType::M31x16, - FiatShamirHashType::Poseidon, - PolynomialCommitmentType::Orion, - GKRScheme::Vanilla, - ); - declare_gkr_config!( - C10, - FieldType::BN254, - FiatShamirHashType::Keccak256, - PolynomialCommitmentType::Hyrax, - GKRScheme::Vanilla, - ); declare_gkr_config!( C11, FieldType::BN254, @@ -152,10 +128,7 @@ fn test_gkr_correctness() { test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); - test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); - test_gkr_correctness_helper::(mpi_config.clone(), None); - test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); test_gkr_correctness_helper::(mpi_config.clone(), None); diff --git a/gkr_engine/src/poly_commit/definition.rs b/gkr_engine/src/poly_commit/definition.rs index 7c3acb6aa..0086bed00 100644 --- a/gkr_engine/src/poly_commit/definition.rs +++ b/gkr_engine/src/poly_commit/definition.rs @@ -197,9 +197,7 @@ pub enum PolynomialCommitmentType { #[default] Raw, KZG, - Hyrax, - Orion, - FRI, + WHIR, } impl FromStr for PolynomialCommitmentType { @@ -209,9 +207,7 @@ impl FromStr for PolynomialCommitmentType { match s { "Raw" => Ok(PolynomialCommitmentType::Raw), "KZG" => Ok(PolynomialCommitmentType::KZG), - "Hyrax" => Ok(PolynomialCommitmentType::Hyrax), - "Orion" => Ok(PolynomialCommitmentType::Orion), - "FRI" => Ok(PolynomialCommitmentType::FRI), + "WHIR" => Ok(PolynomialCommitmentType::WHIR), _ => Err(ExpErrors::PCSTypeError(s.to_string())), } } diff --git a/poly_commit/Cargo.toml b/poly_commit/Cargo.toml index 9404942ef..292f77842 100644 --- a/poly_commit/Cargo.toml +++ b/poly_commit/Cargo.toml @@ -10,7 +10,7 @@ gkr_engine = { path = "../gkr_engine" } polynomials = { path = "../arith/polynomials"} serdes = { path = "../serdes" } transcript = { path = "../transcript" } -tree = { path = "../tree" } +# tree = { path = "../tree" } utils = { path = "../utils" } sumcheck = { path = "../sumcheck" } diff --git a/poly_commit/src/hyrax.rs b/poly_commit/src/hyrax.rs deleted file mode 100644 index 5ec743a81..000000000 --- a/poly_commit/src/hyrax.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod pedersen; -pub use pedersen::PedersenParams; - -mod hyrax_impl; -pub use hyrax_impl::{HyraxCommitment, HyraxOpening}; - -mod pcs_trait_impl; -pub use pcs_trait_impl::HyraxPCS; - -mod expander_api; diff --git a/poly_commit/src/hyrax/expander_api.rs b/poly_commit/src/hyrax/expander_api.rs deleted file mode 100644 index da56bf138..000000000 --- a/poly_commit/src/hyrax/expander_api.rs +++ /dev/null @@ -1,202 +0,0 @@ -use arith::ExtensionField; -use gkr_engine::{ - ExpanderPCS, ExpanderSingleVarChallenge, FieldEngine, MPIEngine, PolynomialCommitmentType, - StructuredReferenceString, Transcript, -}; -use halo2curves::{ff::PrimeField, group::UncompressedEncoding, msm, CurveAffine}; -use polynomials::{ - EqPolynomial, MultilinearExtension, MutRefMultiLinearPoly, MutableMultilinearExtension, - RefMultiLinearPoly, -}; -use serdes::ExpSerde; - -use crate::{ - hyrax::{ - hyrax_impl::{hyrax_commit, hyrax_open, hyrax_setup, hyrax_verify}, - pedersen::pedersen_commit, - }, - traits::BatchOpening, - HyraxCommitment, HyraxOpening, HyraxPCS, PedersenParams, -}; - -use super::hyrax_impl::{ - hyrax_multi_points_batch_open_internal, hyrax_multi_points_batch_verify_internal, -}; - -impl ExpanderPCS for HyraxPCS -where - G: FieldEngine, - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - const NAME: &'static str = "HyraxPCSForExpanderGKR"; - - const PCS_TYPE: PolynomialCommitmentType = PolynomialCommitmentType::Hyrax; - - type Params = usize; - type ScratchPad = (); - - type Commitment = HyraxCommitment; - type Opening = HyraxOpening; - type SRS = PedersenParams; - - type BatchOpening = BatchOpening; - - fn gen_params(n_input_vars: usize, _world_size: usize) -> Self::Params { - n_input_vars - } - - fn init_scratch_pad(_params: &Self::Params, _mpi_engine: &impl MPIEngine) -> Self::ScratchPad {} - - fn gen_srs( - params: &Self::Params, - mpi_engine: &impl MPIEngine, - rng: impl rand::RngCore, - ) -> Self::SRS { - let mpi_vars = mpi_engine.world_size().ilog2() as usize; - - hyrax_setup(*params, mpi_vars, rng) - } - - fn commit( - _params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl polynomials::MultilinearExtension, - _scratch_pad: &mut Self::ScratchPad, - ) -> Option { - let local_commit = hyrax_commit(proving_key, poly); - - if mpi_engine.is_single_process() { - return local_commit.into(); - } - - let mut global_commit: Vec = if mpi_engine.is_root() { - vec![C::default(); mpi_engine.world_size() * local_commit.0.len()] - } else { - vec![] - }; - - mpi_engine.gather_vec(&local_commit.0, &mut global_commit); - if !mpi_engine.is_root() { - return None; - } - - HyraxCommitment(global_commit).into() - } - - fn open( - _params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl polynomials::MultilinearExtension, - x: &ExpanderSingleVarChallenge, - _transcript: &mut impl Transcript, - _scratch_pad: &Self::ScratchPad, - ) -> Option { - if mpi_engine.is_single_process() { - let (_, open) = hyrax_open(proving_key, poly, &x.local_xs()); - return open.into(); - } - - let pedersen_len = proving_key.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let local_vars = x.local_xs(); - let mut local_basis = poly.hypercube_basis(); - let mut local_mle = MutRefMultiLinearPoly::from_ref(&mut local_basis); - local_mle.fix_variables(&local_vars[pedersen_vars..]); - - let eq_mpi_vars = EqPolynomial::build_eq_x_r(&x.r_mpi); - let combined_coeffs = mpi_engine.coef_combine_vec(&local_basis, &eq_mpi_vars); - - if !mpi_engine.is_root() { - return None; - } - - HyraxOpening(combined_coeffs).into() - } - - fn verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitment: &Self::Commitment, - x: &ExpanderSingleVarChallenge, - evals: ::ChallengeField, - _transcript: &mut impl Transcript, - opening: &Self::Opening, - ) -> bool { - if x.r_mpi.is_empty() { - return hyrax_verify(verifying_key, commitment, &x.local_xs(), evals, opening); - } - - let pedersen_len = verifying_key.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let local_vars = x.local_xs(); - let mut non_row_vars = local_vars[pedersen_vars..].to_vec(); - non_row_vars.extend_from_slice(&x.r_mpi); - - let eq_combination: Vec = EqPolynomial::build_eq_x_r(&non_row_vars); - let row_comm = msm::best_multiexp(&eq_combination, &commitment.0); - - if pedersen_commit(verifying_key, &opening.0) != row_comm.into() { - return false; - } - - let mut scratch = vec![C::Scalar::default(); opening.0.len()]; - evals - == RefMultiLinearPoly::from_ref(&opening.0) - .evaluate_with_buffer(&local_vars[..pedersen_vars], &mut scratch) - } - - /// Open a set of polynomials at a set of points. - fn multi_points_batch_open( - _params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - mle_poly_list: &[impl MultilinearExtension], - eval_points: &[ExpanderSingleVarChallenge], - _scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (Vec, Self::BatchOpening) { - if mpi_engine.is_single_process() || mpi_engine.is_root() { - let points = eval_points.iter().map(|x| x.local_xs()).collect::>(); - - hyrax_multi_points_batch_open_internal(proving_key, mle_poly_list, &points, transcript) - } else { - // todo: handle this case? - panic!("Hyrax PCS does not support multi-points batch opening in non-root processes"); - } - } - - /// Verify the opening of a set of polynomials at a set of points. - fn multi_points_batch_verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitments: &[impl AsRef], - x: &[ExpanderSingleVarChallenge], - evals: &[::ChallengeField], - batch_opening: &Self::BatchOpening, - transcript: &mut impl Transcript, - ) -> bool { - for x_i in x { - assert!( - x_i.r_mpi.is_empty(), - "Hyrax PCS does not support multi-points batch verification with MPI challenges" - ); - } - let points = x.iter().map(|x| x.local_xs()).collect::>(); - - hyrax_multi_points_batch_verify_internal( - verifying_key, - commitments, - &points, - evals, - batch_opening, - transcript, - ) - } -} diff --git a/poly_commit/src/hyrax/hyrax_impl.rs b/poly_commit/src/hyrax/hyrax_impl.rs deleted file mode 100644 index f17fa4cba..000000000 --- a/poly_commit/src/hyrax/hyrax_impl.rs +++ /dev/null @@ -1,429 +0,0 @@ -use arith::{ExtensionField, Field}; -use gkr_engine::Transcript; -use halo2curves::{ff::PrimeField, group::UncompressedEncoding, msm, CurveAffine}; -use polynomials::{ - EqPolynomial, MultilinearExtension, MutRefMultiLinearPoly, MutableMultilinearExtension, - RefMultiLinearPoly, -}; -use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -use serdes::ExpSerde; -use utils::timer::Timer; - -use crate::batching::{prover_merge_points, verifier_merge_points}; -use crate::traits::BatchOpening; -use crate::{ - hyrax::{ - pedersen::{pedersen_commit, pedersen_setup}, - PedersenParams, - }, - powers_series, -}; - -use super::HyraxPCS; - -pub(crate) fn hyrax_setup( - local_vars: usize, - mpi_vars: usize, - rng: impl rand::RngCore, -) -> PedersenParams -where - C::Scalar: PrimeField, - C::Base: PrimeField, -{ - let pedersen_vars = { - let total_vars = mpi_vars + local_vars; - let squared_row_var = total_vars.div_ceil(2); - - if mpi_vars + squared_row_var > total_vars { - total_vars - mpi_vars - } else { - squared_row_var - } - }; - - let pedersen_length = 1 << pedersen_vars; - - pedersen_setup(pedersen_length, rng) -} - -#[derive(Clone, Debug, Default)] -pub struct HyraxCommitment(pub Vec) -where - C: CurveAffine + ExpSerde + UncompressedEncoding; - -/// Jutification: from AsRef Documentation: -/// Ideally, `AsRef` would be reflexive, i.e. there would be an `impl AsRef for T` -/// Such a blanket implementation is currently *not* provided due to technical restrictions of -/// Rust's type system -impl AsRef> for HyraxCommitment -where - C: CurveAffine + ExpSerde + UncompressedEncoding, -{ - fn as_ref(&self) -> &HyraxCommitment { - self - } -} - -#[derive(Clone, Debug, Default)] -pub struct HyraxOpening(pub Vec) -where - C: CurveAffine + ExpSerde + UncompressedEncoding; - -impl ExpSerde for HyraxCommitment -where - C: CurveAffine + ExpSerde + UncompressedEncoding, -{ - fn serialize_into(&self, mut writer: W) -> serdes::SerdeResult<()> { - self.0.len().serialize_into(&mut writer)?; - for c in self.0.iter() { - let uncompressed = UncompressedEncoding::to_uncompressed(c); - writer.write_all(uncompressed.as_ref())?; - } - Ok(()) - } - - fn deserialize_from(mut reader: R) -> serdes::SerdeResult { - let num_elements = usize::deserialize_from(&mut reader)?; - let mut uncompressed = ::Uncompressed::default(); - - let mut elements = Vec::with_capacity(num_elements); - for _ in 0..num_elements { - reader.read_exact(uncompressed.as_mut())?; - elements.push( - C::from_uncompressed_unchecked(&uncompressed) - .into_option() - .ok_or(serdes::SerdeError::DeserializeError)?, - ); - } - Ok(Self(elements)) - } -} - -impl ExpSerde for HyraxOpening -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExpSerde, -{ - fn serialize_into(&self, writer: W) -> serdes::SerdeResult<()> { - self.0.serialize_into(writer) - } - - fn deserialize_from(reader: R) -> serdes::SerdeResult { - let buffer: Vec = as ExpSerde>::deserialize_from(reader)?; - Ok(Self(buffer)) - } -} - -pub(crate) fn hyrax_commit( - params: &PedersenParams, - mle_poly: &impl MultilinearExtension, -) -> HyraxCommitment -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - if mle_poly.hypercube_basis_ref().len() < params.msm_len() { - // usually the params should be smaller than mle_poly as we rearrange the polynomial as a - // matrix, and the params are the number of columns. - // - // However, in the batch opening cases, it is possible that some of the polynomials are in - // fact much smaller; whereas the params are determined according to the maximum - // polynomial size of the batch. - - let mut scalars = mle_poly.hypercube_basis(); - scalars.resize(params.msm_len(), C::Scalar::zero()); - let commitment = pedersen_commit(params, scalars.as_ref()); - - return HyraxCommitment(vec![commitment]); - } - - let commitments: Vec = mle_poly - .hypercube_basis_ref() - .chunks(params.msm_len()) - .map(|sub_hypercube| pedersen_commit(params, sub_hypercube)) - .collect(); - - HyraxCommitment(commitments) -} - -// NOTE(HS) the hyrax opening returns an eval and an opening against the eval_point on input. -pub(crate) fn hyrax_open( - params: &PedersenParams, - mle_poly: &impl MultilinearExtension, - eval_point: &[C::Scalar], -) -> (C::Scalar, HyraxOpening) -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let pedersen_len = params.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let mut local_basis = mle_poly.hypercube_basis(); - let mut local_mle = MutRefMultiLinearPoly::from_ref(&mut local_basis); - local_mle.fix_variables(&eval_point[pedersen_vars..]); - - let mut buffer = vec![C::Scalar::default(); local_mle.coeffs.len()]; - let final_eval = local_mle.evaluate_with_buffer(&eval_point[..pedersen_vars], &mut buffer); - - (final_eval, HyraxOpening(local_basis)) -} - -pub(crate) fn hyrax_verify( - params: &PedersenParams, - comm: &HyraxCommitment, - eval_point: &[C::Scalar], - eval: C::Scalar, - proof: &HyraxOpening, -) -> bool -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let pedersen_len = params.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let eq_combination: Vec = EqPolynomial::build_eq_x_r(&eval_point[pedersen_vars..]); - let row_comm = msm::best_multiexp(&eq_combination, &comm.0); - - let pedersen_commitment = pedersen_commit(params, &proof.0); - - if pedersen_commitment != row_comm.into() { - eprintln!("pedersen commitment not match",); - return false; - } - - let mut scratch = vec![C::Scalar::default(); proof.0.len()]; - let res = eval - == RefMultiLinearPoly::from_ref(&proof.0) - .evaluate_with_buffer(&eval_point[..pedersen_vars], &mut scratch); - if !res { - eprintln!("evaluation does not match"); - } - - res -} - -// batch open a set of mle_polys at the same point -// returns a set of eval points and a signle opening -// NOTE: random linear combination is used to merge polynomials -pub(crate) fn hyrax_batch_open( - params: &PedersenParams, - mle_poly_list: &[impl MultilinearExtension], - eval_point: &[C::Scalar], - transcript: &mut impl Transcript, -) -> (Vec, HyraxOpening) -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let len = mle_poly_list.len(); - let pedersen_len = params.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let challenge = transcript.generate_field_element::(); - let challenge_power = powers_series(&challenge, len); - - // the opening is the random linearly combine all the polynomials - let mut res = vec![C::Scalar::default(); 1 << pedersen_vars]; - let mut evals = vec![]; - let mut buffer = vec![C::Scalar::default(); 1 << pedersen_vars]; - - for (mle_poly, challenge) in mle_poly_list.iter().zip(challenge_power.iter()) { - let mut local_basis = mle_poly.hypercube_basis(); - let mut local_mle = MutRefMultiLinearPoly::from_ref(&mut local_basis); - local_mle.fix_variables(&eval_point[pedersen_vars..]); - - evals.push(local_mle.evaluate_with_buffer(&eval_point[..pedersen_vars], &mut buffer)); - - res.iter_mut() - .zip(local_mle.coeffs.iter()) - .for_each(|(r, c)| { - *r += *challenge * *c; - }); - } - (evals, HyraxOpening(res)) -} - -/// Batch verify a list of hyrax commitments/proofs that are opened at the same point. -pub(crate) fn hyrax_batch_verify( - params: &PedersenParams, - comm_list: &[HyraxCommitment], - eval_point: &[C::Scalar], - eval_list: &[C::Scalar], - batch_proof: &HyraxOpening, - transcript: &mut impl Transcript, -) -> bool -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let len = comm_list.len(); - assert_eq!(len, eval_list.len()); - - let pedersen_len = params.msm_len(); - let pedersen_vars = pedersen_len.ilog2() as usize; - - let challenge = transcript.generate_field_element::(); - let challenge_power = powers_series(&challenge, len); - - // random linear combination of the commitments - // for each i we want to do - // comm_i * challenge_i * eq_combination - // we do the second mul first -- this is a field op - // then we do a single multiexp to take advantage of Pippenger's algorithm - - let bases = comm_list - .iter() - .flat_map(|comm| comm.0.clone()) - .collect::>(); - - let mut scalars = vec![]; - let eq_combination: Vec = EqPolynomial::build_eq_x_r(&eval_point[pedersen_vars..]); - for c in challenge_power.iter() { - scalars.extend_from_slice(scale(&eq_combination, c).as_ref()); - } - - let row_comm = msm::best_multiexp(&scalars, &bases); - - if pedersen_commit(params, &batch_proof.0) != row_comm.into() { - eprintln!("commitment not matching"); - return false; - } - - // now we need to check the evaluations - let eval_sum = eval_list - .iter() - .zip(challenge_power.iter()) - .map(|(eval, challenge)| *eval * *challenge) - .sum::(); - - let mut scratch = vec![C::Scalar::default(); batch_proof.0.len()]; - eval_sum - == RefMultiLinearPoly::from_ref(&batch_proof.0) - .evaluate_with_buffer(&eval_point[..pedersen_vars], &mut scratch) -} - -#[inline(always)] -// scale a vector by a scalar -fn scale(base: &[F], scalar: &F) -> Vec { - base.iter().map(|x| *x * scalar).collect() -} - -/// Open a set of polynomials at a multiple points. -/// Requires the length of the polys to be the same as points. -/// Steps: -/// 1. get challenge point t from transcript -/// 2. build eq(t,i) for i in [0..k] -/// 3. build \tilde g_i(b) = eq(t, i) * f_i(b) -/// 4. compute \tilde eq_i(b) = eq(b, point_i) -/// 5. run sumcheck on \sum_i=1..k \tilde eq_i * \tilde g_i -/// 6. build g'(X) = \sum_i=1..k \tilde eq_i(a2) * \tilde g_i(X) where (a2) is the sumcheck's point -/// 7. open g'(X) at point (a2) -/// -/// Returns: -/// - the evaluations of the polynomials at their corresponding points -/// - the batch opening proof containing the sumcheck proof and the opening of g'(X) -#[allow(clippy::type_complexity)] -pub(crate) fn hyrax_multi_points_batch_open_internal( - proving_key: &PedersenParams, - polys: &[impl MultilinearExtension], - points: &[Vec], - transcript: &mut impl Transcript, -) -> (Vec, BatchOpening>) -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let timer = Timer::new("batch_opening", true); - // generate evals for each polynomial at its corresponding point - let eval_timer = Timer::new("eval all polys", true); - let evals: Vec = polys - .par_iter() - .zip_eq(points.par_iter()) - .map(|(poly, point)| poly.evaluate(point)) - .collect(); - eval_timer.stop(); - - let merger_timer = Timer::new("merging points", true); - let (new_point, g_prime, proof) = prover_merge_points::(polys, points, transcript); - merger_timer.stop(); - - // open g'(X) at point (a2) - // g_prime is a MultiLinearPoly, so we can use the hyrax_open function - let pcs_timer = Timer::new("hyrax_open", true); - let (_g_prime_eval, g_prime_proof) = hyrax_open(proving_key, &g_prime, &new_point); - pcs_timer.stop(); - - timer.stop(); - ( - evals, - BatchOpening { - sum_check_proof: proof, - g_prime_proof, - }, - ) -} - -/// Verify the opening of a set of polynomials at a single point. -/// Steps: -/// 1. get challenge point t from transcript -/// 2. build g' commitment -/// 3. ensure \sum_i eq(a2, point_i) * eq(t, ) * f_i_evals matches the sum via SumCheck -/// verification -/// 4. verify commitment -pub(crate) fn hyrax_multi_points_batch_verify_internal( - verifying_key: &PedersenParams, - commitments: &[impl AsRef>], - points: &[Vec], - values: &[C::Scalar], - batch_opening: &BatchOpening>, - transcript: &mut impl Transcript, -) -> bool -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - let a2 = batch_opening.sum_check_proof.export_point_to_expander(); - - let commitments = commitments - .iter() - .map(|c| c.as_ref().0.clone()) - .collect::>(); - - let (sumcheck_verified, tilde_g_eval, g_prime_commit) = verifier_merge_points( - &commitments, - points, - values, - &batch_opening.sum_check_proof, - transcript, - ); - if !sumcheck_verified { - return false; - } - - let g_prime_commit = HyraxCommitment(g_prime_commit); - - // verify commitment - hyrax_verify( - verifying_key, - &g_prime_commit, - a2.as_ref(), - tilde_g_eval, - &batch_opening.g_prime_proof, - ) -} diff --git a/poly_commit/src/hyrax/pcs_trait_impl.rs b/poly_commit/src/hyrax/pcs_trait_impl.rs deleted file mode 100644 index af80ffeb9..000000000 --- a/poly_commit/src/hyrax/pcs_trait_impl.rs +++ /dev/null @@ -1,159 +0,0 @@ -use std::marker::PhantomData; - -use arith::ExtensionField; -use gkr_engine::{StructuredReferenceString, Transcript}; -use halo2curves::{ff::PrimeField, group::UncompressedEncoding, CurveAffine}; -use polynomials::MultiLinearPoly; -use serdes::ExpSerde; - -use crate::traits::BatchOpening; -use crate::{ - hyrax::hyrax_impl::{hyrax_commit, hyrax_open, hyrax_setup, hyrax_verify}, - traits::BatchOpeningPCS, - HyraxCommitment, HyraxOpening, PedersenParams, PolynomialCommitmentScheme, -}; - -use super::hyrax_impl::hyrax_multi_points_batch_open_internal; -use super::hyrax_impl::hyrax_multi_points_batch_verify_internal; -use super::hyrax_impl::{hyrax_batch_open, hyrax_batch_verify}; - -pub struct HyraxPCS -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField, - C::ScalarExt: ExtensionField, -{ - _phantom_c: PhantomData, -} - -impl PolynomialCommitmentScheme for HyraxPCS -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - const NAME: &'static str = "HyraxPCS"; - - type Params = usize; - type Poly = MultiLinearPoly; - type EvalPoint = Vec; - type ScratchPad = (); - - type SRS = PedersenParams; - type Commitment = HyraxCommitment; - type Opening = HyraxOpening; - - fn init_scratch_pad(_params: &Self::Params) -> Self::ScratchPad {} - - fn gen_srs_for_testing(params: &Self::Params, rng: impl rand::RngCore) -> (Self::SRS, usize) { - (hyrax_setup(*params, 0, rng), *params) - } - - fn commit( - _params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - _scratch_pad: &mut Self::ScratchPad, - ) -> Self::Commitment { - hyrax_commit(proving_key, poly) - } - - fn open( - _params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - x: &Self::EvalPoint, - _scratch_pad: &Self::ScratchPad, - _transcript: &mut impl Transcript, - ) -> (C::Scalar, Self::Opening) { - hyrax_open(proving_key, poly, x) - } - - fn verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitment: &Self::Commitment, - x: &Self::EvalPoint, - v: C::Scalar, - opening: &Self::Opening, - _transcript: &mut impl Transcript, - ) -> bool { - hyrax_verify(verifying_key, commitment, x, v, opening) - } -} - -impl BatchOpeningPCS for HyraxPCS -where - C: CurveAffine + ExpSerde + UncompressedEncoding, - C::Scalar: ExtensionField + PrimeField, - C::ScalarExt: ExtensionField + PrimeField, - C::Base: PrimeField, -{ - fn single_point_batch_open( - _params: &Self::Params, - proving_key: &::PKey, - mle_poly_list: &[Self::Poly], - eval_point: &Self::EvalPoint, - _scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (Vec, Self::Opening) { - hyrax_batch_open(proving_key, mle_poly_list, eval_point, transcript) - } - - fn single_point_batch_verify( - _params: &Self::Params, - verifying_key: &::VKey, - comm_list: &[Self::Commitment], - eval_point: &Self::EvalPoint, - eval_list: &[C::Scalar], - batch_proof: &Self::Opening, - transcript: &mut impl Transcript, - ) -> bool { - hyrax_batch_verify( - verifying_key, - comm_list, - eval_point, - eval_list, - batch_proof, - transcript, - ) - } - - /// Open a set of polynomials at a multiple points. - /// Requires the length of the polys to be the same as points. - /// - /// Returns: - /// - the evaluations of the polynomials at their corresponding points - /// - the batch opening proof containing the sumcheck proof and the opening of g'(X) - fn multiple_points_batch_open( - _params: &Self::Params, - proving_key: &::PKey, - polys: &[Self::Poly], - points: &[Self::EvalPoint], - _scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (Vec, BatchOpening) { - hyrax_multi_points_batch_open_internal(proving_key, polys, points, transcript) - } - - /// Verify the opening of a set of polynomials at a single point. - fn multiple_points_batch_verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitments: &[Self::Commitment], - points: &[Self::EvalPoint], - values: &[C::Scalar], - batch_opening: &BatchOpening, - transcript: &mut impl Transcript, - ) -> bool { - hyrax_multi_points_batch_verify_internal( - verifying_key, - commitments, - points, - values, - batch_opening, - transcript, - ) - } -} diff --git a/poly_commit/src/hyrax/pedersen.rs b/poly_commit/src/hyrax/pedersen.rs deleted file mode 100644 index 9b23cae6a..000000000 --- a/poly_commit/src/hyrax/pedersen.rs +++ /dev/null @@ -1,143 +0,0 @@ -use gkr_engine::StructuredReferenceString; -use halo2curves::{ - ff::{Field, PrimeField}, - group::Curve, - msm, CurveAffine, -}; -use serdes::ExpSerde; - -#[derive(Clone, Debug, Default)] -pub struct PedersenParams -where - C: CurveAffine, - C::Base: PrimeField, -{ - pub bases: Vec, - pub pre_bases: Vec, -} - -impl ExpSerde for PedersenParams -where - C: CurveAffine, - C::Base: PrimeField, -{ - fn serialize_into(&self, mut writer: W) -> serdes::SerdeResult<()> { - // basis - { - self.bases.len().serialize_into(&mut writer)?; - for curve_element in self.bases.iter() { - // We want to write both x and y coordinates. - let coord = curve_element.coordinates().unwrap(); - // todo: this incurrs a cost to convert from Montogomery form. - coord.x().to_repr().serialize_into(&mut writer)?; - coord.y().to_repr().serialize_into(&mut writer)?; - } - } - // pre-computed bases - { - self.pre_bases.len().serialize_into(&mut writer)?; - - let mut normalized_bases = vec![C::default(); self.pre_bases.len()]; - C::Curve::batch_normalize(&self.pre_bases, &mut normalized_bases); - - for curve_element in normalized_bases.iter() { - // We want to write both x and y coordinates. - let coord = curve_element.coordinates().unwrap(); - // todo: this incurrs a cost to convert from Montogomery form. - coord.x().to_repr().serialize_into(&mut writer)?; - coord.y().to_repr().serialize_into(&mut writer)?; - } - } - Ok(()) - } - - fn deserialize_from(mut reader: R) -> serdes::SerdeResult { - let mut buf = [0u8; 32]; - - // bases - let bases = { - let bases_len = usize::deserialize_from(&mut reader)?; - let mut bases = Vec::with_capacity(bases_len); - for _ in 0..bases_len { - reader.read_exact(&mut buf)?; - let x = C::Base::from_repr(buf).unwrap(); - reader.read_exact(&mut buf)?; - let y = C::Base::from_repr(buf).unwrap(); - bases.push(C::from_xy(x, y).unwrap()) - } - bases - }; - - // pre-computed bases - let pre_bases = { - let pre_bases_len = usize::deserialize_from(&mut reader)?; - let mut pre_bases = Vec::with_capacity(pre_bases_len); - for _ in 0..pre_bases_len { - reader.read_exact(&mut buf)?; - let x = C::Base::from_repr(buf).unwrap(); - reader.read_exact(&mut buf)?; - let y = C::Base::from_repr(buf).unwrap(); - pre_bases.push(C::from_xy(x, y).unwrap().to_curve()) - } - pre_bases - }; - - Ok(Self { bases, pre_bases }) - } -} - -impl StructuredReferenceString for PedersenParams -where - C: CurveAffine, - C::Base: PrimeField, -{ - type PKey = Self; - type VKey = Self; - - fn into_keys(self) -> (Self::PKey, Self::VKey) { - (self.clone(), self) - } -} - -pub(crate) fn pedersen_setup(length: usize, mut rng: impl rand::RngCore) -> PedersenParams -where - C: CurveAffine, - C::Scalar: PrimeField, - C::Base: PrimeField, -{ - let proj_bases: Vec = (0..length) - .map(|_| { - let scalar = C::Scalar::random(&mut rng); - C::generator() * scalar - }) - .collect(); - - let mut bases = vec![C::default(); length]; - C::Curve::batch_normalize(&proj_bases, &mut bases); - let pre_bases = msm::multiexp_precompute(&bases, 12); - - PedersenParams { bases, pre_bases } -} - -pub(crate) fn pedersen_commit(params: &PedersenParams, coeffs: &[C::Scalar]) -> C -where - C: CurveAffine, - C::Scalar: PrimeField, - C::Base: PrimeField, -{ - let mut what = C::default().to_curve(); - - msm::multiexp_precompute_serial::(coeffs, ¶ms.pre_bases, 12, &mut what); - - what.to_affine() -} - -impl PedersenParams -where - C: CurveAffine, - C::Base: PrimeField, -{ - pub(crate) fn msm_len(&self) -> usize { - self.bases.len() - } -} diff --git a/poly_commit/src/kzg.rs b/poly_commit/src/kzg.rs index 0e9c97986..763426b3f 100644 --- a/poly_commit/src/kzg.rs +++ b/poly_commit/src/kzg.rs @@ -1,8 +1,5 @@ mod uni_kzg; pub use uni_kzg::*; -mod bi_kzg; -pub use bi_kzg::*; - mod utils; pub(crate) use utils::*; diff --git a/poly_commit/src/kzg/bi_kzg.rs b/poly_commit/src/kzg/bi_kzg.rs deleted file mode 100644 index c08c75d82..000000000 --- a/poly_commit/src/kzg/bi_kzg.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod structs_bi_kzg; -pub use structs_bi_kzg::*; - -mod structs_hyper_bi_kzg; -pub use structs_hyper_bi_kzg::*; - -mod bivariate; -pub use bivariate::*; - -mod hyper_bikzg; -pub use hyper_bikzg::*; - -#[cfg(test)] -mod hyper_bikzg_tests; - -mod pcs_trait_impl; -pub use pcs_trait_impl::HyperBiKZGPCS; - -mod expander_api; diff --git a/poly_commit/src/kzg/bi_kzg/bivariate.rs b/poly_commit/src/kzg/bi_kzg/bivariate.rs deleted file mode 100644 index ea08667bb..000000000 --- a/poly_commit/src/kzg/bi_kzg/bivariate.rs +++ /dev/null @@ -1,197 +0,0 @@ -use halo2curves::{ - ff::Field, - group::{prime::PrimeCurveAffine, Curve, Group}, - msm, - pairing::{MillerLoopResult, MultiMillerLoop}, - CurveAffine, -}; -use itertools::izip; -use serdes::ExpSerde; - -use crate::*; - -#[inline(always)] -pub fn generate_coef_form_bi_kzg_local_srs_for_testing( - local_length: usize, - distributed_parties: usize, - party_rank: usize, - mut rng: impl rand::RngCore, -) -> CoefFormBiKZGLocalSRS -where - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - assert!(local_length.is_power_of_two()); - assert!(distributed_parties.is_power_of_two()); - assert!(party_rank < distributed_parties); - - let tau_x = E::Fr::random(&mut rng); - let tau_y = E::Fr::random(&mut rng); - - let g1 = E::G1Affine::generator(); - - let tau_x_geometric_progression = powers_series(&tau_x, local_length); - let tau_y_geometric_progression = powers_series(&tau_y, distributed_parties); - - let g1_prog = g1.to_curve(); - let x_coeff_bases = { - let mut proj_bases = vec![g1_prog * tau_y_geometric_progression[party_rank]; local_length]; - izip!(&mut proj_bases, &tau_x_geometric_progression).for_each(|(b, tau_xi)| *b *= *tau_xi); - - let mut g_bases = vec![E::G1Affine::default(); local_length]; - E::G1::batch_normalize(&proj_bases, &mut g_bases); - - drop(proj_bases); - g_bases - }; - - let tau_x_srs = CoefFormUniKZGSRS:: { - powers_of_tau: x_coeff_bases, - tau_g2: (E::G2Affine::generator() * tau_x).into(), - }; - - let y_coeff_bases = { - let mut proj_bases = vec![g1_prog; distributed_parties]; - izip!(&mut proj_bases, &tau_y_geometric_progression).for_each(|(b, tau_yi)| *b *= *tau_yi); - - let mut g_bases = vec![E::G1Affine::default(); distributed_parties]; - E::G1::batch_normalize(&proj_bases, &mut g_bases); - - drop(proj_bases); - g_bases - }; - - let tau_y_srs = CoefFormUniKZGSRS:: { - powers_of_tau: y_coeff_bases, - tau_g2: (E::G2Affine::generator() * tau_y).into(), - }; - - CoefFormBiKZGLocalSRS { - tau_x_srs, - tau_y_srs, - } -} - -#[inline(always)] -pub fn coeff_form_bi_kzg_open_leader( - srs: &CoefFormBiKZGLocalSRS, - evals_and_opens: &[(E::Fr, E::G1Affine)], - beta: E::Fr, -) -> (E::Fr, BiKZGProof) -where - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - assert_eq!(srs.tau_y_srs.powers_of_tau.len(), evals_and_opens.len()); - - let x_open: E::G1 = evals_and_opens.iter().map(|(_, o)| o.to_curve()).sum(); - let gammas: Vec = evals_and_opens.iter().map(|(e, _)| *e).collect(); - - let (div, eval) = univariate_degree_one_quotient(&gammas, beta); - - let mut y_open = E::G1::generator() * E::Fr::ZERO; - msm::multiexp_serial(&div, &srs.tau_y_srs.powers_of_tau[..div.len()], &mut y_open); - - ( - eval, - BiKZGProof { - quotient_x: x_open.into(), - quotient_y: y_open.into(), - }, - ) -} - -#[inline(always)] -pub fn coeff_form_bi_kzg_verify( - vk: BiKZGVerifierParam, - comm: E::G1Affine, - alpha: E::Fr, - beta: E::Fr, - eval: E::Fr, - opening: BiKZGProof, -) -> bool -where - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - let g1_eval: E::G1Affine = (E::G1Affine::generator() * eval).into(); - let g2_alpha: E::G2 = E::G2Affine::generator() * alpha; - let g2_beta: E::G2 = E::G2Affine::generator() * beta; - - let gt_result = E::multi_miller_loop(&[ - ( - &opening.quotient_x, - &(vk.tau_x_g2.to_curve() - g2_alpha).to_affine().into(), - ), - ( - &opening.quotient_y, - &(vk.tau_y_g2.to_curve() - g2_beta).to_affine().into(), - ), - (&(g1_eval - comm).into(), &E::G2Affine::generator().into()), - ]); - - gt_result.final_exponentiation().is_identity().into() -} - -#[cfg(test)] -mod tests { - use ark_std::test_rng; - use halo2curves::{ - bn256::{Bn256, Fr, G1Affine, G1}, - ff::Field, - group::{prime::PrimeCurveAffine, Curve}, - }; - use itertools::izip; - - use crate::*; - - #[test] - fn test_coefficient_form_bivariate_kzg_e2e() { - let x_degree = 15; - let y_degree = 7; - - let party_srs: Vec> = (0..=y_degree) - .map(|rank| { - let mut rng = test_rng(); - generate_coef_form_bi_kzg_local_srs_for_testing( - x_degree + 1, - y_degree + 1, - rank, - &mut rng, - ) - }) - .collect(); - - let mut rng = test_rng(); - let xy_coeffs: Vec> = (0..=y_degree) - .map(|_| (0..=x_degree).map(|_| Fr::random(&mut rng)).collect()) - .collect(); - - let commitments: Vec<_> = izip!(&party_srs, &xy_coeffs) - .map(|(srs, x_coeffs)| coeff_form_uni_kzg_commit(&srs.tau_x_srs, x_coeffs)) - .collect(); - - let global_commitment_g1: G1 = commitments.iter().map(|c| c.to_curve()).sum::(); - let global_commitment: G1Affine = global_commitment_g1.to_affine(); - - let alpha = Fr::random(&mut rng); - let evals_and_opens: Vec<(Fr, G1Affine)> = izip!(&party_srs, &xy_coeffs) - .map(|(srs, x_coeffs)| coeff_form_uni_kzg_open_eval(&srs.tau_x_srs, x_coeffs, alpha)) - .collect(); - - let beta = Fr::random(&mut rng); - let (final_eval, final_opening) = - coeff_form_bi_kzg_open_leader(&party_srs[0], &evals_and_opens, beta); - - let vk: BiKZGVerifierParam = From::from(&party_srs[0]); - - assert!(coeff_form_bi_kzg_verify( - vk, - global_commitment, - alpha, - beta, - final_eval, - final_opening, - )); - } -} diff --git a/poly_commit/src/kzg/bi_kzg/expander_api.rs b/poly_commit/src/kzg/bi_kzg/expander_api.rs deleted file mode 100644 index 07755873e..000000000 --- a/poly_commit/src/kzg/bi_kzg/expander_api.rs +++ /dev/null @@ -1,170 +0,0 @@ -use arith::ExtensionField; -use gkr_engine::{ - ExpanderPCS, ExpanderSingleVarChallenge, FieldEngine, MPIEngine, PolynomialCommitmentType, - StructuredReferenceString, Transcript, -}; -use halo2curves::{ - ff::PrimeField, - group::prime::PrimeCurveAffine, - pairing::{Engine, MultiMillerLoop}, - CurveAffine, -}; -use polynomials::MultilinearExtension; -use serdes::ExpSerde; - -use crate::{ - utils::{ - lift_expander_challenge_to_n_vars, lift_poly_and_expander_challenge_to_n_vars, - lift_poly_to_n_vars, - }, - *, -}; - -impl ExpanderPCS for HyperBiKZGPCS -where - G: FieldEngine, - E: Engine + MultiMillerLoop, - E::Fr: ExtensionField + PrimeField, - E::G1Affine: ExpSerde + Default + CurveAffine, - E::G2Affine: ExpSerde + Default + CurveAffine, -{ - const NAME: &'static str = "HyperBiKZGForExpander"; - - const PCS_TYPE: PolynomialCommitmentType = PolynomialCommitmentType::KZG; - - type Commitment = BiKZGCommitment; - type Opening = HyperBiKZGOpening; - type Params = usize; - type SRS = CoefFormBiKZGLocalSRS; - type ScratchPad = (); - type BatchOpening = (); - - fn init_scratch_pad(_params: &Self::Params, _mpi_engine: &impl MPIEngine) -> Self::ScratchPad {} - - fn gen_params(n_input_vars: usize, _world_size: usize) -> Self::Params { - std::cmp::max(n_input_vars, Self::MINIMUM_SUPPORTED_NUM_VARS) - } - - fn gen_srs( - params: &Self::Params, - mpi_engine: &impl MPIEngine, - rng: impl rand::RngCore, - ) -> Self::SRS { - let local_num_vars = *params; - - let x_degree_po2 = 1 << local_num_vars; - let y_degree_po2 = mpi_engine.world_size(); - let rank = mpi_engine.world_rank(); - - generate_coef_form_bi_kzg_local_srs_for_testing(x_degree_po2, y_degree_po2, rank, rng) - } - - fn commit( - _params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl polynomials::MultilinearExtension, - _scratch_pad: &mut Self::ScratchPad, - ) -> Option { - // The minimum supported number of variables is 1. - // If the polynomial has no variables, we lift it to a polynomial with 1 variable. - if poly.num_vars() < Self::MINIMUM_SUPPORTED_NUM_VARS { - let poly = lift_poly_to_n_vars(poly, Self::MINIMUM_SUPPORTED_NUM_VARS); - return >::commit( - _params, - mpi_engine, - proving_key, - &poly, - _scratch_pad, - ); - }; - - let local_commitment = - coeff_form_uni_kzg_commit(&proving_key.tau_x_srs, poly.hypercube_basis_ref()); - - if mpi_engine.is_single_process() { - return BiKZGCommitment(local_commitment).into(); - } - - let local_g1 = local_commitment.to_curve(); - let mut root_gathering_commits: Vec = vec![local_g1; mpi_engine.world_size()]; - mpi_engine.gather_vec(&[local_g1], &mut root_gathering_commits); - - if !mpi_engine.is_root() { - return None; - } - - let final_commit = root_gathering_commits.iter().sum::().into(); - - BiKZGCommitment(final_commit).into() - } - - fn open( - _params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl MultilinearExtension, - x: &ExpanderSingleVarChallenge, - transcript: &mut impl Transcript, - _scratch_pad: &Self::ScratchPad, - ) -> Option { - if poly.num_vars() < Self::MINIMUM_SUPPORTED_NUM_VARS { - let (poly, x) = lift_poly_and_expander_challenge_to_n_vars( - poly, - x, - Self::MINIMUM_SUPPORTED_NUM_VARS, - ); - return >::open( - _params, - mpi_engine, - proving_key, - &poly, - &x, - transcript, - _scratch_pad, - ); - }; - - coeff_form_hyper_bikzg_open( - proving_key, - mpi_engine, - poly, - &x.local_xs(), - &x.r_mpi, - transcript, - ) - } - - fn verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitment: &Self::Commitment, - x: &ExpanderSingleVarChallenge, - v: ::ChallengeField, - transcript: &mut impl Transcript, - opening: &Self::Opening, - ) -> bool { - if x.rz.len() < Self::MINIMUM_SUPPORTED_NUM_VARS { - let x = lift_expander_challenge_to_n_vars(x, Self::MINIMUM_SUPPORTED_NUM_VARS); - return >::verify( - _params, - verifying_key, - commitment, - &x, - v, - transcript, - opening, - ); - }; - - coeff_form_hyper_bikzg_verify( - verifying_key, - &x.local_xs(), - &x.r_mpi, - v, - commitment.0, - opening, - transcript, - ) - } -} diff --git a/poly_commit/src/kzg/bi_kzg/hyper_bikzg.rs b/poly_commit/src/kzg/bi_kzg/hyper_bikzg.rs deleted file mode 100644 index 099260c91..000000000 --- a/poly_commit/src/kzg/bi_kzg/hyper_bikzg.rs +++ /dev/null @@ -1,650 +0,0 @@ -// NOTE(HS): the algorithm port for HyperKZG to "HyperBiKZG" is sketched here: -// https://drive.google.com/file/d/1NcRnqdwFLcLi77DvSZH28QwslTuBVyb4/ - -use std::{io::Cursor, iter}; - -use arith::ExtensionField; -use gkr_engine::{MPIEngine, Transcript}; -use halo2curves::{ - ff::Field, - group::{prime::PrimeCurveAffine, Curve, Group, GroupEncoding}, - pairing::MultiMillerLoop, - CurveAffine, -}; -use itertools::{chain, izip}; -use polynomials::MultilinearExtension; -use serdes::ExpSerde; -use transcript::{transcript_root_broadcast, transcript_verifier_sync}; - -use crate::*; - -pub fn coeff_form_hyper_bikzg_open( - srs: &CoefFormBiKZGLocalSRS, - mpi_engine: &impl MPIEngine, - coeffs: &impl MultilinearExtension, - local_alphas: &[E::Fr], - mpi_alphas: &[E::Fr], - fs_transcript: &mut impl Transcript, -) -> Option> -where - E: MultiMillerLoop, - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, - E::Fr: ExtensionField, -{ - // NOTE(HS) deteriorate to vanilla HyperKZG if mpi_alphas is empty, namely single party setting - // since there is no other mpi variables, then the party running is the leader - if mpi_alphas.is_empty() { - let (_, hyperkzg_opening) = coeff_form_uni_hyperkzg_open( - &srs.tau_x_srs, - coeffs.hypercube_basis_ref(), - local_alphas, - fs_transcript, - ); - - let hyper_bikzg_opening: HyperBiKZGOpening = hyperkzg_opening.into(); - return hyper_bikzg_opening.into(); - } - - // - // Locally fold local variables, then commit to construct the poly oracles - // - - let (local_folded_x_oracle_commits, local_folded_x_oracle_coeffs) = - coeff_form_hyperkzg_local_poly_oracles( - &srs.tau_x_srs, - coeffs.hypercube_basis_ref(), - local_alphas, - ); - - let local_final_eval_at_x = { - let last_coeffs = local_folded_x_oracle_coeffs.last().unwrap().clone(); - let last_alpha = local_alphas[local_alphas.len() - 1]; - (E::Fr::ONE - last_alpha) * last_coeffs[0] + last_alpha * last_coeffs[1] - }; - - // - // Leader party gathering evals and oracle commitments - // - - let mut root_gathering_folded_oracle_commits: Vec = - vec![E::G1Affine::default(); mpi_engine.world_size() * local_folded_x_oracle_commits.len()]; - let mut final_evals_at_x: Vec = vec![E::Fr::ZERO; mpi_engine.world_size()]; - - mpi_engine.gather_vec( - &local_folded_x_oracle_commits, - &mut root_gathering_folded_oracle_commits, - ); - mpi_engine.gather_vec(&[local_final_eval_at_x], &mut final_evals_at_x); - - // - // Leader party collect oracle commitments, sum them up for folded oracles - // - - let mut folded_x_oracle_commits: Vec = Vec::new(); - let mut y_oracle_commit: E::G1Affine = E::G1Affine::default(); - - if mpi_engine.is_root() { - let g1_zero = E::G1Affine::default().to_curve(); - let mut folded_x_coms_g1 = vec![g1_zero; local_folded_x_oracle_commits.len()]; - - root_gathering_folded_oracle_commits - .chunks(local_folded_x_oracle_commits.len()) - .for_each(|folded_oracles| { - izip!(&mut folded_x_coms_g1, folded_oracles) - .for_each(|(x_com_i, oracle_i)| *x_com_i += oracle_i.to_curve()) - }); - - folded_x_oracle_commits = vec![E::G1Affine::default(); folded_x_coms_g1.len()]; - E::G1::batch_normalize(&folded_x_coms_g1, &mut folded_x_oracle_commits); - - y_oracle_commit = coeff_form_uni_kzg_commit(&srs.tau_y_srs, &final_evals_at_x); - } - - // - // The leader party continues on folding over "final_evals" over only y variables. - // - - let mut folded_y_oracle_commits: Vec = Vec::new(); - let mut folded_y_oracle_coeffs: Vec> = Vec::new(); - - if mpi_engine.is_root() { - (folded_y_oracle_commits, folded_y_oracle_coeffs) = - coeff_form_hyperkzg_local_poly_oracles(&srs.tau_y_srs, &final_evals_at_x, mpi_alphas); - } - - // - // The leader party feeds all folded oracles into RO, then sync party's transcript state - // - - let mut folded_oracle_commitments: Vec = Vec::new(); - - if mpi_engine.is_root() { - folded_oracle_commitments = { - let mut temp = folded_x_oracle_commits.clone(); - temp.push(y_oracle_commit); - temp.extend_from_slice(&folded_y_oracle_commits); - temp - }; - - chain!( - &folded_x_oracle_commits, - iter::once(&y_oracle_commit), - &folded_y_oracle_commits, - ) - .for_each(|f| fs_transcript.append_u8_slice(f.to_bytes().as_ref())); - } - - transcript_root_broadcast(fs_transcript, mpi_engine); - - let beta_x = fs_transcript.generate_field_element::(); - let beta_y = fs_transcript.generate_field_element::(); - - // - // Local parties run HyperKZG evals at beta_x, -beta_x, beta_x^2 over folded coeffs - // - - let local_folded_x_evals: HyperKZGLocalEvals = coeff_form_hyperkzg_local_evals( - coeffs.hypercube_basis_ref(), - &local_folded_x_oracle_coeffs, - local_alphas, - beta_x, - ); - - let local_exported_folded_x_evals: HyperKZGExportedLocalEvals = - local_folded_x_evals.clone().into(); - - // - // Collect all exported local folded evals at x to the leader party - // - - let mut root_gathering_exported_folded_x_evals: Vec> = - vec![local_exported_folded_x_evals.clone(); mpi_engine.world_size()]; - let mut root_aggregated_x_evals = HyperKZGAggregatedEvals::::default(); - let mut root_folded_y_evals = HyperKZGLocalEvals::::default(); - - { - let mut local_exported_folded_x_evals_bytes: Vec = Vec::new(); - local_exported_folded_x_evals - .serialize_into(&mut local_exported_folded_x_evals_bytes) - .unwrap(); - - let mut gathering_buffer = - vec![0u8; mpi_engine.world_size() * local_exported_folded_x_evals_bytes.len()]; - - mpi_engine.gather_vec(&local_exported_folded_x_evals_bytes, &mut gathering_buffer); - - if mpi_engine.is_root() { - izip!( - &mut root_gathering_exported_folded_x_evals, - gathering_buffer.chunks(local_exported_folded_x_evals_bytes.len()) - ) - .for_each(|(es, bs)| { - let mut cursor = Cursor::new(bs.to_vec()); - *es = HyperKZGExportedLocalEvals::::deserialize_from(&mut cursor).unwrap(); - }) - } - } - - // - // Leader aggregates all local exported evaluations (at x) by evaluating at y - // by three points: beta_y, -beta_y, beta_y^2, then fold the final evals at x, - // which is degree 0 for variable x, along variable y. - // - - if mpi_engine.is_root() { - root_aggregated_x_evals = HyperKZGAggregatedEvals::new_from_exported_evals( - &root_gathering_exported_folded_x_evals, - beta_y, - ); - - root_folded_y_evals = coeff_form_hyperkzg_local_evals( - &final_evals_at_x, - &folded_y_oracle_coeffs, - mpi_alphas, - beta_y, - ); - } - - // - // The leader party feeds all evals into RO, then sync party's transcript state - // - - if mpi_engine.is_root() { - root_aggregated_x_evals.append_to_transcript(fs_transcript); - root_folded_y_evals.append_to_transcript(fs_transcript); - } - - transcript_root_broadcast(fs_transcript, mpi_engine); - - let gamma = fs_transcript.generate_field_element::(); - - // - // The leader party linear combines folded coeffs at y with gamma, - // then broadcast the coeffs back to local. - // - - let mut leader_gamma_aggregated_y_coeffs: Vec = - vec![E::Fr::ZERO; mpi_engine.world_size()]; - - if mpi_engine.is_root() { - leader_gamma_aggregated_y_coeffs = { - let gamma_n = gamma.pow_vartime([local_alphas.len() as u64]); - let mut temp = coeff_form_hyperkzg_local_oracle_polys_aggregate::( - &final_evals_at_x, - &folded_y_oracle_coeffs, - gamma, - ); - temp.iter_mut().for_each(|t| *t *= gamma_n); - temp - }; - } - - // TODO(HS) can be improved to broadcast a vec, returning a coeff to each party - { - let mut serialized_y_coeffs: Vec = Vec::new(); - leader_gamma_aggregated_y_coeffs - .serialize_into(&mut serialized_y_coeffs) - .unwrap(); - - mpi_engine.root_broadcast_bytes(&mut serialized_y_coeffs); - leader_gamma_aggregated_y_coeffs = { - let mut cursor = Cursor::new(serialized_y_coeffs); - Vec::deserialize_from(&mut cursor).unwrap() - }; - } - - // - // Local party compute the linear combined folded coeffs at x with gamma, - // then the degree2 Lagrange over beta_x, -beta_x, beta_x^2, - // then vanish the local aggregated x coeffs at the three points above, - // and commit to the final quotient poly - // - - let mut local_gamma_aggregated_x_coeffs = { - let mut f_gamma_local = coeff_form_hyperkzg_local_oracle_polys_aggregate::( - coeffs.hypercube_basis_ref(), - &local_folded_x_oracle_coeffs, - gamma, - ); - - f_gamma_local[0] += leader_gamma_aggregated_y_coeffs[mpi_engine.world_rank()]; - f_gamma_local - }; - - let local_lagrange_degree2_at_x = { - let mut local_degree_2 = - local_folded_x_evals.interpolate_degree2_aggregated_evals(beta_x, gamma); - - local_degree_2[0] += leader_gamma_aggregated_y_coeffs[mpi_engine.world_rank()]; - local_degree_2 - }; - - let local_gamma_aggregated_x_quotient = { - let mut nom = local_gamma_aggregated_x_coeffs.clone(); - polynomial_add(&mut nom, -E::Fr::ONE, &local_lagrange_degree2_at_x); - univariate_roots_quotient(nom, &[beta_x, -beta_x, beta_x * beta_x]) - }; - - let local_gamma_aggregated_x_quotient_commitment_g1: E::G1 = - coeff_form_uni_kzg_commit(&srs.tau_x_srs, &local_gamma_aggregated_x_quotient).to_curve(); - - // - // Leader collect all the quotient commitment at x, sum it up and feed it to RO, - // then sync transcript state - // - - let mut root_gathering_gamma_aggregated_x_quotient_commitment_g1s: Vec = - vec![E::G1::generator(); mpi_engine.world_size()]; - mpi_engine.gather_vec( - &[local_gamma_aggregated_x_quotient_commitment_g1], - &mut root_gathering_gamma_aggregated_x_quotient_commitment_g1s, - ); - - let mut gamma_aggregated_x_quotient_commitment: E::G1Affine = E::G1Affine::default(); - - if mpi_engine.is_root() { - gamma_aggregated_x_quotient_commitment = - root_gathering_gamma_aggregated_x_quotient_commitment_g1s - .iter() - .sum::() - .to_affine(); - - fs_transcript.append_u8_slice(gamma_aggregated_x_quotient_commitment.to_bytes().as_ref()); - } - - transcript_root_broadcast(fs_transcript, mpi_engine); - - let delta_x = fs_transcript.generate_field_element::(); - - // - // Locally compute the Lagrange-degree2 interpolation at delta_x, pool at leader - // - - let mut degree2_evals_at_delta_x: Vec = vec![E::Fr::ZERO; mpi_engine.world_size()]; - - let local_degree2_eval_at_delta_x = local_lagrange_degree2_at_x[0] - + local_lagrange_degree2_at_x[1] * delta_x - + local_lagrange_degree2_at_x[2] * delta_x * delta_x; - - mpi_engine.gather_vec( - &[local_degree2_eval_at_delta_x], - &mut degree2_evals_at_delta_x, - ); - - // - // Leader does similar thing - quotient at beta_y, -beta_y, beta_y^2, - // commit the quotient polynomial commitment at y, feed it to RO, - // then sync transcript state - // - - let mut leader_quotient_y_coeffs: Vec = vec![E::Fr::ZERO; mpi_engine.world_size()]; - let mut leader_quotient_y_commitment: E::G1Affine = E::G1Affine::default(); - - if mpi_engine.is_root() { - let num_y_coeffs = mpi_engine.world_size(); - - // NOTE(HS) interpolate at beta_y, beta_y2, -beta_y on lagrange_degree2_delta_x - let lagrange_degree2_delta_y = { - let pos_beta_y_pow_series = powers_series(&beta_y, num_y_coeffs); - let neg_beta_y_pow_series = powers_series(&(-beta_y), num_y_coeffs); - let beta_y2_pow_series = powers_series(&(beta_y * beta_y), num_y_coeffs); - - let at_beta_y = univariate_evaluate(°ree2_evals_at_delta_x, &pos_beta_y_pow_series); - let at_neg_beta_y = - univariate_evaluate(°ree2_evals_at_delta_x, &neg_beta_y_pow_series); - let at_beta_y2 = univariate_evaluate(°ree2_evals_at_delta_x, &beta_y2_pow_series); - - coeff_form_degree2_lagrange( - [beta_y, -beta_y, beta_y * beta_y], - [at_beta_y, at_neg_beta_y, at_beta_y2], - ) - }; - - leader_quotient_y_coeffs = { - let mut nom = degree2_evals_at_delta_x.clone(); - polynomial_add(&mut nom, -E::Fr::ONE, &lagrange_degree2_delta_y); - univariate_roots_quotient(nom, &[beta_y, -beta_y, beta_y * beta_y]) - }; - - leader_quotient_y_commitment = - coeff_form_uni_kzg_commit(&srs.tau_y_srs, &leader_quotient_y_coeffs); - - fs_transcript.append_u8_slice(leader_quotient_y_commitment.to_bytes().as_ref()); - } - - transcript_root_broadcast(fs_transcript, mpi_engine); - - let delta_y = fs_transcript.generate_field_element::(); - - // - // Leader send out the quotient on y coefficients back to local parties - // - - // TODO(HS) can be better if the root only send corresponding coeffs to the parties - { - let mut serialized_y_quotient_coeffs: Vec = Vec::new(); - leader_quotient_y_coeffs - .serialize_into(&mut serialized_y_quotient_coeffs) - .unwrap(); - - mpi_engine.root_broadcast_bytes(&mut serialized_y_quotient_coeffs); - leader_quotient_y_coeffs = { - let mut cursor = Cursor::new(serialized_y_quotient_coeffs); - Vec::deserialize_from(&mut cursor).unwrap() - }; - leader_quotient_y_coeffs.resize(mpi_engine.world_size(), E::Fr::ZERO); - } - - // - // Final step for local - trip off the prior quotients at x and y on \pm beta and beta^2 - // - - // NOTE(HS) f_gamma_s - (delta_x - beta_x) ... (delta_x - beta_x2) f_gamma_quotient_s - // - (delta_y - beta_y) ... (delta_y - beta_y2) lagrange_quotient_y - let delta_x_denom = (delta_x - beta_x) * (delta_x - beta_x * beta_x) * (delta_x + beta_x); - let delta_y_denom = (delta_y - beta_y) * (delta_y - beta_y * beta_y) * (delta_y + beta_y); - - polynomial_add( - &mut local_gamma_aggregated_x_coeffs, - -delta_x_denom, - &local_gamma_aggregated_x_quotient, - ); - local_gamma_aggregated_x_coeffs[0] -= - delta_y_denom * leader_quotient_y_coeffs[mpi_engine.world_rank()]; - - // - // BiKZG commit to the last bivariate poly - // - - let mut gathered_eval_opens: Vec<(E::Fr, E::G1Affine)> = - vec![(E::Fr::ZERO, E::G1Affine::default()); mpi_engine.world_size()]; - let local_eval_open = - coeff_form_uni_kzg_open_eval(&srs.tau_x_srs, &local_gamma_aggregated_x_coeffs, delta_x); - - mpi_engine.gather_vec(&[local_eval_open], &mut gathered_eval_opens); - - if !mpi_engine.is_root() { - return None; - } - - let (_, final_opening) = coeff_form_bi_kzg_open_leader(srs, &gathered_eval_opens, delta_y); - - HyperBiKZGOpening { - folded_oracle_commitments, - aggregated_evals: root_aggregated_x_evals, - leader_evals: root_folded_y_evals.into(), - beta_x_commitment: gamma_aggregated_x_quotient_commitment, - beta_y_commitment: leader_quotient_y_commitment, - quotient_delta_x_commitment: final_opening.quotient_x, - quotient_delta_y_commitment: final_opening.quotient_y, - } - .into() -} - -#[allow(clippy::too_many_arguments)] -pub fn coeff_form_hyper_bikzg_verify( - vk: &BiKZGVerifierParam, - local_alphas: &[E::Fr], - mpi_alphas: &[E::Fr], - eval: E::Fr, - commitment: E::G1Affine, - opening: &HyperBiKZGOpening, - fs_transcript: &mut T, -) -> bool -where - E: MultiMillerLoop, - T: Transcript, - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, - E::Fr: ExtensionField, -{ - // NOTE(HS) deteriorate to vanilla HyperKZG verify if mpi_alphas is empty - if mpi_alphas.is_empty() { - let hyper_bikzg_opening = opening.clone(); - let hyper_kzg_opening: HyperUniKZGOpening = hyper_bikzg_opening.into(); - - let what = coeff_form_uni_hyperkzg_verify( - &vk.into(), - commitment, - local_alphas, - eval, - &hyper_kzg_opening, - fs_transcript, - ); - - return what; - } - - let mpi_world_size = 1 << mpi_alphas.len(); - - opening - .folded_oracle_commitments - .iter() - .for_each(|f| fs_transcript.append_u8_slice(f.to_bytes().as_ref())); - - // NOTE(HS) transcript MPI thing ... - transcript_verifier_sync(fs_transcript, mpi_world_size); - - let beta_x = fs_transcript.generate_field_element::(); - let beta_y = fs_transcript.generate_field_element::(); - - // dbg!(beta_x, beta_y); - - // NOTE(HS) evaluation checks - - let beta_y2_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.beta_y2_evals, - local_alphas, - beta_x, - ); - - let pos_beta_y_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.pos_beta_y_evals, - local_alphas, - beta_x, - ); - - let neg_beta_y_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.neg_beta_y_evals, - local_alphas, - beta_x, - ); - - let beta_y2_final_eval = beta_y2_local.multilinear_final_eval(); - let pos_beta_y_final_eval = pos_beta_y_local.multilinear_final_eval(); - let neg_beta_y_final_eval = neg_beta_y_local.multilinear_final_eval(); - - // dbg!( - // &beta_y2_final_eval, - // &pos_beta_y_final_eval, - // &neg_beta_y_final_eval - // ); - - // dbg!( - // &opening.leader_evals.beta_x2_eval, - // &opening.leader_evals.pos_beta_x_evals[0], - // &opening.leader_evals.neg_beta_x_evals[0] - // ); - - if beta_y2_final_eval != opening.leader_evals.beta_x2_eval { - return false; - } - if pos_beta_y_final_eval != opening.leader_evals.pos_beta_x_evals[0] { - return false; - } - if neg_beta_y_final_eval != opening.leader_evals.neg_beta_x_evals[0] { - return false; - } - - let local_final_eval = - HyperKZGLocalEvals::new_from_exported_evals(&opening.leader_evals, mpi_alphas, beta_y); - if eval != local_final_eval.multilinear_final_eval() { - return false; - } - - opening.aggregated_evals.append_to_transcript(fs_transcript); - opening.leader_evals.append_to_transcript(fs_transcript); - - // NOTE(HS) transcript MPI thing ... - transcript_verifier_sync(fs_transcript, mpi_world_size); - - let gamma = fs_transcript.generate_field_element::(); - - // dbg!(gamma); - - let aggregated_oracle_commitment: E::G1Affine = { - let gamma_power_series = powers_series(&gamma, local_alphas.len() + mpi_alphas.len() + 1); - - let com_g1: E::G1 = izip!( - iter::once(&commitment).chain(&opening.folded_oracle_commitments), - &gamma_power_series - ) - .map(|(com, g)| com.to_curve() * g) - .sum(); - - com_g1.into() - }; - - // NOTE(HS) aggregate lagrange degree 2 polys - let (y_beta2, y_beta, y_neg_beta) = { - let gamma_n = gamma.pow_vartime([local_alphas.len() as u64]); - let (v_beta2, v_beta, v_neg_beta) = local_final_eval.gamma_aggregate_evals(gamma); - - (v_beta2 * gamma_n, v_beta * gamma_n, v_neg_beta * gamma_n) - }; - - let mut aggregated_beta_y2_locals = - beta_y2_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_beta_y2_locals[0] += y_beta2; - - let mut aggregated_pos_beta_y_locals = - pos_beta_y_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_pos_beta_y_locals[0] += y_beta; - - let mut aggregated_neg_beta_y_locals = - neg_beta_y_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_neg_beta_y_locals[0] += y_neg_beta; - - fs_transcript.append_u8_slice(opening.beta_x_commitment.to_bytes().as_ref()); - - // NOTE(HS) transcript MPI thing ... - transcript_verifier_sync(fs_transcript, mpi_world_size); - - let delta_x = fs_transcript.generate_field_element::(); - - // dbg!(delta_x); - - let delta_x_pow_series = powers_series(&delta_x, 3); - let at_beta_y2 = univariate_evaluate(&aggregated_beta_y2_locals, &delta_x_pow_series); - let at_beta_y = univariate_evaluate(&aggregated_pos_beta_y_locals, &delta_x_pow_series); - let at_neg_beta_y = univariate_evaluate(&aggregated_neg_beta_y_locals, &delta_x_pow_series); - - // dbg!(at_beta_y2, at_beta_y, at_neg_beta_y); - - let lagrange_degree2_delta_y = coeff_form_degree2_lagrange( - [beta_y, -beta_y, beta_y * beta_y], - [at_beta_y, at_neg_beta_y, at_beta_y2], - ); - - // dbg!(lagrange_degree2_delta_y); - - fs_transcript.append_u8_slice(opening.beta_y_commitment.to_bytes().as_ref()); - - // NOTE(HS) transcript MPI thing ... - transcript_verifier_sync(fs_transcript, mpi_world_size); - - let delta_y = fs_transcript.generate_field_element::(); - - // dbg!(delta_y); - - let delta_y_pow_series = powers_series(&delta_y, 3); - let degree_2_final_eval = univariate_evaluate(&lagrange_degree2_delta_y, &delta_y_pow_series); - - // dbg!(degree_2_final_eval); - - // NOTE(HS) f_gamma_s - (delta_x - beta_x) ... (delta_x - beta_x2) f_gamma_quotient_s - // - (delta_y - beta_y) ... (delta_y - beta_y2) lagrange_quotient_y - let delta_x_denom = (delta_x - beta_x) * (delta_x - beta_x * beta_x) * (delta_x + beta_x); - let delta_y_denom = (delta_y - beta_y) * (delta_y - beta_y * beta_y) * (delta_y + beta_y); - - let com_r = aggregated_oracle_commitment.to_curve() - - (opening.beta_x_commitment * delta_x_denom) - - (opening.beta_y_commitment * delta_y_denom); - - // dbg!(com_r); - - let final_opening = BiKZGProof { - quotient_x: opening.quotient_delta_x_commitment, - quotient_y: opening.quotient_delta_y_commitment, - }; - - coeff_form_bi_kzg_verify( - vk.clone(), - com_r.to_affine(), - delta_x, - delta_y, - degree_2_final_eval, - final_opening, - ) -} diff --git a/poly_commit/src/kzg/bi_kzg/hyper_bikzg_tests.rs b/poly_commit/src/kzg/bi_kzg/hyper_bikzg_tests.rs deleted file mode 100644 index 35d327a55..000000000 --- a/poly_commit/src/kzg/bi_kzg/hyper_bikzg_tests.rs +++ /dev/null @@ -1,603 +0,0 @@ -use std::iter; - -use arith::ExtensionField; -use ark_std::test_rng; -use gkr_engine::Transcript; -use gkr_hashers::MiMC5FiatShamirHasher; -use halo2curves::{ - bn256::{Bn256, Fr, G1Affine, G1}, - ff::Field, - group::{prime::PrimeCurveAffine, Curve, GroupEncoding}, - pairing::MultiMillerLoop, - CurveAffine, -}; -use itertools::{chain, izip}; -use polynomials::MultiLinearPoly; -use serdes::ExpSerde; -use transcript::BytesHashTranscript; - -use crate::*; - -// NOTE(HS) the motivation of introducing an implementation of simulated version is that -// the MPI parallelization is not yet appearing in the CI at this moment (2025/02/28), -// so we hand rolled a version of single-process simulated distributed HyperBiKZG for the -// parallelized PCS opening testing, which gives a reference for the real deal of HyperBiKZG -// implementation of opening and verifying. - -fn coeff_form_hyper_bikzg_open_simulate( - srs_s: &[CoefFormBiKZGLocalSRS], - coeffs_s: &[Vec], - local_alphas: &[E::Fr], - mpi_alphas: &[E::Fr], - fs_transcript: &mut T, -) -> HyperBiKZGOpening -where - E: MultiMillerLoop, - T: Transcript, - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, - E::Fr: ExtensionField, -{ - // NOTE(HS) deteriorate to vanilla HyperKZG if mpi_alphas is empty, namely single party setting - if mpi_alphas.is_empty() { - let (_, hyperkzg_opening) = coeff_form_uni_hyperkzg_open( - &srs_s[0].tau_x_srs, - &coeffs_s[0], - local_alphas, - fs_transcript, - ); - - return hyperkzg_opening.into(); - } - - // - // Locally fold local variables, then commit to construct the poly oracles - // - - let (folded_x_oracle_commits_s, folded_x_oracle_coeffs_s): ( - Vec>, - Vec>>, - ) = izip!(srs_s, coeffs_s) - .map(|(srs, coeffs)| { - coeff_form_hyperkzg_local_poly_oracles(&srs.tau_x_srs, coeffs, local_alphas) - }) - .unzip(); - - let final_evals_at_x: Vec = folded_x_oracle_coeffs_s - .iter() - .map(|folded_x_oracle_coeffs| { - let final_coeffs = folded_x_oracle_coeffs.last().unwrap().clone(); - let final_alpha = local_alphas[local_alphas.len() - 1]; - - (E::Fr::ONE - final_alpha) * final_coeffs[0] + final_alpha * final_coeffs[1] - }) - .collect(); - - // - // Leader party collect oracle commitments, sum them up for folded oracles - // - - let folded_x_oracle_commits: Vec = (0..local_alphas.len() - 1) - .map(|i| { - let ith_fold_commits: E::G1 = folded_x_oracle_commits_s - .iter() - .map(|f| f[i].to_curve()) - .sum(); - - ith_fold_commits.to_affine() - }) - .collect(); - - let y_oracle_commit = coeff_form_uni_kzg_commit(&srs_s[0].tau_y_srs, &final_evals_at_x); - - // - // The leader party continues on folding over "final_evals" over only y variables. - // - - let (folded_y_oracle_commits, folded_y_oracle_coeffs_s) = - coeff_form_hyperkzg_local_poly_oracles(&srs_s[0].tau_y_srs, &final_evals_at_x, mpi_alphas); - - // - // The leader party feeds all folded oracles into RO, then sync party's transcript state - // - - let folded_oracle_commitments = { - let mut temp = folded_x_oracle_commits.clone(); - temp.push(y_oracle_commit); - temp.extend_from_slice(&folded_y_oracle_commits); - temp - }; - - chain!( - &folded_x_oracle_commits, - iter::once(&y_oracle_commit), - &folded_y_oracle_commits, - ) - .for_each(|f| fs_transcript.append_u8_slice(f.to_bytes().as_ref())); - - let beta_x = fs_transcript.generate_field_element::(); - let beta_y = fs_transcript.generate_field_element::(); - - dbg!(beta_x, beta_y); - - // - // Local parties run HyperKZG evals at beta_x, -beta_x, beta_x^2 over folded coeffs - // - - let folded_x_evals_s: Vec> = izip!(coeffs_s, &folded_x_oracle_coeffs_s) - .map(|(coeffs, folded_oracle_coeffs)| { - coeff_form_hyperkzg_local_evals(coeffs, folded_oracle_coeffs, local_alphas, beta_x) - }) - .collect(); - - let exported_folded_x_evals_s: Vec> = - folded_x_evals_s.iter().cloned().map(Into::into).collect(); - - // - // Leader aggregates all local exported evaluations (at x) by evaluating at y - // by three points: beta_y, -beta_y, beta_y^2, then fold the final evals at x, - // which is degree 0 for variable x, along variable y. - // - - let aggregated_evals = - HyperKZGAggregatedEvals::new_from_exported_evals(&exported_folded_x_evals_s, beta_y); - - let root_evals: HyperKZGLocalEvals = coeff_form_hyperkzg_local_evals( - &final_evals_at_x, - &folded_y_oracle_coeffs_s, - mpi_alphas, - beta_y, - ); - - // - // The leader party feeds all evals into RO, then sync party's transcript state - // - - aggregated_evals.append_to_transcript(fs_transcript); - root_evals.append_to_transcript(fs_transcript); - - // NOTE(HS) check if the final eval of root evals match with mle poly evaluation - dbg!(&root_evals.multilinear_final_eval()); - - let gamma = fs_transcript.generate_field_element::(); - - dbg!(gamma); - - // - // The leader party linear combines folded coeffs at y with gamma, - // then broadcast the coeffs back to local. - // - - let f_gamma_global = { - let gamma_n = gamma.pow_vartime([local_alphas.len() as u64]); - let mut temp = coeff_form_hyperkzg_local_oracle_polys_aggregate::( - &final_evals_at_x, - &folded_y_oracle_coeffs_s, - gamma, - ); - temp.iter_mut().for_each(|t| *t *= gamma_n); - temp - }; - - // - // Local party compute the linear combined folded coeffs at x with gamma, - // then the degree2 Lagrange over beta_x, -beta_x, beta_x^2, - // then vanish the local aggregated x coeffs at the three points above, - // and commit to the final quotient poly - // - - let mut f_gamma_s: Vec> = { - let mut f_gamma_s_local: Vec> = izip!(coeffs_s, folded_x_oracle_coeffs_s) - .map(|(coeffs, folded_oracle_coeffs)| { - coeff_form_hyperkzg_local_oracle_polys_aggregate::( - coeffs, - &folded_oracle_coeffs, - gamma, - ) - }) - .collect(); - - izip!(&mut f_gamma_s_local, &f_gamma_global) - .for_each(|(f_g, f_global)| f_g[0] += *f_global); - - f_gamma_s_local - }; - - let lagrange_degree2_s: Vec<[E::Fr; 3]> = izip!(folded_x_evals_s, &f_gamma_global) - .map(|(l, g)| { - let mut local_degree_2 = l.interpolate_degree2_aggregated_evals(beta_x, gamma); - local_degree_2[0] += g; - local_degree_2 - }) - .collect(); - - let f_gamma_quotient_s: Vec> = izip!(&f_gamma_s, &lagrange_degree2_s) - .map(|(f_gamma, lagrange_degree2)| { - let mut nom = f_gamma.clone(); - polynomial_add(&mut nom, -E::Fr::ONE, lagrange_degree2); - univariate_roots_quotient(nom, &[beta_x, -beta_x, beta_x * beta_x]) - }) - .collect(); - let f_gamma_quotient_com_s: Vec = izip!(srs_s, &f_gamma_quotient_s) - .map(|(srs, f_gamma_quotient)| { - coeff_form_uni_kzg_commit(&srs.tau_x_srs, f_gamma_quotient).to_curve() - }) - .collect(); - - // - // Leader collect all the quotient commitment at x, sum it up and feed it to RO, - // then sync transcript state - // - - let f_gamma_quotient_com_x: E::G1Affine = f_gamma_quotient_com_s.iter().sum::().into(); - - fs_transcript.append_u8_slice(f_gamma_quotient_com_x.to_bytes().as_ref()); - - let delta_x = fs_transcript.generate_field_element::(); - - dbg!(delta_x); - - // - // Locally compute the Lagrange-degree2 interpolation at delta_x, pool at leader - // - - let lagrange_degree2_delta_x: Vec = lagrange_degree2_s - .iter() - .map(|l| l[0] + l[1] * delta_x + l[2] * delta_x * delta_x) - .collect(); - - // - // Leader does similar thing - quotient at beta_y, -beta_y, beta_y^2, - // commit the quotient polynomial commitment at y, feed it to RO, - // then sync transcript state - // - - // NOTE(HS) interpolate at beta_y, beta_y2, -beta_y on lagrange_degree2_delta_x - let lagrange_degree2_delta_y = { - let pos_beta_y_pow_series = powers_series(&beta_y, lagrange_degree2_delta_x.len()); - let neg_beta_y_pow_series = powers_series(&(-beta_y), lagrange_degree2_delta_x.len()); - let beta_y2_pow_series = powers_series(&(beta_y * beta_y), lagrange_degree2_delta_x.len()); - let at_pos_beta_y = univariate_evaluate(&lagrange_degree2_delta_x, &pos_beta_y_pow_series); - let at_neg_beta_y = univariate_evaluate(&lagrange_degree2_delta_x, &neg_beta_y_pow_series); - let at_beta_y2 = univariate_evaluate(&lagrange_degree2_delta_x, &beta_y2_pow_series); - - dbg!(at_pos_beta_y, at_neg_beta_y, at_beta_y2); - - coeff_form_degree2_lagrange( - [beta_y, -beta_y, beta_y * beta_y], - [at_pos_beta_y, at_neg_beta_y, at_beta_y2], - ) - }; - - dbg!(lagrange_degree2_delta_y); - - // NOTE(HS) vanish over the three beta_y points above, then commit Q_y - let mut f_gamma_quotient_y = { - let mut nom = lagrange_degree2_delta_x.clone(); - polynomial_add(&mut nom, -E::Fr::ONE, &lagrange_degree2_delta_y); - univariate_roots_quotient(nom, &[beta_y, -beta_y, beta_y * beta_y]) - }; - f_gamma_quotient_y.resize(lagrange_degree2_delta_x.len(), E::Fr::ZERO); - - let f_gamma_quotient_com_y = - coeff_form_uni_kzg_commit(&srs_s[0].tau_y_srs, &f_gamma_quotient_y); - - dbg!(f_gamma_quotient_y.len()); - - // NOTE(HS) sample from RO for delta_y - fs_transcript.append_u8_slice(f_gamma_quotient_com_y.to_bytes().as_ref()); - - let delta_y = fs_transcript.generate_field_element::(); - - dbg!(delta_y); - - // - // Final step for local - trip off the prior quotients at x and y on \pm beta and beta^2 - // - - // NOTE(HS) f_gamma_s - (delta_x - beta_x) ... (delta_x - beta_x2) f_gamma_quotient_s - // - (delta_y - beta_y) ... (delta_y - beta_y2) lagrange_quotient_y - let delta_x_denom = (delta_x - beta_x) * (delta_x - beta_x * beta_x) * (delta_x + beta_x); - let delta_y_denom = (delta_y - beta_y) * (delta_y - beta_y * beta_y) * (delta_y + beta_y); - - izip!(&mut f_gamma_s, &f_gamma_quotient_s, &f_gamma_quotient_y).for_each( - |(f_gamma, f_gamma_quotient, f_gamma_quotient_y_i)| { - polynomial_add(f_gamma, -delta_x_denom, f_gamma_quotient); - f_gamma[0] -= *f_gamma_quotient_y_i * delta_y_denom; - }, - ); - - // NOTE(HS) bivariate KZG opening - let evals_and_opens: Vec<(E::Fr, E::G1Affine)> = izip!(srs_s, &f_gamma_s) - .map(|(srs, x_coeffs)| coeff_form_uni_kzg_open_eval(&srs.tau_x_srs, x_coeffs, delta_x)) - .collect(); - - let (_, final_opening) = coeff_form_bi_kzg_open_leader(&srs_s[0], &evals_and_opens, delta_y); - - HyperBiKZGOpening { - folded_oracle_commitments, - aggregated_evals, - leader_evals: root_evals.into(), - beta_x_commitment: f_gamma_quotient_com_x, - beta_y_commitment: f_gamma_quotient_com_y, - quotient_delta_x_commitment: final_opening.quotient_x, - quotient_delta_y_commitment: final_opening.quotient_y, - } -} - -fn coeff_form_hyper_bikzg_verify_simulate( - vk: &BiKZGVerifierParam, - local_alphas: &[E::Fr], - mpi_alphas: &[E::Fr], - eval: E::Fr, - commitment: E::G1Affine, - opening: &HyperBiKZGOpening, - fs_transcript: &mut T, -) -> bool -where - E: MultiMillerLoop, - T: Transcript, - E::G1Affine: CurveAffine + ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, - E::Fr: ExtensionField, -{ - // NOTE(HS) deteriorate to vanilla HyperKZG verify if mpi_alphas is empty - if mpi_alphas.is_empty() { - let hyper_bikzg_opening = opening.clone(); - let hyper_kzg_opening: HyperUniKZGOpening = hyper_bikzg_opening.into(); - - let what = coeff_form_uni_hyperkzg_verify( - &vk.into(), - commitment, - local_alphas, - eval, - &hyper_kzg_opening, - fs_transcript, - ); - - return what; - } - - opening - .folded_oracle_commitments - .iter() - .for_each(|f| fs_transcript.append_u8_slice(f.to_bytes().as_ref())); - - let beta_x = fs_transcript.generate_field_element::(); - let beta_y = fs_transcript.generate_field_element::(); - - dbg!(beta_x, beta_y); - - // NOTE(HS) evaluation checks - - let beta_y2_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.beta_y2_evals, - local_alphas, - beta_x, - ); - - let pos_beta_y_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.pos_beta_y_evals, - local_alphas, - beta_x, - ); - - let neg_beta_y_local = HyperKZGLocalEvals::new_from_exported_evals( - &opening.aggregated_evals.neg_beta_y_evals, - local_alphas, - beta_x, - ); - - let beta_y2_final_eval = beta_y2_local.multilinear_final_eval(); - let pos_beta_y_final_eval = pos_beta_y_local.multilinear_final_eval(); - let neg_beta_y_final_eval = neg_beta_y_local.multilinear_final_eval(); - - dbg!( - &beta_y2_final_eval, - &pos_beta_y_final_eval, - &neg_beta_y_final_eval - ); - - dbg!( - &opening.leader_evals.beta_x2_eval, - &opening.leader_evals.pos_beta_x_evals[0], - &opening.leader_evals.neg_beta_x_evals[0] - ); - - if beta_y2_final_eval != opening.leader_evals.beta_x2_eval { - return false; - } - if pos_beta_y_final_eval != opening.leader_evals.pos_beta_x_evals[0] { - return false; - } - if neg_beta_y_final_eval != opening.leader_evals.neg_beta_x_evals[0] { - return false; - } - - let local_final_eval = - HyperKZGLocalEvals::new_from_exported_evals(&opening.leader_evals, mpi_alphas, beta_y); - if eval != local_final_eval.multilinear_final_eval() { - return false; - } - - opening.aggregated_evals.append_to_transcript(fs_transcript); - opening.leader_evals.append_to_transcript(fs_transcript); - - let gamma = fs_transcript.generate_field_element::(); - - dbg!(gamma); - - let aggregated_oracle_commitment: E::G1Affine = { - let gamma_power_series = powers_series(&gamma, local_alphas.len() + mpi_alphas.len() + 1); - - let com_g1: E::G1 = izip!( - iter::once(&commitment).chain(&opening.folded_oracle_commitments), - &gamma_power_series - ) - .map(|(com, g)| com.to_curve() * g) - .sum(); - - com_g1.into() - }; - - // NOTE(HS) aggregate lagrange degree 2 polys - let (y_beta2, y_beta, y_neg_beta) = { - let gamma_n = gamma.pow_vartime([local_alphas.len() as u64]); - let (v_beta2, v_beta, v_neg_beta) = local_final_eval.gamma_aggregate_evals(gamma); - - (v_beta2 * gamma_n, v_beta * gamma_n, v_neg_beta * gamma_n) - }; - - let mut aggregated_beta_y2_locals = - beta_y2_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_beta_y2_locals[0] += y_beta2; - - let mut aggregated_pos_beta_y_locals = - pos_beta_y_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_pos_beta_y_locals[0] += y_beta; - - let mut aggregated_neg_beta_y_locals = - neg_beta_y_local.interpolate_degree2_aggregated_evals(beta_x, gamma); - aggregated_neg_beta_y_locals[0] += y_neg_beta; - - fs_transcript.append_u8_slice(opening.beta_x_commitment.to_bytes().as_ref()); - - let delta_x = fs_transcript.generate_field_element::(); - - dbg!(delta_x); - - let delta_x_pow_series = powers_series(&delta_x, 3); - let at_beta_y2 = univariate_evaluate(&aggregated_beta_y2_locals, &delta_x_pow_series); - let at_beta_y = univariate_evaluate(&aggregated_pos_beta_y_locals, &delta_x_pow_series); - let at_neg_beta_y = univariate_evaluate(&aggregated_neg_beta_y_locals, &delta_x_pow_series); - - dbg!(at_beta_y2, at_beta_y, at_neg_beta_y); - - let lagrange_degree2_delta_y = coeff_form_degree2_lagrange( - [beta_y, -beta_y, beta_y * beta_y], - [at_beta_y, at_neg_beta_y, at_beta_y2], - ); - - dbg!(lagrange_degree2_delta_y); - - fs_transcript.append_u8_slice(opening.beta_y_commitment.to_bytes().as_ref()); - - let delta_y = fs_transcript.generate_field_element::(); - - dbg!(delta_y); - - let delta_y_pow_series = powers_series(&delta_y, 3); - let degree_2_final_eval = univariate_evaluate(&lagrange_degree2_delta_y, &delta_y_pow_series); - - dbg!(degree_2_final_eval); - - // NOTE(HS) f_gamma_s - (delta_x - beta_x) ... (delta_x - beta_x2) f_gamma_quotient_s - // - (delta_y - beta_y) ... (delta_y - beta_y2) lagrange_quotient_y - let delta_x_denom = (delta_x - beta_x) * (delta_x - beta_x * beta_x) * (delta_x + beta_x); - let delta_y_denom = (delta_y - beta_y) * (delta_y - beta_y * beta_y) * (delta_y + beta_y); - - let com_r = aggregated_oracle_commitment.to_curve() - - (opening.beta_x_commitment * delta_x_denom) - - (opening.beta_y_commitment * delta_y_denom); - - dbg!(com_r); - - let final_opening = BiKZGProof { - quotient_x: opening.quotient_delta_x_commitment, - quotient_y: opening.quotient_delta_y_commitment, - }; - - let what = coeff_form_bi_kzg_verify( - vk.clone(), - com_r.to_affine(), - delta_x, - delta_y, - degree_2_final_eval, - final_opening, - ); - dbg!(what); - - what -} - -#[test] -fn test_hyper_bikzg_single_process_simulated_e2e() { - let (x_degree, x_vars) = { - let x_vars = 12; - ((1 << x_vars) - 1, x_vars) - }; - - let (y_degree, y_vars) = { - let y_vars = 3; - ((1 << y_vars) - 1, y_vars) - }; - - let mut rng = test_rng(); - - let local_alphas: Vec<_> = (0..x_vars).map(|_| Fr::random(&mut rng)).collect(); - let mpi_alphas: Vec<_> = (0..y_vars).map(|_| Fr::random(&mut rng)).collect(); - - let party_srs: Vec> = (0..=y_degree) - .map(|rank| { - let mut srs_rng = test_rng(); - generate_coef_form_bi_kzg_local_srs_for_testing( - x_degree + 1, - y_degree + 1, - rank, - &mut srs_rng, - ) - }) - .collect(); - - let xy_coeffs: Vec> = (0..=y_degree) - .map(|_| (0..=x_degree).map(|_| Fr::random(&mut rng)).collect()) - .collect(); - - let all_alphas = { - let mut alphas = local_alphas.clone(); - alphas.extend_from_slice(&mpi_alphas); - - alphas - }; - - let eval = { - let global_poly_coeffs: Vec<_> = xy_coeffs.clone().into_iter().flatten().collect(); - let global_poly = MultiLinearPoly::new(global_poly_coeffs); - global_poly.evaluate_jolt(&all_alphas) - }; - - dbg!(eval); - - let global_commitment: G1Affine = { - let commitments: Vec<_> = izip!(&party_srs, &xy_coeffs) - .map(|(srs, x_coeffs)| coeff_form_uni_kzg_commit(&srs.tau_x_srs, x_coeffs)) - .collect(); - - let global_commitment_g1: G1 = commitments.iter().map(|c| c.to_curve()).sum(); - global_commitment_g1.to_affine() - }; - - let mut fs_transcript = BytesHashTranscript::>::new(); - let mut verifier_transcript = fs_transcript.clone(); - - let opening = coeff_form_hyper_bikzg_open_simulate( - &party_srs, - &xy_coeffs, - &local_alphas, - &mpi_alphas, - &mut fs_transcript, - ); - - let vk: BiKZGVerifierParam = From::from(&party_srs[0]); - let what = coeff_form_hyper_bikzg_verify_simulate( - &vk, - &local_alphas, - &mpi_alphas, - eval, - global_commitment, - &opening, - &mut verifier_transcript, - ); - - assert!(what); -} diff --git a/poly_commit/src/kzg/bi_kzg/pcs_trait_impl.rs b/poly_commit/src/kzg/bi_kzg/pcs_trait_impl.rs deleted file mode 100644 index 86b39ff40..000000000 --- a/poly_commit/src/kzg/bi_kzg/pcs_trait_impl.rs +++ /dev/null @@ -1,119 +0,0 @@ -use std::marker::PhantomData; - -use arith::ExtensionField; -use gkr_engine::{StructuredReferenceString, Transcript}; -use halo2curves::{ - ff::PrimeField, - pairing::{Engine, MultiMillerLoop}, - CurveAffine, -}; -use polynomials::{MultiLinearPoly, MultilinearExtension}; -use serdes::ExpSerde; - -use crate::{ - coeff_form_uni_hyperkzg_open, coeff_form_uni_hyperkzg_verify, coeff_form_uni_kzg_commit, - HyperUniKZGOpening, PolynomialCommitmentScheme, -}; - -use super::{ - generate_coef_form_bi_kzg_local_srs_for_testing, BiKZGCommitment, CoefFormBiKZGLocalSRS, - HyperBiKZGOpening, -}; - -pub struct HyperBiKZGPCS -where - E: Engine, - E::Fr: ExtensionField, -{ - _marker_e: PhantomData, -} - -impl HyperBiKZGPCS -where - E: Engine, - E::Fr: ExtensionField, -{ - pub const MINIMUM_SUPPORTED_NUM_VARS: usize = 2; -} - -impl PolynomialCommitmentScheme for HyperBiKZGPCS -where - E: Engine + MultiMillerLoop, - E::Fr: ExtensionField + PrimeField, - E::G1Affine: ExpSerde + Default + CurveAffine, - E::G2Affine: ExpSerde + Default + CurveAffine, -{ - const NAME: &'static str = "HyperBiKZGPCS"; - - type Params = usize; - type Poly = MultiLinearPoly; - type EvalPoint = Vec; - type ScratchPad = (); - - type SRS = CoefFormBiKZGLocalSRS; - type Commitment = BiKZGCommitment; - type Opening = HyperBiKZGOpening; - - fn init_scratch_pad(_params: &Self::Params) -> Self::ScratchPad {} - - fn gen_srs_for_testing(params: &Self::Params, rng: impl rand::RngCore) -> (Self::SRS, usize) { - let local_num_vars = if *params == 0 { 1 } else { *params }; - - let length = 1 << local_num_vars; - let srs = generate_coef_form_bi_kzg_local_srs_for_testing(length, 1, 0, rng); - (srs, local_num_vars) - } - - fn commit( - _params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - _scratch_pad: &mut Self::ScratchPad, - ) -> Self::Commitment { - let local_commitment = - coeff_form_uni_kzg_commit(&proving_key.tau_x_srs, poly.hypercube_basis_ref()); - - BiKZGCommitment(local_commitment) - } - - fn open( - _params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - x: &Self::EvalPoint, - _scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (E::Fr, Self::Opening) { - let (eval, hyperkzg_opening) = coeff_form_uni_hyperkzg_open( - &proving_key.tau_x_srs, - poly.hypercube_basis_ref(), - x, - transcript, - ); - - let hyper_bikzg_opening: HyperBiKZGOpening = hyperkzg_opening.into(); - (eval, hyper_bikzg_opening) - } - - fn verify( - _params: &Self::Params, - verifying_key: &::VKey, - commitment: &Self::Commitment, - x: &Self::EvalPoint, - v: E::Fr, - opening: &Self::Opening, - transcript: &mut impl Transcript, - ) -> bool { - let hyper_bikzg_opening = opening.clone(); - let hyper_kzg_opening: HyperUniKZGOpening = hyper_bikzg_opening.into(); - - coeff_form_uni_hyperkzg_verify( - &verifying_key.into(), - commitment.0, - x, - v, - &hyper_kzg_opening, - transcript, - ) - } -} diff --git a/poly_commit/src/kzg/bi_kzg/structs_bi_kzg.rs b/poly_commit/src/kzg/bi_kzg/structs_bi_kzg.rs deleted file mode 100644 index 161a2461b..000000000 --- a/poly_commit/src/kzg/bi_kzg/structs_bi_kzg.rs +++ /dev/null @@ -1,96 +0,0 @@ -use derivative::Derivative; -use gkr_engine::StructuredReferenceString; -use halo2curves::{pairing::Engine, CurveAffine}; -use serdes::{ExpSerde, SerdeResult}; - -use crate::{CoefFormUniKZGSRS, UniKZGVerifierParams}; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Derivative)] -#[derivative(Default(bound = ""))] -pub struct BiKZGCommitment(pub E::G1Affine) -where - E::G1Affine: CurveAffine; - -// Derive macros does not work for associated types -impl ExpSerde for BiKZGCommitment -where - E::G1Affine: ExpSerde + CurveAffine, -{ - fn serialize_into(&self, writer: W) -> SerdeResult<()> { - self.0.serialize_into(writer) - } - - fn deserialize_from(reader: R) -> SerdeResult { - Ok(Self(::deserialize_from(reader)?)) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Derivative, ExpSerde)] -#[derivative(Default(bound = ""))] -pub struct CoefFormBiKZGLocalSRS -where - E::G1Affine: ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - pub tau_x_srs: CoefFormUniKZGSRS, - pub tau_y_srs: CoefFormUniKZGSRS, -} - -/// Bivariate KZG PCS verifier's params. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, ExpSerde)] -pub struct BiKZGVerifierParam -where - E::G1Affine: ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - /// tau_x over G2. - pub tau_x_g2: E::G2Affine, - /// tau_y over G2. - pub tau_y_g2: E::G2Affine, -} - -impl From<&CoefFormBiKZGLocalSRS> for BiKZGVerifierParam -where - E::G1Affine: ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - fn from(srs: &CoefFormBiKZGLocalSRS) -> Self { - Self { - tau_x_g2: srs.tau_x_srs.tau_g2, - tau_y_g2: srs.tau_y_srs.tau_g2, - } - } -} - -impl StructuredReferenceString for CoefFormBiKZGLocalSRS -where - ::G1Affine: ExpSerde + CurveAffine, - ::G2Affine: ExpSerde + CurveAffine, -{ - type PKey = CoefFormBiKZGLocalSRS; - type VKey = BiKZGVerifierParam; - - fn into_keys(self) -> (Self::PKey, Self::VKey) { - let vk: Self::VKey = From::from(&self); - (self, vk) - } -} - -impl From<&BiKZGVerifierParam> for UniKZGVerifierParams -where - E::G1Affine: ExpSerde, - E::G2Affine: CurveAffine + ExpSerde, -{ - fn from(value: &BiKZGVerifierParam) -> Self { - Self { - tau_g2: value.tau_x_g2, - } - } -} - -/// Proof for Bi-KZG polynomial commitment scheme. -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] -pub struct BiKZGProof { - pub quotient_x: E::G1Affine, - pub quotient_y: E::G1Affine, -} diff --git a/poly_commit/src/kzg/bi_kzg/structs_hyper_bi_kzg.rs b/poly_commit/src/kzg/bi_kzg/structs_hyper_bi_kzg.rs deleted file mode 100644 index a16c84eb1..000000000 --- a/poly_commit/src/kzg/bi_kzg/structs_hyper_bi_kzg.rs +++ /dev/null @@ -1,56 +0,0 @@ -use derivative::Derivative; -use halo2curves::pairing::Engine; -use serdes::ExpSerde; - -use crate::*; - -#[derive(Debug, Clone, Derivative, ExpSerde)] -#[derivative(Default(bound = ""))] -pub struct HyperBiKZGOpening -where - E::Fr: ExpSerde, - E::G1Affine: Default + ExpSerde, -{ - pub folded_oracle_commitments: Vec, - - pub aggregated_evals: HyperKZGAggregatedEvals, - pub leader_evals: HyperKZGExportedLocalEvals, - - pub beta_x_commitment: E::G1Affine, - pub beta_y_commitment: E::G1Affine, - - pub quotient_delta_x_commitment: E::G1Affine, - pub quotient_delta_y_commitment: E::G1Affine, -} - -impl From> for HyperUniKZGOpening -where - E::Fr: ExpSerde, - E::G1Affine: Default + ExpSerde, -{ - fn from(value: HyperBiKZGOpening) -> Self { - Self { - folded_oracle_commitments: value.folded_oracle_commitments, - evals_at_x: value.leader_evals, - beta_x_commitment: value.beta_x_commitment, - quotient_delta_x_commitment: value.quotient_delta_x_commitment, - } - } -} - -impl From> for HyperBiKZGOpening -where - E::Fr: ExpSerde, - E::G1Affine: Default + ExpSerde, -{ - fn from(value: HyperUniKZGOpening) -> Self { - Self { - folded_oracle_commitments: value.folded_oracle_commitments, - leader_evals: value.evals_at_x, - beta_x_commitment: value.beta_x_commitment, - quotient_delta_x_commitment: value.quotient_delta_x_commitment, - - ..Default::default() - } - } -} diff --git a/poly_commit/src/kzg/uni_kzg/structs_hyper_kzg.rs b/poly_commit/src/kzg/uni_kzg/structs_hyper_kzg.rs index 79dce7714..589658f96 100644 --- a/poly_commit/src/kzg/uni_kzg/structs_hyper_kzg.rs +++ b/poly_commit/src/kzg/uni_kzg/structs_hyper_kzg.rs @@ -1,5 +1,3 @@ -use std::ops::{Index, IndexMut}; - use arith::ExtensionField; use derivative::Derivative; use gkr_engine::Transcript; @@ -24,18 +22,6 @@ impl HyperKZGExportedLocalEvals where E::Fr: ExpSerde, { - pub(crate) fn new(evals_num: usize) -> Self { - Self { - beta_x2_eval: E::Fr::default(), - pos_beta_x_evals: vec![E::Fr::default(); evals_num], - neg_beta_x_evals: vec![E::Fr::default(); evals_num], - } - } - - pub(crate) fn len(&self) -> usize { - self.pos_beta_x_evals.len() + self.neg_beta_x_evals.len() + 1 - } - pub(crate) fn append_to_transcript(&self, fs_transcript: &mut T) where T: Transcript, @@ -165,52 +151,6 @@ where } } -impl Index for HyperKZGExportedLocalEvals -where - E::Fr: ExpSerde, -{ - type Output = E::Fr; - - fn index(&self, index: usize) -> &Self::Output { - assert_eq!(self.pos_beta_x_evals.len(), self.neg_beta_x_evals.len()); - assert!(!self.pos_beta_x_evals.is_empty()); - - let evals_len = self.pos_beta_x_evals.len(); - - if index < evals_len { - &self.pos_beta_x_evals[index] - } else if index < 2 * evals_len { - &self.neg_beta_x_evals[index - evals_len] - } else if index == 2 * evals_len { - &self.beta_x2_eval - } else { - unreachable!() - } - } -} - -impl IndexMut for HyperKZGExportedLocalEvals -where - E::Fr: ExpSerde, -{ - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - assert_eq!(self.pos_beta_x_evals.len(), self.neg_beta_x_evals.len()); - assert!(!self.pos_beta_x_evals.is_empty()); - - let evals_len = self.pos_beta_x_evals.len(); - - if index < evals_len { - &mut self.pos_beta_x_evals[index] - } else if index < 2 * evals_len { - &mut self.neg_beta_x_evals[index - evals_len] - } else if index == 2 * evals_len { - &mut self.beta_x2_eval - } else { - unreachable!() - } - } -} - impl From> for HyperKZGExportedLocalEvals where E::Fr: ExpSerde, @@ -223,60 +163,3 @@ where } } } - -#[derive(Clone, Debug, Derivative, ExpSerde)] -#[derivative(Default(bound = ""))] -pub struct HyperKZGAggregatedEvals -where - E::Fr: ExpSerde, -{ - pub beta_y2_evals: HyperKZGExportedLocalEvals, - pub pos_beta_y_evals: HyperKZGExportedLocalEvals, - pub neg_beta_y_evals: HyperKZGExportedLocalEvals, -} - -impl HyperKZGAggregatedEvals -where - E::Fr: ExtensionField, -{ - pub(crate) fn new_from_exported_evals( - exported_evals: &[HyperKZGExportedLocalEvals], - beta_y: E::Fr, - ) -> Self { - let evals_len = exported_evals[0].pos_beta_x_evals.len(); - let num_local_evals = exported_evals[0].len(); - let num_parties = exported_evals.len(); - - assert!(num_parties >= 2 && num_parties.is_power_of_two()); - - let mut aggregated = Self { - beta_y2_evals: HyperKZGExportedLocalEvals::new(evals_len), - pos_beta_y_evals: HyperKZGExportedLocalEvals::new(evals_len), - neg_beta_y_evals: HyperKZGExportedLocalEvals::new(evals_len), - }; - - let beta_y2 = beta_y * beta_y; - let beta_y2_pow_series = powers_series(&beta_y2, num_parties); - let pos_beta_y_pow_series = powers_series(&beta_y, num_parties); - let neg_beta_y_pow_series = powers_series(&(-beta_y), num_parties); - - (0..num_local_evals).for_each(|i| { - let y_poly: Vec = exported_evals.iter().map(|e| e[i]).collect(); - - aggregated.beta_y2_evals[i] = univariate_evaluate(&y_poly, &beta_y2_pow_series); - aggregated.pos_beta_y_evals[i] = univariate_evaluate(&y_poly, &pos_beta_y_pow_series); - aggregated.neg_beta_y_evals[i] = univariate_evaluate(&y_poly, &neg_beta_y_pow_series); - }); - - aggregated - } - - pub(crate) fn append_to_transcript(&self, fs_transcript: &mut T) - where - T: Transcript, - { - self.beta_y2_evals.append_to_transcript(fs_transcript); - self.pos_beta_y_evals.append_to_transcript(fs_transcript); - self.neg_beta_y_evals.append_to_transcript(fs_transcript); - } -} diff --git a/poly_commit/src/lib.rs b/poly_commit/src/lib.rs index b0bc946de..d5aa8cd5b 100644 --- a/poly_commit/src/lib.rs +++ b/poly_commit/src/lib.rs @@ -11,12 +11,6 @@ pub use utils::expander_pcs_init_testing_only; pub mod raw; pub use raw::RawExpanderGKR; -pub mod orion; -pub use orion::*; - -pub mod hyrax; -pub use hyrax::*; - pub mod kzg; pub use kzg::*; diff --git a/poly_commit/src/orion.rs b/poly_commit/src/orion.rs deleted file mode 100644 index e85cc3608..000000000 --- a/poly_commit/src/orion.rs +++ /dev/null @@ -1,28 +0,0 @@ -mod utils; -pub use utils::{ - OrionCommitment, OrionPCSError, OrionProof, OrionResult, OrionSRS, OrionScratchPad, - SubsetSumLUTs, -}; - -mod linear_code; -pub use linear_code::{OrionCodeParameter, ORION_CODE_PARAMETER_INSTANCE}; - -#[cfg(test)] -mod linear_code_tests; - -mod simd_field_impl; -pub use simd_field_impl::{orion_commit_simd_field, orion_open_simd_field}; - -mod mpi_utils; - -mod simd_field_mpi_impl; -pub use simd_field_mpi_impl::{orion_mpi_commit_simd_field, orion_mpi_open_simd_field}; - -mod verify; -pub use verify::orion_verify; - -mod pcs_trait_impl; -pub use pcs_trait_impl::{OrionBaseFieldPCS, OrionSIMDFieldPCS}; - -mod expander_api; -pub use expander_api::OrionPCSForGKR; diff --git a/poly_commit/src/orion/expander_api.rs b/poly_commit/src/orion/expander_api.rs deleted file mode 100644 index 5a82bb414..000000000 --- a/poly_commit/src/orion/expander_api.rs +++ /dev/null @@ -1,204 +0,0 @@ -use arith::{Field, SimdField}; -use gkr_engine::{ - ExpanderPCS, ExpanderSingleVarChallenge, FieldEngine, MPIEngine, PolynomialCommitmentType, - StructuredReferenceString, Transcript, -}; -use polynomials::MultilinearExtension; - -use crate::{ - orion::{ - simd_field_impl::{orion_commit_simd_field, orion_open_simd_field}, - simd_field_mpi_impl::{orion_mpi_commit_simd_field, orion_mpi_open_simd_field}, - verify::orion_verify, - OrionCommitment, OrionProof, OrionSIMDFieldPCS, OrionSRS, OrionScratchPad, - ORION_CODE_PARAMETER_INSTANCE, - }, - utils::{ - lift_expander_challenge_to_n_vars, lift_poly_and_expander_challenge_to_n_vars, - lift_poly_to_n_vars, - }, -}; - -use super::utils::orion_eval_shape; - -impl ExpanderPCS - for OrionSIMDFieldPCS -where - C: FieldEngine, - ComPackF: SimdField, -{ - const NAME: &'static str = "OrionPCSForExpanderGKR"; - - const PCS_TYPE: PolynomialCommitmentType = PolynomialCommitmentType::Orion; - - type Params = usize; - type ScratchPad = OrionScratchPad; - - type Commitment = OrionCommitment; - type Opening = OrionProof; - type BatchOpening = (); - type SRS = OrionSRS; - - /// NOTE(HS): this is the number of variables for local polynomial w.r.t. SIMD field elements. - fn gen_params(n_input_vars: usize, world_size: usize) -> Self::Params { - let num_vars_each_core = n_input_vars + C::SimdCircuitField::PACK_SIZE.ilog2() as usize; - let (_num_leaves_per_mt_query, scaled_num_local_vars, _msg_size) = orion_eval_shape( - world_size, - num_vars_each_core, - C::CircuitField::FIELD_SIZE, - C::SimdCircuitField::PACK_SIZE, - ); - - scaled_num_local_vars - C::SimdCircuitField::PACK_SIZE.ilog2() as usize - } - - fn gen_srs( - params: &Self::Params, - mpi_engine: &impl MPIEngine, - rng: impl rand::RngCore, - ) -> Self::SRS { - let num_vars_each_core = *params + C::SimdCircuitField::PACK_SIZE.ilog2() as usize; - let (srs, calibrated_num_vars_each_core) = OrionSRS::from_random( - mpi_engine.world_size(), - num_vars_each_core, - C::CircuitField::FIELD_SIZE, - ComPackF::PACK_SIZE, - ORION_CODE_PARAMETER_INSTANCE, - rng, - ); - assert_eq!(num_vars_each_core, calibrated_num_vars_each_core); - srs - } - - fn init_scratch_pad(_params: &Self::Params, _mpi_engine: &impl MPIEngine) -> Self::ScratchPad { - Self::ScratchPad::default() - } - - fn commit( - params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl MultilinearExtension, - scratch_pad: &mut Self::ScratchPad, - ) -> Option { - if poly.num_vars() < *params { - let poly = lift_poly_to_n_vars(poly, *params); - return >::commit( - params, - mpi_engine, - proving_key, - &poly, - scratch_pad, - ); - } - - let num_vars_each_core = *params + C::SimdCircuitField::PACK_SIZE.ilog2() as usize; - assert_eq!(num_vars_each_core, proving_key.num_vars); - - if mpi_engine.is_single_process() { - return orion_commit_simd_field::<_, C::SimdCircuitField, ComPackF>( - proving_key, - poly, - scratch_pad, - ) - .ok(); - } - - orion_mpi_commit_simd_field::<_, C::SimdCircuitField, ComPackF>( - mpi_engine, - proving_key, - poly, - scratch_pad, - ) - .ok() - } - - fn open( - params: &Self::Params, - mpi_engine: &impl MPIEngine, - proving_key: &::PKey, - poly: &impl MultilinearExtension, - eval_point: &ExpanderSingleVarChallenge, - transcript: &mut impl Transcript, - scratch_pad: &Self::ScratchPad, - ) -> Option { - if poly.num_vars() < *params { - let (poly, eval_point) = - lift_poly_and_expander_challenge_to_n_vars(poly, eval_point, *params); - return >::open( - params, - mpi_engine, - proving_key, - &poly, - &eval_point, - transcript, - scratch_pad, - ); - } - - let num_vars_each_core = *params + C::SimdCircuitField::PACK_SIZE.ilog2() as usize; - assert_eq!(num_vars_each_core, proving_key.num_vars); - - if mpi_engine.is_single_process() { - let (_, opening) = orion_open_simd_field::<_, C::SimdCircuitField, _, ComPackF>( - proving_key, - poly, - &eval_point.local_xs(), - transcript, - scratch_pad, - ); - return opening.into(); - } - - orion_mpi_open_simd_field::<_, C::SimdCircuitField, _, ComPackF>( - mpi_engine, - proving_key, - poly, - &eval_point.local_xs(), - &eval_point.r_mpi, - transcript, - scratch_pad, - ) - } - - fn verify( - params: &Self::Params, - verifying_key: &::VKey, - commitment: &Self::Commitment, - eval_point: &ExpanderSingleVarChallenge, - eval: C::ChallengeField, - transcript: &mut impl Transcript, /* add transcript here to allow - * interactive arguments */ - opening: &Self::Opening, - ) -> bool { - if eval_point.num_vars() < *params { - let eval_point = lift_expander_challenge_to_n_vars(eval_point, *params); - return >::verify( - params, - verifying_key, - commitment, - &eval_point, - eval, - transcript, - opening, - ); - } - - orion_verify::<_, C::SimdCircuitField, _, ComPackF>( - verifying_key, - commitment, - &eval_point.local_xs(), - &eval_point.r_mpi, - eval, - transcript, - opening, - ) - } -} - -pub type OrionPCSForGKR = OrionSIMDFieldPCS< - ::CircuitField, - ::SimdCircuitField, - ::ChallengeField, - ComPack, ->; diff --git a/poly_commit/src/orion/linear_code.rs b/poly_commit/src/orion/linear_code.rs deleted file mode 100644 index 15bb31236..000000000 --- a/poly_commit/src/orion/linear_code.rs +++ /dev/null @@ -1,291 +0,0 @@ -use std::cmp; - -use arith::Field; -use itertools::{chain, izip}; -use rand::seq::index; -use serdes::ExpSerde; - -use super::{OrionPCSError, OrionResult}; - -/* - * IMPLEMENTATIONS FOR ORION EXPANDER GRAPH - */ - -pub type DirectedEdge = usize; - -pub type DirectedNeighboring = Vec; - -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionExpanderGraph { - // L R vertices size book keeping: - // keep track of message length (l), and "compressed" code length (r) - pub l_vertices_size: usize, - pub r_vertices_size: usize, - - // neighboring stands for all (weighted) connected vertices of a vertex. - // In this context, the neighborings stands for the neighborings - // of vertices in R set of the bipariate graph, which explains why it has - // size of l_vertices_size, while each neighboring reserved r_vertices_size - // capacity. - pub neighborings: Vec, -} - -impl OrionExpanderGraph { - pub fn new( - l_vertices_size: usize, - r_vertices_size: usize, - expanding_degree: usize, - mut rng: impl rand::RngCore, - ) -> Self { - let mut neighborings: Vec = - vec![Vec::with_capacity(l_vertices_size); r_vertices_size]; - - (0..l_vertices_size).for_each(|l_index| { - let random_r_vertices = index::sample(&mut rng, r_vertices_size, expanding_degree); - - random_r_vertices - .iter() - .for_each(|r_index| neighborings[r_index].push(l_index)) - }); - - Self { - neighborings, - l_vertices_size, - r_vertices_size, - } - } - - #[inline(always)] - pub fn expander_mul( - &self, - l_vertices: &[F], - r_vertices: &mut [F], - ) -> OrionResult<()> { - if l_vertices.len() != self.l_vertices_size || r_vertices.len() != self.r_vertices_size { - return Err(OrionPCSError::ParameterUnmatchError); - } - - izip!(r_vertices, &self.neighborings).for_each(|(ri, ni)| { - *ri = ni.iter().map(|&edge_i| l_vertices[edge_i]).sum(); - }); - - Ok(()) - } -} - -/* - * IMPLEMENTATIONS FOR ORION CODE FROM EXPANDER GRAPH - */ - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct OrionCodeParameter { - // parameter for graph g0, that maps n -> (\alpha_g0 n) - // \alpha_g0 should be ranging in (0, 1) - pub alpha_g0: f64, - pub degree_g0: usize, - - // parameter regarding graph generation for the code: - // stopping condition when message is too short for the recursive code - // in the next round. - pub length_threshold_g0s: usize, - - // parameter for graph g1, let the message in the middle has length L, - // then the graph g1 maps L -> (\alpha_g1 L) - pub alpha_g1: f64, - pub degree_g1: usize, - - // code's relateive distance - pub hamming_weight: f64, -} - -// NOTE: This instance of code derives from Orion paper Section 5. -pub const ORION_CODE_PARAMETER_INSTANCE: OrionCodeParameter = OrionCodeParameter { - alpha_g0: 0.33, - degree_g0: 6, - - length_threshold_g0s: 12, - - alpha_g1: 0.337, - degree_g1: 6, - - hamming_weight: 0.055, -}; - -#[allow(clippy::doc_lazy_continuation)] -/// ACKNOWLEDGEMENT: on alphabet being F2 binary case, we appreciate the help from -/// - Section 18 in essential coding theory -/// https://cse.buffalo.edu/faculty/atri/courses/coding-theory/book/web-coding-book.pdf -/// -/// - Notes from coding theory -/// https://www.cs.cmu.edu/~venkatg/teaching/codingtheory/notes/notes8.pdf -/// -/// - Druk-Ishai 2014 -/// https://dl.acm.org/doi/10.1145/2554797.2554815 - -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionExpanderGraphPositioned { - pub graph: OrionExpanderGraph, - - pub input_starts: usize, - pub output_starts: usize, - pub output_ends: usize, -} - -impl OrionExpanderGraphPositioned { - #[inline(always)] - pub fn new( - input_starts: usize, - output_starts: usize, - output_ends: usize, - expanding_degree: usize, - mut rng: impl rand::RngCore, - ) -> Self { - Self { - graph: OrionExpanderGraph::new( - output_starts - input_starts, - output_ends - output_starts + 1, - expanding_degree, - &mut rng, - ), - input_starts, - output_starts, - output_ends, - } - } - - #[inline(always)] - pub fn expander_mul(&self, buffer: &mut [F], scratch: &mut [F]) -> OrionResult<()> { - let input_ref = &buffer[self.input_starts..self.output_starts]; - let output_ref = &mut scratch[self.output_starts..self.output_ends + 1]; - - self.graph.expander_mul(input_ref, output_ref)?; - buffer[self.output_starts..self.output_ends + 1].copy_from_slice(output_ref); - - Ok(()) - } -} - -// NOTE: The OrionCode here is representing an instance of Spielman code -// (Spielman96), that relies on 2 lists of expander graphs serving as -// error reduction code, and thus the linear error correction code derive -// from the parity matrices corresponding to these expander graphs. -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionCode { - pub hamming_weight: f64, - - // empirical parameters for this instance of expander code on input/codeword - pub msg_len: usize, - pub codeword_len: usize, - - // g0s (affecting left side alphabets of the codeword) - // generated from the largest to the smallest - pub g0s: Vec, - - // g1s (affecting right side alphabets of the codeword) - // generated from the smallest to the largest - pub g1s: Vec, -} - -pub type OrionCodeword = Vec; - -impl OrionCode { - pub fn new(params: OrionCodeParameter, msg_len: usize, mut rng: impl rand::RngCore) -> Self { - // NOTE: sanity check - 1 / threshold_len > hamming_weight - // as was part of Druk-Ishai-14 distance proof by induction - assert!(1f64 / (params.length_threshold_g0s as f64) > params.hamming_weight); - - // NOTE: sanity check for both alpha_g0 and alpha_g1 - assert!(0f64 < params.alpha_g0 && params.alpha_g0 < 1f64); - assert!(0f64 < params.alpha_g1 && params.alpha_g1 < 1f64); - - // NOTE: the real deal of code instance generation starts here - let mut recursive_g0_output_starts: Vec = Vec::new(); - - let mut g0s: Vec = Vec::new(); - let mut g1s: Vec = Vec::new(); - - let mut g0_input_starts = 0; - let mut g0_output_starts = msg_len; - - while g0_output_starts - g0_input_starts > params.length_threshold_g0s { - let n = g0_output_starts - g0_input_starts; - let g0_output_len = (n as f64 * params.alpha_g0).round() as usize; - let degree_g0 = cmp::min(params.degree_g0, g0_output_len); - - g0s.push(OrionExpanderGraphPositioned::new( - g0_input_starts, - g0_output_starts, - g0_output_starts + g0_output_len - 1, - degree_g0, - &mut rng, - )); - - recursive_g0_output_starts.push(g0_output_starts); - - (g0_input_starts, g0_output_starts) = - (g0_output_starts, g0_output_starts + g0_output_len); - } - - // After g0s are generated, we generate g1s - let mut g1_output_starts = g0_output_starts; - - while let Some(g1_input_starts) = recursive_g0_output_starts.pop() { - let n = g1_output_starts - g1_input_starts; - let g1_output_len = (n as f64 * params.alpha_g1).round() as usize; - let degree_g1 = cmp::min(params.degree_g1, g1_output_len); - - g1s.push(OrionExpanderGraphPositioned::new( - g1_input_starts, - g1_output_starts, - g1_output_starts + g1_output_len - 1, - degree_g1, - &mut rng, - )); - - g1_output_starts += g1_output_len; - } - - let codeword_len = g1_output_starts; - Self { - hamming_weight: params.hamming_weight, - msg_len, - codeword_len, - g0s, - g1s, - } - } - - #[inline(always)] - pub fn code_len(&self) -> usize { - self.codeword_len - } - - #[inline(always)] - pub fn msg_len(&self) -> usize { - self.msg_len - } - - #[inline(always)] - pub fn hamming_weight(&self) -> f64 { - self.hamming_weight - } - - #[inline(always)] - pub fn encode(&self, msg: &[F]) -> OrionResult> { - let mut codeword = vec![F::ZERO; self.code_len()]; - self.encode_in_place(msg, &mut codeword)?; - Ok(codeword) - } - - #[inline(always)] - pub fn encode_in_place(&self, msg: &[F], buffer: &mut [F]) -> OrionResult<()> { - if msg.len() != self.msg_len() || buffer.len() != self.code_len() { - return Err(OrionPCSError::ParameterUnmatchError); - } - - buffer[..self.msg_len()].copy_from_slice(msg); - let mut scratch = vec![F::ZERO; self.code_len()]; - - chain!(&self.g0s, &self.g1s).try_for_each(|g| g.expander_mul(buffer, &mut scratch)) - } -} diff --git a/poly_commit/src/orion/linear_code_tests.rs b/poly_commit/src/orion/linear_code_tests.rs deleted file mode 100644 index 7c922297b..000000000 --- a/poly_commit/src/orion/linear_code_tests.rs +++ /dev/null @@ -1,84 +0,0 @@ -use arith::{Field, SimdField}; -use ark_std::test_rng; -use gf2::{GF2x8, GF2}; -use transpose::transpose; - -use crate::{orion::linear_code::OrionCode, SubsetSumLUTs, ORION_CODE_PARAMETER_INSTANCE}; - -fn column_combination(mat: &[F], combination: &[F]) -> Vec -where - F: Field, - PackF: SimdField, -{ - assert_eq!(combination.len() % PackF::PACK_SIZE, 0); - - let mut luts = SubsetSumLUTs::new(PackF::PACK_SIZE, combination.len() / PackF::PACK_SIZE); - luts.build(combination); - - mat.chunks(combination.len()) - .map(|p_col| { - let packed: Vec<_> = p_col.chunks(PackF::PACK_SIZE).map(PackF::pack).collect(); - luts.lookup_and_sum(&packed) - }) - .collect() -} - -fn test_orion_code_generic(msg_len: usize, row_num: usize) -where - F: Field, - PackF: SimdField, -{ - let mut rng = test_rng(); - - let encoder = OrionCode::new(ORION_CODE_PARAMETER_INSTANCE, msg_len, &mut rng); - - let weights: Vec<_> = (0..row_num).map(|_| F::random_unsafe(&mut rng)).collect(); - - // NOTE: generate message and codeword in the slice buffer - let mut message_mat = vec![F::ZERO; row_num * encoder.msg_len()]; - let mut codeword_mat = vec![F::ZERO; row_num * encoder.code_len()]; - - message_mat - .chunks_mut(encoder.msg_len()) - .zip(codeword_mat.chunks_mut(encoder.code_len())) - .for_each(|(msg, codeword)| { - msg.fill_with(|| F::random_unsafe(&mut rng)); - encoder.encode_in_place(msg, codeword).unwrap() - }); - - // NOTE: transpose message and codeword matrix - let mut message_mat_transpose = vec![F::ZERO; row_num * encoder.msg_len()]; - transpose( - &message_mat, - &mut message_mat_transpose, - encoder.msg_len(), - row_num, - ); - - let mut codeword_mat_transpose = vec![F::ZERO; row_num * encoder.code_len()]; - transpose( - &codeword_mat, - &mut codeword_mat_transpose, - encoder.code_len(), - row_num, - ); - - // NOTE: message and codeword matrix linear combination with weights - let msg_linear_combined = column_combination::(&message_mat_transpose, &weights); - let codeword_linear_combined = - column_combination::(&codeword_mat_transpose, &weights); - - let codeword_computed = encoder.encode(&msg_linear_combined).unwrap(); - - assert_eq!(codeword_linear_combined, codeword_computed); -} - -#[test] -fn test_orion_code() { - const ROW_NUM: usize = 128; - - (5..=10).for_each(|num_vars| { - let msg_len = 1usize << num_vars; - test_orion_code_generic::(msg_len, ROW_NUM); - }); -} diff --git a/poly_commit/src/orion/mpi_utils.rs b/poly_commit/src/orion/mpi_utils.rs deleted file mode 100644 index 3ed38f840..000000000 --- a/poly_commit/src/orion/mpi_utils.rs +++ /dev/null @@ -1,257 +0,0 @@ -use std::collections::VecDeque; - -use arith::SimdField; -use gkr_engine::{MPIEngine, Transcript}; -use itertools::izip; -use serdes::ExpSerde; -use transpose::transpose_inplace; -use tree::{RangePath, Tree}; - -use crate::{ - orion::{OrionCommitment, OrionResult, OrionSRS, OrionScratchPad}, - traits::TensorCodeIOPPCS, - PCS_SOUNDNESS_BITS, -}; - -/* -In the Orion scenario, the codeword originally look like following in the RAM: - -p(0): *-*-*-*-*-*-*-*-*-*- .... -* - - *-*-*-*-*-*-*-*-*-*- .... -* - -p(1): *-*-*-*-*-*-*-*-*-*- .... -* - - *-*-*-*-*-*-*-*-*-*- .... -* - -... - -p(n - 1): *-*-*-*-*-*-*-*-*-*- .... -* - - *-*-*-*-*-*-*-*-*-*- .... -* - -a local transpose on each process allows for visiting in interleaved codeword order: - -p(0): * * * * * * * * * * .... * - |/|/|/|/|/|/|/|/|/| .... /| - * * * * * * * * * * .... * - -p(1): * * * * * * * * * * .... * - |/|/|/|/|/|/|/|/|/| .... /| - * * * * * * * * * * .... * - -... - -p(n - 1): * * * * * * * * * * .... * - |/|/|/|/|/|/|/|/|/| .... /| - * * * * * * * * * * .... * - -a global MPI ALL TO ALL rewinds the order into the following: - - p(0) p(1) p(2) p(n - 1) - * * * * * * * * * * .... * - |/|/|/| |/|/|/| |/| .... /| - * * * * * * * * * * .... * - / / - / / - / / - / / - / / / - * * * * * * * * * * .... * - |/|/|/| |/|/|/| |/| .... /| - * * * * * * * * * * .... * - / / - / / - / / - / / - / / / - * * * * * * * * * * .... * - |/|/|/| |/|/|/| |/| .... /| - * * * * * * * * * * .... * - -rearrange each row of interleaved codeword on each process, we have: - - p(0) p(1) p(2) p(n - 1) - *-*-*-* *-*-*-* *-*- .... -* - *-*-*-* *-*-*-* *-*- .... -* - / / - / / - / / - / / - / / / - *-*-*-* *-*-*-* *-*- .... -* - *-*-*-* *-*-*-* *-*- .... -* - / / - / / - / / - / / - / / / - *-*-*-* *-*-*-* *-*- .... -* - *-*-*-* *-*-*-* *-*- .... -* - -eventually, a final transpose each row lead to results of ordering by *WHOLE* interleaved alphabet: - - p(0) p(1) .... - * * * * * * * * - | /| /| /| | /| /| /| - * / * / * / * * / * / * / * - | / | / | / | | / | / | / | - * / * / * / * * / * / * / * - |/ |/ |/ | |/ |/ |/ | - * * * * * * * * - -After all these, we can go onwards to MT commitment, and later open alphabets lies in one of the parties. - */ - -#[inline(always)] -pub(crate) fn mpi_commit_encoded( - mpi_engine: &impl MPIEngine, - pk: &OrionSRS, - packed_evals: &[PackF], - scratch_pad: &mut OrionScratchPad, -) -> OrionResult -where - PackF: SimdField, -{ - let packed_rows = pk.local_num_fs_per_query() / PackF::PACK_SIZE; - - // NOTE: packed codeword buffer and encode over packed field - let mut codewords = vec![PackF::ZERO; packed_rows * pk.codeword_len()]; - izip!( - packed_evals.chunks(pk.message_len()), - codewords.chunks_mut(pk.codeword_len()) - ) - .try_for_each(|(evals, codeword)| pk.code_instance.encode_in_place(evals, codeword))?; - - // NOTE: transpose codeword s.t., the matrix has codewords being columns - if packed_rows > 1 { - let mut scratch = vec![PackF::ZERO; std::cmp::max(packed_rows, pk.codeword_len())]; - transpose_inplace(&mut codewords, &mut scratch, pk.codeword_len(), packed_rows); - drop(scratch) - } - - // NOTE: commit the interleaved codeword - // we just directly commit to the packed field elements to leaves - // Also note, when codeword is not power of 2 length, pad to nearest po2 - // to commit by merkle tree - if !codewords.len().is_power_of_two() { - let aligned_po2_len = codewords.len().next_power_of_two(); - codewords.resize(aligned_po2_len, PackF::ZERO); - } - - // NOTE: ALL-TO-ALL transpose go get other world's slice of codeword - mpi_engine.all_to_all_transpose(&mut codewords); - - let codeword_po2_len = pk.codeword_len().next_power_of_two(); - let codeword_this_world_len = packed_rows * codeword_po2_len; - assert_eq!(codewords.len(), codeword_this_world_len); - - let codeword_po2_chunk_len = codeword_po2_len / mpi_engine.world_size(); - let global_packed_rows = packed_rows * mpi_engine.world_size(); - assert_eq!(codeword_po2_len % mpi_engine.world_size(), 0); - - if packed_rows > 1 { - let codeword_chunk_per_world_len = codeword_po2_chunk_len * packed_rows; - - // NOTE: now transpose back to row order of each world's codeword slice - let mut scratch = vec![PackF::ZERO; std::cmp::max(codeword_po2_chunk_len, packed_rows)]; - codewords - .chunks_mut(codeword_chunk_per_world_len) - .for_each(|c| transpose_inplace(c, &mut scratch, packed_rows, codeword_po2_chunk_len)); - drop(scratch); - } - - // NOTE: transpose back into column order of the codeword slice - let mut scratch = vec![PackF::ZERO; std::cmp::max(codeword_po2_chunk_len, global_packed_rows)]; - transpose_inplace( - &mut codewords, - &mut scratch, - codeword_po2_chunk_len, - global_packed_rows, - ); - drop(scratch); - - scratch_pad.interleaved_alphabet_commitment = - Tree::compact_new_with_packed_field_elems(codewords); - - // NOTE: gather local roots and compute the final MT root - let local_commitment = scratch_pad.interleaved_alphabet_commitment.root(); - let mut leaves = vec![tree::Node::default(); mpi_engine.world_size()]; - mpi_engine.gather_vec(&[local_commitment], &mut leaves); - - { - let mut leaves_bytes: Vec = Vec::new(); - leaves.serialize_into(&mut leaves_bytes)?; - mpi_engine.root_broadcast_bytes(&mut leaves_bytes); - - if !mpi_engine.is_root() { - leaves = Vec::deserialize_from(leaves_bytes.as_slice())?; - } - } - - scratch_pad.merkle_cap = leaves.clone(); - - let root = { - let height = 1 + leaves.len().ilog2(); - let internal = tree::Tree::new_with_leaf_nodes(&leaves, height); - internal[0] - }; - - Ok(root) -} - -#[inline(always)] -pub(crate) fn orion_mpi_mt_openings( - mpi_engine: &impl MPIEngine, - pk: &OrionSRS, - scratch_pad: &OrionScratchPad, - transcript: &mut T, -) -> Option> -where - T: Transcript, -{ - let num_leaves_per_opening = pk.num_leaves_per_mt_query(); - - // NOTE: MT opening for point queries - let query_num = pk.query_complexity(PCS_SOUNDNESS_BITS); - let query_indices: Vec = { - let mut indices = transcript.generate_usize_vector(query_num); - indices.iter_mut().for_each(|q| *q %= pk.codeword_len()); - indices - }; - - let index_range_per_world = pk.codeword_len().next_power_of_two() / mpi_engine.world_size(); - let index_starts_this_world = index_range_per_world * mpi_engine.world_rank(); - let index_ends_this_world = index_starts_this_world + index_range_per_world; - - let local_paths: Vec = query_indices - .iter() - .filter(|&&index| index_starts_this_world <= index && index < index_ends_this_world) - .map(|index| { - let left = (index - index_starts_this_world) * num_leaves_per_opening; - scratch_pad - .interleaved_alphabet_commitment - .range_query(left, left + num_leaves_per_opening - 1) - }) - .collect(); - - let mut global_paths: Vec> = Vec::new(); - mpi_engine.gather_varlen_vec(&local_paths, &mut global_paths); - - if !mpi_engine.is_root() { - return None; - } - - let mut global_paths_deque: Vec> = - global_paths.into_iter().map(VecDeque::from).collect(); - - let flattened_paths: Vec = query_indices - .iter() - .map(|q| { - let which_world = q / index_range_per_world; - global_paths_deque[which_world].pop_front().unwrap() - }) - .collect(); - - flattened_paths.into() -} diff --git a/poly_commit/src/orion/pcs_trait_impl.rs b/poly_commit/src/orion/pcs_trait_impl.rs deleted file mode 100644 index bae848e5b..000000000 --- a/poly_commit/src/orion/pcs_trait_impl.rs +++ /dev/null @@ -1,233 +0,0 @@ -use std::marker::PhantomData; - -use arith::{ExtensionField, Field, SimdField}; -use gkr_engine::{StructuredReferenceString, Transcript}; -use polynomials::{MultiLinearPoly, MultilinearExtension, RefMultiLinearPoly}; - -use crate::{ - orion::{ - simd_field_impl::{orion_commit_simd_field, orion_open_simd_field}, - verify::orion_verify, - OrionCommitment, OrionProof, OrionSRS, OrionScratchPad, ORION_CODE_PARAMETER_INSTANCE, - }, - PolynomialCommitmentScheme, -}; - -impl StructuredReferenceString for OrionSRS { - type PKey = OrionSRS; - type VKey = OrionSRS; - - fn into_keys(self) -> (Self::PKey, Self::VKey) { - (self.clone(), self.clone()) - } -} - -#[inline(always)] -fn pack_from_base(es: &[F]) -> Vec -where - F: Field, - PackF: SimdField, -{ - // NOTE: SIMD pack neighboring base field evals - es.chunks(PackF::PACK_SIZE).map(PackF::pack).collect() -} - -pub struct OrionBaseFieldPCS -where - F: Field, - EvalF: ExtensionField, - ComPackF: SimdField, - OpenPackF: SimdField, -{ - _marker_f: PhantomData, - _marker_eval_f: PhantomData, - _marker_commit_f: PhantomData, - _marker_open_f: PhantomData, -} - -impl PolynomialCommitmentScheme - for OrionBaseFieldPCS -where - F: Field, - EvalF: ExtensionField, - ComPackF: SimdField, - OpenPackF: SimdField, -{ - const NAME: &'static str = "OrionBaseFieldPCS"; - - type Params = usize; - type Poly = MultiLinearPoly; - type EvalPoint = Vec; - type ScratchPad = OrionScratchPad; - - type SRS = OrionSRS; - type Commitment = OrionCommitment; - type Opening = OrionProof; - - fn gen_srs_for_testing(params: &Self::Params, rng: impl rand::RngCore) -> (Self::SRS, usize) { - OrionSRS::from_random( - 1, - *params, - F::FIELD_SIZE, - ComPackF::PACK_SIZE, - ORION_CODE_PARAMETER_INSTANCE, - rng, - ) - } - - fn init_scratch_pad(_params: &Self::Params) -> Self::ScratchPad { - OrionScratchPad::default() - } - - fn commit( - params: &Self::Params, - pk: &::PKey, - poly: &Self::Poly, - scratch_pad: &mut Self::ScratchPad, - ) -> Self::Commitment { - assert_eq!(*params, pk.num_vars); - assert_eq!(poly.hypercube_size() % OpenPackF::PACK_SIZE, 0); - - let packed_evals: Vec = pack_from_base(poly.hypercube_basis_ref()); - let simd_poly = RefMultiLinearPoly::from_ref(&packed_evals); - - orion_commit_simd_field::<_, OpenPackF, ComPackF>(pk, &simd_poly, scratch_pad).unwrap() - } - - fn open( - params: &Self::Params, - pk: &::PKey, - poly: &Self::Poly, - x: &Self::EvalPoint, - scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (EvalF, Self::Opening) { - assert_eq!(*params, pk.num_vars); - assert_eq!(poly.hypercube_size() % OpenPackF::PACK_SIZE, 0); - - let packed_evals: Vec = pack_from_base(poly.hypercube_basis_ref()); - let simd_poly = RefMultiLinearPoly::from_ref(&packed_evals); - - orion_open_simd_field::<_, OpenPackF, _, ComPackF>( - pk, - &simd_poly, - x, - transcript, - scratch_pad, - ) - } - - fn verify( - params: &Self::Params, - vk: &::VKey, - commitment: &Self::Commitment, - x: &Self::EvalPoint, - v: EvalF, - opening: &Self::Opening, - transcript: &mut impl Transcript, - ) -> bool { - assert_eq!(*params, vk.num_vars); - orion_verify::<_, OpenPackF, _, ComPackF>(vk, commitment, x, &[], v, transcript, opening) - } -} - -pub struct OrionSIMDFieldPCS -where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - _marker_f: PhantomData, - _marker_simd_f: PhantomData, - _marker_eval_f: PhantomData, - _marker_commit_f: PhantomData, -} - -impl PolynomialCommitmentScheme - for OrionSIMDFieldPCS -where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - const NAME: &'static str = "OrionSIMDFieldPCS"; - - type Params = usize; - type Poly = MultiLinearPoly; - type EvalPoint = Vec; - type ScratchPad = OrionScratchPad; - - type SRS = OrionSRS; - type Commitment = OrionCommitment; - type Opening = OrionProof; - - // NOTE: here we say the number of variables is the sum of 2 following things: - // - number of variables of the multilinear polynomial - // - number of variables reside in the SIMD field - e.g., 3 vars for a SIMD 8 field - fn gen_srs_for_testing(params: &Self::Params, rng: impl rand::RngCore) -> (Self::SRS, usize) { - OrionSRS::from_random( - 1, - *params, - F::FIELD_SIZE, - ComPackF::PACK_SIZE, - ORION_CODE_PARAMETER_INSTANCE, - rng, - ) - } - - fn init_scratch_pad(_params: &Self::Params) -> Self::ScratchPad { - OrionScratchPad::default() - } - - fn commit( - params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - scratch_pad: &mut Self::ScratchPad, - ) -> Self::Commitment { - assert_eq!(*params, proving_key.num_vars); - assert_eq!( - poly.get_num_vars(), - proving_key.num_vars - SimdF::PACK_SIZE.ilog2() as usize - ); - orion_commit_simd_field::<_, SimdF, ComPackF>(proving_key, poly, scratch_pad).unwrap() - } - - fn open( - params: &Self::Params, - proving_key: &::PKey, - poly: &Self::Poly, - x: &Self::EvalPoint, - scratch_pad: &Self::ScratchPad, - transcript: &mut impl Transcript, - ) -> (EvalF, Self::Opening) { - assert_eq!(*params, proving_key.num_vars); - assert_eq!( - poly.get_num_vars(), - proving_key.num_vars - SimdF::PACK_SIZE.ilog2() as usize - ); - orion_open_simd_field::( - proving_key, - poly, - x, - transcript, - scratch_pad, - ) - } - - fn verify( - params: &Self::Params, - vk: &::VKey, - commitment: &Self::Commitment, - x: &Self::EvalPoint, - v: EvalF, - opening: &Self::Opening, - transcript: &mut impl Transcript, - ) -> bool { - assert_eq!(*params, vk.num_vars); - assert_eq!(x.len(), vk.num_vars); - orion_verify::<_, SimdF, _, ComPackF>(vk, commitment, x, &[], v, transcript, opening) - } -} diff --git a/poly_commit/src/orion/simd_field_impl.rs b/poly_commit/src/orion/simd_field_impl.rs deleted file mode 100644 index a86814b76..000000000 --- a/poly_commit/src/orion/simd_field_impl.rs +++ /dev/null @@ -1,120 +0,0 @@ -use arith::{ExtensionField, Field, SimdField}; -use gf2::GF2; -use gkr_engine::Transcript; -use polynomials::{EqPolynomial, MultilinearExtension, RefMultiLinearPoly}; - -use crate::{ - orion::{ - utils::{ - commit_encoded, lut_open_linear_combine, orion_mt_openings, simd_open_linear_combine, - }, - OrionCommitment, OrionProof, OrionResult, OrionSRS, OrionScratchPad, - }, - traits::TensorCodeIOPPCS, - PCS_SOUNDNESS_BITS, -}; - -#[inline(always)] -pub fn orion_commit_simd_field( - pk: &OrionSRS, - poly: &impl MultilinearExtension, - scratch_pad: &mut OrionScratchPad, -) -> OrionResult -where - F: Field, - SimdF: SimdField, - ComPackF: SimdField, -{ - let packed_evals_ref = unsafe { - let relative_pack_size = ComPackF::PACK_SIZE / SimdF::PACK_SIZE; - assert_eq!(ComPackF::PACK_SIZE % SimdF::PACK_SIZE, 0); - - let ptr = poly.hypercube_basis_ref().as_ptr(); - let len = poly.hypercube_size() / relative_pack_size; - assert_eq!(len * relative_pack_size, poly.hypercube_size()); - - std::slice::from_raw_parts(ptr as *const ComPackF, len) - }; - - commit_encoded(pk, packed_evals_ref, scratch_pad) -} - -#[inline(always)] -pub fn orion_open_simd_field( - pk: &OrionSRS, - poly: &impl MultilinearExtension, - point: &[EvalF], - transcript: &mut impl Transcript, - scratch_pad: &OrionScratchPad, -) -> (EvalF, OrionProof) -where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - let msg_size = pk.message_len(); - - let num_vars_in_com_simd = ComPackF::PACK_SIZE.ilog2() as usize; - let num_vars_in_msg = msg_size.ilog2() as usize; - - // NOTE: pre-compute the eq linear combine coeffs for linear combination - let eq_col_coeffs = { - let mut eq_vars = point[..num_vars_in_com_simd].to_vec(); - eq_vars.extend_from_slice(&point[num_vars_in_com_simd + num_vars_in_msg..]); - EqPolynomial::build_eq_x_r(&eq_vars) - }; - - // NOTE: pre-declare the spaces for returning evaluation and proximity queries - let mut eval_row = vec![EvalF::ZERO; msg_size]; - - let proximity_test_num = pk.proximity_repetitions::(PCS_SOUNDNESS_BITS); - let mut proximity_rows = vec![vec![EvalF::ZERO; msg_size]; proximity_test_num]; - - let random_col_coeffs: Vec<_> = (0..proximity_test_num) - .map(|_| { - let rand = transcript.generate_field_elements::(point.len() - num_vars_in_msg); - EqPolynomial::build_eq_x_r(&rand) - }) - .collect(); - - match F::NAME { - GF2::NAME => lut_open_linear_combine( - ComPackF::PACK_SIZE, - poly.hypercube_basis_ref(), - &eq_col_coeffs, - &mut eval_row, - &random_col_coeffs, - &mut proximity_rows, - ), - _ => simd_open_linear_combine( - ComPackF::PACK_SIZE, - poly.hypercube_basis_ref(), - &eq_col_coeffs, - &mut eval_row, - &random_col_coeffs, - &mut proximity_rows, - ), - } - - // NOTE: working on evaluation response, evaluate the rest of the response - let mut scratch = vec![EvalF::ZERO; msg_size]; - let eval = RefMultiLinearPoly::from_ref(&eval_row).evaluate_with_buffer( - &point[num_vars_in_com_simd..num_vars_in_com_simd + num_vars_in_msg], - &mut scratch, - ); - drop(scratch); - - // NOTE: MT opening for point queries - let query_openings = orion_mt_openings(pk, transcript, scratch_pad); - - ( - eval, - OrionProof { - eval_row, - proximity_rows, - query_openings, - merkle_cap: scratch_pad.merkle_cap.clone(), - }, - ) -} diff --git a/poly_commit/src/orion/simd_field_mpi_impl.rs b/poly_commit/src/orion/simd_field_mpi_impl.rs deleted file mode 100644 index 2fe68445e..000000000 --- a/poly_commit/src/orion/simd_field_mpi_impl.rs +++ /dev/null @@ -1,132 +0,0 @@ -use arith::{ExtensionField, Field, SimdField}; -use gf2::GF2; -use gkr_engine::{MPIEngine, Transcript}; -use polynomials::{EqPolynomial, MultilinearExtension}; - -use crate::{ - orion::{ - mpi_utils::{mpi_commit_encoded, orion_mpi_mt_openings}, - utils::{lut_open_linear_combine, simd_open_linear_combine}, - OrionCommitment, OrionProof, OrionResult, OrionSRS, OrionScratchPad, - }, - traits::TensorCodeIOPPCS, - PCS_SOUNDNESS_BITS, -}; - -#[inline(always)] -pub fn orion_mpi_commit_simd_field( - mpi_engine: &impl MPIEngine, - pk: &OrionSRS, - poly: &impl MultilinearExtension, - scratch_pad: &mut OrionScratchPad, -) -> OrionResult -where - F: Field, - SimdF: SimdField, - ComPackF: SimdField, -{ - let packed_evals_ref = unsafe { - let relative_pack_size = ComPackF::PACK_SIZE / SimdF::PACK_SIZE; - assert_eq!(ComPackF::PACK_SIZE % SimdF::PACK_SIZE, 0); - - let ptr = poly.hypercube_basis_ref().as_ptr(); - let len = poly.hypercube_size() / relative_pack_size; - assert_eq!(len * relative_pack_size, poly.hypercube_size()); - - std::slice::from_raw_parts(ptr as *const ComPackF, len) - }; - - mpi_commit_encoded(mpi_engine, pk, packed_evals_ref, scratch_pad) -} - -#[inline(always)] -pub fn orion_mpi_open_simd_field( - mpi_engine: &impl MPIEngine, - pk: &OrionSRS, - poly: &impl MultilinearExtension, - point: &[EvalF], - mpi_point: &[EvalF], - transcript: &mut impl Transcript, - scratch_pad: &OrionScratchPad, -) -> Option> -where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - let msg_size = pk.message_len(); - - let num_vars_in_com_simd = ComPackF::PACK_SIZE.ilog2() as usize; - let num_vars_in_msg = msg_size.ilog2() as usize; - - // NOTE: pre-compute the eq linear combine coeffs for linear combination - let eq_col_coeffs = { - let mut eq_vars = point[..num_vars_in_com_simd].to_vec(); - eq_vars.extend_from_slice(&point[num_vars_in_com_simd + num_vars_in_msg..]); - let mut coeffs = EqPolynomial::build_eq_x_r(&eq_vars); - let mpi_weight = EqPolynomial::ith_eq_vec_elem(mpi_point, mpi_engine.world_rank()); - coeffs.iter_mut().for_each(|c| *c *= mpi_weight); - coeffs - }; - - // NOTE: pre-declare the spaces for returning evaluation and proximity queries - let mut eval_row = vec![EvalF::ZERO; msg_size]; - - let proximity_test_num = pk.proximity_repetitions::(PCS_SOUNDNESS_BITS); - let mut proximity_rows = vec![vec![EvalF::ZERO; msg_size]; proximity_test_num]; - - // NOTE: draw randomness from transcript with log random complexity - let num_of_local_random_vars = point.len() - num_vars_in_msg; - let local_random_coeffs: Vec<_> = (0..proximity_test_num) - .map(|_| { - let local_rand = transcript.generate_field_elements::(num_of_local_random_vars); - let mpi_rand = transcript.generate_field_elements::(mpi_point.len()); - let mut coeffs = EqPolynomial::build_eq_x_r(&local_rand); - let mpi_weight = EqPolynomial::ith_eq_vec_elem(&mpi_rand, mpi_engine.world_rank()); - coeffs.iter_mut().for_each(|c| *c *= mpi_weight); - coeffs - }) - .collect(); - - match F::NAME { - GF2::NAME => lut_open_linear_combine( - ComPackF::PACK_SIZE, - poly.hypercube_basis_ref(), - &eq_col_coeffs, - &mut eval_row, - &local_random_coeffs, - &mut proximity_rows, - ), - _ => simd_open_linear_combine( - ComPackF::PACK_SIZE, - poly.hypercube_basis_ref(), - &eq_col_coeffs, - &mut eval_row, - &local_random_coeffs, - &mut proximity_rows, - ), - } - - // NOTE: MPI sum up local weighed rows - eval_row = mpi_engine.sum_vec(&eval_row); - proximity_rows = proximity_rows - .iter() - .map(|r| mpi_engine.sum_vec(r)) - .collect(); - - // NOTE: MT opening for point queries - let query_openings = orion_mpi_mt_openings(mpi_engine, pk, scratch_pad, transcript); - - if !mpi_engine.is_root() { - return None; - } - - OrionProof { - eval_row, - proximity_rows, - query_openings: query_openings.unwrap(), - merkle_cap: scratch_pad.merkle_cap.clone(), - } - .into() -} diff --git a/poly_commit/src/orion/utils.rs b/poly_commit/src/orion/utils.rs deleted file mode 100644 index 9ada0399e..000000000 --- a/poly_commit/src/orion/utils.rs +++ /dev/null @@ -1,579 +0,0 @@ -use arith::{ExtensionField, Field, SimdField}; -use gkr_engine::Transcript; -use itertools::izip; -use serdes::{ExpSerde, SerdeError}; -use thiserror::Error; -use transpose::{transpose, transpose_inplace}; -use tree::{Node, LEAF_BYTES}; - -use crate::{ - orion::linear_code::{OrionCode, OrionCodeParameter, ORION_CODE_PARAMETER_INSTANCE}, - traits::TensorCodeIOPPCS, - PCS_SOUNDNESS_BITS, -}; - -/* - * PCS ERROR AND RESULT SETUP - */ - -#[derive(Debug, Error)] -pub enum OrionPCSError { - #[error("Orion PCS linear code parameter unmatch error")] - ParameterUnmatchError, - - #[error("field serde error")] - SerializationError(#[from] SerdeError), -} - -pub type OrionResult = std::result::Result; - -/* - * RELEVANT TYPES SETUP - */ - -/// returning leaf number, calibrated local number of variables, and message size -/// NOTE(HS) num of local variables is over base field with no SIMD -pub(crate) const fn orion_eval_shape( - world_size: usize, - num_local_vars: usize, - num_bits_base_field: usize, - field_pack_size: usize, -) -> (usize, usize, usize) { - // for a global polynomial, compute the boolean hypercube size - let hypercube_size = world_size * (1 << num_local_vars); - - // compute how many bits the global polynomial occupy - let polynomial_bits = hypercube_size * num_bits_base_field; - let polynomial_bits_log2 = polynomial_bits.ilog2(); - - // the leaf should be roughly O(\log N) to the global polynomial size - let leaves_lower_bound = match polynomial_bits_log2 { - // 128 bytes MT opening - 0..16 => 2, - - // 256 bytes MT opening - 16..22 => 4, - - // 512 bytes MT opening - 22..28 => 8, - - // 1 KB MT opening - 28..34 => 16, - - // 2 KB MT opening - 34.. => 32, - }; - - // now compute the commitment used SIMD field bits, - // and compared against the suggest leaf size above. - // - // the commitment used SIMD field is the smallest unit of memory in commitment, - // thus each world can contribute as low as 1 commitment used SIMD field element, - // and thus if the world size is too large, we might need to scale up the final - // leaf size based on suggested leaf size - and thus may require padding the poly - // to the right size. - let num_bits_packed_f = field_pack_size * num_bits_base_field; - let minimum_pack_fs_per_world_in_query = { - let leaves_bits_lower_bound = leaves_lower_bound * LEAF_BYTES * 8; - // NOTE(HS) div_ceil ensures each world contribute at least 1 commitment SIMD field element - // in the MT query opening - leaves_bits_lower_bound.div_ceil(num_bits_packed_f * world_size) - }; - - let final_leaves_bits = minimum_pack_fs_per_world_in_query * world_size * num_bits_packed_f; - let final_leaves_per_query = final_leaves_bits / (LEAF_BYTES * 8); - - // once we have decided the leaf size, we know the message size need to be encoded. - // the consideration is that - resulting codeword size should be >= MPI world size. - // - // Otherwise, the MPI transpose cannot go through - the codeword is too short to be - // segmented into the number of shares spreaded across MPI words for all-to-all transpose. - let msg_size = polynomial_bits / final_leaves_bits; - - // we want to know the mininum message size, such that the resulting codeword length - // (pad to next po2) >= the MPI world size. - // - // for small case, when input message is shorter than Expander code length threshold, - // the code is itself (by Druk-Ishai), - // otherwise Expander encoding applies, with a code rate > 1 / 2, eventually pad to 2x length. - // - // NOTE(HS): here we assume that the message size and the MPI world size are both po2, - // while Expander code length threshold might be arbitarary - we scale up the threshold - // to the next po2 to avoid corner case. - let minimum_msg_size = { - let min_expander_po2_code_len = ORION_CODE_PARAMETER_INSTANCE - .length_threshold_g0s - .next_power_of_two(); - - if world_size <= min_expander_po2_code_len { - world_size - } else { - world_size / 2 - } - }; - - // Early exit - if the message size from the global poly is sufficiently large, - // we decide the global MT opening size, and are good with the local polynomial number of vars. - if msg_size >= minimum_msg_size { - return (final_leaves_per_query, num_local_vars, msg_size); - } - - // Scale up the polynomial local number of variable and plan again for the evaluation shape. - let scaled_up_num_local_vars = { - let num_of_field_elems_per_world_in_query = - minimum_pack_fs_per_world_in_query * field_pack_size; - - let minimum_poly_len = minimum_msg_size * num_of_field_elems_per_world_in_query; - minimum_poly_len.ilog2() as usize - }; - - orion_eval_shape( - world_size, - scaled_up_num_local_vars, - num_bits_base_field, - field_pack_size, - ) -} - -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionSRS { - pub num_vars: usize, - pub num_leaves_per_mt_query: usize, - pub code_instance: OrionCode, -} - -impl TensorCodeIOPPCS for OrionSRS { - fn message_len(&self) -> usize { - self.code_instance.msg_len() - } - - fn codeword_len(&self) -> usize { - self.code_instance.code_len() - } - - fn minimum_hamming_weight(&self) -> f64 { - self.code_instance.hamming_weight() - } - - fn num_leaves_per_mt_query(&self) -> usize { - self.num_leaves_per_mt_query - } -} - -impl OrionSRS { - // NOTE(HS) num local variables here refers to the number of variables for base field elements - // rather than SIMD field elements, the number of variables returned for calibration is also - // over base field elements rather than SIMD field elements. - pub fn from_random( - world_size: usize, - num_local_vars: usize, - num_field_bits: usize, - field_pack_size: usize, - code_param_instance: OrionCodeParameter, - mut rng: impl rand::RngCore, - ) -> (Self, usize) { - let (num_leaves_per_mt_query, scaled_num_local_vars, msg_size) = - orion_eval_shape(world_size, num_local_vars, num_field_bits, field_pack_size); - - let srs_sampled = Self { - num_vars: scaled_num_local_vars, - num_leaves_per_mt_query, - code_instance: OrionCode::new(code_param_instance, msg_size, &mut rng), - }; - - (srs_sampled, scaled_num_local_vars) - } - - pub fn local_num_fs_per_query(&self) -> usize { - let local_poly_len = 1 << self.num_vars; - local_poly_len / self.message_len() - } -} - -pub type OrionCommitment = Node; - -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionScratchPad { - pub interleaved_alphabet_commitment: tree::Tree, - pub merkle_cap: Vec, -} - -#[derive(Clone, Debug, Default, ExpSerde)] -pub struct OrionProof { - pub eval_row: Vec, - pub proximity_rows: Vec>, - pub query_openings: Vec, - pub merkle_cap: Vec, -} - -#[inline(always)] -pub(crate) fn commit_encoded( - pk: &OrionSRS, - packed_evals: &[PackF], - scratch_pad: &mut OrionScratchPad, -) -> OrionResult -where - PackF: SimdField, -{ - let packed_rows = pk.local_num_fs_per_query() / PackF::PACK_SIZE; - - // NOTE: packed codeword buffer and encode over packed field - let mut codewords = vec![PackF::ZERO; packed_rows * pk.codeword_len()]; - izip!( - packed_evals.chunks(pk.message_len()), - codewords.chunks_mut(pk.codeword_len()) - ) - .try_for_each(|(evals, codeword)| pk.code_instance.encode_in_place(evals, codeword))?; - - // NOTE: transpose codeword s.t., the matrix has codewords being columns - let mut scratch = vec![PackF::ZERO; std::cmp::max(packed_rows, pk.codeword_len())]; - transpose_inplace(&mut codewords, &mut scratch, pk.codeword_len(), packed_rows); - drop(scratch); - - // NOTE: commit the interleaved codeword - // we just directly commit to the packed field elements to leaves - // Also note, when codeword is not power of 2 length, pad to nearest po2 - // to commit by merkle tree - if !codewords.len().is_power_of_two() { - let aligned_po2_len = codewords.len().next_power_of_two(); - codewords.resize(aligned_po2_len, PackF::ZERO); - } - scratch_pad.interleaved_alphabet_commitment = - tree::Tree::compact_new_with_packed_field_elems(codewords); - - scratch_pad.merkle_cap = vec![scratch_pad.interleaved_alphabet_commitment.root()]; - - Ok(scratch_pad.interleaved_alphabet_commitment.root()) -} - -#[inline(always)] -pub(crate) fn orion_mt_openings( - pk: &OrionSRS, - transcript: &mut T, - scratch_pad: &OrionScratchPad, -) -> Vec -where - T: Transcript, -{ - let leaves_in_range_opening = pk.num_leaves_per_mt_query(); - - // NOTE: MT opening for point queries - let query_num = pk.query_complexity(PCS_SOUNDNESS_BITS); - let query_indices = transcript.generate_usize_vector(query_num); - query_indices - .iter() - .map(|qi| { - let index = *qi % pk.codeword_len(); - let left = index * leaves_in_range_opening; - let right = left + leaves_in_range_opening - 1; - - scratch_pad - .interleaved_alphabet_commitment - .range_query(left, right) - }) - .collect() -} - -#[inline(always)] -pub(crate) fn orion_mt_verify( - vk: &OrionSRS, - query_indices: &[usize], - range_openings: &[tree::RangePath], - merkle_cap: &[Node], -) -> bool { - let world_size = merkle_cap.len(); - let indices_per_merkle_cap = vk.codeword_len().next_power_of_two() / world_size; - - izip!(query_indices, range_openings).all(|(&qi, range_path)| { - let index = qi % vk.codeword_len(); - let merkle_cap_index = index / indices_per_merkle_cap; - let in_sub_tree_index = index % indices_per_merkle_cap; - - range_path.verify(&merkle_cap[merkle_cap_index]) - && in_sub_tree_index == range_path.left / range_path.leaves.len() - }) -} - -/* - * LINEAR OPERATIONS FOR GF2 (LOOKUP TABLE BASED) - */ - -pub struct SubsetSumLUTs { - pub entry_bits: usize, - pub tables: Vec>, -} - -impl SubsetSumLUTs { - #[inline(always)] - pub fn new(entry_bits: usize, table_num: usize) -> Self { - assert!(entry_bits > 0 && table_num > 0); - - Self { - entry_bits, - tables: vec![vec![F::ZERO; 1 << entry_bits]; table_num], - } - } - - #[inline(always)] - pub fn build(&mut self, weights: &[F]) { - assert_eq!(weights.len(), self.entry_bits * self.tables.len()); - - self.tables.iter_mut().for_each(|lut| lut.fill(F::ZERO)); - - // NOTE: we are assuming that the table is for {0, 1}-linear combination - izip!(&mut self.tables, weights.chunks(self.entry_bits)).for_each( - |(lut_i, sub_weights)| { - sub_weights.iter().enumerate().for_each(|(i, weight_i)| { - let bit_mask = 1 << i; - lut_i.iter_mut().enumerate().for_each(|(bit_map, li)| { - if bit_map & bit_mask == bit_mask { - *li += weight_i; - } - }); - }); - }, - ); - } - - #[inline(always)] - pub fn lookup_and_sum(&self, indices: &[EntryF]) -> F - where - EntryF: SimdField, - { - // NOTE: at least the entry field elem should have a matching field size - // and the the entry field being a SIMD field with same packing size as - // the bits for the table entry - assert_eq!(EntryF::FIELD_SIZE, 1); - assert_eq!(EntryF::PACK_SIZE, self.entry_bits); - assert_eq!(indices.len(), self.tables.len()); - - izip!(&self.tables, indices) - .map(|(t_i, index)| t_i[index.as_u32_unchecked() as usize]) - .sum() - } -} - -#[inline(always)] -pub(crate) fn lut_open_linear_combine( - com_pack_size: usize, - packed_evals: &[SimdF], - eq_col_coeffs: &[EvalF], - eval_row: &mut [EvalF], - rand_col_coeffs: &[Vec], - proximity_rows: &mut [Vec], -) where - F: Field, - EvalF: ExtensionField, - SimdF: SimdField, -{ - // NOTE: declare the look up tables for column sums - let table_num = com_pack_size / SimdF::PACK_SIZE; - let mut luts = SubsetSumLUTs::::new(SimdF::PACK_SIZE, table_num); - assert_eq!(com_pack_size % SimdF::PACK_SIZE, 0); - - let combination_size = eq_col_coeffs.len(); - let packed_row_size = combination_size / com_pack_size; - - // NOTE: working on evaluation response of tensor code IOP based PCS - izip!( - eq_col_coeffs.chunks(com_pack_size), - packed_evals.chunks(packed_evals.len() / packed_row_size) - ) - .for_each(|(eq_chunk, packed_evals_chunk)| { - luts.build(eq_chunk); - - izip!(packed_evals_chunk.chunks(table_num), &mut *eval_row) - .for_each(|(p_col, eval)| *eval += luts.lookup_and_sum(p_col)); - }); - - // NOTE: compose proximity response(s) of tensor code IOP based PCS - izip!(proximity_rows, rand_col_coeffs).for_each(|(row_buffer, random_coeffs)| { - izip!( - random_coeffs.chunks(com_pack_size), - packed_evals.chunks(packed_evals.len() / packed_row_size) - ) - .for_each(|(random_chunk, packed_evals_chunk)| { - luts.build(random_chunk); - - izip!(packed_evals_chunk.chunks(table_num), &mut *row_buffer) - .for_each(|(p_col, prox)| *prox += luts.lookup_and_sum(p_col)); - }); - }); - drop(luts); -} - -#[inline(always)] -pub(crate) fn lut_verify_alphabet_check( - codeword: &[ExtF], - fixed_rl: &[ExtF], - query_indices: &[usize], - packed_interleaved_alphabets: &[Vec], -) -> bool -where - F: Field, - SimdF: SimdField, - ExtF: ExtensionField, -{ - // NOTE: build up lookup table - let tables_num = fixed_rl.len() / SimdF::PACK_SIZE; - assert_eq!(fixed_rl.len() % SimdF::PACK_SIZE, 0); - let mut luts = SubsetSumLUTs::::new(SimdF::PACK_SIZE, tables_num); - - luts.build(fixed_rl); - - izip!(query_indices, packed_interleaved_alphabets).all(|(qi, interleaved_alphabet)| { - let index = qi % codeword.len(); - let alphabet = luts.lookup_and_sum(interleaved_alphabet); - alphabet == codeword[index] - }) -} - -/* - * LINEAR OPERATIONS FOR MERSENNE31 (SIMD BASED) - */ - -#[inline(always)] -fn simd_ext_base_inner_prod( - simd_ext_limbs: &[SimdF], - simd_base_elems: &[SimdF], -) -> ExtF -where - F: Field, - SimdF: SimdField, - ExtF: ExtensionField, -{ - assert_eq!(simd_ext_limbs.len(), simd_base_elems.len() * ExtF::DEGREE); - - let mut ext_limbs = vec![F::ZERO; ExtF::DEGREE]; - - izip!(&mut ext_limbs, simd_ext_limbs.chunks(simd_base_elems.len())).for_each( - |(e, simd_ext_limb)| { - let simd_sum: SimdF = izip!(simd_ext_limb, simd_base_elems) - .map(|(a, b)| *a * b) - .sum(); - *e = simd_sum.horizontal_sum(); - }, - ); - - ExtF::from_limbs(&ext_limbs) -} - -#[inline(always)] -pub(crate) fn simd_open_linear_combine( - com_pack_size: usize, - packed_evals: &[SimdF], - eq_col_coeffs: &[EvalF], - eval_row: &mut [EvalF], - rand_col_coeffs: &[Vec], - proximity_rows: &mut [Vec], -) where - F: Field, - EvalF: ExtensionField, - SimdF: SimdField, -{ - // NOTE: check SIMD inner product numbers for column sums - let simd_inner_prods = com_pack_size / SimdF::PACK_SIZE; - assert_eq!(com_pack_size % SimdF::PACK_SIZE, 0); - - let combination_size = eq_col_coeffs.len(); - let packed_row_size = combination_size / com_pack_size; - - let mut buffer = vec![F::ZERO; com_pack_size * EvalF::DEGREE]; - - // NOTE: working on evaluation response of tensor code IOP based PCS - izip!( - eq_col_coeffs.chunks(com_pack_size), - packed_evals.chunks(packed_evals.len() / packed_row_size) - ) - .for_each(|(eq_chunk, packed_evals_chunk)| { - let eq_limbs: Vec<_> = eq_chunk.iter().flat_map(|e| e.to_limbs()).collect(); - transpose(&eq_limbs, &mut buffer, EvalF::DEGREE, com_pack_size); - let simd_limbs: Vec<_> = buffer.chunks(SimdF::PACK_SIZE).map(SimdF::pack).collect(); - - izip!(packed_evals_chunk.chunks(simd_inner_prods), &mut *eval_row).for_each( - |(p_col, eval)| *eval += simd_ext_base_inner_prod::<_, EvalF, _>(&simd_limbs, p_col), - ); - }); - - // NOTE: compose proximity response(s) of tensor code IOP based PCS - izip!(proximity_rows, rand_col_coeffs).for_each(|(prox_row, random_coeffs)| { - izip!( - random_coeffs.chunks(com_pack_size), - packed_evals.chunks(packed_evals.len() / packed_row_size) - ) - .for_each(|(rand_chunk, packed_evals_chunk)| { - let rand_limbs: Vec<_> = rand_chunk.iter().flat_map(|e| e.to_limbs()).collect(); - transpose(&rand_limbs, &mut buffer, EvalF::DEGREE, com_pack_size); - let simd_limbs: Vec<_> = buffer.chunks(SimdF::PACK_SIZE).map(SimdF::pack).collect(); - - izip!(packed_evals_chunk.chunks(simd_inner_prods), &mut *prox_row).for_each( - |(p_col, prox)| { - *prox += simd_ext_base_inner_prod::<_, EvalF, _>(&simd_limbs, p_col) - }, - ); - }); - }); -} - -#[inline(always)] -pub(crate) fn simd_verify_alphabet_check( - codeword: &[ExtF], - fixed_rl: &[ExtF], - query_indices: &[usize], - packed_interleaved_alphabets: &[Vec], -) -> bool -where - F: Field, - SimdF: SimdField, - ExtF: ExtensionField, -{ - // NOTE: check SIMD inner product numbers for column sums - assert_eq!(fixed_rl.len() % SimdF::PACK_SIZE, 0); - - let mut scratch = vec![F::ZERO; fixed_rl.len() * ExtF::DEGREE]; - let rl_limbs: Vec<_> = fixed_rl.iter().flat_map(|e| e.to_limbs()).collect(); - transpose(&rl_limbs, &mut scratch, ExtF::DEGREE, fixed_rl.len()); - let simd_limbs: Vec<_> = scratch.chunks(SimdF::PACK_SIZE).map(SimdF::pack).collect(); - - izip!(query_indices, packed_interleaved_alphabets).all(|(qi, interleaved_alphabet)| { - let index = qi % codeword.len(); - let alphabet: ExtF = simd_ext_base_inner_prod(&simd_limbs, interleaved_alphabet); - alphabet == codeword[index] - }) -} - -#[cfg(test)] -mod tests { - use arith::{Field, SimdField}; - use ark_std::test_rng; - use gf2::{GF2x8, GF2}; - use gf2_128::{GF2_128x8, GF2_128}; - use itertools::izip; - - use crate::orion::utils::SubsetSumLUTs; - - #[test] - fn test_lut_simd_inner_prod_consistency() { - let mut rng = test_rng(); - - let weights: Vec<_> = (0..8).map(|_| GF2_128::random_unsafe(&mut rng)).collect(); - let bases: Vec<_> = (0..8).map(|_| GF2::random_unsafe(&mut rng)).collect(); - - let simd_weights = GF2_128x8::pack(&weights); - let simd_bases = GF2x8::pack(&bases); - - let expected_simd_inner_prod: GF2_128 = (simd_weights * simd_bases).horizontal_sum(); - - let expected_vanilla_inner_prod: GF2_128 = - izip!(&weights, &bases).map(|(w, b)| *w * *b).sum(); - - assert_eq!(expected_simd_inner_prod, expected_vanilla_inner_prod); - - let mut table = SubsetSumLUTs::new(8, 1); - table.build(&weights); - - let actual_lut_inner_prod = table.lookup_and_sum(&[simd_bases]); - - assert_eq!(expected_simd_inner_prod, actual_lut_inner_prod) - } -} diff --git a/poly_commit/src/orion/verify.rs b/poly_commit/src/orion/verify.rs deleted file mode 100644 index 810bdb50a..000000000 --- a/poly_commit/src/orion/verify.rs +++ /dev/null @@ -1,132 +0,0 @@ -use std::iter; - -use arith::{ExtensionField, Field, SimdField}; -use gf2::GF2; -use gkr_engine::Transcript; -use itertools::{chain, izip}; -use polynomials::{EqPolynomial, MultilinearExtension, RefMultiLinearPoly}; -use tree::LEAF_BYTES; - -use crate::{ - orion::{ - utils::{lut_verify_alphabet_check, orion_mt_verify, simd_verify_alphabet_check}, - OrionCommitment, OrionProof, OrionSRS, - }, - traits::TensorCodeIOPPCS, - PCS_SOUNDNESS_BITS, -}; - -#[inline(always)] -pub fn orion_verify( - vk: &OrionSRS, - commitment: &OrionCommitment, - point: &[EvalF], - mpi_point: &[EvalF], - evaluation: EvalF, - transcript: &mut impl Transcript, - proof: &OrionProof, -) -> bool -where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - let world_size = 1 << mpi_point.len(); - let msg_size = vk.message_len(); - - let num_vars_in_com_simd = ComPackF::PACK_SIZE.ilog2() as usize; - let num_vars_in_msg = msg_size.ilog2() as usize; - - // NOTE: working on evaluation response, evaluate the rest of the response - let mut scratch = vec![EvalF::ZERO; msg_size]; - let final_eval = RefMultiLinearPoly::from_ref(&proof.eval_row).evaluate_with_buffer( - &point[num_vars_in_com_simd..num_vars_in_com_simd + num_vars_in_msg], - &mut scratch, - ); - - if final_eval != evaluation { - return false; - } - - // NOTE: working on proximity responses, draw random linear combinations - // then draw query points from fiat shamir transcripts - let proximity_reps = vk.proximity_repetitions::(PCS_SOUNDNESS_BITS); - let random_linear_combinations: Vec<_> = (0..proximity_reps) - .map(|_| { - let num_vars = point.len() - num_vars_in_msg + mpi_point.len(); - let rand = transcript.generate_field_elements::(num_vars); - EqPolynomial::build_eq_x_r(&rand) - }) - .collect(); - - let query_num = vk.query_complexity(PCS_SOUNDNESS_BITS); - let query_indices = transcript.generate_usize_vector(query_num); - - // NOTE: check consistency in MT in the opening trees and against the commitment tree - { - if proof.merkle_cap.len() != world_size { - return false; - } - - let actual_commitment = if world_size > 1 { - let height = 1 + mpi_point.len(); - let internal = tree::Tree::new_with_leaf_nodes(&proof.merkle_cap, height as u32); - internal[0] - } else { - proof.merkle_cap[0] - }; - - if actual_commitment != *commitment { - return false; - } - } - - if !orion_mt_verify(vk, &query_indices, &proof.query_openings, &proof.merkle_cap) { - return false; - } - - // NOTE: prepare the interleaved alphabets from the MT paths - let num_simd_elems_per_leaf = vk.num_leaves_per_mt_query() * LEAF_BYTES / SimdF::SIZE; - let packed_interleaved_alphabets: Vec> = proof - .query_openings - .iter() - .map(|c| unsafe { - let ptr = c.leaves.as_ptr(); - std::slice::from_raw_parts(ptr as *const SimdF, num_simd_elems_per_leaf).to_vec() - }) - .collect(); - - let eq_col_coeffs = { - let mut eq_vars = point[..num_vars_in_com_simd].to_vec(); - eq_vars.extend_from_slice(&point[num_vars_in_com_simd + num_vars_in_msg..]); - eq_vars.extend_from_slice(mpi_point); - EqPolynomial::build_eq_x_r(&eq_vars) - }; - - chain!( - izip!(&random_linear_combinations, &proof.proximity_rows), - iter::once((&eq_col_coeffs, &proof.eval_row)) - ) - .all(|(rl, msg)| { - let codeword = match vk.code_instance.encode(msg) { - Ok(c) => c, - _ => return false, - }; - - match F::NAME { - GF2::NAME => lut_verify_alphabet_check( - &codeword, - rl, - &query_indices, - &packed_interleaved_alphabets, - ), - _ => simd_verify_alphabet_check( - &codeword, - rl, - &query_indices, - &packed_interleaved_alphabets, - ), - } - }) -} diff --git a/poly_commit/src/traits.rs b/poly_commit/src/traits.rs index 50e529a43..ed2e2ce21 100644 --- a/poly_commit/src/traits.rs +++ b/poly_commit/src/traits.rs @@ -1,4 +1,4 @@ -use arith::{ExtensionField, Field}; +use arith::ExtensionField; use gkr_engine::{StructuredReferenceString, Transcript}; use rand::RngCore; use serdes::ExpSerde; @@ -117,30 +117,3 @@ pub trait BatchOpeningPCS: PolynomialCommitmentScheme + Si transcript: &mut impl Transcript, ) -> bool; } - -pub(crate) trait TensorCodeIOPPCS { - fn message_len(&self) -> usize; - - fn codeword_len(&self) -> usize; - - fn minimum_hamming_weight(&self) -> f64; - - fn num_leaves_per_mt_query(&self) -> usize; - - fn query_complexity(&self, soundness_bits: usize) -> usize { - // NOTE: use Ligero (AHIV22) appendix C argument. - let avg_case_dist = self.minimum_hamming_weight() / 2f64; - let sec_bits = -(1f64 - avg_case_dist).log2(); - - (soundness_bits as f64 / sec_bits).ceil() as usize - } - - fn proximity_repetitions(&self, soundness_bits: usize) -> usize { - // NOTE: use Ligero (AHIV22) or Avg-case dist to a code (BKS18) - // version of avg case dist in unique decoding technique. - // Here is the probability union bound - let single_run_soundness_bits = F::FIELD_SIZE - self.codeword_len().ilog2() as usize; - - (soundness_bits as f64 / single_run_soundness_bits as f64).ceil() as usize - } -} diff --git a/poly_commit/tests/test_bi_kzg.rs b/poly_commit/tests/test_bi_kzg.rs deleted file mode 100644 index b0d145045..000000000 --- a/poly_commit/tests/test_bi_kzg.rs +++ /dev/null @@ -1,89 +0,0 @@ -mod common; - -use arith::{Field, Fr}; -use ark_std::test_rng; -use gkr_engine::ExpanderPCS; -use gkr_engine::{BN254Config, ExpanderSingleVarChallenge, MPIConfig, MPIEngine, Transcript}; -use gkr_hashers::Keccak256hasher; -use halo2curves::bn256::Bn256; -use poly_commit::HyperBiKZGPCS; -use polynomials::MultiLinearPoly; -use transcript::BytesHashTranscript; - -const TEST_REPETITION: usize = 3; - -fn test_hyper_bi_kzg_pcs_generics(num_vars_start: usize, num_vars_end: usize) { - let mut rng = test_rng(); - - (num_vars_start..=num_vars_end).for_each(|num_vars| { - let xs: Vec<_> = (0..TEST_REPETITION) - .map(|_| -> Vec { (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect() }) - .collect(); - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - - common::test_pcs::, HyperBiKZGPCS>( - &num_vars, &poly, &xs, - ); - }) -} - -#[test] -fn test_hyper_bi_kzg_pcs_full_e2e() { - test_hyper_bi_kzg_pcs_generics(2, 15) -} - -fn test_hyper_bi_kzg_for_expander_gkr_generics(mpi_config_ref: &MPIConfig, total_num_vars: usize) { - let mut rng = test_rng(); - - // NOTE BN254 GKR SIMD pack size = 1, num vars in SIMD is 0 - let num_vars_in_mpi = mpi_config_ref.world_size().ilog2() as usize; - let num_vars_in_each_poly = total_num_vars - num_vars_in_mpi; - - let global_poly = MultiLinearPoly::::random(total_num_vars, &mut rng); - let challenge_point = ExpanderSingleVarChallenge:: { - r_mpi: (0..num_vars_in_mpi) - .map(|_| Fr::random_unsafe(&mut rng)) - .collect(), - r_simd: Vec::new(), - rz: (0..num_vars_in_each_poly) - .map(|_| Fr::random_unsafe(&mut rng)) - .collect(), - }; - - let mut transcript = BytesHashTranscript::::new(); - - // NOTE separate polynomial into different pieces by mpi rank - let poly_vars_stride = (1 << global_poly.get_num_vars()) / mpi_config_ref.world_size(); - let poly_coeff_starts = mpi_config_ref.world_rank() * poly_vars_stride; - let poly_coeff_ends = poly_coeff_starts + poly_vars_stride; - let local_poly = - MultiLinearPoly::new(global_poly.coeffs[poly_coeff_starts..poly_coeff_ends].to_vec()); - - dbg!(local_poly.get_num_vars(), local_poly.coeffs[0]); - - let params = as ExpanderPCS>::gen_params( - num_vars_in_each_poly, - mpi_config_ref.world_size(), - ); - common::test_pcs_for_expander_gkr::< - BN254Config, - BytesHashTranscript, - HyperBiKZGPCS, - >( - ¶ms, - mpi_config_ref, - &mut transcript, - &local_poly, - &[challenge_point], - None, - ); -} - -#[test] -fn test_hyper_bikzg_for_expander_gkr() { - let universe = MPIConfig::init().unwrap(); - let world = universe.world(); - let mpi_config = MPIConfig::prover_new(Some(&universe), Some(&world)); - test_hyper_bi_kzg_for_expander_gkr_generics(&mpi_config, 1); - test_hyper_bi_kzg_for_expander_gkr_generics(&mpi_config, 15); -} diff --git a/poly_commit/tests/test_hyrax.rs b/poly_commit/tests/test_hyrax.rs deleted file mode 100644 index 9ed3400f4..000000000 --- a/poly_commit/tests/test_hyrax.rs +++ /dev/null @@ -1,93 +0,0 @@ -mod common; - -use arith::{Field, Fr}; -use ark_std::test_rng; -use gkr_engine::{BN254Config, ExpanderSingleVarChallenge, MPIConfig, MPIEngine, Transcript}; -use gkr_hashers::Keccak256hasher; -use halo2curves::bn256::G1Affine; -use poly_commit::HyraxPCS; -use polynomials::MultiLinearPoly; -use transcript::BytesHashTranscript; - -const TEST_REPETITION: usize = 3; - -fn test_hyrax_pcs_generics(num_vars_start: usize, num_vars_end: usize) { - let mut rng = test_rng(); - - (num_vars_start..=num_vars_end).for_each(|num_vars| { - let xs: Vec<_> = (0..TEST_REPETITION) - .map(|_| -> Vec { (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect() }) - .collect(); - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - - common::test_pcs::, HyraxPCS>( - &num_vars, &poly, &xs, - ); - }) -} - -#[test] -fn test_hyrax_pcs_e2e() { - test_hyrax_pcs_generics(1, 17) -} - -fn test_hyrax_for_expander_gkr_generics(mpi_config_ref: &MPIConfig, total_num_vars: usize) { - let mut rng = test_rng(); - - // NOTE BN254 GKR SIMD pack size = 1, num vars in SIMD is 0 - let num_vars_in_mpi = mpi_config_ref.world_size().ilog2() as usize; - let num_vars_in_each_poly = total_num_vars - num_vars_in_mpi; - - let global_poly = MultiLinearPoly::::random(total_num_vars, &mut rng); - let challenge_point = ExpanderSingleVarChallenge:: { - r_mpi: (0..num_vars_in_mpi) - .map(|_| Fr::random_unsafe(&mut rng)) - .collect(), - r_simd: Vec::new(), - rz: (0..num_vars_in_each_poly) - .map(|_| Fr::random_unsafe(&mut rng)) - .collect(), - }; - - let mut transcript = BytesHashTranscript::::new(); - - // NOTE separate polynomial into different pieces by mpi rank - let poly_vars_stride = (1 << global_poly.get_num_vars()) / mpi_config_ref.world_size(); - let poly_coeff_starts = mpi_config_ref.world_rank() * poly_vars_stride; - let poly_coeff_ends = poly_coeff_starts + poly_vars_stride; - let local_poly = - MultiLinearPoly::new(global_poly.coeffs[poly_coeff_starts..poly_coeff_ends].to_vec()); - - dbg!(local_poly.get_num_vars(), local_poly.coeffs[0]); - - common::test_pcs_for_expander_gkr::< - BN254Config, - BytesHashTranscript, - HyraxPCS, - >( - &num_vars_in_each_poly, - mpi_config_ref, - &mut transcript, - &local_poly, - &[challenge_point], - Some("../data/hyrax_srs.bin"), - ); -} - -#[test] -fn test_hyrax_for_expander_gkr() { - let universe = MPIConfig::init().unwrap(); - let world = universe.world(); - let mpi_config = MPIConfig::prover_new(Some(&universe), Some(&world)); - test_hyrax_for_expander_gkr_generics(&mpi_config, 19); -} - -#[test] -fn test_hyrax_batch_open() { - common::test_batching::, HyraxPCS>(); - common::test_batching_for_expander_gkr::< - BN254Config, - BytesHashTranscript, - HyraxPCS, - >(false); -} diff --git a/poly_commit/tests/test_orion.rs b/poly_commit/tests/test_orion.rs deleted file mode 100644 index fc48b8e79..000000000 --- a/poly_commit/tests/test_orion.rs +++ /dev/null @@ -1,141 +0,0 @@ -mod common; - -use arith::{ExtensionField, Field, SimdField}; -use ark_std::test_rng; -use gf2::{GF2x128, GF2x64, GF2x8, GF2}; -use gf2_128::GF2_128; -use gkr_engine::{ - ExpanderSingleVarChallenge, FieldEngine, GF2ExtConfig, Goldilocksx8Config, M31x16Config, - MPIConfig, MPIEngine, Transcript, -}; -use gkr_hashers::Keccak256hasher; -use goldilocks::{Goldilocks, GoldilocksExt2, Goldilocksx8}; -use mersenne31::{M31Ext3, M31x16, M31}; -use poly_commit::*; -use polynomials::MultiLinearPoly; -use transcript::BytesHashTranscript; - -const TEST_REPETITION: usize = 3; - -fn test_orion_simd_pcs_generics( - num_vars_start: usize, - num_vars_end: usize, -) where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, -{ - let mut rng = test_rng(); - - (num_vars_start..=num_vars_end).for_each(|num_vars| { - let poly_num_vars = num_vars - SimdF::PACK_SIZE.ilog2() as usize; - let xs: Vec<_> = (0..TEST_REPETITION) - .map(|_| -> Vec { - (0..num_vars) - .map(|_| EvalF::random_unsafe(&mut rng)) - .collect() - }) - .collect(); - let poly = MultiLinearPoly::::random(poly_num_vars, &mut rng); - - common::test_pcs::< - EvalF, - BytesHashTranscript, - OrionSIMDFieldPCS, - >(&num_vars, &poly, &xs); - }) -} - -#[test] -fn test_orion_simd_pcs_full_e2e() { - test_orion_simd_pcs_generics::(19, 25); - test_orion_simd_pcs_generics::(19, 25); - test_orion_simd_pcs_generics::(16, 22); - test_orion_simd_pcs_generics::(16, 22) -} - -fn test_orion_for_expander_gkr_generics( - mpi_config_ref: &MPIConfig, - total_num_vars: usize, -) where - C: FieldEngine, - ComPackF: SimdField, - T: Transcript, -{ - let mut rng = test_rng(); - - // NOTE: generate global random polynomial - let num_vars_in_simd = C::SimdCircuitField::PACK_SIZE.ilog2() as usize; - let num_vars_in_mpi = mpi_config_ref.world_size().ilog2() as usize; - let num_vars_in_each_poly = total_num_vars - num_vars_in_mpi - num_vars_in_simd; - let num_vars_in_global_poly = total_num_vars - num_vars_in_simd; - - let global_poly = - MultiLinearPoly::::random(num_vars_in_global_poly, &mut rng); - - // NOTE generate srs for each party, and shared challenge point in each party - let challenge_point = ExpanderSingleVarChallenge:: { - r_mpi: (0..num_vars_in_mpi) - .map(|_| C::ChallengeField::random_unsafe(&mut rng)) - .collect(), - r_simd: (0..num_vars_in_simd) - .map(|_| C::ChallengeField::random_unsafe(&mut rng)) - .collect(), - rz: (0..num_vars_in_each_poly) - .map(|_| C::ChallengeField::random_unsafe(&mut rng)) - .collect(), - }; - - let mut transcript = T::new(); - - dbg!(global_poly.get_num_vars(), global_poly.coeffs[0]); - dbg!(&challenge_point.r_mpi); - dbg!(mpi_config_ref.world_size(), mpi_config_ref.world_rank()); - - // NOTE separate polynomial into different pieces by mpi rank - let poly_vars_stride = (1 << global_poly.get_num_vars()) / mpi_config_ref.world_size(); - let poly_coeff_starts = mpi_config_ref.world_rank() * poly_vars_stride; - let poly_coeff_ends = poly_coeff_starts + poly_vars_stride; - let local_poly = - MultiLinearPoly::new(global_poly.coeffs[poly_coeff_starts..poly_coeff_ends].to_vec()); - - dbg!(local_poly.get_num_vars(), local_poly.coeffs[0]); - - common::test_pcs_for_expander_gkr::< - C, - T, - OrionSIMDFieldPCS, - >( - &num_vars_in_each_poly, - mpi_config_ref, - &mut transcript, - &local_poly, - &[challenge_point], - None, - ); -} - -#[test] -fn test_orion_for_expander_gkr() { - let universe = MPIConfig::init().unwrap(); - let world = universe.world(); - let mpi_config = MPIConfig::prover_new(Some(&universe), Some(&world)); - test_orion_for_expander_gkr_generics::< - GF2ExtConfig, - GF2x128, - BytesHashTranscript, - >(&mpi_config, 25); - - test_orion_for_expander_gkr_generics::< - M31x16Config, - M31x16, - BytesHashTranscript, - >(&mpi_config, 25); - - test_orion_for_expander_gkr_generics::< - Goldilocksx8Config, - Goldilocksx8, - BytesHashTranscript, - >(&mpi_config, 25); -} diff --git a/tree/Cargo.toml b/tree/Cargo.toml deleted file mode 100644 index 7e78dd863..000000000 --- a/tree/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "tree" -version = "0.1.0" -edition = "2021" - -[dependencies] -arith = { path = "../arith" } -serdes = { path = "../serdes" } - -ark-std.workspace = true -tiny-keccak.workspace = true - -[dev-dependencies] -criterion.workspace = true -tynm.workspace = true - -gf2 = { path = "../arith/gf2" } -gf2_128 = { path = "../arith/gf2_128" } - -[[bench]] -name = "tree" -harness = false diff --git a/tree/benches/tree.rs b/tree/benches/tree.rs deleted file mode 100644 index b38e2c8d8..000000000 --- a/tree/benches/tree.rs +++ /dev/null @@ -1,112 +0,0 @@ -use arith::{Field, SimdField}; -use ark_std::{rand::RngCore, test_rng}; -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use gf2::{GF2x128, GF2}; -use tree::{Leaf, Tree, LEAF_BYTES}; -use tynm::type_name; - -const FINAL_MT_LEAVES_LOG2: usize = 15; - -fn tree_building_benchmark(c: &mut Criterion) { - let mut group = c.benchmark_group("Keccak merkle tree"); - - let mut rng = test_rng(); - let mut data_buffer = [0u8; LEAF_BYTES]; - let leaves: Vec<_> = (0..(1 << FINAL_MT_LEAVES_LOG2)) - .map(|_| { - Leaf::new({ - rng.fill_bytes(&mut data_buffer); - data_buffer - }) - }) - .collect(); - - for i in 10..=FINAL_MT_LEAVES_LOG2 { - group - .bench_function(BenchmarkId::new(format!("2^{i} leaves"), i), |b| { - let leaves_benchmark = leaves[..(1 << i)].to_vec(); - - b.iter(|| { - Tree::new_with_leaves(leaves_benchmark.clone()); - }) - }) - .sample_size(10); - } -} - -fn compact_field_elem_tree_building_benchmark_generic(c: &mut Criterion) -where - F: Field, - PackF: SimdField, -{ - let mut group = c.benchmark_group(format!( - "Keccak merkle tree with field element {} packed by SIMD field element {}", - type_name::(), - type_name::() - )); - let num_of_elems_in_leaf = LEAF_BYTES * 8 / F::FIELD_SIZE; - - let mut rng = test_rng(); - let field_elems: Vec<_> = (0..(1 << FINAL_MT_LEAVES_LOG2) * num_of_elems_in_leaf) - .map(|_| F::random_unsafe(&mut rng)) - .collect(); - - for i in 10..=FINAL_MT_LEAVES_LOG2 { - group - .bench_function(BenchmarkId::new(format!("2^{i} leaves"), i), |b| { - let field_elems_benchmark = field_elems[..(1 << i) * num_of_elems_in_leaf].to_vec(); - - b.iter(|| { - Tree::compact_new_with_field_elems::(field_elems_benchmark.clone()); - }) - }) - .sample_size(10); - } -} - -fn compact_field_elem_tree_building_benchmark(c: &mut Criterion) { - compact_field_elem_tree_building_benchmark_generic::(c); -} - -fn compact_packed_field_elem_tree_building_benchmark_generic(c: &mut Criterion) -where - F: Field, - PackF: SimdField, -{ - let mut group = c.benchmark_group(format!( - "Keccak merkle tree with SIMD field element {}", - type_name::() - )); - let num_of_elems_in_leaf = LEAF_BYTES / PackF::SIZE; - - let mut rng = test_rng(); - let field_elems: Vec<_> = (0..(1 << FINAL_MT_LEAVES_LOG2) * num_of_elems_in_leaf) - .map(|_| PackF::random_unsafe(&mut rng)) - .collect(); - - for i in 10..=FINAL_MT_LEAVES_LOG2 { - group - .bench_function(BenchmarkId::new(format!("2^{i} leaves"), i), |b| { - let field_elems_benchmark = field_elems[..(1 << i) * num_of_elems_in_leaf].to_vec(); - - b.iter(|| { - Tree::compact_new_with_packed_field_elems::( - field_elems_benchmark.clone(), - ); - }) - }) - .sample_size(10); - } -} - -fn compact_packed_field_elem_tree_building_benchmark(c: &mut Criterion) { - compact_packed_field_elem_tree_building_benchmark_generic::(c); -} - -criterion_group!( - bench, - tree_building_benchmark, - compact_field_elem_tree_building_benchmark, - compact_packed_field_elem_tree_building_benchmark -); -criterion_main!(bench); diff --git a/tree/src/leaf.rs b/tree/src/leaf.rs deleted file mode 100644 index 18f359cdd..000000000 --- a/tree/src/leaf.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::fmt; -use std::fmt::{Debug, Display}; - -use serdes::ExpSerde; -use tiny_keccak::{Hasher, Keccak}; - -use crate::Node; - -/// Each leaf should have 64 bytes or 512 bits -pub const LEAF_BYTES: usize = 64; - -/// Each leaf hash should have 32 bytes -pub const LEAF_HASH_BYTES: usize = 32; - -/// Represents a leaf in the Merkle tree, containing 64 bytes of data stored in a BabyBearx16. -#[derive(Debug, Copy, Clone, PartialEq, Eq, ExpSerde)] -pub struct Leaf { - pub data: [u8; LEAF_BYTES], -} - -impl Default for Leaf { - fn default() -> Self { - Self { - data: [0u8; LEAF_BYTES], - } - } -} - -impl Display for Leaf { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Display the first and last byte of the leaf data for brevity - write!(f, "leaf: 0x{:02x?}", self.data) - } -} - -impl Leaf { - /// Creates a new Leaf with the given data. - pub fn new(data: [u8; LEAF_BYTES]) -> Self { - Self { data } - } - - pub fn leaf_hash(&self) -> Node { - let mut hasher = Keccak::v256(); - hasher.update(&self.data); - let mut res = [0u8; LEAF_HASH_BYTES]; - - hasher.finalize(&mut res); - - Node { data: res } - } -} diff --git a/tree/src/lib.rs b/tree/src/lib.rs deleted file mode 100644 index af3d6363c..000000000 --- a/tree/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! This module defines the core components of a Merkle tree implementation. -//! It includes definitions for tree structures, nodes, leaves, and paths. - -mod tree; -pub use tree::*; - -mod node; -pub use node::*; - -mod leaf; -pub use leaf::*; - -mod path; -pub use path::*; - -#[cfg(test)] -mod tests; diff --git a/tree/src/node.rs b/tree/src/node.rs deleted file mode 100644 index 1ae91506a..000000000 --- a/tree/src/node.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::{fmt, fmt::Display}; - -use serdes::ExpSerde; -use tiny_keccak::{Hasher, Keccak}; - -use crate::LEAF_HASH_BYTES; - -/// A node in the Merkle tree, representing 32 bytes of data. -#[derive(Debug, Copy, Clone, PartialEq, Default, ExpSerde)] -pub struct Node { - pub(crate) data: [u8; LEAF_HASH_BYTES], -} - -impl Display for Node { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Display the first and last byte of the node for brevity - write!(f, "node: 0x{:02x?}...{:02x?}", self.data[0], self.data[31]) - } -} - -impl Node { - /// Creates a new Node with the given data. - pub fn new(data: [u8; LEAF_HASH_BYTES]) -> Self { - Self { data } - } - - /// Computes the hash of two child nodes to create a parent node. - /// - /// This function uses Keccak for hashing and takes the first 32 bytes of the result. - /// - /// # Arguments - /// - /// * `left` - The left child node - /// * `right` - The right child node - /// - /// # Returns - /// - /// A new Node containing the hash of the two input nodes. - #[inline] - pub fn node_hash(left: &Node, right: &Node) -> Node { - let mut hasher = Keccak::v256(); - hasher.update(&left.data); - hasher.update(&right.data); - - let mut result = [0u8; LEAF_HASH_BYTES]; - hasher.finalize(&mut result); - - Node { data: result } - } - - /// Returns the data of the node as a slice of bytes. - pub fn as_bytes(&self) -> &[u8] { - &self.data - } -} diff --git a/tree/src/path.rs b/tree/src/path.rs deleted file mode 100644 index b2c7dbc4b..000000000 --- a/tree/src/path.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::fmt; -use std::fmt::{Debug, Display}; - -use ark_std::{end_timer, start_timer}; -use serdes::ExpSerde; - -use crate::{ - common_ancestor, convert_index_to_last_level, is_left_child, parent_index, Leaf, Node, Tree, -}; - -/// Represents a path in the Merkle tree, used for proving membership. -#[derive(Clone, Debug, PartialEq, Default, ExpSerde)] -pub struct Path { - pub leaf: Leaf, - pub(crate) path_nodes: Vec, - pub index: usize, -} - -impl Display for Path { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "leaf index: {}", self.index)?; - - let position_list = self.position_list(); - for ((i, node), is_right_node) in self.path_nodes.iter().enumerate().zip(position_list) { - writeln!( - f, - "{i}-th node, is right node {is_right_node}, sibling: {node}", - )?; - } - - Ok(()) - } -} - -impl Path { - /// Computes the position of on-path nodes in the Merkle tree. - /// - /// This function converts the leaf index to a boolean array in big-endian form, - /// where `true` indicates a right child and `false` indicates a left child. - #[inline] - fn position_list(&'_ self) -> impl '_ + Iterator { - (0..self.path_nodes.len() + 1).map(move |i| ((self.index >> i) & 1) != 0) - } - - /// Verifies the path against a given root and leaf. - /// - /// # Arguments - /// - /// * `root` - The root node of the Merkle tree - /// * `leaf` - The leaf node to verify - /// * `hasher` - The Poseidon hash parameters - /// - /// # Returns - /// - /// `true` if the path is valid, `false` otherwise. - #[inline] - pub fn verify(&self, root: &Node) -> bool { - let timer = start_timer!(|| "path verify"); - - let position_list = self.position_list().collect::>(); - // let leaf_node = self.leaf.leaf_hash(hasher); - let leaf_node = self.leaf.leaf_hash(); - let mut current_node = leaf_node; - - // Traverse the path from leaf to root - for (i, node) in self.path_nodes.iter().rev().enumerate() { - if position_list[i] { - current_node = Node::node_hash(node, ¤t_node) - } else { - current_node = Node::node_hash(¤t_node, node) - }; - } - - end_timer!(timer); - if current_node != *root { - println!("path does not match the root"); - false - } else { - true - } - } - - #[inline] - pub fn root(&self) -> Node { - let position_list = self.position_list().collect::>(); - // let leaf_node = self.leaf.leaf_hash(hasher); - let leaf_node = self.leaf.leaf_hash(); - let mut current_node = leaf_node; - - // Traverse the path from leaf to root - for (i, node) in self.path_nodes.iter().rev().enumerate() { - if position_list[i] { - current_node = Node::node_hash(node, ¤t_node) - } else { - current_node = Node::node_hash(¤t_node, node) - }; - } - - current_node - } - - /// Return the leaf of the path - #[inline] - pub fn leaf(&self) -> &Leaf { - &self.leaf - } -} - -#[derive(Clone, Debug, PartialEq, Default, ExpSerde)] -pub struct RangePath { - pub leaves: Vec, - pub(crate) path_nodes: Vec, - pub left: usize, - pub right: usize, -} - -impl Display for RangePath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "leaf index range: [{}, {}]", self.left, self.right)?; - - let position_list = self.position_list(); - for ((i, node), is_right_node) in self.path_nodes.iter().enumerate().zip(position_list) { - writeln!( - f, - "{i}-th node, is right node {is_right_node}, sibling: {node}" - )?; - } - - Ok(()) - } -} - -impl RangePath { - #[inline] - fn position_list(&'_ self) -> impl '_ + Iterator { - let common_ancestor = common_ancestor(self.left, self.right); - - (0..self.path_nodes.len() + 1).map(move |i| ((common_ancestor >> i) & 1) != 0) - } - - #[inline] - pub fn root(&self) -> Node { - let sub_tree = Tree::new_with_leaves(self.leaves.clone()); - - let tree_height = sub_tree.height() + self.path_nodes.len(); - let mut current_node = sub_tree.root(); - - drop(sub_tree); - - let left_index_in_tree = convert_index_to_last_level(self.left, tree_height); - let right_index_in_tree = convert_index_to_last_level(self.right, tree_height); - - let mut current_node_index = common_ancestor(left_index_in_tree, right_index_in_tree); - - self.path_nodes.iter().rev().for_each(|node| { - if is_left_child(current_node_index) { - current_node = Node::node_hash(¤t_node, node) - } else { - current_node = Node::node_hash(node, ¤t_node) - } - - current_node_index = parent_index(current_node_index).unwrap(); - }); - - current_node - } - - #[inline] - pub fn verify(&self, root: &Node) -> bool { - self.root() == *root - } -} diff --git a/tree/src/tests.rs b/tree/src/tests.rs deleted file mode 100644 index eb40e9d1e..000000000 --- a/tree/src/tests.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::io::Cursor; - -use ark_std::{rand::RngCore, test_rng}; -use serdes::ExpSerde; - -use crate::{Leaf, Path, Tree}; - -fn random_leaf(rng: &mut R) -> Leaf { - Leaf::new({ - let mut data = [0u8; 64]; - rng.fill_bytes(&mut data); - data - }) -} - -#[test] -fn test_tree() { - // Initialize a random number generator for the test - let mut rng = test_rng(); - - // Create a new instance of PoseidonBabyBearParams for hashing - // let leaf_hasher = PoseidonBabyBearParams::new(&mut rng); - - // Test trees of different heights, from 4 to 14 - for height in 4..15 { - // Generate random leaves for the tree - // The number of leaves is 2^(height-1) - let leaves: Vec = (0..(1 << (height - 1))) - .map(|_| random_leaf(&mut rng)) - .collect(); - - // Create a new tree with the generated leaves - let tree = Tree::new_with_leaves(leaves); - - // Perform 100 random verifications for each tree - for _ in 0..100 { - // Select a random leaf index - let index = rng.next_u32() % (1 << (height - 1)); - - // Generate a proof for the selected leaf - let proof = tree.gen_proof(index as usize, height); - - // Get the root of the tree - let root = tree.root(); - - // Print debug information - println!("index: {}\n", index); - println!("root: {}\n", root); - println!("tree {}\n", tree); - println!("path {}\n", proof); - - // Serialize and deserialize the proof - let mut buffer: Vec = Vec::new(); - proof.serialize_into(&mut buffer).unwrap(); - let mut cursor = Cursor::new(buffer); - let deserialized_proof = Path::deserialize_from(&mut cursor).unwrap(); - - // Verify the proof - // This checks that the leaf at the given index is indeed part of the tree - // with the given root, using the generated proof - assert!(deserialized_proof.verify(&root)); - } - } -} diff --git a/tree/src/tree.rs b/tree/src/tree.rs deleted file mode 100644 index 08a5ac195..000000000 --- a/tree/src/tree.rs +++ /dev/null @@ -1,310 +0,0 @@ -use std::fmt; -use std::fmt::{Debug, Display}; -use std::mem::forget; - -use arith::{Field, SimdField}; -use ark_std::{end_timer, log2, start_timer}; -use serdes::ExpSerde; - -use crate::{Leaf, Node, Path, RangePath, LEAF_BYTES}; - -/// Represents a Merkle tree structure. -#[derive(Clone, Debug, PartialEq, Default, ExpSerde)] -pub struct Tree { - pub nodes: Vec, - pub leaves: Vec, -} - -impl Display for Tree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "nodes:")?; - for (i, e) in self.nodes.iter().enumerate() { - writeln!(f, "{i}: {e}")?; - } - writeln!(f, "leaves:")?; - for (i, e) in self.leaves.iter().enumerate() { - writeln!(f, "{i}: {e}")?; - } - Ok(()) - } -} - -impl Tree { - /// Creates an empty tree with default leaves. - #[inline] - pub fn init(tree_height: usize) -> Self { - let leaves = vec![Leaf::default(); 1 << (tree_height - 1)]; - Self::new_with_leaves(leaves) - } - - /// Builds a tree with the given leaves. - #[inline] - pub fn new_with_leaves(leaves: Vec) -> Self { - let tree_height = log2(leaves.len() + 1); - - let mut leaf_nodes = leaves - .as_slice() - .iter() - .map(|leaf| leaf.leaf_hash()) - .collect::>(); - let mut nodes = Self::new_with_leaf_nodes(&leaf_nodes, tree_height); - nodes.append(&mut leaf_nodes); - Self { nodes, leaves } - } - - /// Create a tree with compact serialization of field elements as leaves, - /// by taking advantage of PackF - #[inline] - pub fn compact_new_with_field_elems(field_elems: Vec) -> Self - where - F: Field, - PackF: SimdField, - { - let packed_elems: Vec = field_elems - .chunks(PackF::PACK_SIZE) - .map(SimdField::pack) - .collect(); - - Self::compact_new_with_packed_field_elems(packed_elems) - } - - /// Create a tree with compact serialization of *packed* field elements as leaves. - #[inline] - pub fn compact_new_with_packed_field_elems(field_elems: Vec) -> Self - where - F: Field, - PackF: SimdField, - { - assert_eq!(field_elems.len() * PackF::SIZE % LEAF_BYTES, 0); - assert!(field_elems.len().is_power_of_two()); - - let leaves = unsafe { - let field_elems_ptr = field_elems.as_ptr(); - let field_elems_len = field_elems.len(); - let field_elems_cap = field_elems.capacity(); - - forget(field_elems); - - Vec::from_raw_parts( - field_elems_ptr as *mut Leaf, - field_elems_len * PackF::SIZE / LEAF_BYTES, - field_elems_cap * PackF::SIZE / LEAF_BYTES, - ) - }; - - Tree::new_with_leaves(leaves) - } - - /// Builds a tree with pre-hashed leaf nodes. - /// - /// # Arguments - /// - /// * `leaf_nodes` - Vector of pre-hashed leaf nodes - /// * `tree_height` - Height of the tree - /// - /// # Returns - /// - /// A tuple containing vectors of non-leaf nodes and leaf nodes. - #[inline(always)] - pub fn new_with_leaf_nodes(leaf_nodes: &[Node], tree_height: u32) -> Vec { - let timer = start_timer!(|| format!("generate new tree with {} leaves", leaf_nodes.len())); - - let len = leaf_nodes.len(); - assert_eq!(len, 1 << (tree_height - 1), "incorrect leaf size"); - - let mut non_leaf_nodes = vec![Node::default(); (1 << (tree_height - 1)) - 1]; - - // Compute the starting indices for each non-leaf level of the tree - let mut index = 0; - let mut level_indices = Vec::with_capacity(tree_height as usize - 1); - for _ in 0..(tree_height - 1) { - level_indices.push(index); - index = left_child_index(index); - } - - // Compute the hash values for the non-leaf bottom layer - { - let start_index = level_indices.pop().unwrap(); - let upper_bound = left_child_index(start_index); - - non_leaf_nodes - .iter_mut() - .enumerate() - .take(upper_bound) - .skip(start_index) - .for_each(|(current_index, e)| { - let left_leaf_index = left_child_index(current_index) - upper_bound; - let right_leaf_index = left_leaf_index + 1; - *e = Node::node_hash( - &leaf_nodes[left_leaf_index], - &leaf_nodes[right_leaf_index], - ); - }); - } - - // Compute the hash values for nodes in every other layer in the tree - level_indices.reverse(); - - for &start_index in &level_indices { - let upper_bound = left_child_index(start_index); - for i in start_index..upper_bound { - let left = left_child_index(i); - let right = left + 1; - non_leaf_nodes[i] = Node::node_hash(&non_leaf_nodes[left], &non_leaf_nodes[right]); - } - } - end_timer!(timer); - - non_leaf_nodes - } - - /// Returns the root node of the tree. - #[inline] - pub fn root(&self) -> Node { - self.nodes[0] - } - - #[inline] - pub fn size(&self) -> usize { - self.leaves.len() - } - - #[inline] - pub fn height(&self) -> usize { - log2(self.leaves.len() + 1) as usize - } - - /// Generates a membership proof for the given index. - #[inline] - pub fn gen_proof(&self, index: usize, tree_height: usize) -> Path { - let timer = start_timer!(|| "generate membership proof"); - - // Leaf - let leaf_index_in_tree = convert_index_to_last_level(index, tree_height); - let leaf = self.leaves[index]; - - // Path nodes - let sibling_index_in_tree = sibling_index(leaf_index_in_tree).unwrap(); - let mut path_nodes = Vec::with_capacity(tree_height - 1); - path_nodes.push(self.nodes[sibling_index_in_tree]); - - // Iterate from the bottom layer after the leaves to the top - let mut current_node = parent_index(leaf_index_in_tree).unwrap(); - while current_node != 0 { - let sibling_node = sibling_index(current_node).unwrap(); - path_nodes.push(self.nodes[sibling_node]); - current_node = parent_index(current_node).unwrap(); - } - - path_nodes.reverse(); - end_timer!(timer); - Path { - index, - leaf, - path_nodes, - } - } - - /// Generates a range membership proof for given index range [left, right]. - #[inline] - pub fn gen_range_proof(&self, left: usize, right: usize, tree_height: usize) -> RangePath { - assert!(right > left); - assert!((right - left + 1).is_power_of_two()); - assert!(left % (right - left + 1) == 0); - - // Leaves - let range_leaves = self.leaves[left..right + 1].to_vec(); - let left_index_in_tree = convert_index_to_last_level(left, tree_height); - let right_index_in_tree = convert_index_to_last_level(right, tree_height); - - // Common ancestor - let mut current_node = common_ancestor(left_index_in_tree, right_index_in_tree); - - // Path node - let mut path_nodes: Vec = Vec::new(); - while current_node != 0 { - let sibling_node = sibling_index(current_node).unwrap(); - path_nodes.push(self.nodes[sibling_node]); - current_node = parent_index(current_node).unwrap(); - } - path_nodes.reverse(); - - RangePath { - left, - right, - path_nodes, - leaves: range_leaves, - } - } - - #[inline] - pub fn index_query(&self, index: usize) -> Path { - let tree_height = log2(self.leaves.len() + 1) as usize; - - self.gen_proof(index, tree_height) - } - - #[inline] - pub fn range_query(&self, left: usize, right: usize) -> RangePath { - let tree_height = log2(self.leaves.len() + 1) as usize; - - self.gen_range_proof(left, right, tree_height) - } -} - -/// Returns the index of the sibling, given an index. -#[inline] -fn sibling_index(index: usize) -> Option { - if index == 0 { - None - } else if is_left_child(index) { - Some(index + 1) - } else { - Some(index - 1) - } -} - -/// Returns the index of the parent, given an index. -#[inline] -pub(crate) fn parent_index(index: usize) -> Option { - if index > 0 { - Some((index - 1) >> 1) - } else { - None - } -} - -/// Returns the index of the left child, given an index. -#[inline] -fn left_child_index(index: usize) -> usize { - 2 * index + 1 -} - -/// Returns the index of the right child, given an index. -#[allow(unused)] -#[inline] -fn right_child_index(index: usize) -> usize { - 2 * index + 2 -} - -/// Converts a leaf index to its position in the last level of the tree. -#[inline] -pub(crate) fn convert_index_to_last_level(index: usize, tree_height: usize) -> usize { - index + (1 << (tree_height - 1)) - 1 -} - -#[inline] -pub(crate) fn common_ancestor(left: usize, right: usize) -> usize { - let (mut current_left, mut current_right) = (left, right); - while current_left != current_right { - current_left = parent_index(current_left).unwrap(); - current_right = parent_index(current_right).unwrap(); - } - current_left -} - -/// Returns true if the given index represents a left child. -#[inline] -pub(crate) fn is_left_child(index: usize) -> bool { - index % 2 == 1 -} From 9b3478a01efb6ac939fecc2c299a8b1f9c9ee74d Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 29 Jul 2025 17:23:51 -0400 Subject: [PATCH 2/4] more cleaning --- poly_commit/Cargo.toml | 8 -- poly_commit/benches/hyrax.rs | 94 ------------------ poly_commit/benches/kzg.rs | 12 +-- poly_commit/benches/orion.rs | 174 --------------------------------- poly_commit/benches/pcs_all.rs | 74 +------------- 5 files changed, 8 insertions(+), 354 deletions(-) delete mode 100644 poly_commit/benches/hyrax.rs delete mode 100644 poly_commit/benches/orion.rs diff --git a/poly_commit/Cargo.toml b/poly_commit/Cargo.toml index 292f77842..07fc0e64f 100644 --- a/poly_commit/Cargo.toml +++ b/poly_commit/Cargo.toml @@ -33,14 +33,6 @@ gkr_hashers = { path = "../hasher" } tynm.workspace = true criterion.workspace = true -[[bench]] -name = "orion" -harness = false - -[[bench]] -name = "hyrax" -harness = false - [[bench]] name = "kzg" harness = false diff --git a/poly_commit/benches/hyrax.rs b/poly_commit/benches/hyrax.rs deleted file mode 100644 index dcc52f8a1..000000000 --- a/poly_commit/benches/hyrax.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::hint::black_box; - -use arith::{Field, Fr}; -use ark_std::test_rng; -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use gkr_engine::Transcript; -use gkr_hashers::Keccak256hasher; -use halo2curves::bn256::G1Affine; -use poly_commit::{HyraxPCS, PolynomialCommitmentScheme}; -use polynomials::MultiLinearPoly; -use transcript::BytesHashTranscript; - -fn hyrax_committing_benchmark_helper( - c: &mut Criterion, - lowest_num_vars: usize, - highest_num_vars: usize, -) { - let mut group = c.benchmark_group("Hyrax PCS committing"); - - let mut rng = test_rng(); - let mut scratch_pad = (); - - for num_vars in lowest_num_vars..=highest_num_vars { - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - - let (srs, _) = HyraxPCS::::gen_srs_for_testing(&num_vars, &mut rng); - - group - .bench_function( - BenchmarkId::new(format!("{num_vars} variables"), num_vars), - |b| { - b.iter(|| { - _ = black_box(HyraxPCS::::commit( - &num_vars, - &srs, - &poly, - &mut scratch_pad, - )) - }) - }, - ) - .sample_size(10); - } -} - -fn hyrax_committing_benchmark(c: &mut Criterion) { - hyrax_committing_benchmark_helper(c, 8, 15) -} - -fn hyrax_opening_benchmark_helper( - c: &mut Criterion, - lowest_num_vars: usize, - highest_num_vars: usize, -) { - let mut group = c.benchmark_group("Hyrax PCS opening"); - - let mut rng = test_rng(); - let mut transcript = BytesHashTranscript::::new(); - let mut scratch_pad = (); - - for num_vars in lowest_num_vars..=highest_num_vars { - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - - let (srs, _) = HyraxPCS::::gen_srs_for_testing(&num_vars, &mut rng); - let eval_point: Vec<_> = (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect(); - - let _ = HyraxPCS::::commit(&num_vars, &srs, &poly, &mut scratch_pad); - - group - .bench_function( - BenchmarkId::new(format!("{num_vars} variables"), num_vars), - |b| { - b.iter(|| { - _ = black_box(HyraxPCS::::open( - &num_vars, - &srs, - &poly, - &eval_point, - &scratch_pad, - &mut transcript, - )) - }) - }, - ) - .sample_size(10); - } -} - -fn hyrax_opening_benchmark(c: &mut Criterion) { - hyrax_opening_benchmark_helper(c, 8, 15) -} - -criterion_group!(bench, hyrax_committing_benchmark, hyrax_opening_benchmark); -criterion_main!(bench); diff --git a/poly_commit/benches/kzg.rs b/poly_commit/benches/kzg.rs index 7483df1e6..fc098ed8a 100644 --- a/poly_commit/benches/kzg.rs +++ b/poly_commit/benches/kzg.rs @@ -6,7 +6,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use gkr_engine::Transcript; use gkr_hashers::Keccak256hasher; use halo2curves::bn256::Bn256; -use poly_commit::{HyperBiKZGPCS, PolynomialCommitmentScheme}; +use poly_commit::{HyperUniKZGPCS, PolynomialCommitmentScheme}; use polynomials::MultiLinearPoly; use transcript::BytesHashTranscript; @@ -23,14 +23,14 @@ fn hyperkzg_committing_benchmark_helper( for num_vars in lowest_num_vars..=highest_num_vars { let poly = MultiLinearPoly::::random(num_vars, &mut rng); - let (srs, _) = HyperBiKZGPCS::::gen_srs_for_testing(&num_vars, &mut rng); + let (srs, _) = HyperUniKZGPCS::::gen_srs_for_testing(&num_vars, &mut rng); group .bench_function( BenchmarkId::new(format!("{num_vars} variables"), num_vars), |b| { b.iter(|| { - _ = black_box(HyperBiKZGPCS::::commit( + _ = black_box(HyperUniKZGPCS::::commit( &num_vars, &srs, &poly, @@ -61,17 +61,17 @@ fn hyperkzg_opening_benchmark_helper( for num_vars in lowest_num_vars..=highest_num_vars { let poly = MultiLinearPoly::::random(num_vars, &mut rng); - let (srs, _) = HyperBiKZGPCS::::gen_srs_for_testing(&num_vars, &mut rng); + let (srs, _) = HyperUniKZGPCS::::gen_srs_for_testing(&num_vars, &mut rng); let eval_point: Vec<_> = (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect(); - let _ = HyperBiKZGPCS::::commit(&num_vars, &srs, &poly, &mut scratch_pad); + let _ = HyperUniKZGPCS::::commit(&num_vars, &srs, &poly, &mut scratch_pad); group .bench_function( BenchmarkId::new(format!("{num_vars} variables"), num_vars), |b| { b.iter(|| { - _ = black_box(HyperBiKZGPCS::::open( + _ = black_box(HyperUniKZGPCS::::open( &num_vars, &srs, &poly, diff --git a/poly_commit/benches/orion.rs b/poly_commit/benches/orion.rs deleted file mode 100644 index afb0e3684..000000000 --- a/poly_commit/benches/orion.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::hint::black_box; - -use arith::{ExtensionField, Field, SimdField}; -use ark_std::test_rng; -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use gf2::{GF2x128, GF2x8, GF2}; -use gf2_128::GF2_128; -use gkr_engine::Transcript; -use gkr_hashers::Keccak256hasher; -use goldilocks::{Goldilocks, GoldilocksExt2, Goldilocksx8}; -use mersenne31::{M31Ext3, M31x16, M31}; -use poly_commit::*; -use polynomials::MultiLinearPoly; -use transcript::BytesHashTranscript; -use tynm::type_name; - -fn simd_field_committing_benchmark_helper( - c: &mut Criterion, - lowest_num_vars: usize, - highest_num_vars: usize, -) where - F: Field, - SimdF: SimdField, - ComPackF: SimdField, -{ - let mut group = c.benchmark_group(format!( - "Orion PCS SIMD field committing: F = {}, SIMD-F = {}, ComPackF = {}", - type_name::(), - type_name::(), - type_name::(), - )); - - let mut rng = test_rng(); - let mut scratch_pad = OrionScratchPad::default(); - - for num_vars in lowest_num_vars..=highest_num_vars { - let packed_num_vars = num_vars - SimdF::PACK_SIZE.ilog2() as usize; - let poly = MultiLinearPoly::::random(packed_num_vars, &mut rng); - - let (srs, _) = OrionSRS::from_random( - 1, - num_vars, - F::FIELD_SIZE, - ComPackF::PACK_SIZE, - ORION_CODE_PARAMETER_INSTANCE, - &mut rng, - ); - - group - .bench_function( - BenchmarkId::new( - format!( - "{num_vars} variables with {packed_num_vars} being packed poly num vars" - ), - num_vars, - ), - |b| { - b.iter(|| { - _ = black_box( - orion_commit_simd_field::<_, SimdF, ComPackF>( - &srs, - &poly, - &mut scratch_pad, - ) - .unwrap(), - ) - }) - }, - ) - .sample_size(10); - } -} - -fn orion_simd_field_committing_benchmark(c: &mut Criterion) { - simd_field_committing_benchmark_helper::(c, 19, 32); - simd_field_committing_benchmark_helper::(c, 19, 27); - simd_field_committing_benchmark_helper::(c, 19, 27); -} - -fn simd_field_opening_benchmark_helper( - c: &mut Criterion, - lowest_num_vars: usize, - highest_num_vars: usize, -) where - F: Field, - SimdF: SimdField, - EvalF: ExtensionField, - ComPackF: SimdField, - T: Transcript, -{ - let mut group = c.benchmark_group(format!( - "Orion PCS SIMD field opening: SIMD-F = {}, EvalF = {}, ComPackF = {}", - type_name::(), - type_name::(), - type_name::(), - )); - - let mut rng = test_rng(); - let mut transcript = T::new(); - let mut scratch_pad = OrionScratchPad::default(); - - for num_vars in lowest_num_vars..=highest_num_vars { - let packed_num_vars = num_vars - SimdF::PACK_SIZE.ilog2() as usize; - let poly = MultiLinearPoly::::random(packed_num_vars, &mut rng); - let eval_point: Vec<_> = (0..num_vars) - .map(|_| EvalF::random_unsafe(&mut rng)) - .collect(); - - let (srs, _) = OrionSRS::from_random( - 1, - num_vars, - F::FIELD_SIZE, - ComPackF::PACK_SIZE, - ORION_CODE_PARAMETER_INSTANCE, - &mut rng, - ); - - let _commitment = - orion_commit_simd_field::<_, SimdF, ComPackF>(&srs, &poly, &mut scratch_pad).unwrap(); - - group - .bench_function( - BenchmarkId::new( - format!( - "{num_vars} variables with {packed_num_vars} being packed poly num vars" - ), - num_vars, - ), - |b| { - b.iter(|| { - _ = black_box(orion_open_simd_field::( - &srs, - &poly, - &eval_point, - &mut transcript, - &scratch_pad, - )) - }) - }, - ) - .sample_size(10); - } -} - -fn orion_simd_field_opening_benchmark(c: &mut Criterion) { - simd_field_opening_benchmark_helper::< - GF2, - GF2x8, - GF2_128, - GF2x128, - BytesHashTranscript, - >(c, 19, 32); - simd_field_opening_benchmark_helper::< - M31, - M31x16, - M31Ext3, - M31x16, - BytesHashTranscript, - >(c, 19, 27); - simd_field_opening_benchmark_helper::< - Goldilocks, - Goldilocksx8, - GoldilocksExt2, - Goldilocksx8, - BytesHashTranscript, - >(c, 19, 27); -} - -criterion_group!( - bench, - orion_simd_field_committing_benchmark, - orion_simd_field_opening_benchmark, -); -criterion_main!(bench); diff --git a/poly_commit/benches/pcs_all.rs b/poly_commit/benches/pcs_all.rs index 5faf0e7d8..da88cd1ae 100644 --- a/poly_commit/benches/pcs_all.rs +++ b/poly_commit/benches/pcs_all.rs @@ -4,10 +4,8 @@ use criterion::black_box; use gkr_engine::StructuredReferenceString; use gkr_engine::{root_println, MPIConfig, MPIEngine, Transcript}; use gkr_hashers::{Keccak256hasher, SHA256hasher}; -use halo2curves::bn256::{Bn256, G1Affine}; -use poly_commit::{ - BatchOpeningPCS, HyperUniKZGPCS, HyraxPCS, OrionBaseFieldPCS, PolynomialCommitmentScheme, -}; +use halo2curves::bn256::Bn256; +use poly_commit::{BatchOpeningPCS, HyperUniKZGPCS, PolynomialCommitmentScheme}; use polynomials::MultiLinearPoly; use rand::RngCore; use serdes::ExpSerde; @@ -24,78 +22,10 @@ fn main() { for num_vars in 18..21 { root_println!(mpi_config, "num vars: {}", num_vars); bench_kzg(&mpi_config, num_vars); - bench_hyrax(&mpi_config, num_vars); - bench_orion(&mpi_config, num_vars); println!("=========================="); } } -fn bench_orion(mpi_config: &MPIConfig, num_vars: usize) { - // full scalar - let mut rng = test_rng(); - let (srs, _) = OrionBaseFieldPCS::::gen_srs_for_testing(&num_vars, &mut rng); - - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - let eval_point: Vec<_> = (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect(); - pcs_bench::>( - mpi_config, - &num_vars, - &srs, - &poly, - &eval_point, - "orion full scalar ", - ); - - // small scalar - let input = (0..1 << num_vars) - .map(|_| Fr::from(rng.next_u32())) - .collect::>(); - let poly = MultiLinearPoly::::new(input); - pcs_bench::>( - mpi_config, - &num_vars, - &srs, - &poly, - &eval_point, - "orion small scalar", - ); -} - -fn bench_hyrax(mpi_config: &MPIConfig, num_vars: usize) { - // full scalar - let mut rng = test_rng(); - let (srs, _) = HyraxPCS::::gen_srs_for_testing(&num_vars, &mut rng); - - let poly = MultiLinearPoly::::random(num_vars, &mut rng); - let eval_point: Vec<_> = (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect(); - - pcs_bench::>( - mpi_config, - &num_vars, - &srs, - &poly, - &eval_point, - "hyrax full scalar ", - ); - - // small scalar - let input = (0..1 << num_vars) - .map(|_| Fr::from(rng.next_u32())) - .collect::>(); - let poly = MultiLinearPoly::::new(input); - pcs_bench::>( - mpi_config, - &num_vars, - &srs, - &poly, - &eval_point, - "hyrax small scalar", - ); - - // batch open - bench_batch_open::>(mpi_config, num_vars, NUM_POLY_BATCH_OPEN); -} - fn bench_kzg(mpi_config: &MPIConfig, num_vars: usize) { // full scalar let mut rng = test_rng(); From f91152bd62d068fccdcf48ff5bf139060dcccf4e Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 29 Jul 2025 18:27:51 -0400 Subject: [PATCH 3/4] bump up arkworks version --- Cargo.lock | 4 ++-- Cargo.toml | 8 ++++---- poly_commit/Cargo.toml | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d6296269..763bda271 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,9 +114,9 @@ dependencies = [ [[package]] name = "ark-std" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", "rand", diff --git a/Cargo.toml b/Cargo.toml index 1154a72ad..a9ede24bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,10 @@ members = [ resolver = "2" [workspace.dependencies] -ark-std = "0.4" -ark-bn254 = "0.4.0" -ark-ec = "0.4.0" -ark-ff = { version = "0.4" } +ark-std = "0.5" +ark-bn254 = "0.5.0" +ark-ec = "0.5.0" +ark-ff = "0.5.0" bytes = "1.6.0" chrono = "0.4.38" clap = { version = "4.1", features = ["derive"] } diff --git a/poly_commit/Cargo.toml b/poly_commit/Cargo.toml index 07fc0e64f..56751d10b 100644 --- a/poly_commit/Cargo.toml +++ b/poly_commit/Cargo.toml @@ -10,7 +10,6 @@ gkr_engine = { path = "../gkr_engine" } polynomials = { path = "../arith/polynomials"} serdes = { path = "../serdes" } transcript = { path = "../transcript" } -# tree = { path = "../tree" } utils = { path = "../utils" } sumcheck = { path = "../sumcheck" } From 5c6a87d5048d8e3b0d54df2e3ab490b4cd140cd5 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Wed, 6 Aug 2025 23:20:32 -0400 Subject: [PATCH 4/4] impl from --- arith/babybear/src/babybear_ext.rs | 11 ++++++++- arith/babybear/src/babybear_ext3x16.rs | 15 +++++++++++- arith/babybear/src/babybearx16.rs | 2 +- .../src/babybearx16/babybear_avx256.rs | 7 ++++++ .../src/babybearx16/babybear_avx512.rs | 7 ++++++ .../babybear/src/babybearx16/babybear_neon.rs | 8 +++++++ arith/gf2/src/gf2.rs | 7 ++++++ arith/gf2/src/gf2x128/avx.rs | 12 ++++++++++ arith/gf2/src/gf2x128/neon.rs | 12 ++++++++++ arith/gf2/src/gf2x64.rs | 12 ++++++++++ arith/gf2/src/gf2x8.rs | 12 ++++++++++ arith/gf2_128/src/gf2_ext128/avx.rs | 9 +++++++ arith/gf2_128/src/gf2_ext128/neon.rs | 9 +++++++ arith/gf2_128/src/gf2_ext128x8/avx256.rs | 11 +++++++++ arith/gf2_128/src/gf2_ext128x8/avx512.rs | 9 +++++++ arith/gf2_128/src/gf2_ext128x8/neon.rs | 18 ++++++++++++++ arith/goldilocks/src/goldilocks_ext2x8.rs | 10 ++++++++ arith/mersenne31/src/m31.rs | 8 +++++++ arith/mersenne31/src/m31_ext3.rs | 10 ++++++++ arith/mersenne31/src/m31_ext3x16.rs | 12 +++++++++- arith/mersenne31/src/m31_ext6.rs | 11 ++++++++- arith/mersenne31/src/m31x16/m31_avx256.rs | 7 ++++++ arith/mersenne31/src/m31x16/m31_avx512.rs | 7 ++++++ arith/mersenne31/src/m31x16/m31_neon.rs | 7 ++++++ arith/mersenne31/src/tests.rs | 24 +++++++++---------- arith/src/bn254xn.rs | 7 ++++++ arith/src/field.rs | 1 + arith/src/monty.rs | 11 +++++++++ sumcheck/src/prover_helper/power_gate.rs | 7 +++--- sumcheck/src/prover_helper/simd_gate.rs | 7 +++--- sumcheck/src/scratch_pad.rs | 14 +++++------ transcript/src/tests.rs | 2 +- 32 files changed, 275 insertions(+), 31 deletions(-) diff --git a/arith/babybear/src/babybear_ext.rs b/arith/babybear/src/babybear_ext.rs index f6956e535..f8635b6de 100644 --- a/arith/babybear/src/babybear_ext.rs +++ b/arith/babybear/src/babybear_ext.rs @@ -207,11 +207,20 @@ impl From for BabyBearExt3 { } } +impl From for BabyBearExt3 { + #[inline(always)] + fn from(x: u64) -> Self { + BabyBearExt3 { + v: [BabyBear::from(x), BabyBear::zero(), BabyBear::zero()], + } + } +} + impl FFTField for BabyBearExt3 { const TWO_ADICITY: usize = 27; fn root_of_unity() -> Self { - Self::from(0x1a427a41) + Self::from(0x1a427a41u32) } } diff --git a/arith/babybear/src/babybear_ext3x16.rs b/arith/babybear/src/babybear_ext3x16.rs index 8e30a79df..7aa457070 100644 --- a/arith/babybear/src/babybear_ext3x16.rs +++ b/arith/babybear/src/babybear_ext3x16.rs @@ -264,7 +264,7 @@ impl FFTField for BabyBearExt3x16 { const TWO_ADICITY: usize = 27; fn root_of_unity() -> Self { - Self::from(0x1a427a41) + Self::from(0x1a427a41u32) } } @@ -333,6 +333,19 @@ impl From for BabyBearExt3x16 { } } +impl From for BabyBearExt3x16 { + #[inline(always)] + fn from(x: u64) -> Self { + BabyBearExt3x16 { + v: [ + BabyBearx16::from(x), + BabyBearx16::zero(), + BabyBearx16::zero(), + ], + } + } +} + #[inline(always)] fn add_internal(a: &BabyBearExt3x16, b: &BabyBearExt3x16) -> BabyBearExt3x16 { let mut vv = a.v; diff --git a/arith/babybear/src/babybearx16.rs b/arith/babybear/src/babybearx16.rs index ef30f46a5..c1a3d8aed 100644 --- a/arith/babybear/src/babybearx16.rs +++ b/arith/babybear/src/babybearx16.rs @@ -39,6 +39,6 @@ impl FFTField for BabyBearx16 { const TWO_ADICITY: usize = 27; fn root_of_unity() -> Self { - Self::from(0x1a427a41) + Self::from(0x1a427a41u32) } } diff --git a/arith/babybear/src/babybearx16/babybear_avx256.rs b/arith/babybear/src/babybearx16/babybear_avx256.rs index 0d65c3248..505ee4942 100644 --- a/arith/babybear/src/babybearx16/babybear_avx256.rs +++ b/arith/babybear/src/babybearx16/babybear_avx256.rs @@ -376,6 +376,13 @@ impl From for AVXBabyBear { } } +impl From for AVXBabyBear { + #[inline(always)] + fn from(x: u64) -> Self { + AVXBabyBear::pack_full(&BabyBear::from(x)) + } +} + impl Neg for AVXBabyBear { type Output = AVXBabyBear; #[inline(always)] diff --git a/arith/babybear/src/babybearx16/babybear_avx512.rs b/arith/babybear/src/babybearx16/babybear_avx512.rs index 73d9a1467..87e15f03d 100644 --- a/arith/babybear/src/babybearx16/babybear_avx512.rs +++ b/arith/babybear/src/babybearx16/babybear_avx512.rs @@ -322,6 +322,13 @@ impl From for AVXBabyBear { } } +impl From for AVXBabyBear { + #[inline(always)] + fn from(x: u64) -> Self { + AVXBabyBear::pack_full(&BabyBear::from(x)) + } +} + impl Neg for AVXBabyBear { type Output = AVXBabyBear; #[inline(always)] diff --git a/arith/babybear/src/babybearx16/babybear_neon.rs b/arith/babybear/src/babybearx16/babybear_neon.rs index 0ba81f583..b22b8a8a1 100644 --- a/arith/babybear/src/babybearx16/babybear_neon.rs +++ b/arith/babybear/src/babybearx16/babybear_neon.rs @@ -267,6 +267,14 @@ impl From for NeonBabyBear { } } +impl From for NeonBabyBear { + #[inline(always)] + fn from(value: u64) -> Self { + // BabyBear::new converts to Montgomery form + NeonBabyBear::pack_full(&BabyBear::new(value)) + } +} + impl Neg for NeonBabyBear { type Output = Self; diff --git a/arith/gf2/src/gf2.rs b/arith/gf2/src/gf2.rs index 83b64b82c..efa0484ea 100644 --- a/arith/gf2/src/gf2.rs +++ b/arith/gf2/src/gf2.rs @@ -158,6 +158,13 @@ impl From for GF2 { } } +impl From for GF2 { + #[inline(always)] + fn from(v: u64) -> Self { + GF2 { v: (v % 2) as u8 } + } +} + impl From for GF2 { #[inline(always)] fn from(value: bool) -> Self { diff --git a/arith/gf2/src/gf2x128/avx.rs b/arith/gf2/src/gf2x128/avx.rs index a61541d69..f45b7fd03 100644 --- a/arith/gf2/src/gf2x128/avx.rs +++ b/arith/gf2/src/gf2x128/avx.rs @@ -293,6 +293,18 @@ impl From for AVXGF2x128 { } } +impl From for AVXGF2x128 { + #[inline(always)] + fn from(v: u64) -> Self { + assert!(v < 2); + if v == 0 { + AVXGF2x128::ZERO + } else { + AVXGF2x128::ONE + } + } +} + impl From for AVXGF2x128 { #[inline(always)] fn from(v: GF2) -> Self { diff --git a/arith/gf2/src/gf2x128/neon.rs b/arith/gf2/src/gf2x128/neon.rs index 376ded5f7..92f562b00 100644 --- a/arith/gf2/src/gf2x128/neon.rs +++ b/arith/gf2/src/gf2x128/neon.rs @@ -294,6 +294,18 @@ impl From for NeonGF2x128 { } } +impl From for NeonGF2x128 { + #[inline(always)] + fn from(v: u64) -> Self { + assert!(v < 2); + if v == 0 { + NeonGF2x128::ZERO + } else { + NeonGF2x128::ONE + } + } +} + impl From for NeonGF2x128 { #[inline(always)] fn from(v: GF2) -> Self { diff --git a/arith/gf2/src/gf2x64.rs b/arith/gf2/src/gf2x64.rs index 4c96fc817..12c260002 100644 --- a/arith/gf2/src/gf2x64.rs +++ b/arith/gf2/src/gf2x64.rs @@ -236,6 +236,18 @@ impl From for GF2x64 { } } +impl From for GF2x64 { + #[inline(always)] + fn from(v: u64) -> Self { + assert!(v < 2); + if v == 0 { + GF2x64 { v: 0 } + } else { + GF2x64 { v: !0u64 } + } + } +} + impl From for GF2x64 { #[inline(always)] fn from(v: GF2) -> Self { diff --git a/arith/gf2/src/gf2x8.rs b/arith/gf2/src/gf2x8.rs index b4c3a5d3e..0db199f39 100644 --- a/arith/gf2/src/gf2x8.rs +++ b/arith/gf2/src/gf2x8.rs @@ -235,6 +235,18 @@ impl From for GF2x8 { } } +impl From for GF2x8 { + #[inline(always)] + fn from(v: u64) -> Self { + assert!(v < 2); + if v == 0 { + GF2x8 { v: 0 } + } else { + GF2x8 { v: 0xFF } + } + } +} + impl From for GF2x8 { #[inline(always)] fn from(v: GF2) -> Self { diff --git a/arith/gf2_128/src/gf2_ext128/avx.rs b/arith/gf2_128/src/gf2_ext128/avx.rs index eb34aef3b..467d6e84b 100644 --- a/arith/gf2_128/src/gf2_ext128/avx.rs +++ b/arith/gf2_128/src/gf2_ext128/avx.rs @@ -325,6 +325,15 @@ impl From for AVXGF2_128 { } } +impl From for AVXGF2_128 { + #[inline(always)] + fn from(v: u64) -> Self { + AVXGF2_128 { + v: unsafe { std::mem::transmute::<[u64; 2], __m128i>([v, 0]) }, + } + } +} + #[inline(always)] fn add_internal(a: &AVXGF2_128, b: &AVXGF2_128) -> AVXGF2_128 { AVXGF2_128 { diff --git a/arith/gf2_128/src/gf2_ext128/neon.rs b/arith/gf2_128/src/gf2_ext128/neon.rs index f55d3e720..db5d20a3f 100644 --- a/arith/gf2_128/src/gf2_ext128/neon.rs +++ b/arith/gf2_128/src/gf2_ext128/neon.rs @@ -271,6 +271,15 @@ impl From for NeonGF2_128 { } } +impl From for NeonGF2_128 { + #[inline(always)] + fn from(v: u64) -> Self { + NeonGF2_128 { + v: unsafe { transmute::<[u64; 2], uint32x4_t>([v, 0]) }, + } + } +} + // multiply the polynomial by x^32, without reducing the irreducible polynomial // equivalent to _mm_shuffle_epi32(a, 147) #[inline(always)] diff --git a/arith/gf2_128/src/gf2_ext128x8/avx256.rs b/arith/gf2_128/src/gf2_ext128x8/avx256.rs index b17215a3a..38c3d6f2a 100644 --- a/arith/gf2_128/src/gf2_ext128x8/avx256.rs +++ b/arith/gf2_128/src/gf2_ext128x8/avx256.rs @@ -358,6 +358,17 @@ impl From for AVX256GF2_128x8 { } } +impl From for AVX256GF2_128x8 { + #[inline(always)] + fn from(v: u64) -> AVX256GF2_128x8 { + assert!(v < 2); // only 0 and 1 are allowed + let data = unsafe { _mm256_set_epi64x(0, v as i64, 0, v as i64) }; + AVX256GF2_128x8 { + data: [data, data, data, data], + } + } +} + impl Neg for AVX256GF2_128x8 { type Output = AVX256GF2_128x8; diff --git a/arith/gf2_128/src/gf2_ext128x8/avx512.rs b/arith/gf2_128/src/gf2_ext128x8/avx512.rs index 8de2d1daf..c4d68cc4b 100644 --- a/arith/gf2_128/src/gf2_ext128x8/avx512.rs +++ b/arith/gf2_128/src/gf2_ext128x8/avx512.rs @@ -339,6 +339,15 @@ impl From for AVX512GF2_128x8 { } } +impl From for AVX512GF2_128x8 { + #[inline(always)] + fn from(v: u64) -> AVX512GF2_128x8 { + assert!(v < 2); // only 0 and 1 are allowed + let data = unsafe { _mm512_set_epi64(0, v as i64, 0, v as i64, 0, v as i64, 0, v as i64) }; + AVX512GF2_128x8 { data: [data, data] } + } +} + impl Neg for AVX512GF2_128x8 { type Output = AVX512GF2_128x8; diff --git a/arith/gf2_128/src/gf2_ext128x8/neon.rs b/arith/gf2_128/src/gf2_ext128x8/neon.rs index 6d23d82b8..749e07cc7 100644 --- a/arith/gf2_128/src/gf2_ext128x8/neon.rs +++ b/arith/gf2_128/src/gf2_ext128x8/neon.rs @@ -224,6 +224,24 @@ impl From for NeonGF2_128x8 { } } +impl From for NeonGF2_128x8 { + fn from(v: u64) -> Self { + NeonGF2_128x8 { + v: [ + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + unsafe { transmute::<[u64; 2], uint64x2_t>([v, 0]) }, + ], + } + } +} + #[inline(always)] fn add_internal(a: &NeonGF2_128x8, b: &NeonGF2_128x8) -> NeonGF2_128x8 { NeonGF2_128x8 { diff --git a/arith/goldilocks/src/goldilocks_ext2x8.rs b/arith/goldilocks/src/goldilocks_ext2x8.rs index cf77151ce..3c3590371 100644 --- a/arith/goldilocks/src/goldilocks_ext2x8.rs +++ b/arith/goldilocks/src/goldilocks_ext2x8.rs @@ -298,6 +298,16 @@ impl From for GoldilocksExt2x8 { } } +impl From for GoldilocksExt2x8 { + #[inline] + fn from(value: u64) -> Self { + Self { + c0: Goldilocksx8::from(value), + c1: Goldilocksx8::ZERO, + } + } +} + #[inline(always)] fn add_internal(a: &GoldilocksExt2x8, b: &GoldilocksExt2x8) -> GoldilocksExt2x8 { GoldilocksExt2x8 { diff --git a/arith/mersenne31/src/m31.rs b/arith/mersenne31/src/m31.rs index b1f44d367..5acf0e4b6 100644 --- a/arith/mersenne31/src/m31.rs +++ b/arith/mersenne31/src/m31.rs @@ -232,6 +232,14 @@ impl From for M31 { } } +impl From for M31 { + #[inline(always)] + fn from(x: u64) -> Self { + assert!(x <= u32::MAX as u64, "Value out of range for M31"); + Self::from(x as u32) + } +} + impl M31 { #[inline(always)] fn exp_power_of_2(&self, power_log: usize) -> Self { diff --git a/arith/mersenne31/src/m31_ext3.rs b/arith/mersenne31/src/m31_ext3.rs index 6c9338c41..4df4f4380 100644 --- a/arith/mersenne31/src/m31_ext3.rs +++ b/arith/mersenne31/src/m31_ext3.rs @@ -207,6 +207,16 @@ impl From for M31Ext3 { } } +impl From for M31Ext3 { + #[inline(always)] + fn from(x: u64) -> Self { + assert!(x <= u32::MAX as u64, "Value out of range for M31Ext3"); + M31Ext3 { + v: [M31::from(x as u32), M31::zero(), M31::zero()], + } + } +} + impl M31Ext3 { #[inline(always)] pub fn to_base_field(&self) -> M31 { diff --git a/arith/mersenne31/src/m31_ext3x16.rs b/arith/mersenne31/src/m31_ext3x16.rs index 48ed68c98..99ce29e8f 100644 --- a/arith/mersenne31/src/m31_ext3x16.rs +++ b/arith/mersenne31/src/m31_ext3x16.rs @@ -261,7 +261,7 @@ impl Mul for M31Ext3x16 { // + (a0*b1 + a1*b0)*x + 5* a2*b2 // + (a0*b2 + a1*b1 + a2*b0)*x^2 - let five = M31::from(5); + let five = M31::from(5u32); let mut res = [M31x16::default(); 3]; res[0] = self.v[0] * rhs.v[0] + self.v[1] * (rhs.v[2] * five) + self.v[2] * (rhs.v[1] * five); @@ -312,6 +312,16 @@ impl From for M31Ext3x16 { } } +impl From for M31Ext3x16 { + #[inline(always)] + fn from(x: u64) -> Self { + assert!(x <= u32::MAX as u64, "Value out of range for M31Ext3x16"); + M31Ext3x16 { + v: [M31x16::from(x as u32), M31x16::zero(), M31x16::zero()], + } + } +} + #[inline(always)] fn add_internal(a: &M31Ext3x16, b: &M31Ext3x16) -> M31Ext3x16 { let mut vv = a.v; diff --git a/arith/mersenne31/src/m31_ext6.rs b/arith/mersenne31/src/m31_ext6.rs index d33d21b46..42dbc515c 100644 --- a/arith/mersenne31/src/m31_ext6.rs +++ b/arith/mersenne31/src/m31_ext6.rs @@ -181,7 +181,7 @@ impl FFTField for M31Ext6 { #[inline(always)] fn root_of_unity() -> Self { Self { - v: [M31Ext3::from(1840555991), M31Ext3::from(599996438)], + v: [M31Ext3::from(1840555991u32), M31Ext3::from(599996438u32)], } } } @@ -214,6 +214,15 @@ impl From for M31Ext6 { } } +impl From for M31Ext6 { + #[inline(always)] + fn from(x: u64) -> Self { + Self { + v: [M31Ext3::from(x), M31Ext3::ZERO], + } + } +} + impl From for M31Ext6 { #[inline(always)] fn from(x: M31Ext3) -> Self { diff --git a/arith/mersenne31/src/m31x16/m31_avx256.rs b/arith/mersenne31/src/m31x16/m31_avx256.rs index cf8a33de6..0fb652a0c 100644 --- a/arith/mersenne31/src/m31x16/m31_avx256.rs +++ b/arith/mersenne31/src/m31x16/m31_avx256.rs @@ -461,6 +461,13 @@ impl From for AVXM31 { } } +impl From for AVXM31 { + #[inline(always)] + fn from(x: u64) -> Self { + AVXM31::pack_full(&M31::from(x)) + } +} + impl Neg for AVXM31 { type Output = AVXM31; #[inline(always)] diff --git a/arith/mersenne31/src/m31x16/m31_avx512.rs b/arith/mersenne31/src/m31x16/m31_avx512.rs index 57c993cbf..15cafaa77 100644 --- a/arith/mersenne31/src/m31x16/m31_avx512.rs +++ b/arith/mersenne31/src/m31x16/m31_avx512.rs @@ -373,6 +373,13 @@ impl From for AVXM31 { } } +impl From for AVXM31 { + #[inline(always)] + fn from(x: u64) -> Self { + AVXM31::pack_full(&M31::from(x)) + } +} + impl Neg for AVXM31 { type Output = AVXM31; #[inline(always)] diff --git a/arith/mersenne31/src/m31x16/m31_neon.rs b/arith/mersenne31/src/m31x16/m31_neon.rs index 7d479f628..b8335bac8 100644 --- a/arith/mersenne31/src/m31x16/m31_neon.rs +++ b/arith/mersenne31/src/m31x16/m31_neon.rs @@ -425,6 +425,13 @@ impl From for NeonM31 { } } +impl From for NeonM31 { + #[inline(always)] + fn from(x: u64) -> Self { + NeonM31::pack_full(&M31::from(x)) + } +} + impl Neg for NeonM31 { type Output = NeonM31; #[inline(always)] diff --git a/arith/mersenne31/src/tests.rs b/arith/mersenne31/src/tests.rs index 7fdf9fb30..bc5494b50 100644 --- a/arith/mersenne31/src/tests.rs +++ b/arith/mersenne31/src/tests.rs @@ -61,7 +61,7 @@ fn test_simd_field() { random_simd_field_tests::("Vectorized M31".to_string()); - let a = M31x16::from(256 + 2); + let a = M31x16::from(256u32 + 2); let mut buffer = vec![]; assert!(a.serialize_into(&mut buffer).is_ok()); let b = M31x16::deserialize_from(buffer.as_slice()); @@ -91,29 +91,29 @@ fn test_ext_field() { #[test] fn test_vectors() { let a = M31Ext3 { - v: [M31::from(1), M31::from(2), M31::from(3)], + v: [M31::from(1u32), M31::from(2u32), M31::from(3u32)], }; let b = M31Ext3 { - v: [M31::from(4), M31::from(5), M31::from(6)], + v: [M31::from(4u32), M31::from(5u32), M31::from(6u32)], }; let expected_prod = M31Ext3 { - v: [M31::from(139), M31::from(103), M31::from(28)], + v: [M31::from(139u32), M31::from(103u32), M31::from(28u32)], }; assert_eq!(expected_prod, a * b); let expected_inv = M31Ext3 { v: [ - M31::from(1279570927), - M31::from(2027416670), - M31::from(696388467), + M31::from(1279570927u32), + M31::from(2027416670u32), + M31::from(696388467u32), ], }; assert_eq!(expected_inv, a.inv().unwrap()); let a_pow_11 = M31Ext3 { v: [ - M31::from(2145691179), - M31::from(1848238717), - M31::from(1954563431), + M31::from(2145691179u32), + M31::from(1848238717u32), + M31::from(1954563431u32), ], }; assert_eq!(a_pow_11, a.exp(11)); @@ -124,7 +124,7 @@ fn test_poseidon_m31_fiat_shamir_hash() { let perm = PoseidonFiatShamirHasher::::new(); { - let state_elems: Vec = [M31::from(114514); M31x16::RATE] + let state_elems: Vec = [M31::from(114514u32); M31x16::RATE] .iter() .flat_map(|x| { let mut xu8 = vec![]; @@ -160,7 +160,7 @@ fn test_poseidon_m31_fiat_shamir_hash() { } { - let state_elems: Vec = [M31::from(114514); M31x16::STATE_WIDTH] + let state_elems: Vec = [M31::from(114514u32); M31x16::STATE_WIDTH] .iter() .flat_map(|x| { let mut xu8 = vec![]; diff --git a/arith/src/bn254xn.rs b/arith/src/bn254xn.rs index 15bcb3ee9..c2802a7f1 100644 --- a/arith/src/bn254xn.rs +++ b/arith/src/bn254xn.rs @@ -89,6 +89,13 @@ impl From for FrxN { } } +impl From for FrxN { + fn from(x: u64) -> Self { + let v = Fr::from(x); + Self { v: [v; N] } + } +} + rep_field_common!( FrxN ); impl Field for FrxN { diff --git a/arith/src/field.rs b/arith/src/field.rs index c876c3d28..0458d502d 100644 --- a/arith/src/field.rs +++ b/arith/src/field.rs @@ -18,6 +18,7 @@ pub trait Field: + Default + PartialEq + From + + From + Neg + Add + Sub diff --git a/arith/src/monty.rs b/arith/src/monty.rs index 5f7679465..c9b724f47 100644 --- a/arith/src/monty.rs +++ b/arith/src/monty.rs @@ -140,6 +140,17 @@ impl From for MontyField31 { } } +impl From for MontyField31 { + #[inline(always)] + fn from(value: u64) -> Self { + assert!( + value <= u32::MAX as u64, + "Value out of range for MontyField31" + ); + Self::new(value as u32) + } +} + impl ExpSerde for MontyField31 { #[inline(always)] fn serialize_into(&self, mut writer: W) -> SerdeResult<()> { diff --git a/sumcheck/src/prover_helper/power_gate.rs b/sumcheck/src/prover_helper/power_gate.rs index 8e7266be2..cd2fee845 100644 --- a/sumcheck/src/prover_helper/power_gate.rs +++ b/sumcheck/src/prover_helper/power_gate.rs @@ -37,11 +37,12 @@ impl SumcheckPowerGateHelper { p[3] += p_add_coef_0 + p_add_coef_1.mul_by_3() + p_add_coef_2.mul_by_3().mul_by_3(); p[4] += p_add_coef_0 + p_add_coef_1.double().double() - + p_add_coef_2 * F::CircuitField::from(16); - p[5] += p_add_coef_0 + p_add_coef_1.mul_by_5() + p_add_coef_2 * F::CircuitField::from(25); + + p_add_coef_2 * F::CircuitField::from(16u32); + p[5] += + p_add_coef_0 + p_add_coef_1.mul_by_5() + p_add_coef_2 * F::CircuitField::from(25u32); p[6] += p_add_coef_0 + p_add_coef_1.mul_by_3().double() - + p_add_coef_2 * F::CircuitField::from(36); + + p_add_coef_2 * F::CircuitField::from(36u32); } #[inline] diff --git a/sumcheck/src/prover_helper/simd_gate.rs b/sumcheck/src/prover_helper/simd_gate.rs index e268189d8..8c4fff492 100644 --- a/sumcheck/src/prover_helper/simd_gate.rs +++ b/sumcheck/src/prover_helper/simd_gate.rs @@ -157,11 +157,12 @@ impl SumcheckSimdProdGateHelper { p[3] += p_add_coef_0 + p_add_coef_1.mul_by_3() + p_add_coef_2.mul_by_3().mul_by_3(); p[4] += p_add_coef_0 + p_add_coef_1.double().double() - + p_add_coef_2 * F::CircuitField::from(16); - p[5] += p_add_coef_0 + p_add_coef_1.mul_by_5() + p_add_coef_2 * F::CircuitField::from(25); + + p_add_coef_2 * F::CircuitField::from(16u32); + p[5] += + p_add_coef_0 + p_add_coef_1.mul_by_5() + p_add_coef_2 * F::CircuitField::from(25u32); p[6] += p_add_coef_0 + p_add_coef_1.mul_by_3().double() - + p_add_coef_2 * F::CircuitField::from(36); + + p_add_coef_2 * F::CircuitField::from(36u32); } #[inline] diff --git a/sumcheck/src/scratch_pad.rs b/sumcheck/src/scratch_pad.rs index 708b45a41..5a5739cb7 100644 --- a/sumcheck/src/scratch_pad.rs +++ b/sumcheck/src/scratch_pad.rs @@ -131,8 +131,8 @@ impl VerifierScratchPad { [ F::ChallengeField::ZERO, F::ChallengeField::ONE, - F::ChallengeField::from(2), - F::ChallengeField::from(3), + F::ChallengeField::from(2u32), + F::ChallengeField::from(3u32), ] }; @@ -151,11 +151,11 @@ impl VerifierScratchPad { let deg6_eval_at = [ F::ChallengeField::ZERO, F::ChallengeField::ONE, - F::ChallengeField::from(2), - F::ChallengeField::from(3), - F::ChallengeField::from(4), - F::ChallengeField::from(5), - F::ChallengeField::from(6), + F::ChallengeField::from(2u32), + F::ChallengeField::from(3u32), + F::ChallengeField::from(4u32), + F::ChallengeField::from(5u32), + F::ChallengeField::from(6u32), ]; let mut deg6_lag_denoms_inv = [F::ChallengeField::ZERO; 7]; diff --git a/transcript/src/tests.rs b/transcript/src/tests.rs index 73a56cde5..9b53229e5 100644 --- a/transcript/src/tests.rs +++ b/transcript/src/tests.rs @@ -30,7 +30,7 @@ where { let mut transcript = T::new(); - let base_field_elems: Vec = vec![F::BaseField::from(1); F::DEGREE]; + let base_field_elems: Vec = vec![F::BaseField::from(1u32); F::DEGREE]; let challenge_field_elem: F = F::from_limbs(&base_field_elems); transcript.append_field_element(&challenge_field_elem);